Browse Source

feat(member-center): 优化权益及赠品配置结构与UI展示

- 将权益配置由扁平对象改为包含图标与路由的数组结构
- 新增油品、快消品、充电、停车等权益的图标及路由配置字段
- 优化权益配置组装逻辑,改为基于数组格式进行组合
- 统一处理优惠券与赠品配置,支持图标和路由首项配置
- 新增解析函数,支持JSON数组或对象格式扁平化处理权益数据
- 调整详情数据加载时的解析方式,支持新结构数据兼容
- 在表单中新增图标上传与路由路径输入控件,并绑定对应启用开关
- 删除已废弃的字段,保证表单数据与接口数据一致性
zouzexu 1 tuần trước cách đây
mục cha
commit
8d8cfa470c
1 tập tin đã thay đổi với 196 bổ sung81 xóa
  1. 196 81
      src/views/member-center/edit-member-type/index.vue

+ 196 - 81
src/views/member-center/edit-member-type/index.vue

@@ -55,8 +55,25 @@ const model = ref({
   rightsDesc: '',
   openChannelCodes: '',
   priceChannelId: '',
-  benefitConfigJson: { oilPerLiterDiscount: 0, mallDiscountRate: 0, chargePerKwhDiscount: 0, parkingDiscountRate: 0 },
+  benefitConfigJson: {
+    oilPerLiterDiscount: 0,
+    oilIcon: '',
+    oilRoutePath: '',
+    mallDiscountRate: 0,
+    mallIcon: '',
+    mallRoutePath: '',
+    chargePerKwhDiscount: 0,
+    chargeIcon: '',
+    chargeRoutePath: '',
+    parkingDiscountRate: 0,
+    parkingIcon: '',
+    parkingRoutePath: ''
+  },
+  couponIcon: '',
+  couponRoutePath: '',
   couponConfigJson: [{ couponId: '', count: 1 }] as any,
+  giftIcon: '',
+  giftRoutePath: '',
   giftConfigJson: [] as any,
   status: 0
 });
