Kaynağa Gözat

```
feat: 添加会员功能相关API定义和类型声明

- 新增 userMemberInfo 接口定义,包含会员权益配置、生效时间、到期时间等字段
- 新增 MemberBenefitRecordVO 接口定义,用于会员权益发放记录
- 新增 giftsListModel 接口定义,用于会员自选赠品信息
- 添加 sys.userVipInfo 和 sys.giftsList API 定义
- 在全局声明中添加 userVipInfo 和 giftsList 方法
- 更新用户状态管理,添加 getUserMemberInfo 方法获取会员信息
- 在首页和我的页面中集成会员信息展示逻辑
- 添加配送方式切换功能,支持即时配送和自提模式

fix: 调整开发环境配置和页面权限设置

- 修改开发环境API地址配置
- 设置会员中心页面需要登录访问
- 修复组件导入声明问题

style: 优化界面UI展示

- 在首页添加会员弹窗展示逻辑
- 在个人中心页面显示会员标识和权益信息
- 更新底部固定元素层级样式
```

Co-authored-by: Copilot <copilot@github.com>

zouzexu 6 gün önce
ebeveyn
işleme
9f2f10bc70

+ 171 - 0
src/api/api.type.d.ts

@@ -93,6 +93,177 @@ namespace Api {
     icon: string
     children: xsbCategoriesChildren[]
   }
