Răsfoiți Sursa

fix(hdApp): 完善花材编辑回填与提交校验

- 恢复图片短路径、原始批发价及分类单位信息,避免编辑提交覆盖异常
- 统一新增和编辑的价格、包装支数、重量及库存校验,并补齐零售店派生价格
shizhongqi 19 ore în urmă
părinte
comite
c43dd8ec02
1 a modificat fișierele cu 178 adăugiri și 111 ștergeri
  1. 178 111
      hdApp/src/admin/item/add.vue

+ 178 - 111
hdApp/src/admin/item/add.vue

@@ -1,3 +1,8 @@
+<!--
+  花材新增/编辑页。
+  使用者:花店管理员在 hdApp 中维护花材。
+  依据 /product/detail 回填表单,提交时按 /product/add 或 /product/update 补齐字段。
+-->
 <template>
   <div class="app-content">
     <!-- 花材基本信息 -->
@@ -286,6 +291,10 @@ export default {
 		...mapGetters(["getLoginInfo","getDictionariesInfo","getMyShopInfo"]),
     coverImgData() {
       return this.form.images || [];
+    },
+    // 有批发店 ID 才展示并提交三档价格;纯零售店只填零售价,提交时再同步到批发价/大客价
+    isWholesaleShop() {
+      return Number(this.getMyShopInfo.pfShopId) > 0;
     }
 	},
   onShow(){
@@ -486,37 +495,57 @@ export default {
         this.form.cost = 0
       })
     },
+    /**
+     * 拉取花材详情并回填表单。
+     * 详情接口会把 cover 转成带域名的展示图、把 price 转成等级价,提交仍需短路径和原始批发价。
+     */
     getDetail() {
       return getProductDetail({ id: this.option.id }).then(res => {
         if (this.$util.isEmpty(res.data)) {
           return;
         }
-        Object.keys(this.form).forEach((i, index) => {
-          this.form[i] = res.data[i];
-        });
-
-        // this.currentImgData.push(res.data.cover)
-        // this.form.images = [res.data.shortCover]
-        // this.form.cover = res.data.shortCover
-        const imageUrls = (res.data.images || '').split(',').filter(i => i);
-        this.form.images = imageUrls;
-        this.currentImgData = imageUrls.map(url => {
-          return this.constant.imgUrl + '/' + url + '?x-oss-process=image/resize,m_fill,h_700,w_700'
-        });
+        this.fillFormFromProductDetail(res.data);
+      });
+    },
+    /**
+     * 把 /product/detail 返回值填进本页表单。
+     * @param {Object} detail 花材详情
+     */
+    fillFormFromProductDetail(detail) {
+      Object.keys(this.form).forEach((key) => {
+        // 接口没有的字段保持表单默认值,避免被 undefined 冲掉
+        if (detail[key] !== undefined && detail[key] !== null) {
+          this.form[key] = detail[key];
+        }
+      });
 
-        this.form.price = res.data.prePrice
-
-        this.itemClassSelectedData = this.itemClassData.filter(
-          e => this.form.classId == e.id
-        )[0];
-        this.smallUnitSelectedData = this.unitData.filter(
-          e => this.form.smallUnitId == e.id
-        )[0];
-       this.bigUnitSelectedData = this.unitData.filter(
-          e => this.form.bigUnitId == e.id
-        )[0];
-        this.productData = res.data
+      const rawImages = detail.images || detail.shortCover || '';
+      const imageUrls = Array.isArray(rawImages)
+        ? rawImages.filter(item => item)
+        : String(rawImages).split(',').filter(item => item);
+      this.form.images = imageUrls;
+      this.currentImgData = imageUrls.map(url => {
+        return this.constant.imgUrl + '/' + url + '?x-oss-process=image/resize,m_fill,h_700,w_700';
       });
+
+      // 封面提交短路径,才能和 images 列表对上并回传给新增/修改接口
+      this.form.cover = detail.shortCover || '';
+      if (!this.form.cover && imageUrls.length > 0) {
+        this.form.cover = imageUrls[0];
+      }
+
+      // groupProductInfo 会改写 price,编辑页批发价要用接口给出的原始价 prePrice
+      if (detail.prePrice !== undefined && detail.prePrice !== null) {
+        this.form.price = detail.prePrice;
+      }
+
+      const currentClass = (this.itemClassData || []).filter(e => this.form.classId == e.id)[0] || {};
+      this.itemClassSelectedData = currentClass;
+      this.form.className = currentClass.name || detail.className || '';
+
+      this.smallUnitSelectedData = (this.unitData || []).filter(e => this.form.smallUnitId == e.id)[0] || {};
+      this.bigUnitSelectedData = (this.unitData || []).filter(e => this.form.bigUnitId == e.id)[0] || {};
+      this.productData = detail;
     },
     imgUploadSuccess(res) {
       var _res = JSON.parse(res.data)
@@ -578,7 +607,34 @@ export default {
         this.itemClassData = res.data;
       });
     },
