quanwei
2 days ago 73b874c72ad55eb9eef21c36160ac0de58f0189e
mobile/pages/user/my_shop/product_add.vue
@@ -84,7 +84,8 @@
                  <view class="uploader-add" @click="handleUpload('image')">+</view>
               </view>
               <!-- 上传组件 -->
               <Upload v-if="showUpload && uploadType === 'image'" :isupload="showUpload && uploadType === 'image'" @getImgs="onUploadComplete" type='frontid'>上传图片</Upload>
               <Upload v-if="showUpload && uploadType === 'image'" :isupload="showUpload && uploadType === 'image'"
                  @getImgs="onUploadComplete" type='frontid'>上传图片</Upload>
            </view>
@@ -99,8 +100,8 @@
                  </view>
               </view>
               <!-- 上传组件 -->
            <upload v-if="showUpload && uploadType === 'video'" :num="1" file_type="video"
               @getImgs="onUploadComplete"></upload>
               <upload v-if="showUpload && uploadType === 'video'" :num="1" file_type="video"
                  @getImgs="onUploadComplete"></upload>
            </view>
            <view class="form-item">
@@ -132,6 +133,8 @@
                     @click="form.model.is_virtual = 1">虚拟商品</view>
                  <view class="radio-item" :class="{ active: form.model.is_virtual === 2 }"
                     @click="form.model.is_virtual = 2">券商品</view>
                  <view class="radio-item" :class="{ active: form.model.is_virtual === 3 }"
                     @click="form.model.is_virtual = 3">服务商品</view>
               </view>
            </view>
@@ -164,7 +167,7 @@
            </view>
            <!-- 虚拟商品设置 -->
            <view class="form-item" v-if="form.model.is_virtual === 1">
            <view class="form-item" v-if="form.model.is_virtual === 1 || form.model.is_virtual === 3">
               <view class="item-label">发货类型</view>
               <view class="radio-group">
                  <view class="radio-item" :class="{ active: form.model.virtual_auto === 1 }"
@@ -179,7 +182,13 @@
               <input class="item-input" v-model="form.model.virtual_content" placeholder="请输入虚拟物品内容" />
            </view>
            <view class="form-item" v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0">
            <view class="form-item" v-if=" form.model.is_virtual === 3">
               <view class="item-label">服务商品内容</view>
               <input class="item-input" v-model="form.model.service_content" placeholder="请输入服务商品内容" />
            </view>
            <view class="form-item"
               v-if="(form.model.is_virtual === 1 || form.model.is_virtual === 3)&& form.model.virtual_auto === 0">
               <view class="item-label">支持线下核销</view>
               <view class="radio-group">
                  <view class="radio-item" :class="{ active: form.model.is_verify === 1 }"
@@ -190,7 +199,7 @@
            </view>
            <view class="form-item"
               v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1">
               v-if="(form.model.is_virtual === 1 || form.model.is_virtual === 3) && form.model.virtual_auto === 0 && form.model.is_verify === 1">
               <view class="item-label">核销到期类型</view>
               <view class="radio-group">
                  <view class="radio-item" :class="{ active: form.model.verify_type === 10 }"
@@ -201,14 +210,14 @@
            </view>
            <view class="form-item"
               v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 10">
               v-if="(form.model.is_virtual === 1 || form.model.is_virtual === 3) && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 10">
               <view class="item-label">核销有效天数</view>
               <input class="item-input" v-model="form.model.verify_day" placeholder="请输入有效天数,0或留空表示永久有效"
                  type="number" />
            </view>
            <view class="form-item"
               v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 20">
               v-if="(form.model.is_virtual === 1 || form.model.is_virtual === 3) && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 20">
               <view class="item-label">核销有效时间</view>
               <picker mode="daterange" class="item-picker" @change="verifyTimeChange" :value="verifyTimeArray">
                  <view class="picker-text">{{ verifyTimeText || '请选择核销有效时间' }}</view>
