Kaynağa Gözat

feat(ticket): 优化优惠券和代金券管理功能

- 移除优惠券详情页的假数据逻辑,改为提示缺少ID参数
- 修复优惠券详情接口调用参数名错误(counponId)
- 更新优惠券详情页标签最小宽度以改善布局
- 新增编辑优惠券API接口(editDiscountCoupon)
- 修复获取优惠券详情接口地址错误
- 优化列表页状态显示逻辑,支持代金券和优惠券不同状态映射
- 调整优惠券列表字段显示(quantityClaimed替代saleNum)
- 隐藏旧的状态列并新增正确的状态列
- 重构状态枚举常量,区分代金券(VO_STATUS)和优惠券(CO_STATUS)
- 更新操作权限配置使用新的状态枚举
- 改进状态标签获取函数,支持根据不同类型返回对应状态文本
- 完善路由监听逻辑,支持从编辑页返回时恢复tab状态
- 保存tab状态到sessionStorage以便编辑后恢复
- 移除Tab切换时多余的数据刷新调用
- 动态显示新建/编辑优惠券页面标题
- 动态显示新建/编辑优惠券提交按钮文本
- 实现优惠券编辑功能,支持调用编辑接口
- 动态显示新建/编辑代金券页面标题
- 动态显示新建/编辑代金券提交按钮文本
congxuesong 4 ay önce
ebeveyn
işleme
c5d1273382

+ 3 - 3
src/api/modules/couponManagement.ts