+  /**
+   * MemberAppInfoVO,小程序当前登录用户会员信息,用于会员中心、首页弹窗和权益展示。
+   */
+  export interface userMemberInfo {
+    /**
+     * 是否为有效会员。true 表示当前会员权益生效中。
+     */
+    active?: boolean
+    /**
+     * 会员权益配置 JSON。包含电商折扣 discountRate、充电每度立减 chargePerKwhDiscount 等配置。
+     */
+    benefitConfigJson?: string
+    /**
+     * 权益明细数组。每项至少包含 benefitType、benefitName、benefitDesc、useStatus。
+     */
+    benefitDetails?: MemberBenefitRecordVO[]
+    /**
+     * 优惠券自动发放配置 JSON。包含优惠券 ID、发放张数等配置。
+     */
+    couponConfigJson?: string
+    /**
+     * 会员生效时间。第三方回调确认后生效;为空时按系统规则生成。
+     */
+    effectiveTime?: Date
+    /**
+     * 会员到期时间。到期后会员权益失效。
+     */
+    expireTime?: Date
+    /**
+     * 自选赠品配置 JSON。包含可领取的赠品 SKU、数量等配置。
+     */
+    giftConfigJson?: string
+    /**
+     * 自选赠品是否已领取。true 表示已领取,不可重复领取。
+     */
+    giftReceived?: boolean
+    /**
+     * 开通后首次进入小程序展示弹窗用。接口返回 true 后会在服务端写入已读记录,后续再次调用返回 false。
+     */
+    isFirstLogin?: boolean
+    /**
+     * 会员账号 ID。一次会员开通对应一条会员账号记录。
+     */
+    memberAccountId?: number
+    /**
+     * 系统会员用户 ID。
+     */
+    memberId?: number
+    /**
+     * 会员状态枚举:ACTIVE=生效中,PENDING_EXPIRE=待失效,EXPIRED=已失效。
+     */
+    memberStatus?: string
+    /**
+     * 会员类型 ID,对应后台会员类型配置。
+     */
+    memberTypeId?: number
+    /**
+     * 会员类型名称。
+     */
+    memberTypeName?: string
+    /**
+     * 权益描述文案,用于后台列表或小程序展示。
+     */
+    rightsDesc?: string
+    [property: string]: any
+  }
+
+  /**
+   * MemberBenefitRecordVO,会员权益发放记录。包含优惠券、自选赠品发放结果及关联单号。
+   */
+  export interface MemberBenefitRecordVO {
+    /**
+     * 权益说明/权益发放备注,用于小程序或后台展示权益描述。
+     */
+    benefitDesc?: string
+    /**
+     * 权益名称。
+     */
+    benefitName?: string
+    /**
+     * 权益类型。COUPON 表示优惠券,GIFT 表示自选赠品。
+     */
+    benefitType?: string
+    /**
+     * 权益内容或配置摘要。
+     */
+    benefitValue?: string
+    /**
+     * 关联业务单号,如优惠券发放记录号、赠品订单号。
+     */
+    businessNo?: string
+    /**
+     * 创建时间。
+     */
+    createTime?: Date
+    /**
+     * 发放状态。1=发放成功,0=发放失败。
+     */
+    grantStatus?: number
+    /**
+     * 主键 ID。
+     */
+    id?: number
+    /**
+     * 会员账号 ID。一次会员开通对应一条会员账号记录。
+     */
+    memberAccountId?: number
+    /**
+     * 系统会员用户 ID。
+     */
+    memberId?: number
+    /**
+     * 备注说明。
+     */
+    remark?: string
+    /**
+     * 权益使用/发放状态。1=成功/可用,0=失败/不可用。
+     */
+    useStatus?: number
+    [property: string]: any
+  }
+  /**
+   * MemberGiftVO,会员自选赠品信息。用户只能在配置的赠品中多选一领取一次。
+   */
+  export interface giftsListModel {
+    /**
+     * 渠道/企业 ID。
+     */
+    channelId?: number
+    /**
+     * 赠品图片地址。
+     */
+    picUrl?: string
+    /**
+     * 商品原价/销售价,单位元。会员价根据该价格和 discountRate 计算。
+     */
+    price?: number
+    /**
+     * 领取数量或商品数量。赠品场景通常为配置的赠品数量。
+     */
+    quantity?: number
+    /**
+     * 当前赠品是否已领取。
+     */
+    received?: boolean
+    /**
+     * 门店 ID。
+     */
+    shopId?: number
+    /**
+     * 商品 SKU ID。
+     */
+    skuId?: number
+    /**
+     * SKU 名称/规格名称。
+     */
+    skuName?: string
+    /**
+     * 商品 SPU ID。
+     */
+    spuId?: number
+    /**
+     * SPU 商品名称。
+     */
+    spuName?: string
+    /**
+     * 库存数量。
+     */
+    stock?: number
+    [property: string]: any
+  }
   interface xsbCategoryProductList {
     /**
      * 多规格

+ 2 - 0
src/api/apiDefinitions.ts

@@ -36,6 +36,8 @@ export default {
   'sys.updateUserInfo': ['PUT', '/smqjh-system/app-api/v1/members/{memberId}'],
   'sys.selectZhUser': ['GET', '/smqjh-system/app-api/v1/claim/select'],
   'sys.zhUserReceived': ['POST', '/smqjh-system/app-api/v1/claim/received'],
+  'sys.userVipInfo':['GET', '/smqjh-system/app-api/v1/member/current'],
+  'sys.giftsList':['GET', '/smqjh-system/app-api/v1/member/gifts'],
 
   'xsb.categories':['GET', '/smqjh-pms/app-api/v1/categories'],
   'xsb.getCategoryProductList':['POST', '/smqjh-pms/app-api/v1/spu/getCategoryProductList'],

+ 12 - 1
src/api/globals.d.ts

@@ -203,6 +203,17 @@ declare global {
       >(
         config: Config
       ): Alova2Method<listData<Api.sysDict>, 'sys.dictPage', Config>;
+
+      userVipInfo<
+        Config extends Alova2MethodConfig<apiResData<Api.userMemberInfo>> & {}
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.userMemberInfo>, 'sys.userVipInfo', Config>;
+      giftsList<
+        Config extends Alova2MethodConfig<apiResData<Api.giftsListModel>> & {}
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.giftsListModel>, 'sys.giftsList', Config>;
     }
     xsb: {
       orderCoupons<
@@ -1323,7 +1334,7 @@ declare global {
       ): Alova2Method<apiResData<string>, 'refueling.getPayCode', Config>;
       cancelOrder<
         Config extends Alova2MethodConfig<apiResData<any>> & {
-         params: {
+          params: {
             /**
              * 订单ID
              */

+ 1 - 0
src/components.d.ts

@@ -42,6 +42,7 @@ declare module 'vue' {
     WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
     WdRate: typeof import('wot-design-uni/components/wd-rate/wd-rate.vue')['default']
     WdSearch: typeof import('wot-design-uni/components/wd-search/wd-search.vue')['default']
+    WdSegmented: typeof import('wot-design-uni/components/wd-segmented/wd-segmented.vue')['default']
     WdSkeleton: typeof import('wot-design-uni/components/wd-skeleton/wd-skeleton.vue')['default']
     WdSortButton: typeof import('wot-design-uni/components/wd-sort-button/wd-sort-button.vue')['default']
     WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']

+ 2 - 2
src/config/index.ts

@@ -11,9 +11,9 @@ const mapEnvVersion = {
   // develop: 'http://192.168.0.11:8080', // 王
   // develop: 'http://192.168.1.21:8080', // 田
   // develop: 'http://74949mkfh190.vicp.fun', // 付
-  // develop: 'http://47.109.84.152:8081',
+  develop: 'http://47.109.84.152:8081',
   // develop: 'https://5ed0f7cc.r9.vip.cpolar.cn',
-  develop: 'https://smqjh.api.zswlgz.com',
+  // develop: 'https://smqjh.api.zswlgz.com',
   /**
    * 体验版
    */

+ 1 - 1
src/pages.json

@@ -313,7 +313,7 @@
         {
           "path": "userVip/userVip",
           "name": "smqjh-user-vip",
-          "islogin": false,
+          "islogin": true,
           "style": {
             "navigationBarTitleText": "会员中心",
             "navigationStyle": "custom"

+ 4 - 3
src/pages/index/index.vue

@@ -19,7 +19,7 @@ const { show } = useGlobalToast()
 const addressStore = useAddressStore()
 const { statusBarHeight, MenuButtonHeight, opcity, isOnlineAudit } = storeToRefs(useSysStore())
 const { name } = storeToRefs(addressStore)
-const { userInfo } = storeToRefs(useUserStore())
+const { userInfo, userMemberInfo } = storeToRefs(useUserStore())
 const xsbStore = ref<typeof import('@/subPack-xsb/store-xsb/sys')>()
 const { data: goodsList, isLastPage, page, reload, error, refresh } = usePagination((pageNum, pageSize) =>
   Apis.xsb.getSearchProductList({ data: { pageNum, pageSize, salesNum: 'DESC', shopId: xsbStore.value?.useSysXsbStore().SelectShopInfo.shopId || 2, channelId: userInfo.value.channelId || 1 } }), {
@@ -37,6 +37,7 @@ const currentIndex = ref(0)
 const loading = ref(true)
 onShow(async () => {
   useSysStore().getAudit()
+  useUserStore().getUserMemberInfo()
   useSmqjhCartStore().getCartList('XSB')
   getSelectZhUser()
   xsbStore.value = await AsyncImport('@/subPack-xsb/store-xsb/sys')
@@ -328,11 +329,11 @@ function handleJyBanner() {
             </view>
           </view>
         </wd-overlay>
-        <wd-overlay :show="showoverlay2" @click="showoverlay2 = false">
+        <wd-overlay :show="showoverlay2 && userMemberInfo.isFirstLogin" @click="showoverlay2 = false">
           <view class="mt-280rpx flex items-center justify-center">
             <view class="relative h-906rpx w-644rpx flex flex-col items-center justify-center text-center" :style="{ backgroundImage: `url(${StaticUrl}/vip-index-popup.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
               <view class="absolute top-120rpx w-406rpx border-[1rpx_solid_#FFFFFF] rounded-50rpx border-solid px-30rpx py-8rpx text-center text-24rpx text-#FFF">
-                您的会员权益已生效有效期至2027-04-08 23:59:59
+                您的会员权益已生效有效期至{{ userMemberInfo.expireTime }}
               </view>
               <image :src="`${StaticUrl}/vip-index-check.png`" class="absolute top-690rpx h-84rpx w-372rpx" @click="router.push({ name: 'smqjh-user-vip' })" />
               <image :src="`${StaticUrl}/vip-index-shopping.png`" class="absolute top-800rpx h-84rpx w-288rpx" @click="router.push({ name: 'xsb-homeTabbar' })" />

+ 14 - 9
src/pages/my/index.vue

@@ -21,7 +21,7 @@ const tabList = ref([
 onMounted(() => {
   useUserStore().getUserInfo()
 })
-const { token, userInfo, getUserAvatar } = storeToRefs(useUserStore())
+const { token, userInfo, getUserAvatar, userMemberInfo } = storeToRefs(useUserStore())
 function handleLoginOut() {
   useGlobalMessage().confirm({
     title: '提示',
@@ -59,10 +59,10 @@ function handleGo(item: { name: string, status: string }) {
         </template>
         <template v-else>
           <view class="flex items-center">
-            <view class="relative" @click="router.push({ name: 'smqjh-user-vip' })">
-              <image :src="`${StaticUrl}/user-head-vip.png`" class="absolute right-[-20rpx] top-[-20rpx] h-50rpx w-50rpx" />
+            <view class="relative">
+              <image v-if="userMemberInfo.active" :src="`${StaticUrl}/user-head-vip.png`" class="absolute right-[-20rpx] top-[-20rpx] h-50rpx w-50rpx" />
               <image :src="getUserAvatar" alt="" class="h-100rpx w-100rpx flex-shrink-0 rounded-full" />
-              <view class="absolute left-[-6rpx] top-90rpx h-40rpx w-112rpx rounded-22rpx bg-[linear-gradient(132deg,#F0C568_0%,#FFF3B2_20.02%,#EBBA5E_44.19%,#FFF3B2_71.13%,#F0C26C_100%)] text-center text-24rpx text-#7F5935 line-height-40rpx">
+              <view v-if="userMemberInfo.active" class="absolute left-[-6rpx] top-90rpx h-40rpx w-112rpx rounded-22rpx bg-[linear-gradient(132deg,#F0C568_0%,#FFF3B2_20.02%,#EBBA5E_44.19%,#FFF3B2_71.13%,#F0C26C_100%)] text-center text-24rpx text-#7F5935 line-height-40rpx">
                 尊贵会员
               </view>
             </view>
@@ -75,13 +75,13 @@ function handleGo(item: { name: string, status: string }) {
               </view>
             </view>
           </view>
-          <view class="flex flex-col items-center" @click="router.push({ name: 'common-user-center' })">
+          <view class="flex flex-col items-center" @click="router.push({ name: 'smqjh-user-vip' })">
             <image
-              :src="`${StaticUrl}/user-setting.png`"
-              class="h-48rpx w-48rpx"
+              :src="`${StaticUrl}/vip-center-icon.png`"
+              class="h-56rpx w-66rpx"
             />
-            <view class="mt-12rpx text-24rpx text-[var(--them-color)]">
-              账户设置
+            <view class="mt-12rpx text-24rpx text-#7F5935">
+              会员中心
             </view>
           </view>
         </template>
@@ -131,6 +131,11 @@ function handleGo(item: { name: string, status: string }) {
               </view>
             </template>
           </wd-cell>
+          <wd-cell title="账户设置" custom-title-class="cell-title" clickable is-link @click="router.push({ name: 'common-user-center' })">
+            <template #icon>
+              <image :src="`${StaticUrl}/mine-setting-icon.png`" class="h-50rpx w-50rpx" />
+            </template>
+          </wd-cell>
         </wd-cell-group>
       </wd-card>
     </view>

+ 19 - 0
src/store/user.ts

@@ -27,6 +27,10 @@ interface userStroe {
    * 市民请集合购物车用户选中的收货地址
    */
   smqjhSelectedAddress: Api.addressList | null
+  /**
+   * 用户会员信息
+   */
+  userMemberInfo: Api.userMemberInfo
 }
 export const useUserStore = defineStore('user', {
   state: (): userStroe => ({
@@ -40,6 +44,11 @@ export const useUserStore = defineStore('user', {
     addresses: [],
     selectedAddress: null,
     smqjhSelectedAddress: null,
+    userMemberInfo: {
+      active: false,
+      isFirstLogin: false,
+      expireTime: undefined,
+    },
   }),
   getters: {
     getUserAvatar(): string {
@@ -54,11 +63,21 @@ export const useUserStore = defineStore('user', {
       if (this.token) {
         const { data } = await api.sys.userInfo({})
         this.userInfo = data
+        await this.getUserMemberInfo()
         await this.getuserAddresslist()
         this.getSelectedAddress()
         await useSmqjhCartStore().getCartList('XSB')
       }
     },
+    /**
+     * 获取用户会员信息
+     */
+    async getUserMemberInfo() {
+      if (this.token) {
+        const { data } = await Apis.sys.userVipInfo({})
+        this.userMemberInfo = data
+      }
+    },
     async updataUserInfo(data: Api.userInfo) {
       uni.showLoading({ mask: true })
       await Apis.sys.updateUserInfo({ pathParams: { memberId: data.id }, data })

+ 65 - 0
src/subPack-smqjh/giveawaysVip/giveawaysVip.vue

@@ -0,0 +1,65 @@
+<script setup lang="ts">
+const isChecked = ref(false)
+definePage({
+  name: 'smqjh-giveaways-vip',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '选择赠品',
+  },
+})
+onMounted(() => {
+  getGiftsList()
+})
+
+const giveawaysList = ref<Api.giftsListModel>()
+async function getGiftsList() {
+  const res = await Apis.sys.giftsList({})
+  giveawaysList.value = res.data
+}
+function handleChange(value: any) {
+  console.log(value)
+}
+</script>
+
+<template>
+  <view class="px24rpx">
+    <view class="h-20rpx" />
+    <view v-for="item in giveawaysList" :key="item.channelId" class="mb-20rpx flex items-center gap-20rpx rounded-16rpx bg-#FFF p-24rpx">
+      <view class="w-32rpx" @click="isChecked = !isChecked">
+        <wd-icon :name="isChecked ? 'check-circle-filled' : 'circle1'" size="20px" color="#9ED605" />
+      </view>
+      <view class="flex items-center gap-20rpx">
+        <image
+          :src="item.picUrl"
+          class="h-200rpx w-200rpx rounded-16rpx"
+        />
+        <view>
+          <view class="text-32rpx font-bold line-height-40rpx">
+            <text class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
+              赠品
+            </text>
+            {{ item.spuName }}
+          </view>
+          <view class="mt-14rpx text-24rpx text-#AAA">
+            规格:{{ item.skuName }}
+          </view>
+          <view class="mt-14rpx flex items-center justify-between">
+            <view class="text-36rpx text-#FF4D3A font-800">
+              ¥{{ item.price }}
+            </view>
+            <wd-input-number v-model="item.quantity" disabled @change="handleChange" />
+          </view>
+        </view>
+      </view>
+    </view>
+    <StatusTip v-if="giveawaysList?.length === 0" tip="暂无内容" />
+    <view class="h-180rpx" />
+  </view>
+  <view class="fixed bottom-0 left-0 right-0 z-9999 h-140rpx w-702rpx rounded-16rpx bg-#FFF p-24rpx shadow-[0rpx_-6rpx_12rpx_2rpx_rgba(0,0,0,0.05)]">
+    <wd-button custom-class="h-80rpx w-full">
+      免费领取
+    </wd-button>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 126 - 0
src/subPack-smqjh/userVip/userVip.vue

@@ -0,0 +1,126 @@
+<script setup lang="ts">
+import { rightsList } from './vip-data'
+import router from '@/router'
+import { StaticUrl } from '@/config'
+
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
+definePage({
+  name: 'smqjh-user-vip',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '会员中心',
+    navigationStyle: 'custom',
+  },
+
+})
+onMounted(() => {
+  opcity.value = 0
+})
+const { userMemberInfo } = storeToRefs(useUserStore())
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+
+function toUse(value: any) {
+  if (value.id === 1) {
+    wx.openOfficialAccountArticle({
+      url: 'https://mp.weixin.qq.com/s/lxpdZ6DUhgqg00AT9klu5Q',
+    })
+  }
+  if (value.route === '') {
+    useGlobalToast().show('该权益正在快马加鞭赶来~')
+  }
+  else {
+    router.push({ name: value.route })
+  }
+}
+</script>
+
+<template>
+  <view class="min-h-screen" :class="userMemberInfo.active ? 'bg-[linear-gradient(225deg,#13141D_0%,#55565D_34.72%,#15161F_100%)]' : ''">
+    <wd-navbar
+      title="会员中心" :custom-style="`background-color: rgba(226, 255, 145, ${opcity});color: ${opcity > 0.5 ? '#000' : '#FFF'};`"
+      :bordered="false" :z-index="999" safe-area-inset-top left-arrow fixed @click-left="router.back()"
+    />
+    <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
+    <view v-if="userMemberInfo.active" class="px24rpx">
+      <view class="mt-54rpx">
+        <image :src="`${StaticUrl}/vip-welcome.png`" class="h-46rpx w-339rpx" />
+        <view class="mt-36rpx text-28rpx text-#b5b5b5">
+          甄选权益,开启您的购物之旅
+        </view>
+      </view>
+      <view class="mt-36rpx h-370rpx pl-50rpx" :style="{ backgroundImage: `url(${StaticUrl}/vip-card.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
+        <image :src="`${StaticUrl}/vip-tags.png`" class="mt-72rpx h-54rpx w-238rpx" />
+        <view class="mt-20rpx text-24rpx text-#b5b5b5">
+          <text v-if="userMemberInfo.memberStatus === 'ACTIVE'">
+            有效期至
+          </text>
+          <text v-if="userMemberInfo.memberStatus === 'PENDING_EXPIRE'">
+            会员已退订
+          </text>
+          <text v-if="userMemberInfo.memberStatus === 'EXPIRED'">
+            会员已失效
+          </text>
+        </view>
+        <view class="mt-20rpx text-28rpx text-#b5b5b5">
+          <text v-if="userMemberInfo.memberStatus === 'PENDING_EXPIRE'">
+            权益将于
+          </text>
+          <text v-if="userMemberInfo.memberStatus === 'EXPIRED'">
+            失效时间
+          </text>
+        </view>
+        <view class="mt-20rpx text-28rpx text-#b5b5b5">
+          {{ userMemberInfo.expireTime }}
+          <text v-if="userMemberInfo.memberStatus != 'ACTIVE'">
+            失效
+          </text>
+        </view>
+      </view>
+      <view class="mt-30rpx">
+        <view class="flex items-center justify-center gap-36rpx">
+          <view class="flex items-center gap-6rpx">
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(30deg);" />
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(30deg);" />
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(30deg);" />
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(30deg);" />
+          </view>
+          <view class="text-36rpx text-#FEE3AD font-800">
+            我的权益
+          </view>
+          <view class="flex items-center gap-6rpx">
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(-30deg);" />
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(-30deg);" />
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(-30deg);" />
+            <view class="h-16rpx w-8rpx bg-#FEE3AD" style="transform: skew(-30deg);" />
+          </view>
+        </view>
+      </view>
+      <view class="mt-44rpx flex flex-wrap gap-20rpx">
+        <view v-for="value in rightsList" :key="value.id" class="w-304rpx border-[1rpx_solid_#F4E5BD] rounded-32rpx bg-[rgba(255,255,255,0.3)] p-20rpx">
+          <view class="text-28rpx text-#FEE3AD font-bold">
+            {{ value.title }}
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                {{ value.desc }}
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx bg-#F4E5BD text-center text-24rpx text-#7F5935 line-height-42rpx" @click="toUse(value)">
+                去使用
+              </view>
+            </view>
+            <image :src="value.icon" class="h-80rpx w-80rpx" />
+          </view>
+        </view>
+      </view>
+    </view>
+    <StatusTip v-else image="vip-not-data.png" tip="敬请期待" />
+  </view>
+</template>
+
+<style lang="scss" scoped>
+
+</style>

+ 47 - 0
src/subPack-smqjh/userVip/vip-data.ts

@@ -0,0 +1,47 @@
+import { StaticUrl } from '@/config'
+
+// const { userMemberInfo } = storeToRefs(useUserStore())
+export const rightsList = [
+  {
+    id: 1,
+    title: '全省中石化优惠',
+    desc: '每升立减0.3元',
+    icon: `${StaticUrl}/vip-zshyh.png`,
+    route: '',
+  },
+  {
+    id: 2,
+    title: '市民请集合平台快消品',
+    desc: '折扣率9.5折',
+    icon: `${StaticUrl}/vip-ptkxp.png`,
+    route: 'xsb-homeTabbar',
+  },
+  {
+    id: 3,
+    title: '全省贵阳城投充电桩优惠',
+    desc: '每度电立减0.03元',
+    icon: `${StaticUrl}/vip-cdzyh.png`,
+    route: 'charge-index',
+  },
+  {
+    id: 4,
+    title: '贵阳城投停车场优惠',
+    desc: '折扣率9.5折',
+    icon: `${StaticUrl}/vip-tccyh.png`,
+    route: '',
+  },
+  {
+    id: 5,
+    title: '优惠券',
+    desc: '优惠券3张',
+    icon: `${StaticUrl}/vip-yhq.png`,
+    route: 'xsb-coupon',
+  },
+  {
+    id: 6,
+    title: '自选赠品',
+    desc: ``, // 自选赠品${userMemberInfo.value.}个
+    icon: `${StaticUrl}/vip-zxzp.png`,
+    route: 'smqjh-giveaways-vip',
+  },
+]

+ 53 - 4
src/subPack-xsb/confirmOrder/index.vue

@@ -18,7 +18,15 @@ const remarks = ref('')
 const initialCouponId = ref<string | undefined>(undefined)
 const confirmedCouponId = ref<string | undefined>(undefined)
 const draftCouponId = ref<string | undefined>(undefined)
-
+const list = ref<string[]>(['即时配送', '自提'])
+const current = ref('即时配送')
+const model = reactive<{
+  value1: string
+  value2: string
+}>({
+  value1: '',
+  value2: '',
+})
 const deliveryType = ref(1)
 
 // 优惠券选择
@@ -164,8 +172,10 @@ async function handlePay() {
 
 <template>
   <view class="page px20rpx py20rpx">
+    <wd-segmented v-model:value="current" :options="list" />
     <view
-      class="mb20rpx rounded-16rpx bg-white p24rpx"
+      v-if="current === '即时配送'"
+      class="my20rpx rounded-16rpx bg-white p24rpx"
       @click="router.push({ name: 'common-addressList', params: { type: 'select' } })"
     >
       <view class="flex items-center justify-between">
@@ -197,6 +207,45 @@ async function handlePay() {
       </view>
     </view>
 
+    <view v-else class="my20rpx rounded-16rpx bg-white p24rpx">
+      <view class="flex items-center gap-50rpx">
+        <view>
+          <view class="text-28rpx font-semibold">
+            自提点:星闪豹(贵阳店)
+          </view>
+          <view class="mt-20rpx text-24rpx text-#AAAAAA">
+            贵州省贵阳市贵阳市观山湖区金麦安置小区12组团26号-28号门面
+          </view>
+        </view>
+        <view>
+          <view class="mb-20rpx text-24rpx text-#AAAAAA">
+            距你XXkm
+          </view>
+          <wd-icon name="location" size="22px" color="#9ED605" />
+        </view>
+      </view>
+      <view>
+        <wd-input
+          v-model="model.value1"
+          label="联系人"
+          label-width="80px"
+          prop="value1"
+          clearable
+          placeholder="请输入联系人"
+          :rules="[{ required: true, message: '请填写联系人' }]"
+        />
+        <wd-input
+          v-model="model.value2"
+          label="预留电话"
+          label-width="80px"
+          prop="value1"
+          clearable
+          placeholder="请输入预留电话"
+          :rules="[{ required: true, pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/, message: '请输入正确的手机号' }]"
+        />
+      </view>
+    </view>
+
     <view class="rounded-16rpx bg-white p24rpx">
       <view class="flex items-center text-28rpx font-semibold">
         {{ orderInfo?.shopName }}
@@ -277,7 +326,7 @@ async function handlePay() {
         备注
       </view>
       <view class="flex-1">
-        <wd-input v-model="remarks" placeholder="选填,请先和商家协商一致,付款后商家可见" no-border clearable />
+        <wd-input v-model="remarks" placeholder="选填,请先和商家协商一致,付款后商家可见" clearable no-border />
       </view>
     </view>
     <view class="h250rpx" />
@@ -356,7 +405,7 @@ async function handlePay() {
         </view>
       </template>
     </Zpopup>
-    <view class="ios footer fixed bottom-0 left-0 box-border w-full rounded-t-16rpx bg-white px24rpx">
+    <view class="ios footer fixed bottom-0 left-0 z-1000 box-border w-full rounded-t-16rpx bg-white px24rpx">
       <view class="box-border w-full flex items-center justify-between py20rpx">
         <view class="flex items-center text-#FF4D3A">
           <view class="font-semibold10 flex items-baseline text-36rpx">