@@ -254,7 +263,8 @@
               <view class="form-item">
                  <view class="item-label">产品价格</view>
                  <input class="item-input" v-model="form.model.sku.product_price" placeholder="请输入产品价格" type="digit" />
                  <input class="item-input" v-model="form.model.sku.product_price" placeholder="请输入产品价格"
                     type="digit" />
               </view>
               <view class="form-item">
@@ -265,7 +275,8 @@
               <view class="form-item">
                  <view class="item-label">库存数量</view>
                  <input class="item-input" v-model="form.model.sku.stock_num" placeholder="请输入库存数量" type="number" />
                  <input class="item-input" v-model="form.model.sku.stock_num" placeholder="请输入库存数量"
                     type="number" />
               </view>
               <view class="form-item">
@@ -307,7 +318,9 @@
                  <view class="item-label">SKU列表</view>
                  <view class="sku-list">
                     <view class="sku-item" v-for="(sku, index) in form.model.spec_many.spec_list" :key="index">
                        <view class="sku-info">{{ sku.spec_text }}</view>
                        <view class="sku-info">
                           <text v-for="(row, rowIdx) in sku.rows" :key="rowIdx">{{ row.spec_value }}{{ rowIdx < sku.rows.length - 1 ? ' ' : '' }}</text>
                        </view>
                        <view class="form-item">
                           <view class="item-label">规格图片</view>
                           <view class="uploader">
@@ -323,11 +336,14 @@
                        </view>
                        <view class="sku-inputs">
                           <input class="sku-input" v-model="sku.spec_form.product_no" placeholder="产品编码" />
                           <input class="sku-input" v-model="sku.spec_form.product_price" placeholder="产品价格" type="digit" />
                           <input class="sku-input" v-model="sku.spec_form.product_price" placeholder="产品价格"
                              type="digit" />
                           <input class="sku-input" v-model="sku.spec_form.line_price" placeholder="产品划线价"
                              type="digit" />
                           <input class="sku-input" v-model="sku.spec_form.stock_num" placeholder="库存数量" type="number" />
                           <input class="sku-input" v-model="sku.spec_form.product_weight" placeholder="商品重量(Kg)" type="digit" />
                           <input class="sku-input" v-model="sku.spec_form.stock_num" placeholder="库存数量"
                              type="number" />
                           <input class="sku-input" v-model="sku.spec_form.product_weight"
                              placeholder="商品重量(Kg)" type="digit" />
                        </view>
                     </view>
                  </view>
@@ -340,15 +356,15 @@
            <view class="form-item">
               <view class="item-label">详情类型</view>
               <view class="radio-group">
                  <view class="radio-item" :class="{ active: form.model.content_type === 10 }"
                     @click="form.model.content_type = 10">图文</view>
                  <view class="radio-item" :class="{ active: form.model.content_type === 20 }"
                     @click="form.model.content_type = 20">纯图</view>
                  <view class="radio-item" :class="{ active: form.model.is_picture == 0 }"
                     @click="form.model.is_picture = 0">图文</view>
                  <view class="radio-item" :class="{ active: form.model.is_picture === 1 }"
                     @click="form.model.is_picture = 1">纯图</view>
               </view>
            </view>
            <!-- 图文类型 -->
            <view v-if="form.model.content_type === 10" class="form-item">
            <view v-if="form.model.is_picture === 0" class="form-item">
               <view class="item-label">商品详情</view>
               <view class="editor">
                  <!-- 富文本编辑器 -->
@@ -439,7 +455,7 @@
            </view>
            <!-- 纯图类型 -->
            <view v-else-if="form.model.content_type === 20" class="form-item">
            <view v-else-if="form.model.is_picture == 1" class="form-item">
               <view class="item-label">商品详情图片</view>
               <view class="uploader">
                  <view class="uploader-item" v-for="(item, index) in form.model.contentImage" :key="index">
@@ -450,7 +466,8 @@
               </view>
               <view class="editor-tips">提示:最多上传20张图片</view>
               <!-- 上传组件 -->
               <upload v-if="showUpload && uploadType === 'content'" :isupload="showUpload && uploadType === 'content'" :num="20 - form.model.contentImage.length"
               <upload v-if="showUpload && uploadType === 'content'"
                  :isupload="showUpload && uploadType === 'content'" :num="20 - form.model.contentImage.length"
                  @getImgs="onUploadComplete"></upload>
            </view>
         </view>
