|
|
@@ -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>
|