5
0

19 Коммитууд c7920b411f ... f1f66c8f15

Эзэн SHA1 Мессеж Огноо
  hsy f1f66c8f15 f 3 сар өмнө
  hsy cfe1b36506 f 3 сар өмнө
  hsy 2e094f0853 f 3 сар өмнө
  hsy f1756fae1d f 3 сар өмнө
  hsy 2f7fc23bb5 fix 3 сар өмнө
  hsy 6d400889b4 fix 3 сар өмнө
  hsy 47736553a7 fix 3 сар өмнө
  hsy c2b6236355 fix 3 сар өмнө
  hsy 83c3bd5668 fix 3 сар өмнө
  hsy 0a921b8ac8 fix 3 сар өмнө
  hsy 341dd8ed76 fix 3 сар өмнө
  hsy ffe9658cec fix 3 сар өмнө
  hsy 920961b13e f 3 сар өмнө
  hsy a48109e9dc f 3 сар өмнө
  hsy 274ca4cef8 f 3 сар өмнө
  hsy 463036e00b f 3 сар өмнө
  hsy 01b2065391 f 3 сар өмнө
  hsy 9663b44db7 f 3 сар өмнө
  hsy 93af2fc74d f 3 сар өмнө

+ 1 - 1
.env.development

@@ -2,7 +2,7 @@
 VITE_PORT = 9031
 
 # 开发环境读取配置文件路径
-VITE_PUBLIC_PATH = ./
+VITE_PUBLIC_PATH = /
 # 是否在打包时使用cdn替换本地库 替换 true 不替换 false
 VITE_CDN = false
 # 开发环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")

+ 1 - 1
.env.production

@@ -1,5 +1,5 @@
 # 线上环境平台打包路径
-VITE_PUBLIC_PATH = ./
+VITE_PUBLIC_PATH = /
 
 # 线上环境路由历史模式(Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数")
 VITE_ROUTER_HISTORY = "hash"

+ 1 - 1
build/index.ts

