<template> <BasicContainer ref='basicContainer' :option="option"> <!-- 头部 --> <template #head> </template> <!-- 主体 --> <template #body> <view class="main"> <scroll-view class="scvmabx" :style="{height: details.scrollheight}" @scrolltolower="()=>{}" scroll-y="true" @touchmove.stop> <view class="main_container"> <!-- 行 -- 售后类型 --> <view class="info_item border_bottom"> <view class="info_item_title flex-c-sb"> <view class=""> 售 后 包 件 </view> <!-- 新增售后包件 --> <view class="flex addBtn" @click="handleAddPackage"> <view class="addButton"> <u-icon name="close-circle" color="#2F8DFF" size="36"></u-icon> </view> <text class="ml10 fwn"> 添加 </text> </view> </view> </view> <!-- 售后包件列表 --> <view :class="{packageList: true, pd20: details.packageList.length > 0}" :style="{height: (details.packageList.length > 0 ?(40 * details.packageList.length) + ((details.packageList.length - 1) * 10): 0) + 'px'}"> <block v-for="(item, index) in details.packageList"> <view :class="{'packageItem': true, 'flex-c-sb': true, 'mt20': index !== 0}"> <view class="inputBox flex1 flex"> <input class="packageInput flex1" v-model="item.code" placeholder="请输入包条码" /> <view class="scanIcon flex-c-c" @click.stop="()=> handleScan(item)"> <u-icon name="scan" color="#2F8DFF" size="60"></u-icon> </view> </view> <view class="ml20 flex-c-c" @click="()=> handleRemovePackage(index)"> <u-icon name="trash" color="#8792AA" size="36"></u-icon> <text class="ml10 info"> 删除 </text> </view> </view> </block> </view> <!-- 行 -- 售后类型 --> <view class="info_item border_bottom"> <view class="info_item_title flex-c-sb" @click="details.popUpObj.afterSalesType = true"> <view class=""> 售 后 类 型 </view> <view class="flex" @click="handleShowMyDrawer"> <text class="mr10 fwn info"> {{ details.form.typeName || '待确定'}} </text> <u-icon name="arrow-right" color="#AFB4BA" size="36"></u-icon> </view> </view> </view> <!-- 行 -- 图片 --> <view class="info_item border_bottom"> <view class="info_item_title"> 图 片 </view> <view class="imgList flex mt20"> <!-- 单个图片 --> <block v-for="(item, index) in details.imgList" :key="item"> <view class="image_conatiner mr20"> <image :src="item.url" mode=""></image> <!-- 删除 --> <view class="removeIcon" @click="()=> handleRmove(index)"> <u-icon name="close-circle-fill" color="#666" size="50"></u-icon> </view> </view> </block> <!-- 添加图片 --> <view class="image_conatiner addImg flex-c-c" @click="handleUploadFile"> <u-icon name="photo-fill" color="#999" size="100"></u-icon> </view> </view> </view> <!-- 行 -- 备注 --> <view class="info_item "> <view class="info_item_title"> 备 注 </view> <view class="mt20"> <u--textarea v-model="details.form.remark" placeholder="请输入备注"></u--textarea> </view> </view> </view> </scroll-view> <view class="footer" @click="handleSubmit"> <view class="button subColor"> 确 认 </view> </view> </view> </template> </BasicContainer> <MyDrawer ref="myDrawer"> <template #content> <picker-view v-if="details.visible" :indicator-style="details.indicatorStyle" :immediate-change="true" :value="details.value" @change="bindChange" class="picker-view"> <picker-view-column> <view class="item" v-for="(item, index) in details.pickerArr" :key="index"> {{ item.label }} </view> </picker-view-column> </picker-view> </template> </MyDrawer> <tips ref="tip" /> <!-- #ifdef APP --> <saomiao2 :ishidestop="scanState !== 0"></saomiao2> <!-- #endif --> </template> <script lang="ts" setup> import { postInstallAfterSales, } from '@/api/user.js' import { onLoad, onShow, onHide, } from '@dcloudio/uni-app' import { nextTick, reactive, ref, toRefs } from "vue"; import utils from '@/utils/utils.js' import useSystemSettingsStore from '@/store/useSystemSettingsStore'; import { storeToRefs } from 'pinia'; const { scanState } = storeToRefs(useSystemSettingsStore()) // 组件配置 const option = reactive({ // 标题 title: '发起售后', // 下拉刷新回调函数 async pullDownRefreshInitPage() { return null }, // 触底加载回到函数 reachBottomInitPage: async () => { return null }, haveData: true, isEnd: false, pageType: 'add' as 'add' | 'edit', pageLoading: false }) // 组件实例 const basicContainer = ref() const myDrawer = ref() const tip = ref() let details = reactive({ /** 主页面高度 */ scrollheight: '80vh', /** 表单数据 */ form: { type: '', typeName: '', /** 备注 */ remark: '' }, /** 售后包件列表 */ packageList: [{ code: '' }], /** 售后图片列表 */ imgList: [], /** 扫描码值 */ scancode: '', /** 异常类型数组 */ afterSalesTypeOptions: [ [{ label: '雪月夜', // 其他属性值 id: 2021 // ... }, { label: '冷夜雨', id: 804 }] ], scanStateChooseIndex: 0, /** 是否显示弹窗 */ popUpObj: { /** 异常类型 */ afterSalesType: false }, /** picker行高度 */ indicatorStyle: `height: 40px;`, visible: false, value: [0], pickerArr: [ { label: '调试', value: '1' }, { label: '维修', value: '2' }, { label: '理赔', value: '3' }, { label: '待确认', value: '4' }, { label: '换货', value: '5' }, { label: '工厂补单', value: '6' }, ], /** 页面信息 */ pageInfo: { id: '' } }) onLoad((e) => { details.pageInfo.id = e.id }) onShow(async () => { // #ifdef APP // 初始化关闭监听 uni.$off('scancodedate') // init() uni.$on('scancodedate', function (code) { console.log('code :>> ', code); if (code) { console.log(code); details.scancode = code scandata() } }) // #endif await nextTick() // basicContainer.value.startPullDownRefresh() const _height = await utils.getViewDistanceFormTop('.scvmabx') details.scrollheight = Number(_height.replace('px', '')) - 100 + 'px' }) const scandata = () => { } const initpage = () => { } /** 关闭弹窗 */ const hidePopUp = (node) => { details.visible = false node.value.details.showPopUp = false } /** 显示售后类型选择弹窗 */ const handleShowMyDrawer = () => { details.visible = true myDrawer.value.setDetails({ showPopUp: true, height: '50vh', success() { console.log('details.value :>> ', details.value); try { const _item = details.pickerArr[details.value[0]] details.form.type = _item.value details.form.typeName = _item.label } catch (err) { console.log('err :>> ', err); } finally { hidePopUp(myDrawer) } }, close() { hidePopUp(myDrawer) } }) } /** 显示扫描 */ const handleScan = (value) => { console.log('value :>> ', value); // #ifdef MP-WEIXIN // 微信小程序适配 uni.scanCode({ success(res) { console.log('res :>> ', res); console.log('res.result :>> ', res.result); for (let i = 0; i < details.packageList.length; i++) { const value = details.packageList[i] if (value.code === res.result) return utils.handleToast('码值已存在') } value.code = res.result // scandata() } }) return // #endif uni.navigateTo({ url: '/pagesHome/pages/Video/Video' }) } /** 新增售后包件 */ const handleAddPackage = () => { details.packageList.push({ code: '' }) } /** 删除售后包件 */ const handleRemovePackage = (index : number) => { details.packageList.splice(index, 1) } /** picker切换时执行 */ const bindChange = function (e, type) { console.log('type :>> ', type); console.log('e :>> ', e); details.value = e.detail.value } /** 新增图片 */ const handleUploadFile = () => { const successByUpload = (res) => { console.log('res :>> ', res); const { data } = res const _data = JSON.parse(data) console.log('_data :>> ', _data); const { code, data: img } = _data details.imgList.push({ url: img, name: img }) } utils.handleUploadFile({ successByUpload }) } /** 移除图片 */ const handleRmove = (index) => { tip.value.setdetails({ isshow: true, content: '确认移除', cancelTxt: '取消', confirmTxt: '确认', success() { details.imgList.splice(index, 1) // 关闭弹窗 tip.value.setdetails({ isshow: false }) }, cancel() { // 关闭弹窗 tip.value.setdetails({ isshow: false }) } }) } /** 提交 */ const handleSubmit = () => { if (!details.form.type) return utils.handleToast('请选择售后类型') tip.value.setdetails({ isshow: true, content: '确认提交', cancelTxt: '取消', confirmTxt: '确认', async success() { try { option.pageLoading = true const submitData = { type: details.form.type, install_id: details.pageInfo.id, remark: details.form.remark, images: details.imgList, packages: [] } for (let i = 0; i < details.packageList.length; i++) { const _item = details.packageList[i] _item.code && submitData.packages.push(_item.code) } const res = await postInstallAfterSales(submitData) const { code, data } = res if (code !== 200) return uni.navigateBack() } catch (err) { console.log('err :>> ', err); //TODO handle the exception } finally { option.pageLoading = false } // 关闭弹窗 tip.value.setdetails({ isshow: false }) }, cancel() { // 关闭弹窗 tip.value.setdetails({ isshow: false }) } }) } </script> <style lang="scss" scoped> @import url("@/utils/style/common.scss"); // 主体内容 .main { font-family: 黑体; position: relative; border-top-right-radius: 20upx; border-top-left-radius: 20upx; background-color: #fff; .scvmabx { background-color: #fff; } .info { color: #AFB4BA; } .main_container { // padding: 0 20upx; } // 行 .info_item { margin: 0 20upx; padding: 20upx; .info_item_title { // padding: 0 0 20upx; font-weight: bold; height: 40upx; line-height: 40upx; } &.border_bottom { border-bottom: 2upx solid #eee; } :deep(.u-textarea) { background-color: #f5f5f6; border: none; height: 200upx; } // 添加 .addBtn { color: #2F8DFF; .addButton { transform: rotate(45deg); } } } // 包件列表 .packageList { background: #f5f5f6; transition: all 0.3s; overflow: hidden; .packageItem { $inputHeight: 80upx; .inputBox { position: relative; border-radius: calc($inputHeight / 2); overflow: hidden; background: #fff; .packageInput { height: $inputHeight; padding: 0 40upx; } .scanIcon { padding: 0 20upx; // position: absolute; // right: 40upx; // top: 50%; // transform: translateY(-50%); } } } } // 图片列表 .imgList { flex-wrap: wrap; .image_conatiner { position: relative; .removeIcon { position: absolute; top: 0; right: 0; transform: translate(40%, -40%); opacity: 0.9; } } .addImg { width: 160upx; height: 160upx; border-radius: 20upx; box-sizing: border-box; border: 2upx solid #eee; } image { width: 160upx; height: 160upx; border-radius: 20upx; } } } // 底部 .footer { box-sizing: border-box; height: 100px; padding-top: 30upx; display: flex; justify-content: space-between; .button { height: 80upx; display: flex; align-items: center; justify-content: center; flex: 1; // margin: 10upx; border: 2upx solid #b5babf; border-radius: 80upx; margin: 0 10upx; padding: 0 10upx; font-size: 0.9rem; font-weight: bold; &.subColor { // border-color: var(--subjectColor); // color: var(--subjectColor); background-color: var(--subjectColor); color: #fff; border: none; } &.primaryColor { // border-color: var(--primaryColor); // color: var(--primaryColor); background-color: var(--primaryColor); color: #fff; border: none; } &.errColor { // border-color: var(--errColor); // color: var(--errColor); background-color: var(--errColor); color: #fff; border: none; } } } </style>