-    // 确认
+    /**
+     * 金额是否合法(允许 0 和最多两位小数),对齐新增/修改接口的数字校验。
+     */
+    isValidAmount(val) {
+      return /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(val);
+    },
+    /**
+     * 纯零售店页面只展示零售价,提交前按接口要求补齐批发价/大客价和三档特价。
+     * @param {Boolean} isAdd 新增时加价清零,与历史提交逻辑保持一致
+     */
+    fillRetailDerivedPrices(isAdd) {
+      if (this.isWholesaleShop) {
+        return;
+      }
+      this.form.hjPrice = this.form.skPrice;
+      this.form.price = this.form.skPrice;
+      this.form.hjDiscountPrice = this.form.skDiscountPrice;
+      this.form.discountPrice = this.form.skDiscountPrice;
+      if (isAdd) {
+        this.form.skMore = 0;
+        this.form.hjAddPrice = 0;
+        this.form.addPrice = 0;
+      }
+    },
+    /**
+     * 组装提交给 /product/add、/product/update 的字段。
+     * 新增、修改都要带齐价格;固定支数时必须有 ratio。
+     */
     confirmFn() {
       if (this.$util.isEmpty(this.form.images)) {
         this.$msg("请上传图片")
@@ -587,77 +643,74 @@ export default {
       if (!this.form.cover && this.form.images.length > 0) {
         this.form.cover = this.form.images[0];
       }
-      let requestHost = addProduct
-      if(this.form.id && this.form.id != 0){
-        requestHost = updateProduct;
-      }else{
-				if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.stock) == false){
-					uni.showToast({title:"请填写库存,没库存填0",icon:"none"})
-					return;
-				}
-				if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.cost) == false){
-					uni.showToast({title:"请填写成本",icon:"none"})
-					return;
-				}
-				if(Number(this.getMyShopInfo.pfShopId)>0){
-					//批发店下面价格都要传
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.price) == false){
-						uni.showToast({title:"请填写批发价",icon:"none"})
-						return;
-					}
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.hjPrice) == false){
-						uni.showToast({title:"请填写大客价",icon:"none"})
-						return;
-					}
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.skPrice) == false){
-						uni.showToast({title:"请填写零售价",icon:"none"})
-						return;
-					}
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.hjAddPrice) == false){
-						uni.showToast({title:"请填写大客加价",icon:"none"})
-						return;
-					}
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.addPrice) == false){
-						uni.showToast({title:"请填写批发加价",icon:"none"})
-						return;
-					}
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.skMore) == false){
-						uni.showToast({title:"请填写零售加价",icon:"none"})
-						return;
-					}
-				}else{
-					if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.skPrice) == false){
-						uni.showToast({title:"请填写销售价格",icon:"none"})
-						return;
-					}
-					//纯零售店,批发价和大客价等于零售价
-					this.form.hjPrice = this.form.skPrice
-					this.form.price = this.form.skPrice
-					//纯零售店,加价全部为0
-					this.form.skMore = 0
-					this.form.hjAddPrice = 0
-					this.form.addPrice = 0
-					//特价
-					this.form.hjDiscountPrice = this.form.skDiscountPrice
-					this.form.discountPrice = this.form.skDiscountPrice
-				}
+      const isEdit = this.form.id && this.form.id != 0;
+      const requestHost = isEdit ? updateProduct : addProduct;
+      this.fillRetailDerivedPrices(!isEdit);
+
+      // 没有固定支数时后端会写成 10,提交前补上避免空值
+      if (Number(this.form.ratioType) === 1) {
+        this.form.ratio = this.form.ratio || 10;
+      } else if (!this.form.ratio || Number(this.form.ratio) <= 0) {
+        uni.showToast({title:"请填写几支装",icon:"none"})
+        return;
+      }
 