@@ -2,7 +2,7 @@
 const warpperEnv = (envConf: Recordable): ViteEnv => {
   /** 此处为默认值 */
   const ret: ViteEnv = {
-    VITE_PORT: 9009,
+    VITE_PORT: 9031,
     VITE_PUBLIC_PATH: "",
     VITE_ROUTER_HISTORY: "",
     VITE_CDN: false,

+ 0 - 2
index.html

@@ -10,8 +10,6 @@
   <title></title>
 
   <script src="//res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
-  <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.1.js"></script>
-
   <script>
     window.process = {};
 

+ 0 - 1
public/index.html

@@ -11,7 +11,6 @@
   <!-- <link rel="icon" href="/favicon.ico" /> -->
 
   <script src="//res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
-  <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.1.js"></script>
 
   <style>
     body {

BIN
src/assets/icon-link-error.png


+ 6 - 21
src/router/index.ts

@@ -25,7 +25,7 @@ Object.keys(modules).forEach((key) => {
 console.log(routes);
 
 const router = createRouter({
-  history: createWebHashHistory(),
+  history: createWebHistory('/'),
   routes,
   scrollBehavior(to, from, savedPosition) {
     return new Promise((resolve) => {
@@ -44,18 +44,18 @@ const router = createRouter({
 
 router.beforeEach((to: ToRouteType, _from, next) => {
   NProgress.start();
-  to.meta?.needService && appendCustomService();
   if (to.meta?.title) {
     document.title = to.meta?.title;
   }
+  console.log("before to", to);
   next();
 });
 
 router.afterEach((to) => {
-  if (to.params?.mechanismId) {
-    localStorage.setItem("mechanismId", to.params.mechanismId as string);
-  }
-  console.log("to", to.query);
+  // if (to.params?.mechanismId) {
+  //   localStorage.setItem("mechanismId", to.params.mechanismId as string);
+  // }
+  console.log("after to", to);
 
   if (to.query?.caringMode == "open") {
     handleChangeHtmlFontSize();
@@ -65,19 +65,4 @@ router.afterEach((to) => {
   NProgress.done();
 });
 
-const appendCustomService = () => {
-  const el = document.querySelector("#customService");
-  const a = document.createElement("a");
-  a.id = "customService";
-  a.href = "https://work.weixin.qq.com/kfid/kfca0513e081f5317d9";
-  a.style.position = "fixed";
-  a.style.bottom = "20%";
-  a.style.right = "20px";
-  a.innerHTML = `<svg t="1697164746002" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5127" width="48" height="48"><path d="M513 514m-425 0a425 425 0 1 0 850 0 425 425 0 1 0-850 0Z" fill="#DCEDFF" p-id="5128"></path><path d="M799.76 435.68q-4.23-13.43-9.74-26.48a297.57 297.57 0 0 0-548 0q-5.52 13.08-9.75 26.52a72.29 72.29 0 0 0-56.06 70.44v45.67a72.27 72.27 0 0 0 72.27 72.27 29 29 0 0 0 29-29v-140a21.21 21.21 0 0 0-12.69-19.42 266.8 266.8 0 0 1 502.58 0.07 21.21 21.21 0 0 0-12.54 19.35v140a29 29 0 0 0 29 29A72.27 72.27 0 0 0 856 551.83v-45.67a72.28 72.28 0 0 0-56.24-70.48z" fill="#88C4FF" p-id="5129"></path><path d="M516 297.94c-101.22 0-187 66.15-216.43 157.54v139.68c29.51 91.4 115.25 157.53 216.43 157.53h203.35a12.87 12.87 0 0 0 12.9-12.8l-43.48-66.72a226.43 226.43 0 0 0 43.62-77.71V455.24C702.85 364 617.17 297.94 516 297.94z" fill="#468EF7" p-id="5130"></path></svg>`;
-  if (el) {
-    el.remove();
-  } else {
-    document.body.appendChild(a);
-  }
-};
 export default router;

+ 0 - 1
src/router/modules/login.ts

@@ -13,5 +13,4 @@ export default [
       title: "",
     },
   },
-  
 ] as RouteConfigsTable[];

+ 10 - 0
src/router/modules/open.ts

@@ -0,0 +1,10 @@
+export default [
+  {
+    path: "/error",
+    name: "error",
+    component: () => import("@/views/open/error.vue"),
+    meta: {
+      title: '会员权益'
+    },
+  }
+] as RouteConfigsTable[];

+ 10 - 2
src/router/modules/promotion.ts

@@ -4,7 +4,15 @@ export default [
     name: "promotionGoods",
     component: () => import("@/views/promotion/goods.vue"),
     meta: {
-      title: '会员权益'
+      title: "会员权益",
     },
-  }
+  },
+  {
+    path: "/promotion/payResult",
+    name: "promotionPayResult",
+    component: () => import("@/views/promotion/payResult.vue"),
+    meta: {
+      title: "支付完成",
+    },
+  },
 ] as RouteConfigsTable[];

+ 1 - 0
src/views/entry.vue

@@ -13,6 +13,7 @@ console.log(route)
 //   localStorage.setItem('mechanismId', params.mechanismId)
 // }
 
+
 router.replace({
   name: 'promotionGoods',
   query: route.query

+ 26 - 0
src/views/open/error.vue

@@ -0,0 +1,26 @@
+<template>
+  <div class="h-screen flex items-center justify-center flex-col">
+    <img src="@/assets/icon-link-error.png" alt="" class="w-40">
+    <div class="text-xl mt-4 text-gray-600 whitespace-pre-wrap text-center">
+      <div v-html="msg"></div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, computed, watch } from 'vue';
+
+import { useRoute, useRouter } from 'vue-router';
+
+import { request } from '@/utils';
+
+const [route, router] = [useRoute(), useRouter()];
+const msg = ref(route.query.msg || '未知错误');
+document.title = '错误';
+
+</script>
+
+<style lang='scss' scoped>
+
+</style>
+

+ 4 - 28
src/views/promotion/components/PaymentDialog.vue

@@ -31,6 +31,7 @@
             v-model.trim="verificationCode"
             placeholder="请输入验证码"
             :border="false"
+            :maxlength="4"
             class="!bg-gray-100 rounded-lg flex-1"
           />
           <van-button
@@ -83,8 +84,8 @@ const props = defineProps({
 
 const emit = defineEmits(["update:show"]);
 
-const phone = ref("17612888982");
-const verificationCode = ref("8888");
+const phone = ref("");
+const verificationCode = ref("");
 const countdown = ref(0);
 const timer = ref(null);
 
@@ -126,38 +127,13 @@ const handleGetCode = async () => {
   // 这里添加获取验证码的逻辑
   showToast("验证码已发送");
 };
-const preCheck = async () => {
-  const { data } = await request.get(
-    `/archivesService/member/promotionGoods/preData`,
-    {
-      params: {
-        promotionGoodsId: route.query.promotionGoodsId,
-      },
-    }
-  );
-  return data;
-};
-
 const handleConfirm = async () => {
   if (!phone.value || !verificationCode.value) {
     showToast("请填写完整信息");
     return;
   }
-  const { appId, errMsg, paymentSettingId } = await preCheck();
-  if (errMsg) {
-    return showToast(errMsg);
-  }
-  if (appId) {
-    //缓存信息
-    localStorage.setItem("paymentSettingId", paymentSettingId);
-    //跳转微信授权
-
-    const redirectUri = encodeURIComponent(location.href);
-    location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=123#wechat_redirect`;
-    return;
-  }
 
-  // props.onConfirm?.();
+  props.onConfirm?.(phone.value, verificationCode.value);
 };
 </script>
 

+ 117 - 0
src/views/promotion/components/PaymentHistoryDialog.vue

@@ -0,0 +1,117 @@
+<template>
+  <van-popup
+    v-model:show="dialogVisible"
+    round
+    position="bottom"
+    :style="{ height: '80%' }"
+  >
+    <div class="p-4 flex flex-col h-full">
+      <!-- Header -->
+      <div class="flex justify-between items-center mb-4">
+        <div class="text-gray-400 cursor-pointer" @click="handleClose">取消</div>
+        <div class="text-lg font-medium">购买记录</div>
+        <div class="w-8"></div>
+      </div>
+
+<!-- Loading State -->
+      <van-loading v-if="loading" class="self-center my-8" />
+
+      <!-- Empty State -->
+      <van-empty v-else-if="!records.length" description="暂无购买记录" />
+
+      <!-- Records List -->
+      <div v-else class="flex-1 overflow-y-auto">
+        <div  v-for="(record, index) in records" :key="index" class="bg-gray-50 rounded-lg p-4 mb-4">
+          <div class="flex justify-between items-center mb-2">
+            <span class="text-gray-600">购买手机号:</span>
+            <span>{{ record.mobile }}</span>
+          </div>
+          <div class="flex justify-between items-center mb-2">
+            <span class="text-gray-600">支付时间:</span>
+            <span>{{ record.createdAt }}</span>
+          </div>
+          <div class="flex justify-between items-center mb-2">
+            <span class="text-gray-600">支付金额:</span>
+            <span class="text-red-500">¥{{ (record.balance / 100 ).toFixed(2) }}</span>
+          </div>
+          <div class="flex justify-between items-center">
+            <span class="text-gray-600">商品名称:</span>
+            <span>{{ record.promotionGoods?.memberCardName }}</span>
+          </div>
+        </div>
+        <div v-if="goodsDetail && goodsDetail.paidSlogan" v-html="goodsDetail.paidSlogan" class="p-2"></div>
+      </div>
+
+    </div>
+  </van-popup>
+</template>
+<script setup>
+import { ref, computed, watch, inject } from "vue";
+import { showToast } from "vant";
+import { useRoute, useRouter } from "vue-router";
+import { request } from "@/utils";
+
+const [route, router] = [useRoute(), useRouter()];
+const props = defineProps({
+  show: Boolean,
+  onClose: Function,
+  onConfirm: Function,
+  openId: String
+});
+
+const goodsDetail = inject('goodsDetail')
+// 使用computed处理show
+const dialogVisible = computed({
+  get: () => props.show,
+  set: (value) => emit("update:show", value),
+});
+
+const emit = defineEmits(["update:show"]);
+
+// 数据相关
+const loading = ref(false);
+const records = ref([]);
+
+// 处理关闭
+const handleClose = () => {
+  dialogVisible.value = false
+  props.onClose?.();
+};
+
+// 获取购买记录
+const fetchRecords = async () => {
+  try {
+    loading.value = true;
+    const { data } = await request.get(`/archivesService/member/promotionGoods/order/paginate`, {
+      params: {
+        openId: props.openId,
+        page: 1,
+        // size: 1,
+      }
+    });
+    records.value = data.list;
+  } finally {
+    loading.value = false;
+  }
+};
+
+watch(() => [dialogVisible.value, props.openId], () => {
+  if (dialogVisible.value && props.openId) {
+    fetchRecords()
+  }
+})
+</script>
+
+<style scoped>
+:deep(.van-field) {
+  background-color: #f5f5f5 !important;
+}
+
+:deep(.van-field__control) {
+  color: #333;
+}
+
+:deep(.van-popup) {
+  background-color: white;
+}
+</style>

+ 199 - 50
src/views/promotion/goods.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="min-h-screen w-full ">
+  <div class="min-h-screen w-full">
     <div class="relative overflow-hidden py-4 pb-10 bg-[#fdedc5]">
       <img
         src="https://oss.hhmdtech.com/merchant/RmW4frEmQRr99JJ4RJ5hwdZR8FYDhTe8PKn6inRBijRJMRcA.png"
@@ -8,75 +8,85 @@
       />
       <div class="relative">
         <div class="h-full w-full overflow-hidden px-4">
-            <div
-              class="flex h-full w-full rounded bg-[#ffc72f] transition-all duration-150"
-            >
-              <div class="flex-1 p-4">
-                <div
-                  class="mb-2 max-w-[8em] truncate whitespace-nowrap text-2xl"
-                >
-                  {{ goodsDetail.memberCardName }}
-                </div>
-                <div v-if="goodsDetail?.originPrice" class="text-gray-500 line-through">
-                  <span>¥</span>
-                  <span>
-                    {{ parseFloat((goodsDetail?.originPrice / 100).toFixed(2)) }}
-                  </span>
-                  <span>/{{ goodsDetail.memberCard?.lifespan }}天</span>
-                </div>
-                <div :class="goodsDetail?.originPrice ? 'pb-3' : 'py-3'">
-                  <span>¥</span>
-                  <span class="text-2xl">
-                    {{ parseFloat((goodsDetail.memberCard?.price / 100).toFixed(2)) }}
-                  </span>
-                  <span>/{{ goodsDetail.memberCard?.lifespan }}天</span>
-                </div>
-                <div class="text-base text-gray-500">{{ goodsDetail.title }}</div>
+          <div
+            class="flex h-full w-full rounded bg-[#ffc72f] transition-all duration-150"
+          >
+            <div class="flex-1 p-4">
+              <div class="mb-2 max-w-[8em] truncate whitespace-nowrap text-2xl">
+                {{ goodsDetail.memberCardName }}
               </div>
-              <img
-                src="@/assets/icon-vip.png"
-                class="m-4 h-12 w-12"
-              />
+              <div
+                v-if="goodsDetail?.originPrice"
+                class="text-gray-500 line-through"
+              >
+                <span>¥</span>
+                <span>
+                  {{ parseFloat((goodsDetail?.originPrice / 100).toFixed(2)) }}
+                </span>
+                <span>/{{ goodsDetail.memberCard?.lifespan }}天</span>
+              </div>
+              <div :class="goodsDetail?.originPrice ? 'pb-3' : 'py-3'">
+                <span>¥</span>
+                <span class="text-2xl">
+                  {{ parseFloat((goodsDetail?.price / 100).toFixed(2)) }}
+                </span>
+                <span>/{{ goodsDetail.memberCard?.lifespan }}天</span>
+              </div>
+              <div class="text-base text-gray-500">{{ goodsDetail.title }}</div>
             </div>
+            <img src="@/assets/icon-vip.png" class="m-4 h-12 w-12" />
+          </div>
         </div>
       </div>
     </div>
     <div class="relative -top-6 rounded rounded-t-2xl bg-white z-10">
       <div class="p-4 pb-20">
-        <div class="" v-html="goodsDetail.memberCard?.content"></div>
+        <div class="" v-html="goodsDetail.saleSlogan"></div>
       </div>
     </div>
 
-    <div class="z-[2000] fixed bottom-6 left-0 flex w-full items-center justify-center">
+    <div
+      class="z-[2000] fixed bottom-6 left-0 flex w-full items-center justify-center"
+    >
       <div
-        class=" flex w-10/12 items-center justify-center overflow-hidden rounded-xl bg-[#2c2c2c]">
+        class="flex w-10/12 items-center justify-center overflow-hidden rounded-xl bg-[#2c2c2c]"
+      >
         <button
           class="flex-1 whitespace-nowrap border-0 bg-[#2c2c2c] p-4 text-sm text-[#e59223] after:hidden"
-          @click="buy">
-
+          @click="buyHistory"
+        >
+          <span class="text-base">购买记录</span>
+        </button>
+        <div class="h-5 w-px bg-[#e59223]"></div>
+        <button
+          class="flex-1 whitespace-nowrap border-0 bg-[#2c2c2c] p-4 text-sm text-[#e59223] after:hidden"
+          @click="buy"
+        >
           <span class="text-base">立即购买</span>
         </button>
-
       </div>
     </div>
     <PaymentDialog
-      :show="showDialog"
+      v-model:show="showDialog"
       :onClose="handleClose"
       :onConfirm="handleConfirm"
     />
+    <PaymentHistoryDialog v-model:show="showHistory" :openId="openId" />
   </div>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, computed, watch } from "vue";
+import { ref, reactive, onMounted, computed, watch, provide } from "vue";
 
-import PaymentDialog from './components/PaymentDialog.vue'
+import PaymentDialog from "./components/PaymentDialog.vue";
+import PaymentHistoryDialog from "./components/PaymentHistoryDialog.vue";
 import { useRoute, useRouter } from "vue-router";
 
 import { request } from "@/utils";
 
 const [route, router] = [useRoute(), useRouter()];
-const goodsDetail = ref({})
+const goodsDetail = ref({});
+provide("goodsDetail", goodsDetail);
 const getGoodsDetail = async () => {
   const { data } = await request.get(
     `archivesService/member/promotionGoods/detail`,
@@ -86,24 +96,163 @@ const getGoodsDetail = async () => {
       },
     }
   );
-  goodsDetail.value = data.detail
+  goodsDetail.value = data.detail;
 };
 getGoodsDetail();
 
-
-const showDialog = ref(false)
+const showDialog = ref(false);
 
 const handleClose = () => {
-  showDialog.value = false
-}
-
-const handleConfirm = () => {
-  console.log('Payment confirmed')
-  showDialog.value = false
+  showDialog.value = false;
+};
+function onBridgeReady(paySign) {
+  if (!WeixinJSBridge) {
+    return showToast("请在微信浏览器中打开");
+  }
+  WeixinJSBridge.invoke(
+    "getBrandWCPayRequest",
+    {
+      appId: appId.value, //公众号ID,由商户传入
+      ...paySign,
+    },
+    function (res) {
+      console.log(res);
+      if (res.err_msg == "get_brand_wcpay_request:ok") {
+        // 使用以上方式判断前端返回,微信团队郑重提示:
+        //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠,商户需进一步调用后端查单确认支付结果。
+        console.log("支付成功");
+        router.push({
+          name: "promotionPayResult",
+          query: {
+            promotionGoodsId: route.query.promotionGoodsId,
+            promotionSiteId: route.query.promotionSiteId,
+          },
+        });
+      } else {
+        showToast("支付失败" + res.err_msg);
+      }
+    }
+  );
 }
+const handleConfirm = async (mobile, captcha) => {
+  console.log("Payment confirmed");
+  showDialog.value = false;
+  const { data } = await request.post(
+    `/archivesService/member/promotionGoods/paymentParams`,
+    {
+      promotionGoodsId: route.query.promotionGoodsId,
+      promotionSiteId: route.query.promotionSiteId,
+      mobile,
+      captcha,
+      openId: openId.value,
+    }
+  );
+  console.log(data.paymentParams);
+  data.paymentParams?.paySign && onBridgeReady(data.paymentParams.paySign);
+};
+const showHistory = ref(false);
+const buyHistory = () => {
+  showHistory.value = true;
+};
 const buy = () => {
-  showDialog.value = true
-}
+  showDialog.value = true;
+};
+
+const preCheck = async () => {
+  const { data } = await request.get(
+    `/archivesService/member/promotionGoods/preData`,
+    {
+      params: {
+        promotionGoodsId: route.query.promotionGoodsId,
+        promotionSiteId: route.query.promotionSiteId,
+      },
+    }
+  );
+  return data;
+};
+// const jsSdkConfig = async () => {
+//   const { data } = await request.post(
+//     "archivesService/member/promotionGoods/getJssdk",
+//     {
+//       url: location.href,
+//       promotionGoodsId: route.query.promotionGoodsId,
+//     }
+//   );
+//   return data;
+// };
+// const wxConfig = async () => {
+//   const { data } = await jsSdkConfig();
+//   window["wx"]?.config?.(data.config);
+//   window["wx"]?.error((res) => {
+//     console.log(res);
+//   });
+// };
+const appId = ref(sessionStorage.getItem("appId"));
+// const openId = ref("KfZnJNKFaFXWWCagSlX0dT4tNkwsLEwQVlrzpHvo");
+const openId = ref("");
+const getWeChatAuth = async () => {
+  const { appId, errMsg, paymentSettingId } = await preCheck();
+  if (errMsg) {
+    // return showToast(errMsg);
+    router.push({
+      name: "error",
+      query: {
+        msg: errMsg,
+      },
+    });
+    return;
+  }
+  if (appId) {
+    //缓存信息
+    sessionStorage.setItem("appId", appId);
+    sessionStorage.setItem("paymentSettingId", paymentSettingId);
+    //跳转微信授权
+
+    const redirectUri = encodeURIComponent(location.href);
+    location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=123#wechat_redirect`;
+    return;
+  }
+  showToast("微信配置不存在");
+};
+const getOpenId = async () => {
+  const { code } = route.query;
+  const paymentSettingId = sessionStorage.getItem("paymentSettingId");
+  if (!code) {
+    return;
+  }
+  const { data } = await request.get(
+    `archivesService/member/promotionGoods/getOpenId`,
+    {
+      params: {
+        code,
+        paymentSettingId,
+      },
+    }
+  );
+  if (data.openId) {
+    openId.value = data.openId;
+  } else {
+    showToast("获取openId失败");
+  }
+};
+const init = async () => {
+  const { code, promotionGoodsId, promotionSiteId } = route.query;
+  if (!promotionSiteId || !promotionGoodsId) {
+    return router.push({
+      name: "error",
+      query: {
+        msg: "参数异常",
+      },
+    });
+  }
+  const paymentSettingId = sessionStorage.getItem("paymentSettingId");
+  if (!code || !paymentSettingId) {
+    return getWeChatAuth();
+  }
+  getOpenId()
+  // wxConfig();
+};
+onMounted(() => init());
 </script>
 
 <style lang="scss" scoped></style>

+ 39 - 0
src/views/promotion/payResult.vue

@@ -0,0 +1,39 @@
+<template>
+  <div>
+
+    <div class="flex items-center justify-center py-16">
+      <van-icon name="checked" class="text-[64px] text-green-500 mr-2" />
+      <span class="text-2xl font-bold text-green-600">购买成功!</span>
+    </div>
+    <div class="p-2">
+      <div v-html="goodsDetail.paidSlogan"></div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, computed, watch } from 'vue';
+
+import { useRoute, useRouter } from 'vue-router';
+
+import { request } from '@/utils';
+
+const [route, router] = [useRoute(), useRouter()];
+const goodsDetail = ref({});
+const getGoodsDetail = async () => {
+  const { data } = await request.get(
+    `archivesService/member/promotionGoods/detail`,
+    {
+      params: {
+        promotionGoodsId: route.query.promotionGoodsId,
+      },
+    }
+  );
+  goodsDetail.value = data.detail;
+};
+getGoodsDetail();
+</script>
+
+<style lang='scss' scoped>
+
+</style>