@@ -17,12 +17,12 @@ export const updateNum = params => {
 export const addDiscountCoupon = params => {
   return http.post(PORT_NONE + `/discountCouponPlatform/addDiscountCoupon`, params);
 };
-export const getMenuByStoreId = params => {
-  return http.get(PORT_NONE + `/menuPlatform/getMenuByStoreId`, params);
+export const editDiscountCoupon = params => {
+  return http.post(PORT_NONE + `/discountCouponPlatform/editDiscountCoupon`, params);
 };
 export const getHolidayList = (params: any) => {
   return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/couponPlatform/getHolidayList`, params);
 };
 export const getCouponDetail = (params: StoreUser.ReqUserParams) => {
-  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/store/info/getStoreDetail`, params);
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/discountCouponPlatform/getCounponDetailById`, params);
 };

+ 3 - 30
src/views/ticketManagement/couponDetail.vue

@@ -159,8 +159,7 @@ onMounted(async () => {
   if (id.value) {
     await loadDetailData();
   } else {
-    // 如果没有ID,使用假数据展示
-    loadMockData();
+    ElMessage.warning("缺少优惠券ID参数");
   }
 });
 
@@ -180,45 +179,19 @@ const goBack = () => {
  */
 const loadDetailData = async () => {
   try {
-    const params: any = {
-      id: id.value
-    };
-    const res: any = await getCouponDetail(params);
+    const res: any = await getCouponDetail({ counponId: id.value });
     if (res && res.code == 200) {
       // 合并主数据
       couponModel.value = { ...couponModel.value, ...res.data };
     } else {
       ElMessage.error("加载详情数据失败");
-      // 加载失败时使用假数据
-      loadMockData();
     }
   } catch (error) {
     console.error("加载详情数据出错:", error);
     ElMessage.error("加载详情数据出错");
-    // 加载失败时使用假数据
-    loadMockData();
   }
 };
 
-/**
- * 加载假数据(用于展示)
- */
-const loadMockData = () => {
-  couponModel.value = {
-    name: "5元通用优惠券",
-    nominalValue: "5",
-    beginGetDate: "2025-01-01",
-    endGetDate: "2025-04-20",
-    specifiedDay: "30",
-    singleQty: "2000",
-    claimRule: "day",
-    attentionCanReceived: 0,
-    hasMinimumSpend: 1,
-    minimumSpendingAmount: "100",
-    supplementaryInstruction: "本优惠券适用于全场商品,不可与其他优惠叠加使用。"
-  };
-};
-
 // ==================== 工具函数 ====================
 
 /**
@@ -314,7 +287,7 @@ const getClaimRuleText = () => {
 }
 .detail-label {
   flex-shrink: 0;
-  min-width: 120px;
+  min-width: 200px;
   font-size: 14px;
   font-weight: 500;
   line-height: 32px;

+ 62 - 48
src/views/ticketManagement/index.vue

@@ -25,8 +25,8 @@
       <template #status="scope">
         <!-- 代金券:显示状态和审核状态两行 -->
         <template v-if="activeName === '1'">
-          <p style="margin: 0; line-height: 1.5">状态:{{ getStatusLabel(scope.row.status) || "--" }}</p>
-          <p style="margin: 0; line-height: 1.5">审核状态:{{ getReviewStatusLabel(scope.row.reviewType) || "--" }}</p>
+          <p style="margin: 0; line-height: 1.5">状态:{{ getStatusLabel(scope.row.status, scope.row.dataType) || "--" }}</p>
+          <p style="margin: 0; line-height: 1.5">审核状态:{{ scope.row.statusName || "--" }}</p>
         </template>
         <!-- 优惠券:只显示状态一行 -->
         <template v-else>
@@ -286,17 +286,19 @@ const voucherColumns = reactive<ColumnProps<any>[]>([
 // 优惠券表格列配置
 const couponColumns = reactive<ColumnProps<any>[]>([
   {
-    prop: "couponName",
+    prop: "name",
     label: "券名称",
     search: {
       el: "input"
     }
   },
   {
-    prop: "saleNum",
+    prop: "quantityClaimed",
     label: "已领",
     render: scope => {
-      return scope.row.saleNum === null || scope.row.saleNum === undefined || scope.row.saleNum === "" ? 0 : scope.row.saleNum;
+      return scope.row.quantityClaimed === null || scope.row.quantityClaimed === undefined || scope.row.quantityClaimed === ""
+        ? 0
+        : scope.row.quantityClaimed;
     }
   },
   {
@@ -315,6 +317,7 @@ const couponColumns = reactive<ColumnProps<any>[]>([
   {
     prop: "couponStatus",
     label: "状态",
+    isShow: false,
     search: {
       el: "select",
       props: { placeholder: "请选择" }
@@ -322,6 +325,10 @@ const couponColumns = reactive<ColumnProps<any>[]>([
     enum: statusEnumY,
     fieldNames: { label: "label", value: "value" }
   },
+  {
+    prop: "status",
+    label: "状态"
+  },
   { prop: "operation", label: "操作", fixed: "right", width: 330 }
 ]);
 
@@ -336,7 +343,7 @@ const allTabOptions = [
 ];
 
 // 状态枚举:1草稿 1待审核 2未开始 3审核拒绝 4已售罄 5进行中 6已下架 7已结束
-const STATUS = {
+const VO_STATUS = {
   草稿: 1,
   待审核: 1,
   未开始: 2,
@@ -346,39 +353,47 @@ const STATUS = {
   已下架: 6,
   已结束: 7
 } as const;
-
+// 状态枚举:1草稿 1待审核 2未开始 3审核拒绝 4已售罄 5进行中 6已下架 7已结束
+const CO_STATUS = {
+  进行中: 0,
+  已结束: 1,
+  未开始: 2,
+  已下架: 3,
+  已售罄: 4,
+  草稿: 5
+} as const;
 // 代金券操作按钮权限配置:定义每个操作按钮在哪些状态下显示
 const VOUCHER_OPERATION_PERMISSIONS = {
   // 查看详情:待审核、未开始、审核拒绝、进行中、已售罄、已下架
-  查看详情: [STATUS.待审核, STATUS.未开始, STATUS.审核拒绝, STATUS.进行中, STATUS.已售罄, STATUS.已下架],
+  查看详情: [VO_STATUS.待审核, VO_STATUS.未开始, VO_STATUS.审核拒绝, VO_STATUS.进行中, VO_STATUS.已售罄, VO_STATUS.已下架],
   // 上架:未开始、已下架
-  上架: [STATUS.未开始, STATUS.已下架],
+  上架: [VO_STATUS.未开始, VO_STATUS.已下架],
   // 下架:进行中
-  下架: [STATUS.进行中],
+  下架: [VO_STATUS.进行中],
   // 修改库存:未开始、进行中、已售罄
-  修改库存: [STATUS.未开始, STATUS.进行中, STATUS.已售罄],
+  修改库存: [VO_STATUS.未开始, VO_STATUS.进行中, VO_STATUS.已售罄],
   // 编辑:草稿、审核拒绝、已售罄、已下架、已结束
-  编辑: [STATUS.草稿, STATUS.审核拒绝, STATUS.已售罄, STATUS.已下架, STATUS.已结束],
+  编辑: [VO_STATUS.草稿, VO_STATUS.审核拒绝, VO_STATUS.已售罄, VO_STATUS.已下架, VO_STATUS.已结束],
   // 删除:草稿、未开始、审核拒绝、已售罄、已结束
-  删除: [STATUS.草稿, STATUS.未开始, STATUS.审核拒绝, STATUS.已售罄, STATUS.已结束],
+  删除: [VO_STATUS.草稿, VO_STATUS.未开始, VO_STATUS.审核拒绝, VO_STATUS.已售罄, VO_STATUS.已结束],
   // 查看拒绝原因:审核拒绝
-  查看拒绝原因: [STATUS.审核拒绝]
+  查看拒绝原因: [VO_STATUS.审核拒绝]
 } as const;
 
 // 优惠券操作按钮权限配置
 const COUPON_OPERATION_PERMISSIONS = {
   // 查看详情:草稿、未开始、进行中、已下架、已结束、已售罄
-  查看详情: [STATUS.草稿, STATUS.未开始, STATUS.进行中, STATUS.已下架, STATUS.已结束, STATUS.已售罄],
+  查看详情: [CO_STATUS.草稿, CO_STATUS.未开始, CO_STATUS.进行中, CO_STATUS.已下架, CO_STATUS.已结束, CO_STATUS.已售罄],
   // 上架:未开始、已下架
-  上架: [STATUS.未开始, STATUS.已下架],
+  上架: [CO_STATUS.未开始, CO_STATUS.已下架],
   // 下架:进行中
-  下架: [STATUS.进行中],
+  下架: [CO_STATUS.进行中],
   // 修改库存:未开始、进行中、已售罄
-  修改库存: [STATUS.未开始, STATUS.进行中, STATUS.已售罄],
+  修改库存: [CO_STATUS.未开始, CO_STATUS.进行中, CO_STATUS.已售罄],
   // 编辑:草稿、未开始、进行中、已下架、已结束、已售罄
-  编辑: [STATUS.草稿, STATUS.未开始, STATUS.进行中, STATUS.已下架, STATUS.已结束, STATUS.已售罄],
+  编辑: [CO_STATUS.草稿, CO_STATUS.未开始, CO_STATUS.进行中, CO_STATUS.已下架, CO_STATUS.已结束, CO_STATUS.已售罄],
   // 删除:草稿、已结束、已售罄
-  删除: [STATUS.草稿, STATUS.已结束, STATUS.已售罄]
+  删除: [CO_STATUS.草稿, CO_STATUS.已结束, CO_STATUS.已售罄]
 } as const;
 
 // 判断按钮是否显示的工具函数
@@ -398,31 +413,24 @@ const isVoucher = computed(() => activeName.value === "1");
 const isCoupon = computed(() => activeName.value === "2");
 
 // 获取状态标签
-const getStatusLabel = (status: number) => {
-  const statusMap: Record<number, string> = {
-    0: "草稿",
-    1: "待审核",
-    2: "未开始",
-    3: "审核拒绝",
-    4: "已售罄",
-    5: "进行中",
-    6: "已下架",
-    7: "已结束"
-  };
-  return statusMap[status] || "--";
-};
-
-// 获取审核状态标签
-const getReviewStatusLabel = (reviewType: string | number) => {
-  if (reviewType === null || reviewType === undefined || reviewType === "") {
-    return "";
+const getStatusLabel = (status: number, dataType?: number) => {
+  // 代金券且状态为1时,根据dataType判断
+  if (isVoucher.value && status === 1) {
+    if (dataType === 0) {
+      return "待审核";
+    } else if (dataType === 1) {
+      return "草稿";
+    }
   }
-  const reviewStatusMap: Record<string, string> = {
-    "0": "待审核",
-    "1": "审核通过",
-    "2": "审核驳回"
-  };
-  return reviewStatusMap[String(reviewType)] || "";
+  // 根据当前选中的tab选择对应的状态枚举
+  const statusEnum = isVoucher.value ? VO_STATUS : CO_STATUS;
+  // 从状态枚举中查找对应的标签
+  for (const [label, value] of Object.entries(statusEnum)) {
+    if (value === status) {
+      return label;
+    }
+  }
+  return "--";
 };
 
 // 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
@@ -459,17 +467,20 @@ onActivated(() => {
   proTable.value?.getTableList();
 });
 
-// 监听路由变化,当从详情页返回时恢复 activeName
+// 监听路由变化,当从详情页或编辑页返回时恢复 activeName
 watch(
   () => route.path,
   (newPath, oldPath) => {
-    // 如果当前路径是列表页,且之前路径是详情页,则恢复 activeName
+    // 如果当前路径是列表页,且之前路径是详情页或编辑页,则恢复 activeName
     if (
       newPath.includes("/ticketManagement") &&
       !newPath.includes("/detail") &&
       !newPath.includes("/newVoucher") &&
       !newPath.includes("/newCoupon") &&
-      (oldPath?.includes("/ticketManagement/detail") || oldPath?.includes("/ticketManagement/couponDetail"))
+      (oldPath?.includes("/ticketManagement/detail") ||
+        oldPath?.includes("/ticketManagement/couponDetail") ||
+        oldPath?.includes("/ticketManagement/newVoucher") ||
+        oldPath?.includes("/ticketManagement/newCoupon"))
     ) {
       restoreActiveName();
     }
@@ -531,6 +542,8 @@ const toDetail = (row: any) => {
 };
 // 编辑行数据
 const editRow = (row: any) => {
+  // 保存当前 activeName 到 sessionStorage
+  sessionStorage.setItem("ticketManagement_activeName", activeName.value);
   const path = isVoucher.value
     ? `/ticketManagement/newVoucher?id=${row.id}&type=edit`
     : `/ticketManagement/newCoupon?id=${row.id}&type=edit`;
@@ -570,7 +583,8 @@ const deleteRow = (row: any) => {
 };
 // Tab切换处理
 const handleClick = () => {
-  proTable.value?.getTableList();
+  // initParam 中的 couponType 是响应式的,当 activeName 变化时会自动触发 ProTable 内部的 watch 监听,无需手动调用
+  // proTable.value?.getTableList();
 };
 
 // 修改状态(上架/下架)

+ 18 - 9
src/views/ticketManagement/newCoupon.vue

@@ -3,7 +3,7 @@
   <div class="table-box" style="width: 100%; min-height: 100%; background-color: white">
     <div class="header">
       <el-button @click="goBack"> 返回 </el-button>
-      <h2 class="title">新建优惠券</h2>
+      <h2 class="title">{{ type == "add" ? "新建" : "编辑" }}优惠券</h2>
     </div>
     <el-form :model="couponModel" ref="ruleFormRef" :rules="rules" label-width="200px" class="formBox">
       <div class="content">
@@ -93,7 +93,7 @@
     <!-- 底部按钮区域 -->
     <div class="button-container">
       <el-button @click="() => handleSubmit('draft')"> 存草稿 </el-button>
-      <el-button type="primary" @click="() => handleSubmit()"> 新建优惠券 </el-button>
+      <el-button type="primary" @click="() => handleSubmit()"> {{ type == "add" ? "新建" : "编辑" }}优惠券 </el-button>
     </div>
   </div>
 </template>
@@ -107,9 +107,10 @@ import { ref, reactive, watch, nextTick, onMounted } from "vue";
 import { ElMessage } from "element-plus";
 import { useRoute, useRouter } from "vue-router";
 import type { FormInstance } from "element-plus";
-import { getCouponDetail, addDiscountCoupon } from "@/api/modules/couponManagement";
+import { getCouponDetail, addDiscountCoupon, editDiscountCoupon } from "@/api/modules/couponManagement";
 import { validatePositiveNumber, validatePositiveInteger, validateDateRange } from "@/utils/eleValidate";
 import { localGet } from "@/utils";
+import { getVoucherDetail } from "@/api/modules/voucherManagement";
 // ==================== 响应式数据定义 ====================
 
 // 路由相关
@@ -286,8 +287,8 @@ onMounted(async () => {
   id.value = (route.query.id as string) || "";
   type.value = (route.query.type as string) || "";
   if (type.value != "add") {
-    // TODO: 加载优惠券详情数据
-    // let res: any = await getCouponDetail({ id: id.value });
+    let res: any = await getCouponDetail({ counponId: id.value });
+    couponModel.value = { ...couponModel.value, ...res.data };
   }
 });
 /**
@@ -329,11 +330,19 @@ const handleSubmit = async (submitType?: string) => {
   // 验证表单
   ruleFormRef.value!.validate(async (valid: boolean) => {
     if (!valid) return;
-    let res: any = await addDiscountCoupon(params);
-    if (res && res.code == 200) {
-      ElMessage.success("创建成功");
-      goBack();
+    if (type.value == "add") {
+      let res: any = await addDiscountCoupon(params);
+      if (res && res.code == 200) {
+        ElMessage.success("创建成功");
+      }
+    } else {
+      params.couponId = id.value;
+      let res: any = await editDiscountCoupon(params);
+      if (res && res.code == 200) {
+        ElMessage.success("修改成功");
+      }
     }
+    goBack();
   });
 };
 

+ 2 - 2
src/views/ticketManagement/newVoucher.vue

@@ -3,7 +3,7 @@
   <div class="table-box" style="width: 100%; min-height: 100%; background-color: white">
     <div class="header">
       <el-button @click="goBack"> 返回 </el-button>
-      <h2 class="title">新建代金券</h2>
+      <h2 class="title">{{ type == "add" ? "新建" : "编辑" }}代金券</h2>
     </div>
     <el-form :model="voucherModel" ref="ruleFormRef" :rules="rules" label-width="120px" class="formBox">
       <div class="content">
@@ -227,7 +227,7 @@
     <!-- 底部按钮区域 -->
     <div class="button-container">
       <el-button @click="handleSubmit('draft')"> 存草稿 </el-button>
-      <el-button type="primary" @click="handleSubmit()"> 新建代金券 </el-button>
+      <el-button type="primary" @click="handleSubmit()"> {{ type == "add" ? "新建" : "编辑" }}代金券 </el-button>
     </div>
   </div>
 </template>