congxuesong пре 2 недеља
родитељ
комит
af3248d67b

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

@@ -6,7 +6,7 @@ import http from "@/api";
 
 // 获取好友优惠券列表
 export const getFriendCouponList = (params: any) => {
-  return http.post(`/api/friendCoupon/list`, params);
+  return http.post(`/life-discount-coupon-store-friend/getReceivedSendFriendCouponList`, params);
 };
 
 // 赠送优惠券给好友

+ 15 - 0
src/assets/json/authMenuList.json

@@ -758,6 +758,21 @@
             "isAffix": false,
             "isKeepAlive": false
           }
+        },
+        {
+          "path": "/dynamicManagement/friendCouponDetail",
+          "name": "friendCouponDetail",
+          "component": "/dynamicManagement/friendCouponDetail",
+          "meta": {
+            "icon": "Document",
+            "title": "好友优惠券详情",
+            "activeMenu": "/dynamicManagement/friendCoupon",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
         }
       ]
     }

+ 41 - 74
src/views/dynamicManagement/friendCoupon.vue

@@ -69,7 +69,7 @@ import { ElMessage, ElMessageBox } from "element-plus";
 import ProTable from "@/components/ProTable/index.vue";
 import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
 import { localGet } from "@/utils";
-// import { getFriendCouponList, sendCouponToFriend, deleteFriendCoupon } from "@/api/modules/friendCoupon";
+import { getFriendCouponList, sendCouponToFriend, deleteFriendCoupon } from "@/api/modules/friendCoupon";
 
 const router = useRouter();
 
@@ -121,34 +121,35 @@ const friendMessageColumns = reactive<ColumnProps<any>[]>([
     }
   },
   {
-    prop: "couponAmount",
+    prop: "couponName",
+    label: "优惠券名称"
+  },
+  {
+    prop: "nominalValue",
     label: "优惠券额",
     render: (scope: any) => {
-      return `¥${scope.row.couponAmount || 0}`;
+      return `¥${scope.row.nominalValue || 0}`;
     }
   },
   {
-    prop: "validUntil",
+    prop: "endDate",
     label: "有效期至",
     render: (scope: any) => {
-      return scope.row.validUntil?.replace(/-/g, "/") || "--";
+      return scope.row.endDate?.replace(/-/g, "/") || "--";
     }
   },
   {
-    prop: "senderName",
+    prop: "acName",
     label: "赠送人"
   },
   {
-    prop: "receiveTime",
-    label: "接收时间",
-    render: (scope: any) => {
-      return scope.row.receiveTime?.replace(/-/g, "/") || "--";
-    }
+    prop: "couponNum",
+    label: "优惠券数量"
   },
   { prop: "operation", label: "操作", fixed: "right", width: 200 }
 ]);
 