@@ -535,7 +552,8 @@
                  selling_point: '',
                  spec_type: 10,
                  deduct_stock_type: 20,
                  content_type: 10,
                  is_picture: 0,
                  service_content: '',
                  sku: {
                     product_no: '',
                     product_price: '',
@@ -751,12 +769,52 @@
               placeholderText: '例如:颜色',
               success: (res) => {
                  if (res.confirm && res.content.trim()) {
                     this.form.model.spec_many.spec_attr.push({
                        name: res.content.trim(),
                        values: []
                     const specName = res.content.trim();
                     // 继续输入第一个规格值
                     uni.showModal({
                        title: '添加第一个规格值',
                        content: '',
                        editable: true,
                        placeholderText: '例如:红色',
                        success: (valueRes) => {
                           if (valueRes.confirm && valueRes.content.trim()) {
                              const specValue = valueRes.content.trim();
                              // 调用API添加规格组和第一个规格值
                              this._post('supplier.product.spec/addSpec', {
                                 spec_name: specName,
                                 spec_value: specValue
                              }, (response) => {
                                 if (response.code === 1 && response.data) {
                                    this.form.model.spec_many.spec_attr.push({
                                       group_id: response.data.spec_id,
                                       name: specName,
                                       values: [specValue],
                                       items: [{
                                          item_id: response.data.spec_value_id,
                                          spec_value: specValue
                                       }]
                                    });
                                    // 生成SKU列表
                                    this.generateSkuList();
                                    uni.showToast({
                                       title: '添加成功',
                                       icon: 'success'
                                    });
                                 } else {
                                    uni.showToast({
                                       title: response.msg || '添加失败',
                                       icon: 'none'
                                    });
                                 }
                              });
                           } else if (valueRes.confirm) {
                              uni.showToast({
                                 title: '请输入规格值',
                                 icon: 'none'
                              });
                           }
                        }
                     });
                     // 生成SKU列表
                     this.generateSkuList();
                  }
               }
            });
@@ -778,10 +836,32 @@
               placeholderText: '例如:红色',
               success: (res) => {
                  if (res.confirm && res.content.trim()) {
                     const specValue = res.content.trim();
                     const attr = this.form.model.spec_many.spec_attr[attrIndex];
                     attr.values.push(res.content.trim());
                     // 重新生成SKU列表
                     this.generateSkuList();
                     // 调用API添加规格值
                     this._post('supplier.product.spec/addSpecValue', {
                        spec_id: attr.group_id,
                        spec_value: specValue
                     }, (response) => {
                        if (response.code === 1 && response.data) {
                           attr.values.push(specValue);
                           attr.items.push({
                              item_id: response.data.spec_value_id,
                              spec_value: specValue
                           });
                           // 重新生成SKU列表
                           this.generateSkuList();
                           uni.showToast({
                              title: '添加成功',
                              icon: 'success'
                           });
                        } else {
                           uni.showToast({
                              title: response.msg || '添加失败',
                              icon: 'none'
                           });
                        }
                     });
                  }
               }
            });
@@ -790,11 +870,14 @@
         // 删除规格值
         deleteSpecValue(attrIndex, valueIndex) {
            const attr = this.form.model.spec_many.spec_attr[attrIndex];
            if (attr.values.length > 1) {
            //if (attr.values.length > 1) {
               attr.values.splice(valueIndex, 1);
               if (attr.items && attr.items.length > valueIndex) {
                  attr.items.splice(valueIndex, 1);
               }
               // 重新生成SKU列表
               this.generateSkuList();
            }
            //}
         },
         // 生成SKU列表