-				if(/(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/.test(this.form.skDiscountPrice) == false){
-					uni.showToast({title:"请填写特价,没有特价填0",icon:"none"})
-					return;
-				}
-				if(Number(this.form.skDiscountPrice)>0 && Number(this.form.hjDiscountPrice)>0 && Number(this.form.discountPrice)>0){
+      if (Number(this.form.weight) <= 0) {
+        uni.showToast({title:"请填写重量,最小0.1",icon:"none"})
+        return;
+      }
 
-				}else{
-					if(Number(this.form.skDiscountPrice)==0 && Number(this.form.hjDiscountPrice)==0 && Number(this.form.discountPrice)==0){
-					}else{
-						uni.showToast({title:"特价栏要等于0,或全部大于0",icon:"none"})
-						return 
-					}
-				}
+      if (this.isValidAmount(this.form.stock) == false) {
+        uni.showToast({title:"请填写库存,没库存填0",icon:"none"})
+        return;
+      }
+      if (this.isValidAmount(this.form.cost) == false) {
+        uni.showToast({title:"请填写成本",icon:"none"})
+        return;
+      }
+      if (this.isWholesaleShop) {
+        if (this.isValidAmount(this.form.price) == false) {
+          uni.showToast({title:"请填写批发价",icon:"none"})
+          return;
+        }
+        if (this.isValidAmount(this.form.hjPrice) == false) {
+          uni.showToast({title:"请填写大客价",icon:"none"})
+          return;
+        }
+        if (this.isValidAmount(this.form.skPrice) == false) {
+          uni.showToast({title:"请填写零售价",icon:"none"})
+          return;
+        }
+        if (this.isValidAmount(this.form.hjAddPrice) == false) {
+          uni.showToast({title:"请填写大客加价",icon:"none"})
+          return;
+        }
+        if (this.isValidAmount(this.form.addPrice) == false) {
+          uni.showToast({title:"请填写批发加价",icon:"none"})
+          return;
+        }
+        if (this.isValidAmount(this.form.skMore) == false) {
+          uni.showToast({title:"请填写零售加价",icon:"none"})
+          return;
+        }
+      } else if (this.isValidAmount(this.form.skPrice) == false) {
+        uni.showToast({title:"请填写销售价格",icon:"none"})
+        return;
+      }
+
+      if (this.isValidAmount(this.form.skDiscountPrice) == false) {
+        uni.showToast({title:"请填写特价,没有特价填0",icon:"none"})
+        return;
       }
+      const hasAllDiscount = Number(this.form.skDiscountPrice) > 0 && Number(this.form.hjDiscountPrice) > 0 && Number(this.form.discountPrice) > 0;
+      const hasNoDiscount = Number(this.form.skDiscountPrice) == 0 && Number(this.form.hjDiscountPrice) == 0 && Number(this.form.discountPrice) == 0;
+      if (!hasAllDiscount && !hasNoDiscount) {
+        uni.showToast({title:"特价栏要等于0,或全部大于0",icon:"none"})
+        return;
+      }
+
       let form = JSON.parse(JSON.stringify(this.form))
-      form.images = form.images.join(',')
+      form.images = Array.isArray(form.images) ? form.images.join(',') : form.images
       uni.showLoading({mask:true,title:'提交中'})
       requestHost({...form,appVersion:1}).then(res => {
         uni.hideLoading()
@@ -677,9 +730,10 @@ export default {
         }
       });
     },
-    // 表单验证
-    formSubmit(e) {
-      // 表单规则
+    /**
+     * 提交前校验。用 this.form 而不是原生 form 值,零售店隐藏的批发价不参与必填。
+     */
+    formSubmit() {
       let rules = [
         {
           name: "name",
@@ -705,20 +759,15 @@ export default {
           rule: ["required"],
           msg: ["请选择小单位"]
         },
-        {
-          name: "price",
-          rule: ["required"],
-          msg: ["请填写批发价"]
-        },
         {
           name: "skPrice",
           rule: ["required"],
           msg: ["请填写零售价"]
         },
         {
-          name: "hjPrice",
+          name: "skDiscountPrice",
           rule: ["required"],
-          msg: ["请填写大客价"]
+          msg: ["请填写特价,没有特价填0"]
         },
         {
           name: "skMore",
@@ -735,11 +784,6 @@ export default {
           rule: ["required"],
           msg: ["请填写大客加价"]
         },
-        {
-          name: "discountPrice",
-          rule: ["required"],
-          msg: ["没特价请填0"]
-        },
         {
           name: "cost",
           rule: ["required"],
@@ -761,10 +805,33 @@ export default {
           msg: ["请填写库存预警"]
         }
       ];
-      // 进行表单检查
-      let formData = e.detail.value;
-      let checkRes = form.validation(formData, rules);
-      // 验证通过!
+      // 批发店必须传三档价格;零售店由 confirmFn 用零售价补齐后再提交
+      if (this.isWholesaleShop) {
+        rules.push({
+          name: "price",
+          rule: ["required"],
+          msg: ["请填写批发价"]
+        });
+        rules.push({
+          name: "hjPrice",
+          rule: ["required"],
+          msg: ["请填写大客价"]
+        });
+        rules.push({
+          name: "discountPrice",
+          rule: ["required"],
+          msg: ["没特价请填0"]
+        });
+      }
+      // 固定支数时新增/修改接口都要求 ratio > 0
+      if (Number(this.form.ratioType) === 0) {
+        rules.push({
+          name: "ratio",
+          rule: ["required"],
+          msg: ["请填写几支装"]
+        });
+      }
+      let checkRes = form.validation(this.form, rules);
       if (!checkRes) {
           this.confirmFn()
       } else {