@@ -367,51 +384,70 @@ function handleValidateButtonClick(e: MouseEvent) {
       let rightsDesc = '';
       let num = 0;
 
-      // 除了权益配置 加油 充电 停车 快消品数据
-      if (!isCheckedChargePerKwhDiscount.value) {
-        delete form.benefitConfigJson.chargePerKwhDiscount;
-      } else {
-        num += 1;
-        rightsDesc += `${num}、全省贵阳城投充电桩充电优惠${form.benefitConfigJson.chargePerKwhDiscount}元/度;\n `;
-      }
-      if (!isCheckedOilPerLiterDiscount.value) {
-        delete form.benefitConfigJson.oilPerLiterDiscount;
-      } else {
+      // 组装权益配置为数组格式
+      const benefitArray: any[] = [];
+      if (isCheckedOilPerLiterDiscount.value) {
         num += 1;
         rightsDesc += `${num}、全省中国石化加油站加油优惠${form.benefitConfigJson.oilPerLiterDiscount}元/升;\n `;
+        benefitArray.push({
+          oilPerLiterDiscount: form.benefitConfigJson.oilPerLiterDiscount,
+          oilIcon: form.benefitConfigJson.oilIcon,
+          oilRoutePath: form.benefitConfigJson.oilRoutePath
+        });
       }
-      if (!isCheckedMallDiscountRate.value) {
-        delete form.benefitConfigJson.mallDiscountRate;
-      } else {
+      if (isCheckedMallDiscountRate.value) {
         num += 1;
         rightsDesc += `${num}、市民请结合平台超6000+快消品优惠${form.benefitConfigJson.mallDiscountRate}%;\n `;
+        benefitArray.push({
+          mallDiscountRate: form.benefitConfigJson.mallDiscountRate,
+          mallIcon: form.benefitConfigJson.mallIcon,
+          mallRoutePath: form.benefitConfigJson.mallRoutePath
+        });
       }
-      if (!isCheckedParkingDiscountRate.value) {
-        delete form.benefitConfigJson.parkingDiscountRate;
-      } else {
+      if (isCheckedChargePerKwhDiscount.value) {
+        num += 1;
+        rightsDesc += `${num}、全省贵阳城投充电桩充电优惠${form.benefitConfigJson.chargePerKwhDiscount}元/度;\n `;
+        benefitArray.push({
+          chargePerKwhDiscount: form.benefitConfigJson.chargePerKwhDiscount,
+          chargeIcon: form.benefitConfigJson.chargeIcon,
+          chargeRoutePath: form.benefitConfigJson.chargeRoutePath
+        });
+      }
+      if (isCheckedParkingDiscountRate.value) {
         num += 1;
         rightsDesc += `${num}、全场18000+贵阳城投停车位停车优惠${form.benefitConfigJson.parkingDiscountRate}%;\n `;
+        benefitArray.push({
+          parkingDiscountRate: form.benefitConfigJson.parkingDiscountRate,
+          parkingIcon: form.benefitConfigJson.parkingIcon,
+          parkingRoutePath: form.benefitConfigJson.parkingRoutePath
+        });
       }
 
-      form.benefitConfigJson = JSON.stringify(form.benefitConfigJson);
+      form.benefitConfigJson = JSON.stringify(benefitArray);
 
       // 处理优惠券配置
       if (!isCheckedCouponConfigJson.value) {
         form.couponConfigJson = '';
       } else {
         num += 1;
-        form.couponConfigJson = JSON.stringify(form.couponConfigJson);
+        const couponArr = [{ icon: form.couponIcon, routePath: form.couponRoutePath }, ...form.couponConfigJson];
         rightsDesc += `${num}、市民请集合本地生活服务平台${form.couponConfigJson.length}张优惠券;\n `;
+        form.couponConfigJson = JSON.stringify(couponArr);
       }
+      delete form.couponIcon;
+      delete form.couponRoutePath;
 
       // 处理赠品配置
       if (!isCheckedGiftConfigJson.value) {
         form.giftConfigJson = '';
       } else {
         num += 1;
-        form.giftConfigJson = JSON.stringify(form.giftConfigJson);
+        const giftArr = [{ icon: form.giftIcon, routePath: form.giftRoutePath }, ...form.giftConfigJson];
         rightsDesc += `${num}、提供${form.giftConfigJson.length}种选1种商品赠送;\n `;
+        form.giftConfigJson = JSON.stringify(giftArr);
       }
+      delete form.giftIcon;
+      delete form.giftRoutePath;
       form.rightsDesc = rightsDesc;
       let res;
       if (route.query.mode == 'edit') {
@@ -434,65 +470,68 @@ function handleValidateButtonClick(e: MouseEvent) {
   });
 }
 
+/** 解析权益配置JSON(数组/对象格式转为扁平对象) */
+function parseBenefitConfig(jsonStr: string | undefined) {
+  const benefitFlat: any = {
+    oilPerLiterDiscount: 0,
+    oilIcon: '',
+    oilRoutePath: '',
+    mallDiscountRate: 0,
+    mallIcon: '',
+    mallRoutePath: '',
+    chargePerKwhDiscount: 0,
+    chargeIcon: '',
+    chargeRoutePath: '',
+    parkingDiscountRate: 0,
+    parkingIcon: '',
+    parkingRoutePath: ''
+  };
+  if (!jsonStr) return benefitFlat;
+  const benefitArr = JSON.parse(jsonStr);
+  if (Array.isArray(benefitArr)) {
+    benefitArr.forEach((item: any) => Object.assign(benefitFlat, item));
+  } else {
+    Object.assign(benefitFlat, benefitArr);
+  }
+  return benefitFlat;
+}
+
+/** 解析带图标路由配置的数组JSON(首项为icon/routePath) */
+function parseConfigWithIcon(jsonStr: string | undefined) {
+  if (!jsonStr) return { icon: '', routePath: '', list: [] as any[] };
+  const arr = JSON.parse(jsonStr);
+  if (Array.isArray(arr) && arr.length > 0 && arr[0].icon !== undefined) {
+    return { icon: arr[0].icon || '', routePath: arr[0].routePath || '', list: arr.slice(1) };
+  }
+  return { icon: '', routePath: '', list: arr };
+}
+
 async function getDetail() {
   // 获取详情接口
   const res = await fetchTypeDetail(route.query.id);
   if (res.data) {
     model.value = res.data;
-    if (res.data.benefitConfigJson) {
-      model.value.benefitConfigJson = JSON.parse(res.data.benefitConfigJson);
-    } else {
-      model.value.benefitConfigJson = {
-        oilPerLiterDiscount: 0,
-        mallDiscountRate: 0,
-        chargePerKwhDiscount: 0,
-        parkingDiscountRate: 0
-      };
-    }
+    model.value.benefitConfigJson = parseBenefitConfig(res.data.benefitConfigJson);
 
-    // 处理配置权益
-    if (model.value.benefitConfigJson.chargePerKwhDiscount) {
-      isCheckedChargePerKwhDiscount.value = true;
-    } else {
-      model.value.benefitConfigJson.chargePerKwhDiscount = 0;
-    }
-    if (model.value.benefitConfigJson.oilPerLiterDiscount) {
-      isCheckedOilPerLiterDiscount.value = true;
-    } else {
-      model.value.benefitConfigJson.oilPerLiterDiscount = 0;
-      console.log('dfasfasf', model.value.benefitConfigJson.oilPerLiterDiscount);
-    }
-    if (model.value.benefitConfigJson.parkingDiscountRate) {
-      isCheckedParkingDiscountRate.value = true;
-    } else {
-      model.value.benefitConfigJson.parkingDiscountRate = 0;
-    }
-    if (model.value.benefitConfigJson.mallDiscountRate) {
-      isCheckedMallDiscountRate.value = true;
-    } else {
-      model.value.benefitConfigJson.mallDiscountRate = 0;
-    }
+    // 处理配置权益勾选状态
+    if (model.value.benefitConfigJson.oilPerLiterDiscount) isCheckedOilPerLiterDiscount.value = true;
+    if (model.value.benefitConfigJson.mallDiscountRate) isCheckedMallDiscountRate.value = true;
+    if (model.value.benefitConfigJson.chargePerKwhDiscount) isCheckedChargePerKwhDiscount.value = true;
+    if (model.value.benefitConfigJson.parkingDiscountRate) isCheckedParkingDiscountRate.value = true;
 
     // 处理优惠券配置
-    if (model.value.couponConfigJson) {
-      isCheckedCouponConfigJson.value = true;
-    }
-    if (res.data.couponConfigJson) {
-      model.value.couponConfigJson = JSON.parse(res.data.couponConfigJson);
-    } else {
-      model.value.couponConfigJson = [];
-    }
+    if (model.value.couponConfigJson) isCheckedCouponConfigJson.value = true;
+    const couponParsed = parseConfigWithIcon(res.data.couponConfigJson);
+    model.value.couponIcon = couponParsed.icon;
+    model.value.couponRoutePath = couponParsed.routePath;
+    model.value.couponConfigJson = couponParsed.list;
 
     // 处理赠品配置
-    if (model.value.giftConfigJson) {
-      isCheckedGiftConfigJson.value = true;
-    }
-
-    if (res.data.giftConfigJson) {
-      model.value.giftConfigJson = JSON.parse(res.data.giftConfigJson);
-    } else {
-      model.value.giftConfigJson = [];
-    }
+    if (model.value.giftConfigJson) isCheckedGiftConfigJson.value = true;
+    const giftParsed = parseConfigWithIcon(res.data.giftConfigJson);
+    model.value.giftIcon = giftParsed.icon;
+    model.value.giftRoutePath = giftParsed.routePath;
+    model.value.giftConfigJson = giftParsed.list;
   }
 }
 
@@ -672,11 +711,25 @@ onMounted(() => {
               <div class="ml-10px text-12px">(保留2位小数,范围0-50)</div>
             </div>
-            <div class="mt-6px">
-              <NCheckbox v-model:checked="isCheckedOilPerLiterDiscount" class="ml-6px">启用该权益</NCheckbox>
-            </div>
           </div>
         </NFormItem>
+        <NFormItem label="图标" path="benefitConfigJson.oilIcon">
+          <ZUpload
+            v-model:value="model.benefitConfigJson.oilIcon"
+            :max="1"
+            :disabled="!isCheckedOilPerLiterDiscount"
+          ></ZUpload>
+        </NFormItem>
+        <NFormItem label="路由配置" path="benefitConfigJson.oilRoutePath">
+          <NInput
+            v-model:value="model.benefitConfigJson.oilRoutePath"
+            :disabled="!isCheckedOilPerLiterDiscount"
+            placeholder="请输入路由路径,如:/pages/oil/index"
+          />
+        </NFormItem>
+        <div class="mt-6px">
+          <NCheckbox v-model:checked="isCheckedOilPerLiterDiscount" class="ml-6px">启用该权益</NCheckbox>
+        </div>
       </div>
 
       <div class="my-6px text-12px">市民请集合平台快消品</div>
@@ -700,11 +753,25 @@ onMounted(() => {
               %
               <div class="ml-10px text-12px">(输入95表示9.5折,范围0-100)</div>
             </div>
-            <div class="mt-6px">
-              <NCheckbox v-model:checked="isCheckedMallDiscountRate" class="ml-6px">启用该权益</NCheckbox>
-            </div>
           </div>
         </NFormItem>
+        <NFormItem label="图标" path="benefitConfigJson.mallIcon">
+          <ZUpload
+            v-model:value="model.benefitConfigJson.mallIcon"
+            :max="1"
+            :disabled="!isCheckedMallDiscountRate"
+          ></ZUpload>
+        </NFormItem>
+        <NFormItem label="路由配置" path="benefitConfigJson.mallRoutePath">
+          <NInput
+            v-model:value="model.benefitConfigJson.mallRoutePath"
+            :disabled="!isCheckedMallDiscountRate"
+            placeholder="请输入路由路径,如:/pages/mall/index"
+          />
+        </NFormItem>
+        <div class="mt-6px">
+          <NCheckbox v-model:checked="isCheckedMallDiscountRate" class="ml-6px">启用该权益</NCheckbox>
+        </div>
       </div>
 
       <div class="my-6px text-12px">贵阳城投充电桩优惠</div>
@@ -730,11 +797,25 @@ onMounted(() => {
               <div class="ml-10px text-12px">(保留2位小数,范围0-50)</div>
             </div>
-            <div class="mt-6px">
-              <NCheckbox v-model:checked="isCheckedChargePerKwhDiscount" class="ml-6px">启用该权益</NCheckbox>
-            </div>
           </div>
         </NFormItem>
+        <NFormItem label="图标" path="benefitConfigJson.chargeIcon">
+          <ZUpload
+            v-model:value="model.benefitConfigJson.chargeIcon"
+            :max="1"
+            :disabled="!isCheckedChargePerKwhDiscount"
+          ></ZUpload>
+        </NFormItem>
+        <NFormItem label="路由配置" path="benefitConfigJson.chargeRoutePath">
+          <NInput
+            v-model:value="model.benefitConfigJson.chargeRoutePath"
+            :disabled="!isCheckedChargePerKwhDiscount"
+            placeholder="请输入路由路径,如:/pages/charge/index"
+          />
+        </NFormItem>
+        <div class="mt-6px">
+          <NCheckbox v-model:checked="isCheckedChargePerKwhDiscount" class="ml-6px">启用该权益</NCheckbox>
+        </div>
       </div>
 
       <div class="my-6px text-12px">贵阳城投停车位停车优惠</div>
@@ -758,11 +839,25 @@ onMounted(() => {
               %
               <div class="ml-10px text-12px">(输入95表示9.5折,范围0-100)</div>
             </div>
-            <div class="mt-6px">
-              <NCheckbox v-model:checked="isCheckedParkingDiscountRate" class="ml-6px">启用该权益</NCheckbox>
-            </div>
           </div>
         </NFormItem>
+        <NFormItem label="图标" path="benefitConfigJson.parkingIcon">
+          <ZUpload
+            v-model:value="model.benefitConfigJson.parkingIcon"
+            :max="1"
+            :disabled="!isCheckedParkingDiscountRate"
+          ></ZUpload>
+        </NFormItem>
+        <NFormItem label="路由配置" path="benefitConfigJson.parkingRoutePath">
+          <NInput
+            v-model:value="model.benefitConfigJson.parkingRoutePath"
+            :disabled="!isCheckedParkingDiscountRate"
+            placeholder="请输入路由路径,如:/pages/parking/index"
+          />
+        </NFormItem>
+        <div class="mt-6px">
+          <NCheckbox v-model:checked="isCheckedParkingDiscountRate" class="ml-6px">启用该权益</NCheckbox>
+        </div>
       </div>
 
       <div class="my-6px text-12px">市民请集合平台优惠券</div>
@@ -816,6 +911,16 @@ onMounted(() => {
           </NButton>
         </div>
 
+        <NFormItem label="图标" path="couponIcon">
+          <ZUpload v-model:value="model.couponIcon" :max="1" :disabled="!isCheckedCouponConfigJson"></ZUpload>
+        </NFormItem>
+        <NFormItem label="路由配置" path="couponRoutePath">
+          <NInput
+            v-model:value="model.couponRoutePath"
+            :disabled="!isCheckedCouponConfigJson"
+            placeholder="请输入路由路径,如:/pages/coupon/index"
+          />
+        </NFormItem>
         <div class="mt-6px">
           <NCheckbox v-model:checked="isCheckedCouponConfigJson" class="ml-100px">启用该权益</NCheckbox>
         </div>
@@ -866,6 +971,16 @@ onMounted(() => {
           </div>
         </NFormItem>
 
+        <NFormItem label="图标" path="giftIcon">
+          <ZUpload v-model:value="model.giftIcon" :max="1" :disabled="!isCheckedGiftConfigJson"></ZUpload>
+        </NFormItem>
+        <NFormItem label="路由配置" path="giftRoutePath">
+          <NInput
+            v-model:value="model.giftRoutePath"
+            :disabled="!isCheckedGiftConfigJson"
+            placeholder="请输入路由路径,如:/pages/gift/index"
+          />
+        </NFormItem>
         <div class="mt-6px">
           <NCheckbox v-model:checked="isCheckedGiftConfigJson" class="ml-100px">启用该权益</NCheckbox>
         </div>