@@ -810,17 +893,37 @@
            // 生成SKU列表
            const skuList = combinations.map(comb => {
               const spec_text = comb.map((val, idx) => `${attrs[idx].name}:${val}`).join('; ');
               const rows = [];
               const specSkuIdAttr = [];
               comb.forEach((val, idx) => {
                  const attr = attrs[idx];
                  // 查找对应的 item_id
                  const itemIndex = attr.values.indexOf(val);
                  const itemId = (attr.items && attr.items[itemIndex]) ? attr.items[itemIndex].item_id : 0;
                  rows.push({
                     item_id: itemId,
                     spec_value: val
                  });
                  specSkuIdAttr.push(itemId);
               });
               const spec_sku_id = specSkuIdAttr.join('_');
               return {
                  spec_text,
                  product_sku_id: 0,
                  spec_sku_id,
                  rows,
                  image: [],
                  product_no: '',
                  price: '',
                  line_price: '',
                  stock: '',
                  weight: '',
                  cost_price: '',
                  bar_code: ''
                  spec_form: {
                     product_no: '',
                     product_price: '',
                     line_price: '',
                     stock_num: '',
                     product_weight: '',
                     bar_code: ''
                  }
               };
            });
@@ -851,15 +954,15 @@
         save() {
            let self = this;
            // 先获取富文本编辑器内容
            if (self.form.model.content_type === 10 && self.editorCtx) {
            if (self.form.model.is_picture == 0 && self.editorCtx) {
               // 图文类型,获取编辑器内容
               self.editorCtx.getContents({
               self.editorCtx.getContents({
                  success: (res) => {
                     // 将编辑器内容赋值给表单字段
                     self.form.model.content = res.html;
                     // 继续执行保存逻辑
                     self.doSave();
                  },
                  },
                  fail: () => {
                     // 获取内容失败,继续执行保存逻辑
                     self.doSave();
@@ -871,7 +974,7 @@
               self.doSave();
            }
         },
         // 实际保存逻辑
         doSave() {
            let self = this;
@@ -930,6 +1033,7 @@
               for (let i = 0; i < self.form.model.spec_many.spec_list.length; i++) {
                  const sku = self.form.model.spec_many.spec_list[i];
                  console.log(sku);
                  if (!sku.spec_form.product_price || parseFloat(sku.spec_form.product_price) <= 0) {
                     uni.showToast({
                        title: '请输入有效的SKU价格',
@@ -949,7 +1053,7 @@
            }
            // 根据详情类型验证内容
            if (self.form.model.content_type === 10) {
            if (self.form.model.is_picture === 0) {
               // 图文类型,验证富文本内容
               if (!self.form.model.content || self.form.model.content.trim() === '') {
                  uni.showToast({
@@ -958,7 +1062,7 @@
                  });
                  return;
               }
            } else if (self.form.model.content_type === 20) {
            } else if (self.form.model.is_picture == 1) {
               // 纯图类型,验证详情图片
               if (self.form.model.contentImage.length === 0) {
                  uni.showToast({
@@ -969,11 +1073,26 @@
               }
            }
            // 转换spec_attr数据格式为后端期望的格式
            let submitData = JSON.parse(JSON.stringify(self.form.model));
            if (submitData.spec_type == 20 && submitData.spec_many && submitData.spec_many.spec_attr) {
               submitData.spec_many.spec_attr = submitData.spec_many.spec_attr.map(attr => {
                  return {
                     group_id: attr.group_id || 0,
                     name: attr.name,
                     spec_items: attr.values.map((val, idx) => ({
                        item_id: (attr.items && attr.items[idx] && attr.items[idx].item_id) ? attr.items[idx].item_id : 0,
                        spec_value: val
                     }))
                  };
               });
            }
            self.loading = true;
            self._post('supplier.product/add', {
               params: JSON.stringify(self.form.model)
               params: JSON.stringify(submitData)
            }, (res) => {
               if (res.code === 0) {
               if (res.code === 1) {
                  uni.showToast({
                     title: '保存成功'
                  });
@@ -1294,7 +1413,8 @@
   .radio-group {
      display: flex;
      gap: 40rpx;
      gap: 15rpx;
      flex-wrap: wrap;
   }
   .radio-item {