Parcourir la source

feat(ticket): 优化券管理功能并调整接口调用方式

- 更新 authMenuList.json,新增代金券和优惠券详情页路由配置
- 修改 ticketManagement/index.vue,优化按钮显示逻辑和数据处理
- 调整表格列配置,区分代金券和优惠券展示字段
- 更新状态枚举值,统一状态码管理
- 新增 activeName 恢复机制,支持页面间状态保持
- 监听路由变化,在返回列表页时恢复 tab 状态
- 修改接口调用方式,将 get 请求改为 post 请求
- 完善数据回调处理,分别处理代金券和优惠券数据结构
- 修复库存和销量数据显示问题,增加空值判断
- 优化详情页跳转逻辑,记录当前活动 tab 状态
congxuesong il y a 4 semaines
Parent
commit
e06b0990b2

+ 1 - 1
src/api/modules/voucherManagement.ts

@@ -3,7 +3,7 @@ import { PORT_NONE } from "@/api/config/servicePort";
 import http from "@/api";
 
 export const getThaliList = params => {
-  return http.get<ResPage<StoreUser.ResStoreUserList>>(PORT_NONE + `/couponPlatform/getCouponList`, params);
+  return http.post<ResPage<StoreUser.ResStoreUserList>>(PORT_NONE + `/couponPlatform/getCouponList`, params);
 };
 export const delThaliById = (params: { id: string }) => {
   return http.get(PORT_NONE + `/couponPlatform/deleteCoupon`, params);

+ 16 - 1
src/assets/json/authMenuList.json

@@ -171,7 +171,22 @@
           "component": "/ticketManagement/detail",
           "meta": {
             "icon": "Menu",
-            "title": "券管理详情",
+            "title": "代金券详情",
+            "activeMenu": "/ticketManagement",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/ticketManagement/couponDetail",
+          "name": "ticketManagementCouponDetail",
+          "component": "/ticketManagement/couponDetail",
+          "meta": {
+            "icon": "Menu",
+            "title": "优惠券详情",
             "activeMenu": "/ticketManagement",
             "isLink": "",
             "isHide": true,

+ 100 - 28
src/views/ticketManagement/index.vue

@@ -73,7 +73,11 @@
         </el-button>
         <!-- 查看详情按钮 -->
         <el-button
-          v-if="canShowButton(scope.row.status, currentOperationPermissions.查看详情) && (isCoupon || scope.row.dataType != 1)"
+          v-if="
+            isVoucher
+              ? canShowButton(scope.row.status, currentOperationPermissions.查看详情) && scope.row.dataType != 1
+              : canShowButton(scope.row.status, currentOperationPermissions.查看详情)
+          "
           link
           type="primary"
           @click="toDetail(scope.row)"
@@ -82,7 +86,11 @@
         </el-button>
         <!-- 编辑按钮 -->
         <el-button
-          v-if="canShowButton(scope.row.status, currentOperationPermissions.编辑) || (isVoucher && scope.row.dataType == 1)"
+          v-if="
+            isVoucher
+              ? canShowButton(scope.row.status, currentOperationPermissions.编辑) && scope.row.dataType == 1
+              : canShowButton(scope.row.status, currentOperationPermissions.编辑)
+          "
           link
           type="primary"
           @click="editRow(scope.row)"
@@ -91,7 +99,11 @@
         </el-button>
         <!-- 删除按钮 -->
         <el-button
-          v-if="canShowButton(scope.row.status, currentOperationPermissions.删除) || (isVoucher && scope.row.dataType == 1)"
+          v-if="
+            isVoucher
+              ? canShowButton(scope.row.status, currentOperationPermissions.删除) && scope.row.dataType == 1
+              : canShowButton(scope.row.status, currentOperationPermissions.删除)
+          "
           link
           type="primary"
           @click="deleteRow(scope.row)"
@@ -145,8 +157,8 @@
 </template>
 
 <script setup lang="tsx" name="voucherManagement">
-import { computed, onActivated, onMounted, reactive, ref } from "vue";
-import { useRouter } from "vue-router";
+import { computed, onActivated, onMounted, reactive, ref, watch } from "vue";
+import { useRouter, useRoute } from "vue-router";
 import type { FormInstance, FormRules } from "element-plus";
 import { ElMessage } from "element-plus";
 import ProTable from "@/components/ProTable/index.vue";
@@ -163,6 +175,7 @@ import { ElMessageBox } from "element-plus/es";
 import { localGet, usePermission } from "@/utils";
 
 const router = useRouter();
+const route = useRoute();
 const dialogFormVisible = ref(false);
 const formInventory: any = ref({
   id: "",
@@ -206,7 +219,6 @@ const rules = reactive<FormRules<RuleForm>>({
   ]
 });
 const statusEnum = [
-  { label: "全部", value: "" },
   { label: "草稿", value: "0" },
   { label: "进行中", value: "5" },
   { label: "未开始", value: "2" },
@@ -214,6 +226,11 @@ const statusEnum = [
   { label: "已售罄", value: "4" },
   { label: "已结束", value: "7" }
 ];
+const statusEnumY = [
+  { label: "草稿", value: "3" },
+  { label: "进行中", value: "1" },
+  { label: "已结束", value: "2" }
+];
 // ProTable 实例(需要在使用它的地方之前定义)
 const proTable = ref<ProTableInstance>();
 
@@ -237,14 +254,16 @@ const voucherColumns = reactive<ColumnProps<any>[]>([
     prop: "saleNum",
     label: "已售",
     render: scope => {
-      return scope.row.saleNum === null || scope.row.saleNum === undefined ? 0 : scope.row.saleNum;
+      return scope.row.saleNum === null || scope.row.saleNum === undefined || scope.row.saleNum === "" ? 0 : scope.row.saleNum;
     }
   },
   {
     prop: "singleQty",
     label: "剩余库存",
     render: scope => {
-      return scope.row.singleQty === null || scope.row.singleQty === undefined ? 0 : scope.row.singleQty;
+      return scope.row.singleQty === null || scope.row.singleQty === undefined || scope.row.singleQty === ""
+        ? 0
+        : scope.row.singleQty;
     }
   },
   {
@@ -267,7 +286,7 @@ const voucherColumns = reactive<ColumnProps<any>[]>([
 // 优惠券表格列配置
 const couponColumns = reactive<ColumnProps<any>[]>([
   {
-    prop: "name",
+    prop: "couponName",
     label: "券名称",
     search: {
       el: "input"
@@ -277,28 +296,30 @@ const couponColumns = reactive<ColumnProps<any>[]>([
     prop: "saleNum",
     label: "已领",
     render: scope => {
-      return scope.row.saleNum === null || scope.row.saleNum === undefined ? 0 : scope.row.saleNum;
+      return scope.row.saleNum === null || scope.row.saleNum === undefined || scope.row.saleNum === "" ? 0 : scope.row.saleNum;
     }
   },
   {
     prop: "singleQty",
     label: "剩余库存",
     render: scope => {
-      return scope.row.singleQty === null || scope.row.singleQty === undefined ? 0 : scope.row.singleQty;
+      return scope.row.singleQty === null || scope.row.singleQty === undefined || scope.row.singleQty === ""
+        ? 0
+        : scope.row.singleQty;
     }
   },
   {
-    prop: "endDate",
+    prop: "endGetDate",
     label: "结束时间"
   },
   {
-    prop: "status",
+    prop: "couponStatus",
     label: "状态",
     search: {
       el: "select",
       props: { placeholder: "请选择" }
     },
-    enum: statusEnum,
+    enum: statusEnumY,
     fieldNames: { label: "label", value: "value" }
   },
   { prop: "operation", label: "操作", fixed: "right", width: 330 }
@@ -314,9 +335,9 @@ const allTabOptions = [
   { label: "优惠券", name: "2" }
 ];
 
-// 状态枚举:0草稿 1待审核 2未开始 3审核拒绝 4已售罄 5进行中 6已下架 7已结束
+// 状态枚举:1草稿 1待审核 2未开始 3审核拒绝 4已售罄 5进行中 6已下架 7已结束
 const STATUS = {
-  草稿: 0,
+  草稿: 1,
   待审核: 1,
   未开始: 2,
   审核拒绝: 3,
@@ -404,46 +425,95 @@ const getReviewStatusLabel = (reviewType: string | number) => {
   return reviewStatusMap[String(reviewType)] || "";
 };
 
-// 数据类型:1-草稿,0-已发布,2-全部
-const dataType = computed(() => {
-  if (!activeName.value) return 2;
-  return activeName.value === "0" ? 1 : 0;
-});
-
 // 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
 const initParam = reactive({
   storeId: localGet("createdId"),
   groupType: localGet("businessSection"),
-  status: activeName,
-  dataType: dataType
+  couponType: activeName
 });
 const type = ref(false);
 const typeCoupon = ref(false);
+// 恢复 activeName 的函数
+const restoreActiveName = () => {
+  const savedActiveName = sessionStorage.getItem("ticketManagement_activeName");
+  if (savedActiveName && (savedActiveName === "1" || savedActiveName === "2")) {
+    activeName.value = savedActiveName;
+    // 恢复后清除 sessionStorage,避免影响其他场景
+    sessionStorage.removeItem("ticketManagement_activeName");
+  }
+};
+
 // 页面加载时触发查询
 onMounted(async () => {
   type.value = await usePermission("新建代金券");
   typeCoupon.value = await usePermission("新建优惠券");
+  // 从 sessionStorage 恢复 activeName
+  restoreActiveName();
   proTable.value?.getTableList();
 });
 
 // 从其他页面返回时触发查询
 onActivated(() => {
+  // 从 sessionStorage 恢复 activeName
+  restoreActiveName();
   proTable.value?.getTableList();
 });
 
+// 监听路由变化,当从详情页返回时恢复 activeName
+watch(
+  () => route.path,
+  (newPath, oldPath) => {
+    // 如果当前路径是列表页,且之前路径是详情页,则恢复 activeName
+    if (
+      newPath.includes("/ticketManagement") &&
+      !newPath.includes("/detail") &&
+      !newPath.includes("/newVoucher") &&
+      !newPath.includes("/newCoupon") &&
+      (oldPath?.includes("/ticketManagement/detail") || oldPath?.includes("/ticketManagement/couponDetail"))
+    ) {
+      restoreActiveName();
+    }
+  },
+  { immediate: false }
+);
+
 // dataCallback 是对于返回的表格数据做处理,如果你后台返回的数据不是 list && total 这些字段,可以在这里进行处理成这些字段
 // 或者直接去 hooks/useTable.ts 文件中把字段改为你后端对应的就行
 const dataCallback = (data: any) => {
-  return {
-    list: data.records,
-    total: data.total
-  };
+  // 代金券从 couponList.records 取值,优惠券从 discountList.records 取值
+  if (activeName.value === "1") {
+    // 代金券
+    return {
+      list: data.couponList?.records || [],
+      total: data.couponList?.total || 0
+    };
+  } else {
+    // 优惠券
+    return {
+      list: data.discountList?.records || [],
+      total: data.discountList?.total || 0
+    };
+  }
 };
 
 // 如果你想在请求之前对当前请求参数做一些操作,可以自定义如下函数:params 为当前所有的请求参数(包括分页),最后返回请求列表接口
 // 默认不做操作就直接在 ProTable 组件上绑定	:requestApi="getUserList"
 const getTableList = (params: any) => {
   let newParams = JSON.parse(JSON.stringify(params));
+  if (activeName.value === "1") {
+    // 代金券
+    if (newParams.status === "0") {
+      newParams.dataType = 1; // 草稿
+    } else if (newParams.status) {
+      newParams.dataType = 0;
+    } else {
+      newParams.dataType = 2;
+    }
+  } else {
+    // 优惠券
+    delete newParams.dataType;
+    newParams.couponsFromType = 1;
+  }
   return getThaliList(newParams);
 };
 const newGroupBuying = () => {
@@ -454,6 +524,8 @@ const newCoupon = () => {
 };
 // 跳转详情页 - 根据类型跳转不同页面
 const toDetail = (row: any) => {
+  // 保存当前 activeName 到 sessionStorage
+  sessionStorage.setItem("ticketManagement_activeName", activeName.value);
   const path = isVoucher.value ? `/ticketManagement/detail?id=${row.id}` : `/ticketManagement/couponDetail?id=${row.id}`;
   router.push(path);
 };