-// 我好友表格列配置
+// 我好友表格列配置
 const myGiftColumns = reactive<ColumnProps<any>[]>([
   {
     prop: "storeName",
@@ -158,42 +159,43 @@ const myGiftColumns = reactive<ColumnProps<any>[]>([
     }
   },
   {
-    prop: "couponAmount",
+    prop: "couponName",
+    label: "优惠券名称"
+  },
+  {
+    prop: "nominalValue",
     label: "优惠券额",
     render: (scope: any) => {
-      return `¥${scope.row.couponAmount || 0}`;
+      return `¥${scope.row.nominalValue || 0}`;
     }
   },
   {
-    prop: "validUntil",
+    prop: "endDate",
     label: "有效期至",
     render: (scope: any) => {
-      return scope.row.validUntil?.replace(/-/g, "/") || "--";
+      return scope.row.endDate?.replace(/-/g, "/") || "--";
     }
   },
   {
-    prop: "receiverName",
+    prop: "acName",
     label: "接收人"
   },
   {
+    prop: "couponNum",
+    label: "优惠券数量"
+  },
+  {
     prop: "status",
     label: "状态",
     render: (scope: any) => {
-      const statusMap: Record<number, string> = {
-        0: "未使用",
-        1: "已使用",
-        2: "已过期"
+      const statusMap: Record<string, string> = {
+        "0": "未使用",
+        "1": "已使用",
+        "2": "已过期"
       };
       return statusMap[scope.row.status] || "--";
     }
   },
-  {
-    prop: "sendTime",
-    label: "赠送时间",
-    render: (scope: any) => {
-      return scope.row.sendTime?.replace(/-/g, "/") || "--";
-    }
-  },
   { prop: "operation", label: "操作", fixed: "right", width: 200 }
 ]);
 
@@ -217,8 +219,8 @@ const handleTabClick = () => {
 // dataCallback 是对于返回的表格数据做处理
 const dataCallback = (data: any) => {
   return {
-    list: data?.records || [],
-    total: data?.total || 0
+    list: data || [],
+    total: data?.length || 0
   };
 };
 
@@ -226,50 +228,10 @@ const dataCallback = (data: any) => {
 const getTableList = (params: any) => {
   const newParams = {
     ...params,
-    type: activeName.value
+    type: activeName.value === "friendMessage" ? 0 : 1 // 0-好友赠我,1-我赠好友
   };
 
-  // TODO: 集成真实接口时,取消下面的注释
-  // return getFriendCouponList(newParams);
-
-  // 临时方案:返回模拟数据
-  return new Promise(resolve => {
-    setTimeout(() => {
-      const mockData = activeName.value === "friendMessage" ? generateMockFriendMessages() : generateMockMyGifts();
-      resolve({
-        code: 200,
-        data: {
-          records: mockData,
-          total: mockData.length
-        }
-      });
-    }, 500);
-  });
-};
-
-// 生成模拟的好友留言数据
-const generateMockFriendMessages = () => {
-  return Array.from({ length: 2 }, (_, i) => ({
-    id: i + 1,
-    storeName: i === 0 ? "甜客优越" : "洗浴优越铺",
-    couponAmount: 200,
-    validUntil: "2025-05-01",
-    senderName: "张三",
-    receiveTime: "2025-03-01"
-  }));
-};
-
-// 生成模拟的我感好友数据
-const generateMockMyGifts = () => {
-  return Array.from({ length: 3 }, (_, i) => ({
-    id: i + 1,
-    storeName: `店铺${i + 1}`,
-    couponAmount: 200,
-    validUntil: "2025-05-01",
-    receiverName: `好友${i + 1}`,
-    status: i % 3,
-    sendTime: "2025-03-01"
-  }));
+  return getFriendCouponList(newParams);
 };
 
 // 打开赠送对话框
@@ -319,8 +281,13 @@ const handleGiftSubmit = async () => {
 
 // 查看详情
 const viewDetail = (row: any) => {
-  ElMessage.info(`查看详情: ${row.storeName}`);
-  // TODO: 跳转到详情页或显示详情对话框
+  router.push({
+    path: "/dynamicManagement/friendCouponDetail",
+    query: {
+      id: row.id,
+      type: activeName.value
+    }
+  });
 };
 
 // 删除行数据

+ 346 - 0
src/views/dynamicManagement/friendCouponDetail.vue

@@ -0,0 +1,346 @@
+<template>
+  <!-- 好友优惠券 - 详情页面 -->
+  <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>
+    </div>
+    <div class="content">
+      <!-- 左侧内容区域 -->
+      <div class="contentLeft">
+        <!-- 基础信息模块 -->
+        <div class="model">
+          <h3 style="font-weight: bold">基础信息:</h3>
+          <!-- 店铺名称 -->
+          <div class="detail-item">
+            <div class="detail-label">店铺名称</div>
+            <div class="detail-value">
+              {{ couponModel.storeName || "--" }}
+            </div>
+          </div>
+          <!-- 优惠券名称 -->
+          <div class="detail-item">
+            <div class="detail-label">优惠券名称</div>
+            <div class="detail-value">
+              {{ couponModel.couponName || "--" }}
+            </div>
+          </div>
+          <!-- 面值 -->
+          <div class="detail-item">
+            <div class="detail-label">面值(元)</div>
+            <div class="detail-value">
+              {{ formatCurrency(couponModel.nominalValue, 2, "¥") }}
+            </div>
+          </div>
+          <!-- 有效期至 -->
+          <div class="detail-item">
+            <div class="detail-label">有效期至</div>
+            <div class="detail-value">
+              {{ couponModel.endDate ? formatDate(couponModel.endDate) : "--" }}
+            </div>
+          </div>
+          <!-- 优惠券数量 -->
+          <div class="detail-item">
+            <div class="detail-label">优惠券数量</div>
+            <div class="detail-value">
+              {{ couponModel.couponNum || "--" }}
+            </div>
+          </div>
+          <!-- 最低消费金额 -->
+          <div class="detail-item">
+            <div class="detail-label">最低消费金额</div>
+            <div class="detail-value">
+              {{ formatCurrency(couponModel.minimumSpendingAmount, 2, "¥") }}
+            </div>
+          </div>
+        </div>
+        <!-- 好友信息模块 -->
+        <div class="model">
+          <h3 style="font-weight: bold">好友信息:</h3>
+          <!-- 好友名称 -->
+          <div class="detail-item">
+            <div class="detail-label">
+              {{ type === "friendMessage" ? "赠送人" : "接收人" }}
+            </div>
+            <div class="detail-value">
+              {{ couponModel.acName || "--" }}
+            </div>
+          </div>
+          <!-- 状态 -->
+          <div class="detail-item" v-if="type === 'myGift' && couponModel.status !== undefined">
+            <div class="detail-label">状态</div>
+            <div class="detail-value">
+              {{ getStatusText() }}
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 右侧内容区域 -->
+      <div class="contentRight">
+        <!-- 优惠券详细列表 -->
+        <div
+          class="model"
+          v-if="couponModel.lifeDiscountCouponFriendRuleDetailVos && couponModel.lifeDiscountCouponFriendRuleDetailVos.length > 0"
+        >
+          <h3 style="font-weight: bold">优惠券详细列表:</h3>
+          <div v-for="(detail, index) in couponModel.lifeDiscountCouponFriendRuleDetailVos" :key="index" class="detail-card">
+            <div class="detail-item">
+              <div class="detail-label">店铺名称</div>
+              <div class="detail-value">
+                {{ detail.storeName || "--" }}
+              </div>
+            </div>
+            <div class="detail-item">
+              <div class="detail-label">优惠券名称</div>
+              <div class="detail-value">
+                {{ detail.couponName || "--" }}
+              </div>
+            </div>
+            <div class="detail-item">
+              <div class="detail-label">优惠券数量</div>
+              <div class="detail-value">
+                {{ detail.couponNum || "--" }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="tsx" name="friendCouponDetail">
+/**
+ * 好友优惠券 - 详情页面
+ * 功能:显示好友优惠券的详细信息
+ */
+import { ref, onMounted } from "vue";
+import { useRouter, useRoute } from "vue-router";
+import { ElMessage } from "element-plus";
+import { getFriendCouponList } from "@/api/modules/friendCoupon";
+import { formatCurrency } from "@/utils/formatCurrency";
+import { localGet } from "@/utils";
+
+// ==================== 响应式数据定义 ====================
+
+// 路由相关
+const router = useRouter();
+const route = useRoute();
+
+// 页面ID参数
+const id = ref<string>("");
+
+// 优惠券类型(好友赠我 friendMessage / 我赠好友 myGift)
+const type = ref<string>("");
+
+// ==================== 优惠券信息数据模型 ====================
+const couponModel = ref<any>({
+  // 账户名称(赠送人/接收人)
+  acName: "",
+  // 优惠券名称
+  couponName: "",
+  // 优惠券数量
+  couponNum: 0,
+  // 删除标志
+  deleteFlag: 0,
+  // 结束日期
+  endDate: "",
+  // ID
+  id: 0,
+  // 图片URL
+  imgUrl: "",
+  // 详细列表
+  lifeDiscountCouponFriendRuleDetailVos: [],
+  // 最低消费金额
+  minimumSpendingAmount: 0,
+  // 金额上限
+  moneyHigh: 0,
+  // 金额下限
+  moneyLow: 0,
+  // 面值
+  nominalValue: 0,
+  // 状态
+  status: "",
+  // 店铺ID
+  storeId: 0,
+  // 店铺名称
+  storeName: ""
+});
+
+// ==================== 生命周期钩子 ====================
+
+/**
+ * 组件挂载时初始化
+ * 从路由参数中获取ID并加载详情数据
+ */
+onMounted(async () => {
+  id.value = (route.query.id as string) || "";
+  type.value = (route.query.type as string) || "";
+  if (id.value) {
+    await loadDetailData();
+  } else {
+    ElMessage.warning("缺少优惠券ID参数");
+  }
+});
+
+// ==================== 事件处理函数 ====================
+
+/**
+ * 返回上一页
+ */
+const goBack = () => {
+  router.go(-1);
+};
+
+// ==================== 数据加载函数 ====================
+
+/**
+ * 加载详情数据
+ */
+const loadDetailData = async () => {
+  try {
+    // 临时方案:使用列表接口获取数据后根据ID筛选
+    // TODO: 如果后端提供了单独的详情接口,可以替换这里的实现
+    const res: any = await getFriendCouponList({
+      type: type.value === "friendMessage" ? 0 : 1,
+      storeId: localGet("createdId") || ""
+    });
+
+    if (res && res.code === 0 && res.success) {
+      // 从列表中找到对应的数据
+      const detail = res.data?.find((item: any) => item.id === Number(id.value));
+      if (detail) {
+        couponModel.value = { ...couponModel.value, ...detail };
+      } else {
+        ElMessage.error("未找到对应的优惠券详情");
+      }
+    } else {
+      ElMessage.error("加载详情数据失败");
+    }
+  } catch (error) {
+    console.error("加载详情数据出错:", error);
+    ElMessage.error("加载详情数据出错");
+  }
+};
+
+// ==================== 工具函数 ====================
+
+/**
+ * 格式化日期
+ * @param date 日期字符串 (YYYY-MM-DD)
+ * @returns 格式化后的日期字符串 (YYYY/MM/DD)
+ */
+const formatDate = (date: string) => {
+  if (!date) return "--";
+  return date.replace(/-/g, "/");
+};
+
+/**
+ * 获取状态文本
+ */
+const getStatusText = () => {
+  const statusMap: Record<string, string> = {
+    "0": "未使用",
+    "1": "已使用",
+    "2": "已过期"
+  };
+  return statusMap[couponModel.value.status] || "--";
+};
+</script>
+
+<style scoped lang="scss">
+/* 页面容器 */
+.table-box {
+  display: flex;
+  flex-direction: column;
+  height: auto !important;
+  min-height: 100%;
+}
+
+/* 头部区域 */
+.header {
+  display: flex;
+  align-items: center;
+  padding: 20px 24px;
+  background-color: #ffffff;
+  border-bottom: 1px solid #e4e7ed;
+  box-shadow: 0 2px 4px rgb(0 0 0 / 2%);
+}
+.title {
+  flex: 1;
+  margin: 0;
+  font-size: 18px;
+  font-weight: 600;
+  color: #303133;
+  text-align: center;
+}
+
+/* 内容区域布局 */
+.content {
+  display: flex;
+  flex: 1;
+  column-gap: 24px;
+  width: 98%;
+  padding: 0 12px;
+  margin: 24px auto;
+
+  /* 左侧内容区域 */
+  .contentLeft {
+    width: 50%;
+    padding-right: 12px;
+  }
+
+  /* 右侧内容区域 */
+  .contentRight {
+    width: 50%;
+    padding-left: 12px;
+  }
+}
+
+/* 模块容器 */
+.model {
+  margin-bottom: 50px;
+  h3 {
+    padding-bottom: 12px;
+    margin: 0 0 20px;
+    font-size: 16px;
+    color: #303133;
+    border-bottom: 2px solid #e4e7ed;
+  }
+}
+
+/* 详情项样式 */
+.detail-item {
+  display: flex;
+  align-items: flex-start;
+  min-height: 32px;
+  margin-bottom: 24px;
+}
+.detail-label {
+  flex-shrink: 0;
+  min-width: 200px;
+  font-size: 14px;
+  font-weight: 500;
+  line-height: 32px;
+  color: #606266;
+}
+.detail-value {
+  flex: 1;
+  font-size: 14px;
+  line-height: 32px;
+  color: #303133;
+  word-break: break-word;
+}
+.empty-text {
+  color: #909399;
+}
+
+/* 详情卡片样式 */
+.detail-card {
+  padding: 16px;
+  margin-bottom: 16px;
+  background-color: #f5f7fa;
+  border: 1px solid #e4e7ed;
+  border-radius: 4px;
+}
+</style>