<template> <!--面料建模--> <view> <!--导航栏 navbar--> <view id="header"> <u-navbar title="面料建模" :border-bottom="false" :background="{backgroundColor: 'whitesmoke'}"> </u-navbar> </view> <!--主题内容--> <view class="body" :style="{ bottom: footerHeight + 'px', top: headerHeight+ 'px'}"> <u-form :model="detail" label-position="top" ref="uForm"> <view class="u-p-30 bg-fff u-m-b-20"> <hs-tip-title title="面料建模"></hs-tip-title> <u-form-item label="面料名称" prop="materialName" required> <u-input v-model="detail.materialName" placeholder="请输入面料名称" /> </u-form-item> <u-form-item label="建模品类" prop="modelingCategoryText" required> <u-input v-model="detail.modelingCategoryText" placeholder="请输入建模品类" type="select" :select-open="show" @click="show = true;"/> </u-form-item> <view class="brandList-tips u-p-t-24 u-p-r-30 u-p-b-24 u-p-l-30" > <view> 项目价格<text class="u-p-l-40">{{detail.price}}元</text> </view> </view> <u-form-item label="面料门幅" prop="clothWidth"> <u-number-box v-model="detail.clothWidth" :step="0.1"></u-number-box>cm </u-form-item> <u-form-item label="面料成分" prop="component" required> <u-input v-model="detail.component" placeholder="请输入面料成分" /> </u-form-item> <u-form-item label="面料图片" prop="modelingTaskPictureDTOList" required> <view class="wrap"> <view> <view v-for="(item, index) in detail.modelingTaskPictureDTOList" :key="index" class="float-left "> <view class="pre-item pre-item--80 u-relative" v-if="item.pictureCode" > <image class="pre-item-image" :src="`${imgUrl}${item.pictureCode}`" mode="aspectFill"></image> <text class="u-absolute pre-item-text text-center">{{ item.pictureType === 1 ? '正面': '反面'}}</text> <view class="u-absolute pre-item-del" @click="triggerDel(index)"> <u-icon name="close" size="28" color="#fff"></u-icon> </view> </view> <u-upload :custom-btn="true" :ref="`upload${index}`" :disabled="!!item.pictureCode" @on-success="(data) => { uploadSuccess(data,index)}" width="160" height="160" class="pre-item--80 float-left" :header="header" @on-choose-fail="beforeUploadWithError" :show-upload-list="true" :action="action" :max-count="1"> <view slot="addBtn" class=" slot-btn" hover-class="slot-btn__hover" hover-stay-time="150"> <u-icon name="plus" size="60" color="#c0c4cc"></u-icon> </view> </u-upload> </view> </view> </view> </u-form-item> </view> <!--委托建模信息--> <view class="u-p-30 bg-fff u-m-b-20"> <hs-tip-title title="委托建模信息"></hs-tip-title> <u-form-item label="完成期限" prop="expirationDate" required> <u-input v-model="detail.expirationDate" :disabled="true" @click="timePickerShow = true"/> </u-form-item> <!--指定面料颜色数量--> <u-form-item label="指定面料颜色数量" prop="component" required> <u-number-box v-model="detail.clothRowColourQuantity" :max="10" @minus="addModelingTaskColourDTOList" @plus="addModelingTaskColourDTOList" @blur="addModelingTaskColourDTOList"></u-number-box> </u-form-item> <view class="brandList-tips u-p-t-24 u-p-r-30 u-p-b-24 u-p-l-30" > <view class="u-border-bottom u-flex u-p-b-18 "> <view class="u-flex-1"> <view class="u-flex" @click="showAddColorListDialog"> <view class="label u-flex-1">指定面料颜色名称</view> <view class="value u-width-100" > {{colorListNames}} </view> </view> </view> <u-icon name="arrow-right"></u-icon> </view> <view class="u-border-bottom u-flex u-p-t-18 u-p-b-18"> <view class="label u-flex-1">设计机构提供颜色数量</view> <view class="value">{{designAgencyColourQuantity}}种</view> </view> <view class="u-border-bottom u-flex u-p-t-18 u-p-b-18"> <view class="u-flex-1"> <view class="u-flex" @click="showAddColorDialog"> <view class="label u-flex-1">设计机构提供颜色名称</view> <view class="value u-width-100" > {{taskColorNames}} </view> </view> </view> <u-icon name="arrow-right"></u-icon> </view> </view> </view> </u-form> </view> <!--底部按钮--> <view class="footer" id="footer"> <view class="footer-btn"> <view class="custom-style-round-circle custom-style-btn custom-style"> <view class="custom-style-left save" @click="saveData">保存</view> <view class="custom-style-right submit" @click="submitData"> <view class="title">立即发布</view> </view> </view> </view> </view> <!--提示--> <u-toast ref="uToast" /> <!--日期选择--> <u-picker v-model="timePickerShow" mode="time" @confirm="timePickerCallback"></u-picker> <!--面料颜色--> <u-popup v-model="colorListDialogOptions.show" mode="bottom" height="100%"> <!--导航栏 navbar--> <u-navbar title="填写面料颜色" :border-bottom="false" :custom-back="() => {colorListDialogOptions.show = false}" :background="{backgroundColor: 'whitesmoke'}"> <template v-slot:right> <view class="u-p-40"> <u-icon name="close" @click="colorListDialogOptions.show = false;"></u-icon> </view> </template> </u-navbar> <view class="body" :style="{ bottom: footerHeight + 'px', top: headerHeight+ 'px'}"> <view class="u-p-t-26 u-p-r-30 u-p-l-30"> <hs-tip-title title="面料颜色名称"></hs-tip-title> <view v-for="(color,index) in activeColors" :key="index"> <view class="u-font-28 u-m-t-18 u-m-b-8 required">颜色{{index+1}}</view> <view class="u-flex"> <u-input v-model="color.colourName" placeholder="请输入面料颜色名称"></u-input> </view> </view> </view> </view> <!--底部按钮--> <view class="footer"> <view class="u-p-t-18 u-p-r-30 u-p-b-18 u-p-l-30"> <view class="u-flex"> <view class="u-flex-1">共填写{{detail.clothRowColourQuantity}}种颜色名称,请不要重名</view> <view class="custom-style-round-circle custom-style-btn custom-style dialog-btn"> <view class="custom-style-right" @click="submitColors">确定</view> </view> </view> </view> </view> </u-popup> <!--颜色库选择--> <u-popup v-model="color.show" mode="bottom" height="100%"> <!--导航栏 navbar--> <u-navbar title="选择设计机构提供的颜色" :border-bottom="false" :custom-back="() => {color.show = false}" :background="{backgroundColor: 'whitesmoke'}"> <template v-slot:right> <view class="u-p-40"> <u-icon name="close" @click="color.show = false;"></u-icon> </view> </template> </u-navbar> <view class="body" :style="{ bottom: footerHeight + 'px', top: headerHeight+ 'px'}"> <view class="u-p-t-26 u-p-r-30 u-p-l-30"> <view class="pre-item pre-item--80 u-relative" :class="[color.checked ? 'active': '']" @click="selectColor(color)" v-for="(color,index) in computedModelingTaskColorLibraryList" :key="index"> <image class="pre-item-image" :src="`${imgUrl}${color.pictureCode}`" mode="aspectFill"></image> <text class="u-absolute pre-item-text text-center">{{ color.colorName }}</text> </view> </view> </view> <!--底部按钮--> <view class="footer"> <view class="u-p-t-18 u-p-r-30 u-p-b-18 u-p-l-30"> <view class="u-flex"> <view class="u-flex-1">共填写{{detail.clothRowColourQuantity}}种颜色名称,请不要重名</view> <view class="custom-style-round-circle custom-style-btn custom-style dialog-btn"> <view class="custom-style-right" @click="submitColor">确定</view> </view> </view> </view> </view> </u-popup> <!--建模品类选择--> <u-select mode="single-column" :list="modelingTaskCategory" v-model="show" @confirm="confirm"> </u-select> <u-modal v-model="modal.show" :content="modal.content" @confirm="modelConfirm"></u-modal> </view> </template> <script> import dom from "../../mixins/dom"; // import permission from "../../js_sdk/wa-permission/permission"; export default { name: "addItem", mixins: [dom], data(){ return { detail:{ clothRowColourQuantity: 0, // 布行指定面料颜色数量 clothWidth: 0, // 门幅 clothWidthUnit: 'cm', // 门幅单位 component: '', // 成分 // designAgencyColourQuantity: '', // 设计机构提供的颜色数量 expirationDate: '', // 截止日期 materialName: '', // 面料名称 modelingCategoryId: '', // 建模品类id modelingCategoryText: '', // 建模品类文本 modelingTaskColourDTOList: [], // 布行指定面料颜色名称集合 modelingTaskMaterialColourList: [], //建模任务的图片 颜色库 modelingTaskPictureDTOList: [ {pictureType: 1}, {pictureType: 2}, ], // 建模单 图片信息 price: 0, }, timePickerShow: false, action: this.$UPLOAD_URL, // 上传地址 imgUrl: this.$IMG_URL, // 上传地址 header:{ 'blade-auth':"Bearer " + uni.getStorageSync("token"), 'Authorization-Basic': "Basic c3dvcmQ6c3dvcmRfc2VjcmV0" }, // 如果将某个ref的组件实例赋值给data中的变量,在小程序中会因为循环引用而报错 colorListDialogOptions:{ show: false }, // 表单验证逻辑 rules: { materialName: [ { required: true, message: '请输入面料名称', // 可以单个或者同时写两个触发验证方式 trigger: ['change','blur'], }, { max: 20, message: '文字字数不能超过20字', // 可以单个或者同时写两个触发验证方式 trigger: ['change','blur'], }, { // reg '^[a-zA-Z\u4e00-\u9fa5][a-zA-Z0-9\u4e00-\u9fa5]*$', // 自定义验证函数,见上说明 validator: (rule, value, callback) => { // 上面有说,返回true表示校验通过,返回false表示不通过 // this.$u.test.mobile()就是返回true或者false的 let reg = new RegExp('^[\u4e00-\u9fa5][a-zA-Z0-9\u4e00-\u9fa5]*$') return reg.test(value); }, message: '请不要输入特殊符号', trigger: ['change','blur'], } ], modelingCategoryText: [ { required: true, message: '请选择面料品类', trigger: 'change' } ], component: [ { required: true, message: '请输入面料成分', // 可以单个或者同时写两个触发验证方式 trigger: ['change','blur'], }, { max: 20, message: '文字字数不能超过20字', // 可以单个或者同时写两个触发验证方式 trigger: ['change','blur'], }, ], modelingTaskPictureDTOList: { validator: (rule,value) =>{ return value.filter((item) => { return item.pictureCode }).length === value.length }, required: true, message: '请输入上传图片', }, expirationDate:{ required: true, message: '请选择完成期限', } }, // 暂存用的颜色组 modelingTaskColourDTOList: [], // 暂存用的颜色库 modelingTaskMaterialColourList: [], // 物料建模品类 modelingTaskCategory: [], // 设计机构提供的颜色库m modelingTaskColorLibraryList: [], show: false, delModelingTaskPictureDTOList: [], modal:{ show: false, content: '是否删除图片', index: '', }, color:{ show: false }, checkedList: [], } }, computed:{ modelingTaskPictureDTOList(){ return this.detail.modelingTaskPictureDTOList.filter((item) =>{ return item.isDeleted !== true }) }, // 设计机构提供的颜色数量 designAgencyColourQuantity(){ return 10 - this.detail.clothRowColourQuantity }, activeColors(){ return this.detail.modelingTaskColourDTOList .filter((item) => item.isDeleted === false) }, colorListNames(){ return this.activeColors .map((item) => item.colourName) .filter(item => item) .join("|") }, // 设计机构提供颜色 activeTaskMaterialColour(){ return this.detail.modelingTaskMaterialColourList .filter((item) => item.isDeleted === false) }, // taskColorNames(){ return this.activeTaskMaterialColour .map((item) => item.colorName).join("|") }, // modelingTaskMaterialColourIds(){ return this.activeTaskMaterialColour.map(item => item.colorId) }, computedModelingTaskColorLibraryList(){ return this.modelingTaskColorLibraryList.map((item) =>{ return { ...item, checked: this.checkedList.indexOf(item.id) > -1 } }) } }, methods:{ clearColors(){ let target = this.detail.modelingTaskMaterialColourList; for (let i = 0; i < target.length; i++) { this.$set(target[i],'isDeleted', true) } this.checkedList = [] }, // 颜色库选择好回调 submitColor(){ if(this.checkedList.length === this.designAgencyColourQuantity){ this.removeColor(); let row = this.computedModelingTaskColorLibraryList .filter((item) => item.checked) .map((item) =>{ let { id,...other} = item; return { ...other, colorId: id, type: 2 } }); this.addColor(row); this.color.show = false; }else{ this.$refs.uToast.show({ title: `请选择${this.designAgencyColourQuantity}条数据` }) } }, addColor(row){ this.detail.modelingTaskMaterialColourList = this.detail.modelingTaskMaterialColourList.concat(row); }, removeColor(){ let list = this.detail.modelingTaskMaterialColourList; let checked = this.checkedList; for (let i = 0; i < list.length; i++) { if(checked.indexOf(list[i].id) > -1){ this.$set(list[i],'isDeleted',true) }else{ list.splice(i,1) } } }, // 颜色库选择 点击时间 存一份选中状态 在确定的时候过滤 selectColor(colorItem){ let index = this.checkedList.indexOf(colorItem.id); if(index > -1){ this.checkedList.splice(index,1); }else{ this.checkedList.push(colorItem.id); } }, triggerDel(index){ this.modal.show = true; this.modal.activeIndex = index; }, modelConfirm(){ this.uploadRemove(this.modal.activeIndex) }, uploadRemove(index){ let item = this.detail.modelingTaskPictureDTOList[index]; if(item.id){ this.delModelingTaskPictureDTOList.push( Object.assign({},item,{ isDeleted: true }) ) } this.$set(this.detail.modelingTaskPictureDTOList,index,{pictureType: index+1}); }, beforeUploadWithError(err){ // permission.requestAndroidPermission('camera') // .then(res =>{ // permission.gotoAppPermissionSetting() // }) }, uploadSuccess(data, index, lists, name){ if(data.code === 200){ let item = this.detail.modelingTaskPictureDTOList[index]; this.$set(this.detail.modelingTaskPictureDTOList,index,{ ...item, pictureCode: data.data.fileCode, pictureId: data.data.id, }) this.$refs[`upload${index}`][0].remove(0) } }, confirm(data){ let { value,extra, label} = data[0]; this.detail.modelingCategoryId = value; this.detail.modelingCategoryText = label; this.detail.price = extra; }, getModelingTaskCategoryList(){ this.$http("modelingTaskCategory.list") .then(res =>{ let { code,data } = res; if(code === 200){ this.modelingTaskCategory = data.map((item) =>{ return { label: item.name, value: item.id, extra: item.price, } }); } }) }, getModelingTaskColorLibrary(){ this.$http("modelingTaskColorLibrary.list") .then(res =>{ let { code,data } = res; if(code === 200){ this.modelingTaskColorLibraryList = data } }) }, init(){ this.getModelingTaskCategoryList(); this.getModelingTaskColorLibrary(); }, validateList(callback){ // 指定面料颜色 let colorList = this.activeColors; // 设计机构提供颜色 let colorPicList = this.activeTaskMaterialColour; let checkColorPicList = colorPicList.filter((item) => !item.colorId).length === 0 && colorPicList.length === this.designAgencyColourQuantity; let checkColorList = colorList.filter((item) => !item.colourName).length === 0; if(checkColorPicList && checkColorList){ callback() }else{ this.$refs.uToast.show({ title: '颜色不能为空' }) } }, validate(callback){ this.$refs['uForm'].validate((res) =>{ if (res) { this.validateList(callback) } }) }, saveData(){ this.submit(0) }, submitData(){ this.validate(() =>{ this.submit(1) }) }, submit(type){ let {modelingTaskPictureDTOList, ...onther} = this.detail; this.$http("modeling.submit",Object.assign({}, onther, { designAgencyColourQuantity: this.designAgencyColourQuantity, operationType:type, modelingTaskPictureDTOList: modelingTaskPictureDTOList.concat(this.delModelingTaskPictureDTOList)}) ).then(res =>{ let { code,msg } = res; if(code === 200){ this.$refs.uToast.show({ title: msg, back: true }); }else{ this.$refs.uToast.show({ title: msg }); } }) }, getDefaultColor(){ return { colourName: '',isDeleted: false} }, addModelingTaskColourDTOList(item){ let res = [],target = this.detail.modelingTaskColourDTOList; // 如果存在历史数据 for (let i = 0; i < target.length; i++) { if(target[i].id){ this.$set(target[i], 'isDeleted',true) } } for (let i = 0; i < item.value; i++) { res.push(this.getDefaultColor()) } // console.log(target) // console.log(res) this.detail.modelingTaskColourDTOList = target.filter((item) => item.id).concat(res) this.clearColors(); }, validateColorName(){ return this.activeColors.filter((item) => { return !item.colourName }).length }, validateColors(){ let res = this.activeColors.map((item) => { return item.colourName }); let diff = new Set(res) return diff.size === res.length; }, submitColors(){ if(this.validateColorName().length > 1){ this.$refs.uToast.show({ title: '颜色名称不能为空' }); return; } if(this.validateColors()){ this.colorListDialogOptions.show = false; }else{ this.$refs.uToast.show({ title: '颜色名称请不要重名' }); } }, showAddColorListDialog(){ if(this.detail.clothRowColourQuantity > 0){ this.colorListDialogOptions.show = true; } }, showAddColorDialog(){ if(this.designAgencyColourQuantity > 0){ this.color.show = true; } }, timePickerCallback(e){ let { day, month, year, } = e; this.detail.expirationDate = [year,month,day].join("-") }, getDetail(id){ this.$http("modeling.detail",{ modelingTaskId:id }) .then(res => { let { code, data } = res; if(code === 200){ this.detail = Object.assign({},data,{ modelingCategoryText: data['modelingCategory']['name'], modelingTaskColourDTOList: data['modelingTaskColourList'], modelingTaskPictureDTOList: data['modelingTaskPictureList'] }); this.checkedList = this.detail.modelingTaskMaterialColourList.map((item) => item.colorId); this.$nextTick(() =>{ this.modelingTaskColourDTOList = data['modelingTaskColourList']; }) } }) }, }, onLoad(options) { let id = options.id; this.init(); if(id){ this.getDetail(id); } }, mounted() { // 得到整个组件对象,内部图片列表变量为"lists" // this.lists = this.$refs.uUpload.lists; this.$refs.uForm.setRules(this.rules); } } </script> <style scoped lang="scss"> .u-width-100{ width: 200rpx; } .dialog-btn{ width: 160rpx; height: 64rpx; } .required::before{ //position: absolute; //left: 8px; color: #ee0a24; font-size: 14px; content: '*'; margin-right: 4px; } .float-left{ float: left; margin-right: 10rpx; } .wrap { padding: 24rpx; } .slot-btn { width: 160rpx; height: 160rpx; display: flex; justify-content: center; align-items: center; background: rgb(244, 245, 246); border-radius: 10rpx; } .slot-btn__hover { background-color: rgb(235, 236, 238); } .pre-box { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; } .pre-item { border-radius: 10rpx; //overflow: hidden; position: relative; margin-right: 30rpx; &.active{ border: 1px solid red; } &-text{ bottom: 0; left: 0; font-size: 24rpx; color: #333; width: 100%; background: rgba(255,255,255,.7); } &-image { width: 100%; height: 160rpx; } &--80{ width: 160rpx; height: 160rpx; display: inline-block; } &-del{ right: -20rpx; top: -20rpx; background: red; width: 40rpx; height: 40rpx; text-align: center; border-radius: 50%; line-height: 40rpx; } } @mixin vue-flex($direction: row) { /* #ifndef APP-NVUE */ display: flex; flex-direction: $direction; /* #endif */ } .brandList-tips{ background: #fcfaf7; border: 1px solid rgba(68,53,37,0.10); border-radius: 8rpx; min-height: 88rpx; line-height: 44rpx; .brandList-tip{ } } .bg-fff{ background: #fafafa; } .body{ position: absolute; width: 100%; height: auto; left: 0; right: 0; bottom: 0; top: 0; overflow-y: auto; } .custom-style{ color: #fff; height: 88rpx; line-height: 88rpx; @include vue-flex; &-btn{ overflow: hidden; } &-round-circle{ border-radius: 100rpx; } /*background: #000;*/ .custom-style-left{ width: 240rpx; background: #d6d6d6; text-align: center } .custom-style-right{ flex: 1; background: rgba(0,0,0,0.80);text-align: center} .save{ font-size: 34rpx; color: #000000; } .submit{ font-weight: 500; font-size: 34rpx; //line-height: 100%; .title{ //margin: 8rpx 0; } .desc{ font-size: 20rpx; .color{ color: #DDA973; } } } } .footer { position: fixed; width: 100%; bottom: 0; z-index: 998; background: #fff; box-shadow: 0px -4rpx 6rpx 0px rgba(178,182,214,0.10); padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); .footer-btn{ padding: 20rpx 60rpx; } } </style>