Ver código fonte

feat(activity): 新增活动中心及积分兑换功能

- 新增积分兑换弹窗IntegralPopup组件,封装积分兑换相关UI和逻辑
- 重构加油详情页,替换积分兑换弹窗为IntegralPopup组件使用
- 新增活动中心列表页和活动详情页,实现活动浏览和领取功能
- 修改路由配置,添加活动中心及详情页面路径
- 首页活动入口加跳转,方便用户进入活动中心查看
- 更新类型定义,新增IntegralPopup和相关UniPages路径声明
zhangtao 1 semana atrás
pai
commit
1befa0336e

+ 4 - 0
src/components.d.ts

@@ -12,14 +12,18 @@ declare module 'vue' {
     GlobalLoading: typeof import('./components/GlobalLoading.vue')['default']
     GlobalMessage: typeof import('./components/GlobalMessage.vue')['default']
     GlobalToast: typeof import('./components/GlobalToast.vue')['default']
+    IntegralPopup: typeof import('./components/integralPopup.vue')['default']
     PrivacyPopup: typeof import('./components/PrivacyPopup.vue')['default']
     WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
     WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
     WdGap: typeof import('wot-design-uni/components/wd-gap/wd-gap.vue')['default']
     WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
     WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default']
+    WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default']
     WdNotify: typeof import('wot-design-uni/components/wd-notify/wd-notify.vue')['default']
     WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default']
+    WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
+    WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
     WdSticky: typeof import('wot-design-uni/components/wd-sticky/wd-sticky.vue')['default']
     WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
     WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']

+ 78 - 0
src/components/integralPopup.vue

@@ -0,0 +1,78 @@
+<script setup lang="ts">
+const show = defineModel({ default: false })
+</script>
+
+<template>
+  <Zpopup v-model="show" bg="#fff">
+    <view class="px24rpx py28rpx">
+      <view class="text-center text-32rpx font-semibold">
+        积分兑换
+      </view>
+      <view class="mt20rpx flex items-center">
+        <view class="jf-box mr16rpx flex-shrink-0 rounded-16rpx p20rpx">
+          <view class="text-center text-48rpx text-#FF4D3A font-semibold">
+            ¥ 50
+          </view>
+          <view class="my8rpx text-center">
+            满20元可用
+          </view>
+        </view>
+        <view class="ml20rpx">
+          <view class="text-32rpx font-semibold">
+            兑换需50积分
+          </view>
+          <view class="text-#aaa">
+            <view class="mt10rpx">
+              已兑换:232/1000
+            </view>
+            <view class="mt10rpx">
+              兑换期截至:2026-07-06 23:59:59
+            </view>
+            <view class="mt10rpx">
+              使用有效期:兑换后15天有效
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+      <view class="text-28rpx font-semibold">
+        使用规则:
+      </view>
+      <view class="text-#aaa">
+        <view class="mt20rpx">
+          ·订单满20元可用
+        </view>
+        <view class="mt20rpx">
+          ·每单限用1张,不与其他优惠同享
+        </view>
+        <view class="mt20rpx">
+          ·兑换成功后,不可再逆兑换成积分
+        </view>
+      </view>
+      <view class="mt24rpx text-28rpx font-semibold">
+        适用油站:
+      </view>
+      <view class="text-#aaa">
+        <view class="mt20rpx flex items-center">
+          <wd-icon name="check-circle-filled" size="30rpx" color="#52C41A" class="mr10rpx" /> 全部合作油站
+        </view>
+        <view class="mt20rpx flex items-center">
+          <wd-icon name="close-circle-filled" size="30rpx" color="#FF4A39" class="mr10rpx" /> 部分特殊油站不可用
+        </view>
+      </view>
+    </view>
+    <FixedLayout>
+      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
+      <view class="box-border w-full flex items-center justify-end gap20rpx px24rpx">
+        <wd-button type="info" @click="show = false">
+          取消
+        </wd-button>
+        <wd-button>确认兑换</wd-button>
+      </view>
+    </FixedLayout>
+  </Zpopup>
+</template>
+
+<style scoped>
+
+</style>

+ 18 - 0
src/pages.json

@@ -9,6 +9,24 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/activityCenter/index",
+      "name": "activityCenter-detail",
+      "islogin": true,
+      "style": {
+        "navigationBarTitleText": "活动详情",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/activityList/index",
+      "name": "activityList",
+      "islogin": true,
+      "style": {
+        "navigationBarTitleText": "活动中心",
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/confirmOrder/index",
       "name": "confimOrder",

+ 126 - 0
src/pages/activityCenter/index.vue

@@ -0,0 +1,126 @@
+<script setup lang="ts">
+definePage({
+  name: 'activityCenter-detail',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '活动详情',
+    navigationStyle: 'custom',
+  },
+})
+
+// 活动数据
+const activityInfo = ref({
+  title: '企业用户专享礼包',
+  discount: '抵扣15元(满100元可用)',
+  status: '进行中',
+  activityId: 'SDIE-DLEIJ-31095',
+  stock: 168,
+})
+const staticUrl = import.meta.env.VITE_STATIC_BASE_URL
+// 活动规则
+const rules = ref([
+  {
+    title: '1.抵扣券',
+    items: ['抵扣15元(满100元可用)'],
+  },
+  {
+    title: '2.使用限制',
+    items: ['每单限用1张', '不可与其他优惠同享'],
+  },
+  {
+    title: '3.使用油站',
+    items: ['全部合作油站', '部分油站不可用'],
+  },
+  {
+    title: '4.有效期',
+    items: ['领取后7天内有效'],
+  },
+])
+
+// 领取活动
+function handleClaim() {
+  // TODO: 调用领取接口
+  useGlobalToast().show('领取成功')
+}
+</script>
+
+<template>
+  <view class="activity-page pt20rpx">
+    <!-- 活动卡片 -->
+    <view class="mx24rpx overflow-hidden rounded-16rpx">
+      <view class="pages-bg flex items-center justify-between px24rpx py28rpx">
+        <view>
+          <view class="text-32rpx text-#333 font-semibold">
+            {{ activityInfo.title }}
+          </view>
+          <view class="mt12rpx text-28rpx">
+            {{ activityInfo.discount }}
+          </view>
+        </view>
+        <image
+          :src="`${staticUrl}/smqjh-jy-center.png`"
+          class="h156rpx w156rpx"
+        />
+      </view>
+    </view>
+
+    <!-- 活动状态信息 -->
+    <view class="mx24rpx mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+      <view class="flex items-center text-28rpx">
+        <view class="text-#666">
+          活动状态:
+        </view>
+        <view class="text-#333">
+          {{ activityInfo.status }}
+        </view>
+      </view>
+      <view class="mt20rpx flex items-center text-28rpx">
+        <view class="text-#666">
+          活动ID:
+        </view>
+        <view class="text-#333">
+          {{ activityInfo.activityId }}
+        </view>
+      </view>
+      <view class="mt20rpx flex items-center text-28rpx">
+        <view class="text-#666">
+          剩余库存:
+        </view>
+        <view class="text-#333">
+          {{ activityInfo.stock }}张
+        </view>
+      </view>
+    </view>
+
+    <!-- 活动规则 -->
+    <view class="mx24rpx mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
+      <view class="text-32rpx text-#333 font-semibold">
+        活动规则
+      </view>
+      <view v-for="(rule, index) in rules" :key="index" class="mt24rpx">
+        <view class="text-28rpx text-#333 font-medium">
+          {{ rule.title }}
+        </view>
+        <view v-for="(item, idx) in rule.items" :key="idx" class="mt12rpx text-26rpx text-#666">
+          · {{ item }}
+        </view>
+      </view>
+    </view>
+
+    <!-- 底部占位 -->
+    <view class="h200rpx" />
+  </view>
+
+  <!-- 底部固定按钮 -->
+  <FixedLayout>
+    <wd-button block size="large" @click="handleClaim">
+      立即领取
+    </wd-button>
+  </FixedLayout>
+</template>
+
+<style lang="scss" scoped>
+.pages-bg{
+  background: linear-gradient( 180deg, #FFDCDC 0%, #FFFFFF 100%);
+}
+</style>

+ 135 - 0
src/pages/activityList/index.vue

@@ -0,0 +1,135 @@
+<script setup lang="ts">
+import router from '@/router'
+
+definePage({
+  name: 'activityList',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '活动中心',
+    navigationStyle: 'custom',
+  },
+})
+
+const staticUrl = import.meta.env.VITE_STATIC_BASE_URL
+
+// 活动列表数据
+const activityList = ref([
+  {
+    id: 1,
+    title: '企业用户专享礼包',
+    discount: '抵扣15元(满100元可用)',
+    validity: '领取后7天有效',
+    claimed: 832,
+    total: 1000,
+    status: 'unclaimed', // unclaimed: 未领取, claimed: 已领取
+    expireDate: '',
+  },
+  {
+    id: 2,
+    title: '企业用户专享礼包',
+    discount: '抵扣25元(满150元可用)',
+    validity: '',
+    claimed: 0,
+    total: 0,
+    status: 'claimed',
+    expireDate: '2024-12-13 11:12:30',
+  },
+])
+
+// 积分兑换
+function handleExchange(_item: any) {
+  // TODO: 调用积分兑换接口
+  useGlobalToast().show('兑换成功')
+}
+
+// 查看详情
+function handleViewDetail(item: any) {
+  router.push({
+    name: 'activityCenter-detail',
+    params: { id: item.id },
+  })
+}
+</script>
+
+<template>
+  <view class="activity-list-page px24rpx pt20rpx">
+    <!-- 活动卡片列表 -->
+    <view
+      v-for="item in activityList"
+      :key="item.id"
+      class="activity-card mb24rpx overflow-hidden rounded-16rpx bg-white"
+    >
+      <view class="page-box flex flex-1 items-start justify-between px24rpx py28rpx">
+        <view class="flex-1">
+          <!-- 标题 -->
+          <view class="text-32rpx font-semibold">
+            {{ item.title }}
+          </view>
+          <!-- 抵扣信息 -->
+          <view class="mt16rpx text-28rpx text-#333">
+            {{ item.discount }}
+          </view>
+          <!-- 有效期 -->
+          <view v-if="item.validity" class="mt12rpx text-26rpx text-#666">
+            有效期:{{ item.validity }}
+          </view>
+          <view v-if="item.expireDate" class="mt12rpx text-26rpx text-#666">
+            有效期:{{ item.expireDate }}
+          </view>
+          <!-- 已领取数量 -->
+          <view v-if="item.status === 'unclaimed'" class="mt12rpx text-26rpx text-#666">
+            已领取:{{ item.claimed }}/{{ item.total }}
+          </view>
+          <!-- 状态 -->
+          <view v-if="item.status === 'claimed'" class="mt12rpx text-26rpx text-#666">
+            状态:已领取
+          </view>
+        </view>
+
+        <!-- 右侧礼包图片 -->
+        <image
+          :src="`${staticUrl}/smqjh-jy-center.png`"
+          class="ml20rpx h212rpx w212rpx flex-shrink-0"
+        />
+      </view>
+
+      <!-- 底部按钮 -->
+      <view class="flex justify-center pb28rpx">
+        <wd-button
+          v-if="item.status === 'unclaimed'"
+          size="small"
+          custom-class="exchange-btn"
+          @click="handleExchange(item)"
+        >
+          积分兑换
+        </wd-button>
+        <wd-button
+          v-else
+          size="small"
+          plain
+          custom-class="detail-btn"
+          @click="handleViewDetail(item)"
+        >
+          查看详情
+        </wd-button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+:deep(.exchange-btn) {
+  min-width: 180rpx !important;
+  border-radius: 32rpx !important;
+}
+
+:deep(.detail-btn) {
+  min-width: 180rpx !important;
+  border-radius: 32rpx !important;
+  border-color: var(--them-color) !important;
+  color: var(--them-color) !important;
+}
+.page-box{
+  background: linear-gradient( 180deg, #FFDCDC 0%, #FFF8F8 36.01%, #FFFFFF 100%);
+}
+</style>

+ 1 - 0
src/pages/index/index.vue

@@ -75,6 +75,7 @@ function handleView(_item: any) {
     <image
       :src="`${staticUrl}/smqjh-jy-dkj.png`"
       class="fixed bottom-524rpx right-24rpx h114rpx w124rpx"
+      @click="router.push({ name: 'activityList' })"
     />
   </view>
 </template>

+ 1 - 68
src/pages/refuelDetaile/index.vue

@@ -98,74 +98,7 @@ const showModel = ref(false)
       立即加油
     </wd-button>
   </FixedLayout>
-  <Zpopup v-model="showModel" bg="#fff">
-    <view class="px24rpx py28rpx">
-      <view class="text-center text-32rpx font-semibold">
-        积分兑换
-      </view>
-      <view class="mt20rpx flex items-center">
-        <view class="jf-box mr16rpx flex-shrink-0 rounded-16rpx p20rpx">
-          <view class="text-center text-48rpx text-#FF4D3A font-semibold">
-            ¥ 50
-          </view>
-          <view class="my8rpx text-center">
-            满20元可用
-          </view>
-        </view>
-        <view class="ml20rpx">
-          <view class="text-32rpx font-semibold">
-            兑换需50积分
-          </view>
-          <view class="text-#aaa">
-            <view class="mt10rpx">
-              已兑换:232/1000
-            </view>
-            <view class="mt10rpx">
-              兑换期截至:2026-07-06 23:59:59
-            </view>
-            <view class="mt10rpx">
-              使用有效期:兑换后15天有效
-            </view>
-          </view>
-        </view>
-      </view>
-      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-      <view class="text-28rpx font-semibold">
-        使用规则:
-      </view>
-      <view class="text-#aaa">
-        <view class="mt20rpx">
-          ·订单满20元可用
-        </view>
-        <view class="mt20rpx">
-          ·每单限用1张,不与其他优惠同享
-        </view>
-        <view class="mt20rpx">
-          ·兑换成功后,不可再逆兑换成积分
-        </view>
-      </view>
-      <view class="mt24rpx text-28rpx font-semibold">
-        适用油站:
-      </view>
-      <view class="text-#aaa">
-        <view class="mt20rpx flex items-center">
-          <wd-icon name="check-circle-filled" size="30rpx" color="#52C41A" class="mr10rpx" /> 全部合作油站
-        </view>
-        <view class="mt20rpx flex items-center">
-          <wd-icon name="close-circle-filled" size="30rpx" color="#FF4A39" class="mr10rpx" /> 部分特殊油站不可用
-        </view>
-      </view>
-    </view>
-    <FixedLayout>
-      <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
-      <view class="box-border w-full flex items-center justify-end gap20rpx px24rpx">
-        <wd-button type="info" @click="showModel = false">
-          取消
-        </wd-button>
-        <wd-button>确认兑换</wd-button>
-      </view>
-    </FixedLayout>
-  </Zpopup>
+  <IntegralPopup v-model="showModel" />
 </template>
 
 <style lang="scss" scoped>

+ 3 - 1
src/uni-pages.d.ts

@@ -4,7 +4,9 @@
 // Generated by @uni-ku/pages-json
 
 interface NavigateToOptions {
-  url: "/pages/confirmOrder/index" |
+  url: "/pages/activityCenter/index" |
+       "/pages/activityList/index" |
+       "/pages/confirmOrder/index" |
        "/pages/login/index" |
        "/pages/refuelDetaile/index";
 }