Browse Source

Merge branch 'master' into ch-h5

zhangtao 3 days ago
parent
commit
7a7e1e94b7

+ 15 - 0
.idea/git_toolbox_prj.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GitToolBoxProjectSettings">
+    <option name="commitMessageIssueKeyValidationOverride">
+      <BoolValueOverride>
+        <option name="enabled" value="true" />
+      </BoolValueOverride>
+    </option>
+    <option name="commitMessageValidationEnabledOverride">
+      <BoolValueOverride>
+        <option name="enabled" value="true" />
+      </BoolValueOverride>
+    </option>
+  </component>
+</project>

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

@@ -93,6 +93,227 @@ 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 | string
+    /**
+     * 当前赠品是否已领取。
+     */
+    received?: boolean
+    /**
+     * 门店 ID。
+     */
+    shopId?: number
+    /**
+     * 商品 SKU ID。
+     */
+    skuId?: number
+    /**
+     * SKU 名称/规格名称。
+     */
+    skuName?: string
+    /**
+     * 商品 SPU ID。
+     */
+    spuId?: number
+    /**
+     * SPU 商品名称。
+     */
+    spuName?: string
+    /**
+     * 库存数量。
+     */
+    stock?: number
+    [property: string]: any
+  }
+  /**
+   * MemberGiftReceiveVO,会员赠品领取结果。返回会员账号和生成的赠品订单号。
+   */
+  export interface giftsReceiveItem {
+    /**
+     * 渠道/企业 ID。
+     */
+    channelId: number
+    /**
+     * 领取数量。
+     */
+    quantity: number
+    /**
+     * 门店 ID。
+     */
+    shopId: number
+    /**
+     * 商品 SKU ID。
+     */
+    skuId: number
+  }
+  export interface giftsReceiveForm {
+    /**
+     * 用户收货地址 ID。
+     */
+    addressId: number
+    /**
+     * 多商品合单领取明细。
+     */
+    items: giftsReceiveItem[]
+  }
+  export interface giftsReceiveModel {
+    /**
+     * 会员账号 ID。一次会员开通对应一条会员账号记录。
+     */
+    memberAccountId?: number
+    /**
+     * 订单编号。赠品领取成功后返回 0 元赠品订单号。
+     */
+    orderNumber?: string
+    /**
+     * 商品 SKU ID。
+     */
+    skuId?: number
+    /**
+     * 合单领取的 SKU ID 列表。
+     */
+    skuIds?: number[]
+    [property: string]: any
+  }
   interface xsbCategoryProductList {
     /**
      * 多规格
@@ -1176,6 +1397,10 @@ namespace Api {
     coupon: number
     couponName: string
     orderCouponItemDTOS?: AppMemberCouponVO[]
+    /**
+     * 店铺地址信息
+     */
+    shopAddressDTO?: ShopAddressDTO
     [property: string]: any
   }
   interface AppletOrderSkuVo {
@@ -1200,6 +1425,36 @@ namespace Api {
      * sku
      */
     sku?: SkuConfirmVo
+    /**
+     * 店铺地址信息
+     */
+    shopAddressDTO?: ShopAddressDTO
+    [property: string]: any
+  }
+  /**
+   * 店铺地址信息
+   */
+  export interface ShopAddressDTO {
+    /**
+     * 距离(单位:千米)
+     */
+    distance?: number
+    /**
+     * 完整店铺地址(省+市+区+详细地址 拼接结果)
+     */
+    shopAddress?: string
+    /**
+     * 纬度
+     */
+    shopLat?: string
+    /**
+     * 经度
+     */
+    shopLng?: string
+    /**
+     * 店铺名称
+     */
+    shopName?: string
     [property: string]: any
   }
   interface SkuConfirmVo {
@@ -2408,6 +2663,7 @@ namespace Api {
      * 充电订单号
      */
     chargeOrderNo?: string
+    orderMoney?: number
     /**
      * 充电时间:秒
      */
@@ -2476,6 +2732,18 @@ namespace Api {
      * 用户实付
      */
     actualTotal?: number
+    /**
+     * 会员优惠金额,单位元。非会员、非 XSB 电商商品或无可用权益时为 0。
+     */
+    memberDiscountAmount?: number
+    /**
+     * 会员优惠说明,例如“会员权益(9.5折)”或“会员权益(每度立减0.3元)”。
+     */
+    memberDiscountDesc?: string
+    /**
+     * 会员每度立减金额,单位元/度。
+     */
+    memberPerKwhDiscount?: number
     platformVolume?: number
 
   }

+ 5 - 1
src/api/apiDefinitions.ts

@@ -37,6 +37,9 @@ export default {
   'sys.selectZhUser': ['GET', '/smqjh-system/app-api/v1/claim/select'],
   'sys.zhUserReceived': ['POST', '/smqjh-system/app-api/v1/claim/received'],
   'sys.appAccess': ['GET', '/smqjh-system/app-api/v1/appAccess/{accessId}'],
+  'sys.userVipInfo':['GET', '/smqjh-system/app-api/v1/member/current'],
+  'sys.giftsList': ['GET', '/smqjh-system/app-api/v1/member/gifts'],
+  'sys.giftsReceive': ['POST', '/smqjh-system/app-api/v1/member/gifts/receive'],
 
   'xsb.categories':['GET', '/smqjh-pms/app-api/v1/categories'],
   'xsb.getCategoryProductList':['POST', '/smqjh-pms/app-api/v1/spu/getCategoryProductList'],
@@ -52,7 +55,8 @@ export default {
   'xsb.orderInfo':['GET', '/smqjh-oms/api/v1/order/orderInfo'],
   'xsb.cancelOrder':['GET', '/smqjh-oms/api/v1/order/cancelOrder'],
   'xsb.deleteOrder':['DELETE', '/smqjh-oms/api/v1/order/deleteOrder/{ids}'],
-  'xsb.skuOrderConfirm':['GET', '/smqjh-oms/api/v1/order/skuOrderConfirm'],
+  'xsb.skuOrderConfirm':['POST', '/smqjh-oms/api/v1/order/skuOrderConfirmNew'],
+  // 'xsb.skuOrderConfirm':['GET', '/smqjh-oms/api/v1/order/skuOrderConfirm'],
   'xsb.myShoppingCartCategory':['GET', '/smqjh-oms/app-api/v1/shoppingCart/myShoppingCartCategory'],
   'xsb.delivery':['GET', '/smqjh-system/app-api/v1/delivery'],
   'xsb.confirmReceipt':['GET', '/smqjh-oms/api/v1/order/confirmReceipt'],

+ 3 - 0
src/api/core/instance.ts

@@ -13,6 +13,9 @@ export const alovaInstance = createAlova({
     if (['POST', 'PUT', 'PATCH'].includes(method.type)) {
       method.config.headers['Content-Type'] = 'application/json'
     }
+    // if (['POST', 'PUT', 'PATCH', 'DELETE', 'GET'].includes(method.type)) {
+    //   method.config.headers['X-Tenant-Domain'] = BASE_URL
+    // }
     const { token } = useUserStore()
     method.config.headers.Authorization = token || 'Basic c21xamgtYXBwbGV0OjEyMzQ1Ng=='
     method.config.headers['X-Tenant-Domain'] = 'http://192.168.1.40:5174'

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

@@ -210,6 +210,51 @@ 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>;
+
+      giftsReceive<
+        Config extends Alova2MethodConfig<apiResData<Api.giftsReceiveModel>> & {
+          data: {
+            /**
+ * 用户收货地址 ID,用于创建赠品订单。
+ */
+            addressId: number;
+            /**
+             * 渠道/企业 ID。
+             */
+            channelId?: number;
+            /**
+             * 领取数量或商品数量。赠品场景通常为配置的赠品数量。
+             */
+            quantity?: number;
+            /**
+             * 门店 ID。
+             */
+            shopId?: number;
+            /**
+             * 商品 SKU ID。
+             */
+            skuId?: number;
+            /**
+             * 多商品合单领取明细。
+             */
+            items: Api.giftsReceiveItem[];
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.giftsReceiveModel>, 'sys.giftsReceive', Config>;
     }
     xsb: {
       orderCoupons<
@@ -532,6 +577,18 @@ declare global {
         Config extends Alova2MethodConfig<apiResData<Api.AppletOrderSkuVo>> & {
           data: {
             channelId?: number;
+            /**
+             * 配送类型 1:快递 2:自提 3:及时配送
+             */
+            dvyType?: number;
+            /**
+             * 当前位置纬度
+             */
+            latitude?: number;
+            /**
+             * 当前位置经度
+             */
+            longitude?: number;
             num?: number;
             shopId?: number;
             skuId?: number;
@@ -653,6 +710,14 @@ declare global {
              * 企业ID
              */
             channelId: number;
+            /**
+             * 预留电话 自提时需要填写
+             */
+            consigneeMobile?: string;
+            /**
+             * 联系人姓名 自提时需要填写
+             */
+            consigneeName?: string;
             /**
              * 配送类型 1:快递 2:自提 3:及时配送
              */
@@ -1330,7 +1395,7 @@ declare global {
       ): Alova2Method<apiResData<string>, 'refueling.getPayCode', Config>;
       cancelOrder<
         Config extends Alova2MethodConfig<apiResData<any>> & {
-         params: {
+          params: {
             /**
              * 订单ID
              */

+ 1 - 11
src/components.d.ts

@@ -15,7 +15,6 @@ declare module 'vue' {
     PrivacyPopup: typeof import('./components/PrivacyPopup.vue')['default']
     QCode: typeof import('./components/QCode.vue')['default']
     StatusTip: typeof import('./components/StatusTip.vue')['default']
-    WdActionSheet: typeof import('wot-design-uni/components/wd-action-sheet/wd-action-sheet.vue')['default']
     WdBadge: typeof import('wot-design-uni/components/wd-badge/wd-badge.vue')['default']
     WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
     WdCard: typeof import('wot-design-uni/components/wd-card/wd-card.vue')['default']
@@ -23,9 +22,7 @@ declare module 'vue' {
     WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default']
     WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default']
     WdCheckboxGroup: typeof import('wot-design-uni/components/wd-checkbox-group/wd-checkbox-group.vue')['default']
-    WdCircle: typeof import('wot-design-uni/components/wd-circle/wd-circle.vue')['default']
     WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
-    WdCountDown: typeof import('wot-design-uni/components/wd-count-down/wd-count-down.vue')['default']
     WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
     WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
     WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
@@ -37,27 +34,20 @@ declare module 'vue' {
     WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
     WdNotify: typeof import('wot-design-uni/components/wd-notify/wd-notify.vue')['default']
     WdOverlay: typeof import('wot-design-uni/components/wd-overlay/wd-overlay.vue')['default']
-    WdPicker: typeof import('wot-design-uni/components/wd-picker/wd-picker.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']
-    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']
-    WdStep: typeof import('wot-design-uni/components/wd-step/wd-step.vue')['default']
-    WdSteps: typeof import('wot-design-uni/components/wd-steps/wd-steps.vue')['default']
-    WdSticky: typeof import('wot-design-uni/components/wd-sticky/wd-sticky.vue')['default']
     WdSwiper: typeof import('wot-design-uni/components/wd-swiper/wd-swiper.vue')['default']
     WdTab: typeof import('wot-design-uni/components/wd-tab/wd-tab.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']
     WdTabs: typeof import('wot-design-uni/components/wd-tabs/wd-tabs.vue')['default']
     WdTag: typeof import('wot-design-uni/components/wd-tag/wd-tag.vue')['default']
-    WdTextarea: typeof import('wot-design-uni/components/wd-textarea/wd-textarea.vue')['default']
     WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
-    WdUpload: typeof import('wot-design-uni/components/wd-upload/wd-upload.vue')['default']
     Zcontact: typeof import('./components/Zcontact.vue')['default']
     Zpopup: typeof import('./components/Zpopup.vue')['default']
     Zupload: typeof import('./components/Zupload.vue')['default']

+ 5 - 4
src/config/index.ts

@@ -7,21 +7,22 @@ const mapEnvVersion = {
   // develop: 'http://192.168.0.157:8080',
   // develop: 'http://192.168.1.253:8080',
   // develop: 'http://192.168.0.19:8080', // 邓
-  // develop: 'http://192.168.0.217:8080', // 黄
+  // develop: 'http://192.168.1.20:8080', // 黄
   // 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://25740642.r3.cpolar.top',
   // develop: 'https://smqjh.api.zswlgz.com',
   /**
    * 体验版
    */
   // trial: "http://192.168.1.166:8080/jeecg-boot",
   // trial: 'http://192.168.0.157:8080',
-  trial: 'http://47.109.84.152:8081',
+  // trial: 'http://47.109.84.152:8081',
   // trial: 'http://192.168.1.166:8080,
-  // trial: 'https://smqjh.api.zswlgz.com',
+  trial: 'https://smqjh.api.zswlgz.com',
   /**
    * 正式版
    */

+ 17 - 0
src/pages.json

@@ -314,6 +314,14 @@
             "navigationBarTitleText": "详情"
           }
         },
+        {
+          "path": "giveawaysVip/giveawaysVip",
+          "name": "smqjh-giveaways-vip",
+          "islogin": true,
+          "style": {
+            "navigationBarTitleText": "选择赠品"
+          }
+        },
         {
           "path": "order/index",
           "name": "smqjh-order",
@@ -321,6 +329,15 @@
           "style": {
             "navigationBarTitleText": "订单列表"
           }
+        },
+        {
+          "path": "userVip/userVip",
+          "name": "smqjh-user-vip",
+          "islogin": true,
+          "style": {
+            "navigationBarTitleText": "会员中心",
+            "navigationStyle": "custom"
+          }
         }
       ]
     },

+ 19 - 2
src/pages/cart/index.vue

@@ -4,6 +4,7 @@ import router from '@/router'
 
 import selectAddressTemplate from '@/subPack-smqjh/components/selectAddress/index.vue?async'
 
+const { userMemberInfo } = storeToRefs(useUserStore())
 definePage({
   name: 'smqjh-cart',
   layout: 'tabbar',
@@ -119,7 +120,15 @@ async function handleSelectAddress() {
                     规格:{{ item.spec }}
                   </view>
                   <view class="mt-14rpx flex items-center justify-between">
-                    <view class="text-36rpx text-[#FF4A39] font-semibold">
+                    <view v-if="userMemberInfo.active" class="flex items-center gap-20rpx">
+                      <view class="text-36rpx text-[#FF4A39] font-semibold">
+                        ¥{{ item.memberPrice }}
+                      </view>
+                      <view class="text-26rpx text-#AAAAAA line-through">
+                        ¥{{ item.price }}
+                      </view>
+                    </view>
+                    <view v-else class="text-36rpx text-[#FF4A39] font-semibold">
                       ¥{{ item.price }}
                     </view>
                     <!-- <wd-input-number v-model="item.num" disable-input @change="handleChangeNum($event, item)" /> -->
@@ -182,7 +191,7 @@ async function handleSelectAddress() {
                 ¥ {{ totalProduct?.amount || 0 }}
               </view>
               <view v-if="totalProduct?.coupon" class="ml-10rpx text-24rpx text-[#FF4A39]">
-                共减¥{{ totalProduct?.coupon }}
+                共减¥{{ totalProduct?.coupon + (totalProduct?.memberDiscountAmount || 0) }}
               </view>
               <view v-if="totalProduct?.amount" class="ml10rpx flex items-center text-24rpx text-gray" @click="priceDetailPopup = !priceDetailPopup">
                 明细 <view class="flex items-center" :class="[priceDetailPopup ? 'rotate-180' : '']">
@@ -244,6 +253,14 @@ async function handleSelectAddress() {
             </view>
           </view>
         </template>
+        <view v-if="totalProduct?.memberDiscountAmount" class="flex items-center justify-between py-20rpx">
+          <view class="text-28rpx text-#333">
+            {{ totalProduct?.memberBenefitDesc }}
+          </view>
+          <view class="text-28rpx text-#FF4A39 font-semibold">
+            -¥{{ totalProduct?.memberDiscountAmount }}
+          </view>
+        </view>
         <view class="flex items-center justify-between py-20rpx">
           <view class="text-28rpx text-[#333]">
             配送费

+ 31 - 0
src/pages/index/calcNavSwiperHeight.ts

@@ -0,0 +1,31 @@
+/**
+ * 计算金刚区 swiper 高度(单位:rpx)
+ *
+ * @param totalItems 可显示的总项数(已过滤 show)
+ * @param currentPageIndex 当前页面索引(从 0 开始)
+ * @param options 可选配置,支持覆盖每页项数、列数、单项高度等
+ */
+export interface CalcOptions {
+  itemsPerPage?: number
+  columns?: number
+  perImageHeight?: number
+  titleHeight?: number
+  rowGap?: number
+  extraSpace?: number
+}
+
+export function calcNavSwiperHeight(totalItems: number, currentPageIndex: number, options: CalcOptions = {}): number {
+  const itemsPerPage = options.itemsPerPage ?? 8
+  const columns = options.columns ?? 4
+  const perImageHeight = options.perImageHeight ?? 120
+  const titleHeight = options.titleHeight ?? 24
+  const rowGap = options.rowGap ?? 12
+  const extraSpace = options.extraSpace ?? 40
+
+  const start = currentPageIndex * itemsPerPage
+  const remaining = Math.max(0, totalItems - start)
+  const pageItems = Math.min(itemsPerPage, remaining)
+  const rows = Math.max(1, Math.ceil(pageItems / columns))
+
+  return rows * (perImageHeight + titleHeight) + Math.max(0, rows - 1) * rowGap + extraSpace
+}

+ 75 - 18
src/pages/index/index.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
+import { calcNavSwiperHeight } from './calcNavSwiperHeight'
 import { StaticUrl } from '@/config'
 import router from '@/router'
 
@@ -19,7 +20,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 +38,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')
@@ -68,6 +70,14 @@ const navList = computed(() => {
   ]
   return list
 })
+const itemsPerPage = 8
+const columnsCount = 4
+const visibleNavList = computed(() => navList.value.filter(i => i.show))
+const swiperHeight = computed(() => {
+  const total = visibleNavList.value.length
+  return calcNavSwiperHeight(total, currentIndex.value, { itemsPerPage, columns: columnsCount })
+})
+const swiperStyle = computed(() => ({ height: `${swiperHeight.value}rpx` }))
 onMounted(() => {
   addressStore.getLocation()
   opcity.value = 0
@@ -107,6 +117,7 @@ onShareAppMessage(() => {
   }
 })
 const showoverlay = ref(false)
+const showoverlay2 = ref(true)
 async function getSelectZhUser() {
   const res = await Apis.sys.selectZhUser({})
   if (res.data.channelId === 54 && !res.data.isClaimed) {
@@ -201,7 +212,8 @@ function handleJyBanner() {
 
           ]"
         >
-          <swiper :duration="300" class="h340rpx" @change="handleChangeSwiper">
+          <!-- h340rpx -->
+          <swiper :duration="300" :style="swiperStyle" class="transition-height" @change="handleChangeSwiper">
             <swiper-item
               v-for="pageIndex in Math.ceil(navList.filter(i => i.show).length / 8)" :key="pageIndex"
             >
@@ -280,7 +292,26 @@ function handleJyBanner() {
                         {{ item.prodName }}
                       </view>
                     </view>
-                    <view class="mt-20rpx flex items-end text-[#FF4D3A]">
+                    <view v-if="item.isMember" class="mt-20rpx flex items-center gap-16rpx">
+                      <view class="flex items-end text-[#FF4D3A]">
+                        <view class="text-24rpx">
+                          ¥
+                        </view>
+                        <view class="text-36rpx line-height-[36rpx]">
+                          {{ item.memberPrice }}
+                        </view>
+                        <view class="text-24rpx">
+                          元
+                        </view>
+                      </view>
+                      <view class="rounded-8rpx bg-#FF4A39 px-8rpx py-4rpx text-22rpx text-#FFF">
+                        会员价
+                      </view>
+                      <view class="text-24rpx text-#AAA line-through">
+                        ¥{{ item.channelProdPrice }}
+                      </view>
+                    </view>
+                    <view v-else class="mt-20rpx flex items-end text-[#FF4D3A]">
                       <view class="text-24rpx">
                       </view>
@@ -292,6 +323,17 @@ function handleJyBanner() {
                       </view>
                     </view>
                   </view>
+                  <view class="mt-20rpx flex items-end text-[#FF4D3A]">
+                    <view class="text-24rpx">
+                      ¥
+                    </view>
+                    <view class="text-36rpx line-height-[36rpx]">
+                      {{ item.channelProdPrice }}
+                    </view>
+                    <view class="text-24rpx">
+                      元
+                    </view>
+                  </view>
                 </view>
                 <view
                   v-if="!item.spuStock"
@@ -317,25 +359,36 @@ function handleJyBanner() {
             </view>
           </view>
         </wd-skeleton>
-        <wd-loadmore v-if="goodsList.length > 9" :state="state" :loading-props="{ color: '#9ED605', size: 20 }" @reload="reload" />
-        <wd-overlay :show="showoverlay" @click="showoverlay = false">
-          <view class="mt-280rpx flex items-center justify-center">
-            <view class="relative h-906rpx w-644rpx flex flex-col justify-center text-center" :style="{ backgroundImage: `url(${StaticUrl}/home-overlay-img.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
-              <view>
-                <view class="text-80rpx text-#FF1B51 font-600">
-                  ¥200
-                </view>
-                <view class="text-28rpx font-800">
-                  现金抵扣券
-                </view>
+      </view>
+      <wd-loadmore v-if="goodsList.length > 9" :state="state" :loading-props="{ color: '#9ED605', size: 20 }" @reload="reload" />
+      <wd-overlay :show="showoverlay" @click="showoverlay = false">
+        <view class="mt-280rpx flex items-center justify-center">
+          <view class="relative h-906rpx w-644rpx flex flex-col justify-center text-center" :style="{ backgroundImage: `url(${StaticUrl}/home-overlay-img.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
+            <view>
+              <view class="text-80rpx text-#FF1B51 font-600">
+                ¥200
               </view>
-              <view class="absolute bottom-110rpx left-42% text-60rpx text-#FF1B51 font-bold" @click="getZhUserReceived">
-                
+              <view class="text-28rpx font-800">
+                现金抵扣券
               </view>
             </view>
+            <view class="absolute bottom-110rpx left-42% text-60rpx text-#FF1B51 font-bold" @click="getZhUserReceived">
+              领
+            </view>
           </view>
-        </wd-overlay>
-      </view>
+        </view>
+      </wd-overlay>
+      <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">
+              您的会员权益已生效有效期至{{ 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' })" />
+          </view>
+        </view>
+      </wd-overlay>
     </view>
   </view>
 </template>
@@ -361,5 +414,9 @@ function handleJyBanner() {
     background: rgba(0, 0, 0, .3);
   }
 
+  .transition-height {
+    transition: height 0.3s ease;
+  }
+
 }
 </style>

+ 20 - 10
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: '提示',
@@ -64,7 +64,13 @@ function handleGo(item: { name: string, status: string }) {
         </template>
         <template v-else>
           <view class="flex items-center">
-            <image :src="getUserAvatar" alt="" class="h-100rpx w-100rpx flex-shrink-0 rounded-full" />
+            <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 v-if="userMemberInfo.active" class="absolute left-50% top-90rpx h-40rpx whitespace-nowrap rounded-22rpx bg-[linear-gradient(132deg,#F0C568_0%,#FFF3B2_20.02%,#EBBA5E_44.19%,#FFF3B2_71.13%,#F0C26C_100%)] px-16rpx text-center text-24rpx text-#7F5935 line-height-40rpx -translate-x-50%">
+                {{ userMemberInfo.memberTypeName }}
+              </view>
+            </view>
             <view class="ml-20rpx flex-1">
               <view class="text-32rpx font-semibold">
                 {{ userInfo.nickName }}
@@ -74,14 +80,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' })">
-            <!-- <image
-              :src="`${StaticUrl}/user-setting.png`"
-              class="h-48rpx w-48rpx"
-            /> -->
-            <wd-icon name="setting" size="22px" color="var(--them-color)" />
-            <view class="mt-12rpx text-24rpx text-[var(--them-color)]">
-              账户设置
+          <view class="flex flex-col items-center" @click="router.push({ name: 'smqjh-user-vip' })">
+            <image
+              :src="`${StaticUrl}/vip-center-icon.png`"
+              class="h-56rpx w-66rpx"
+            />
+            <view class="mt-12rpx text-24rpx text-#7F5935">
+              会员中心
             </view>
           </view>
         </template>
@@ -133,6 +138,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>

+ 41 - 13
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 })
@@ -168,25 +187,31 @@ export const useUserStore = defineStore('user', {
     getOrderPayMent(freightFee: number, businessType: string, dvyType: number, shopId: number, orderItemList: {
       prodCount?: number
       skuId?: number
-    }[], remarks?: string, allowanceId?: string): Promise<string> {
+    }[], remarks?: string, allowanceId?: string, pickupInfo?: {
+      consigneeName?: string
+      consigneeMobile?: string
+    }): Promise<string> {
       uni.showLoading({ mask: true })
       return new Promise((resolve, reject) => {
-        if (!this.selectedAddress) {
+        if (dvyType !== 2 && !this.selectedAddress) {
+          uni.hideLoading()
           reject(new Error('请选择收货地址'))
           return
         }
+        const orderData = {
+          channelId: Number(this.userInfo.channelId),
+          businessType,
+          addressId: Number(this.selectedAddress?.id),
+          dvyType,
+          freightAmount: freightFee,
+          shopId,
+          orderItemList,
+          remarks,
+          allowanceIds: allowanceId ? [allowanceId] : [],
+          ...pickupInfo,
+        }
         Apis.common.addOrder({
-          data: {
-            channelId: Number(this.userInfo.channelId),
-            businessType,
-            addressId: this.selectedAddress.id,
-            dvyType,
-            freightAmount: freightFee,
-            shopId,
-            orderItemList,
-            remarks,
-            allowanceIds: allowanceId ? [allowanceId] : [],
-          },
+          data: orderData,
         }).then((res) => {
           resolve(res.data)
           uni.hideLoading()
@@ -265,10 +290,13 @@ export const useUserStore = defineStore('user', {
         */
 
     clearCart(skuList: Api.CartSkuVo[]) {
+      console.log('进入清空购物车')
       uni.showLoading({ mask: true })
       return new Promise((resolve) => {
         const skuids = skuList.map(item => item.id).join(',')
+        console.log(skuids, '执行前')
         if (skuids.length) {
+          console.log(skuids, '执行中')
           Apis.common.deleteShoppingCart({
             pathParams: {
               ids: skuids,

+ 10 - 2
src/subPack-charge/chargeOrderDetail/chargeOrderDetail.vue

@@ -161,7 +161,15 @@ async function getOrderDetail() {
             订单金额
           </view>
           <view class="text-28rpx text-#F44033">
-            {{ chargeOrderDetail?.actualTotal || '--' }}元
+            {{ chargeOrderDetail?.orderMoney || '--' }}元
+          </view>
+        </view>
+        <view v-if="(chargeOrderDetail?.memberDiscountAmount ?? 0) > 0" class="mt-28rpx flex items-center justify-between">
+          <view class="text-24rpx">
+            {{ chargeOrderDetail?.memberDiscountDesc }}
+          </view>
+          <view class="text-24rpx text-#F44033">
+            - {{ chargeOrderDetail?.memberDiscountAmount || '--' }}元
           </view>
         </view>
         <view class="mt-28rpx flex items-center justify-between">
@@ -169,7 +177,7 @@ async function getOrderDetail() {
             积分扣减
           </view>
           <view class="text-24rpx text-#F44033">
-            {{ chargeOrderDetail ? (chargeOrderDetail.actualTotal || 0) - (chargeOrderDetail.platformVolume || 0) : '--' }}元
+            - {{ chargeOrderDetail ? (chargeOrderDetail.actualTotal || 0) - (chargeOrderDetail.platformVolume || 0) : '--' }}元
           </view>
         </view>
         <view class="mt-28rpx flex items-center justify-between">

+ 3 - 0
src/subPack-charge/chargePlateList/chargePlateList.vue

@@ -92,6 +92,9 @@ function handleDelete(id: number) {
         <view class="mt-10rpx">
           4.车牌绑定未按正确操作流程或车牌未对应现场充电车辆导致无法减免停车费,因此产生的一切损失与本平台无关。
         </view>
+        <view class="mt-10rpx">
+          5.部分充电站以停车场收费规则为准,暂不支持充电免停车费,请留意场站页面停车规则提示。
+        </view>
       </view>
     </view>
     <view

+ 1 - 1
src/subPack-smqjh/components/xsb-orderList/xsb-orderList.vue

@@ -177,7 +177,7 @@ async function handleLogistics(_order: Api.xsbOrderList) {
           </wd-button>
         </view>
       </template>
-      <template v-if="order.refundStatus != 2 && [OrderStatus.OrderWaitDelivery, OrderStatus.OrderAccepted].includes(order.hbOrderStatus) ">
+      <template v-if="!order.giftOrder && order.refundStatus != 2 && [OrderStatus.OrderWaitDelivery, OrderStatus.OrderAccepted].includes(order.hbOrderStatus) ">
         <view class="mr-20rpx">
           <wd-button size="small" plain type="info" @click.stop="() => handleAfterSale(order)">
             申请售后

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

@@ -0,0 +1,145 @@
+<script setup lang="ts">
+import router from '@/router'
+
+definePage({
+  name: 'smqjh-giveaways-vip',
+  islogin: true,
+  style: {
+    navigationBarTitleText: '选择赠品',
+  },
+})
+onMounted(() => {
+  getGiftsList()
+})
+const { selectedAddress } = storeToRefs(useUserStore())
+const giveawaysList = ref<Api.giftsListModel[]>([])
+const isPicking = ref(false)
+async function getGiftsList() {
+  const res = await Apis.sys.giftsList({})
+  giveawaysList.value = res.data || []
+}
+function handleChange(value: any) {
+  console.log(value)
+}
+
+async function pickUp() {
+  const addressId = selectedAddress.value?.id
+  if (!addressId) {
+    useGlobalToast().show({ msg: '请选择收货地址' })
+    return
+  }
+  if (!giveawaysList.value.length) {
+    useGlobalToast().show({ msg: '暂无可领取赠品' })
+    return
+  }
+
+  const firstGift = giveawaysList.value[0]
+  const hasInvalidGift = giveawaysList.value.some(item => !item.skuId || !item.shopId || !item.channelId)
+  if (hasInvalidGift) {
+    useGlobalToast().show({ msg: '赠品数据异常' })
+    return
+  }
+
+  const hasDifferentShopOrChannel = giveawaysList.value.some((item) => {
+    return item.shopId !== firstGift.shopId || item.channelId !== firstGift.channelId
+  })
+  if (hasDifferentShopOrChannel) {
+    useGlobalToast().show({ msg: '赠品需来自同一门店和渠道' })
+    return
+  }
+
+  if (isPicking.value) {
+    return
+  }
+  isPicking.value = true
+  try {
+    const items = giveawaysList.value.map((item) => {
+      return {
+        skuId: item.skuId!,
+        quantity: Number(item.quantity || 1),
+        shopId: item.shopId!,
+        channelId: item.channelId!,
+      }
+    })
+    const totalGoodsPrice = Number(giveawaysList.value.reduce((sum, item) => {
+      return sum + Math.round(Number(item.price || 0) * 100) * Number(item.quantity || 1)
+    }, 0) / 100)
+    const orderInfo = {
+      totalPrice: 0,
+      transfee: 0,
+      offsetPoints: 0,
+      shopName: firstGift.shopName || '',
+      price: totalGoodsPrice,
+      amount: 0,
+      coupon: 0,
+      couponName: '',
+      orderCouponItemDTOS: [],
+      memberGiftAddressId: addressId,
+      memberGiftItems: items,
+      skuList: giveawaysList.value.map((item) => {
+        return {
+          prodId: item.spuId || 0,
+          num: Number(item.quantity || 1),
+          pic: item.picUrl,
+          price: item.price ?? '0',
+          shopId: item.shopId!,
+          shopSkuStocks: String(item.stock ?? ''),
+          skuId: item.skuId!,
+          skuName: item.spuName || item.skuName,
+          spec: item.skuName,
+        }
+      }),
+    }
+    router.push({
+      name: 'xsb-confirmOrder',
+      params: { data: JSON.stringify(orderInfo) },
+    })
+  }
+  finally {
+    isPicking.value = false
+  }
+}
+</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">
+        <wd-icon name="check-circle-filled" size="20px" color="var(--them-color)" />
+      </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 :model-value="Number(item.quantity) || 1" 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" :loading="isPicking" @click="pickUp">
+      免费领取
+    </wd-button>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

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

@@ -0,0 +1,229 @@
+<script setup lang="ts">
+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',
+  },
+
+})
+const { userMemberInfo } = storeToRefs(useUserStore())
+const rightsInfo = ref()
+const showRightsContent = computed(() => userMemberInfo.value.active || userMemberInfo.value.memberStatus === 'EXPIRED')
+const isMemberExpired = computed(() => userMemberInfo.value.memberStatus === 'EXPIRED')
+onMounted(() => {
+  useUserStore().getUserInfo()
+  opcity.value = 0
+  try {
+    rightsInfo.value = userMemberInfo.value.benefitConfigJson
+      ? JSON.parse(userMemberInfo.value.benefitConfigJson)
+      : null
+  }
+  catch {
+    rightsInfo.value = null
+  }
+})
+
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+
+function toUse() {
+  if (isMemberExpired.value)
+    return
+  wx.openOfficialAccountArticle({
+    url: 'https://mp.weixin.qq.com/s/lxpdZ6DUhgqg00AT9klu5Q',
+  })
+}
+function toShoppingList() {
+  if (isMemberExpired.value)
+    return
+  if (!userMemberInfo?.value.giftReceived) {
+    router.push({ name: 'smqjh-giveaways-vip' })
+  }
+  else {
+    useGlobalToast().show({ msg: '您已经领取过咯~~' })
+  }
+}
+function handleRightsClick(callback: () => void) {
+  if (isMemberExpired.value) {
+    useGlobalToast().show({ msg: '会员已失效,请重新开通' })
+    return
+  }
+  callback()
+}
+</script>
+
+<template>
+  <view class="min-h-screen" :class="showRightsContent ? '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="showRightsContent" 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-14rpx">
+        <view v-if="rightsInfo?.oilPerLiterDiscount" 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">
+            全省中石化优惠
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                每升立减{{ rightsInfo?.oilPerLiterDiscount }}元
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx text-center text-24rpx text-#7F5935 line-height-42rpx" :class="isMemberExpired ? 'bg-#999 text-#ccc' : 'bg-#F4E5BD'" @click="toUse">
+                去使用
+              </view>
+            </view>
+            <image :src="rightsInfo?.oilIcon" class="h-80rpx w-80rpx" />
+          </view>
+        </view>
+        <view v-if="rightsInfo?.mallDiscountRate" 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">
+            市民请集合平台快消品
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                折扣率{{ rightsInfo?.mallDiscountRate }}折
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx text-center text-24rpx text-#7F5935 line-height-42rpx" :class="isMemberExpired ? 'bg-#999 text-#ccc' : 'bg-#F4E5BD'" @click="handleRightsClick(() => router.push({ name: 'xsb-homeTabbar' }))">
+                去使用
+              </view>
+            </view>
+            <image :src="rightsInfo?.mallIcon" class="h-80rpx w-80rpx" />
+          </view>
+        </view>
+        <view v-if="rightsInfo?.chargePerKwhDiscount" 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">
+            全省贵阳城投充电桩优惠
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                每度电立减{{ rightsInfo?.chargePerKwhDiscount }}元
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx text-center text-24rpx text-#7F5935 line-height-42rpx" :class="isMemberExpired ? 'bg-#999 text-#ccc' : 'bg-#F4E5BD'" @click="handleRightsClick(() => router.push({ name: 'charge-index' }))">
+                去使用
+              </view>
+            </view>
+            <image :src="rightsInfo?.chargeIcon" class="h-80rpx w-80rpx" />
+          </view>
+        </view>
+        <view v-if="rightsInfo?.parkingDiscountRate" 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">
+            贵阳城投停车场优惠
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                折扣率{{ rightsInfo?.parkingDiscountRate }}折
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx text-center text-24rpx text-#7F5935 line-height-42rpx" :class="isMemberExpired ? 'bg-#999 text-#ccc' : 'bg-#F4E5BD'" @click="handleRightsClick(() => router.push({ name: rightsInfo?.parkingRoutePath }))">
+                去使用
+              </view>
+            </view>
+            <image :src="rightsInfo?.parkingIcon" class="h-80rpx w-80rpx" />
+          </view>
+        </view>
+        <view v-if="userMemberInfo?.couponConfig?.length > 0" 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">
+            优惠券
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                优惠券{{ userMemberInfo?.couponCount }}张
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx text-center text-24rpx text-#7F5935 line-height-42rpx" :class="isMemberExpired ? 'bg-#999 text-#ccc' : 'bg-#F4E5BD'" @click="handleRightsClick(() => router.push({ name: 'xsb-coupon', params: { type: 'VIP' } }))">
+                去查看
+              </view>
+            </view>
+            <image :src="userMemberInfo?.couponConfig?.[0]?.icon" class="h-80rpx w-80rpx" />
+          </view>
+        </view>
+        <view v-if="userMemberInfo?.giftConfig?.length > 0" 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">
+            自选赠品
+          </view>
+          <view class="mt-20rpx flex items-center justify-between">
+            <view>
+              <view class="text-28rpx text-#b5b5b5">
+                自选赠品{{ userMemberInfo?.giftCount }}个
+              </view>
+              <view class="mt-16rpx h-42rpx w-108rpx rounded-22rpx text-center text-24rpx text-#7F5935 line-height-42rpx" :class="isMemberExpired ? 'bg-#999 text-#ccc' : 'bg-#F4E5BD'" @click="toShoppingList">
+                {{ userMemberInfo?.giftReceived ? '已领取' : '待领取' }}
+              </view>
+            </view>
+            <image :src="userMemberInfo?.giftConfig?.[0]?.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: `优惠券${userMemberInfo.value.couponCount}张`,
+    icon: `${StaticUrl}/vip-yhq.png`,
+    route: 'xsb-coupon',
+  },
+  {
+    id: 6,
+    title: '自选赠品',
+    desc: `自选赠品${userMemberInfo.value.giftCount}个`,
+    icon: `${StaticUrl}/vip-zxzp.png`,
+    route: 'smqjh-giveaways-vip',
+  },
+]

+ 19 - 3
src/subPack-xsb/commonTab/components/cart.vue

@@ -4,7 +4,7 @@ import router from '@/router'
 import { useSmqjhCartStore } from '@/store/cart'
 
 const emit = defineEmits(['changeTab'])
-
+const { userMemberInfo } = storeToRefs(useUserStore())
 const { cartList, isCartAllChecked, totalProduct } = storeToRefs(useSmqjhCartStore())
 const cartStore = useSmqjhCartStore()
 const priceDetailPopup = ref(false)
@@ -84,7 +84,15 @@ onMounted(async () => {
                       规格:{{ item.spec }}
                     </view>
                     <view class="mt14rpx flex items-center justify-between">
-                      <view class="text-36rpx text-#FF4A39 font-semibold">
+                      <view v-if="userMemberInfo.active" class="flex items-center gap-20rpx">
+                        <view class="text-36rpx text-[#FF4A39] font-semibold">
+                          ¥{{ item.memberPrice }}
+                        </view>
+                        <view class="text-26rpx text-#AAAAAA line-through">
+                          ¥{{ item.price }}
+                        </view>
+                      </view>
+                      <view v-else class="text-36rpx text-[#FF4A39] font-semibold">
                         ¥{{ item.price }}
                       </view>
                       <!-- <wd-input-number v-model="item.num" disable-input @change="handleChangeNum($event, item)" /> -->
@@ -149,7 +157,7 @@ onMounted(async () => {
                 ¥ {{ totalProduct?.amount || 0 }}
               </view>
               <view v-if="totalProduct?.coupon" class="ml10rpx text-24rpx text-#FF4A39">
-                共减¥{{ totalProduct?.coupon }}
+                共减¥{{ totalProduct?.coupon + (totalProduct?.memberDiscountAmount || 0) }}
               </view>
               <view v-if="totalProduct?.amount" class="ml10rpx flex items-center text-24rpx text-gray" @click="priceDetailPopup = !priceDetailPopup">
                 明细 <view class="flex items-center" :class="[priceDetailPopup ? 'rotate-180' : '']">
@@ -211,6 +219,14 @@ onMounted(async () => {
             </view>
           </view>
         </template>
+        <view v-if="totalProduct?.memberDiscountAmount" class="flex items-center justify-between py-20rpx">
+          <view class="text-28rpx text-#333">
+            {{ totalProduct?.memberBenefitDesc }}
+          </view>
+          <view class="text-28rpx text-#FF4A39 font-semibold">
+            -¥{{ totalProduct?.memberDiscountAmount }}
+          </view>
+        </view>
         <view class="flex items-center justify-between py-20rpx">
           <view class="text-28rpx text-#333">
             配送费

+ 25 - 4
src/subPack-xsb/commonTab/components/classfiy.vue

@@ -433,7 +433,7 @@ export default {
       :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }"
     >
       <scroll-view
-        :scroll-into-view-offset="-150" enable-passive scroll-with-animation scroll-x
+        :scroll-into-view-offset="-150" scroll-x enable-passive scroll-with-animation
         class="scrollx w-90% flex-shrink-0 whitespace-nowrap" :scroll-into-view="`id${topScrollView}`"
       >
         <view class="flex items-end pb10rpx">
@@ -569,7 +569,20 @@ export default {
                       </view>
                     </view>
                     <view class="flex items-center justify-between">
-                      <view class="text-#FF4D3A font-semibold">
+                      <view v-if="item.isMember" class="flex items-center gap-8rpx text-#FF4D3A">
+                        <text class="text-24rpx">
+                          ¥
+                        </text> <text class="text-30rpx">
+                          {{ item.memberPrice }}
+                        </text>
+                        <!--                        <view class="rounded-8rpx bg-#FF4A39 px-8rpx py-4rpx text-22rpx text-#FFF"> -->
+                        <!--                          会员价 -->
+                        <!--                        </view> -->
+                        <text class="text-24rpx text-#AAA line-through">
+                          {{ item.channelProdPrice }}
+                        </text>
+                      </view>
+                      <view v-else class="text-#FF4D3A">
                         <text class="text-24rpx">
                         </text> <text class="text-36rpx">
@@ -664,7 +677,7 @@ export default {
                 ¥ {{ totalProduct?.amount || 0 }}
               </view>
               <view v-if="totalProduct?.coupon" class="ml10rpx text-24rpx text-#FF4A39">
-                共减¥{{ totalProduct?.coupon }}
+                共减¥{{ totalProduct?.coupon + (totalProduct?.memberDiscountAmount || 0) }}
               </view>
               <view
                 v-if="totalProduct?.amount" class="ml10rpx flex items-center text-24rpx text-gray"
@@ -747,6 +760,14 @@ export default {
             </view>
           </view>
         </template>
+        <view v-if="totalProduct?.memberDiscountAmount" class="flex items-center justify-between py-20rpx">
+          <view class="text-28rpx text-#333">
+            {{ totalProduct?.memberBenefitDesc }}
+          </view>
+          <view class="text-28rpx text-#FF4A39 font-semibold">
+            -¥{{ totalProduct?.memberDiscountAmount }}
+          </view>
+        </view>
         <!-- 配送费 -->
         <view class="flex items-center justify-between py-20rpx">
           <view class="text-28rpx text-#333">
@@ -853,7 +874,7 @@ export default {
       <template #footer>
         <view class="box-border w-full flex items-center justify-between py20rpx">
           <view class="w-48%">
-            <wd-button hairline plain block @click="selectGoods = false">
+            <wd-button plain hairline block @click="selectGoods = false">
               取消
             </wd-button>
           </view>

+ 2 - 1
src/subPack-xsb/commonTab/index.vue

@@ -51,11 +51,12 @@ function handleTabbarChange({ value }: { value: string }) {
   tabbarName.value = value
 }
 watch(() => isClassfiyPageOpen.value, () => {
+  console.log('isClassfiyPageOpen')
   if (isClassfiyPageOpen.value) {
     handleChange('xsb-classfiy')
     isClassfiyPageOpen.value = false
   }
-})
+}, { deep: true, immediate: true })
 function setTabbarItemActive(name: string) {
   tabbarItems.value.forEach((item) => {
     if (item.name === name) {

+ 11 - 5
src/subPack-xsb/components/coupon/index.vue

@@ -3,20 +3,26 @@ import { dayjs } from 'wot-design-uni'
 import { StaticUrl } from '@/config'
 import router from '@/router'
 
-defineProps<{
+const props = defineProps<{
   itemcoupon: Api.AppMemberCouponVO
   /** 是否显示"去使用"按鈕,默认 true */
   showUseBtn?: boolean
   /** 隐藏所有操作按鈕(选券模式用) */
   hideAllBtn?: boolean
+  /** 路由参数类型 */
+  routeType?: string
 }>()
 const {
   isClassfiyPageOpen,
 } = storeToRefs(useSysXsbStore())
 function handleUseCoupon() {
-  isClassfiyPageOpen.value = true
-  // router.replace({ name: 'xsb-homeTabbar', params: { name: 'xsb-classfiy' } })
-  router.back()
+  if (props.routeType === 'VIP') {
+    router.replace({ name: 'xsb-homeTabbar', params: { name: 'xsb-classfiy' } })
+  }
+  else {
+    isClassfiyPageOpen.value = true
+    router.back()
+  }
 }
 </script>
 
@@ -81,7 +87,7 @@ function handleUseCoupon() {
             >
               去使用
             </view>
-            <wd-button v-if="itemcoupon.useStatus === 1" hairline plain size="small" type="info" @click="router.replace({ name: 'xsb-orderDetaile', params: { id: String(itemcoupon.lockOrderId) } })">
+            <wd-button v-if="itemcoupon.useStatus === 1" plain hairline size="small" type="info" @click="router.replace({ name: 'xsb-orderDetaile', params: { id: String(itemcoupon.lockOrderId) } })">
               查看订单
             </wd-button>
             <wd-button v-if="itemcoupon.useStatus === 7" plain hairline size="small" type="info" @click="router.replace({ name: 'xsb-orderDetaile', params: { id: String(itemcoupon.lockOrderId) } })">

+ 17 - 1
src/subPack-xsb/components/goodsItem/index.vue

@@ -33,7 +33,23 @@ defineProps<{ itemGoods: Api.xsbCategoryProductList }>()
 
         <view class="mt10rpx flex items-center justify-between">
           <view>
-            <view class="mt20rpx flex items-end text-#FF4D3A font-semibold">
+            <view v-if="itemGoods.isMember" class="mt-20rpx flex items-center gap-16rpx">
+              <view class="flex items-end text-[#FF4D3A]">
+                <view class="text-24rpx">
+                  ¥
+                </view>
+                <view class="text-36rpx line-height-[36rpx]">
+                  {{ itemGoods.memberPrice }}
+                </view>
+                <view class="text-24rpx">
+                  元
+                </view>
+              </view>
+              <view class="text-24rpx text-#AAA line-through">
+                ¥{{ itemGoods.channelProdPrice }}
+              </view>
+            </view>
+            <view v-else class="mt20rpx flex items-end text-#FF4D3A font-semibold">
               <view class="text-24rpx">
               </view>

+ 240 - 28
src/subPack-xsb/confirmOrder/index.vue

@@ -2,6 +2,7 @@
 import CouponItem from '../components/coupon/index.vue'
 import router from '@/router'
 
+const { userMemberInfo } = storeToRefs(useUserStore())
 definePage({
   name: 'xsb-confirmOrder',
   islogin: true,
@@ -11,15 +12,39 @@ definePage({
 })
 const { selectedAddress, userInfo } = storeToRefs(useUserStore())
 const { SelectShopInfo } = storeToRefs(useSysXsbStore())
-const orderInfo = ref<Api.shoppingCartOrderConfirm>()
+const { Location } = storeToRefs(useAddressStore())
+type ConfirmOrderInfo = Api.shoppingCartOrderConfirm & Partial<Api.AppletOrderSkuVo>
+
+const orderInfo = ref<ConfirmOrderInfo>()
 const { totalProduct } = storeToRefs(useSmqjhCartStore())
 const isPay = ref(false)
 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 mobilePattern = /^1[3-9]\d{9}$/
+const mobileRules = [{ required: true, pattern: mobilePattern, message: '请输入正确的手机号' }]
 const deliveryType = ref(1)
+const isMemberGiftOrder = computed(() => !!orderInfo.value?.memberGiftItems?.length)
+const isSingleSkuOrder = computed(() => (orderInfo.value?.skuList?.length || 0) <= 1)
+const isSelfPickup = computed(() => current.value === '自提')
+const shopAddressInfo = computed(() => orderInfo.value?.shopAddressDTO)
+const shopDistanceText = computed(() => {
+  const distance = shopAddressInfo.value?.distance
+  if (distance === undefined || distance === null) {
+    return ''
+  }
+  return `距你${Number(distance).toFixed(2)}km`
+})
 
 // 优惠券选择
 const couponPopup = ref(false)
@@ -37,9 +62,15 @@ const currentCouponDiscount = computed(() => {
   }
   return Number(orderInfo.value?.coupon || 0)
 })
+const memberDiscountCents = computed(() => {
+  if (!isMemberGiftOrder.value && userMemberInfo.value?.active) {
+    return Math.round(Number(unref(orderInfo)?.memberDiscountAmount || 0) * 100)
+  }
+  return 0
+})
 const offsetPoints = computed(() => {
   const couponCents = Math.round(currentCouponDiscount.value * 100)
-  const money = Math.round(Number(unref(orderInfo)?.transfee) * 100) + Math.round(Number(unref(orderInfo)?.price) * 100) - couponCents
+  const money = Math.round(Number(unref(orderInfo)?.transfee) * 100) + Math.round(Number(unref(orderInfo)?.price) * 100) - couponCents - memberDiscountCents.value
   const cap = Math.max(0, money)
   if (Number(unref(orderInfo)?.offsetPoints) > cap) {
     return cap
@@ -62,21 +93,35 @@ const displayTotalPrice = computed(() => {
   const goodsPrice = Number(orderInfo.value.price || 0)
   const freight = Number(orderInfo.value.transfee || 0)
   const pointsDiscount = offsetPoints.value / 100
-  return Math.max(0, Number((goodsPrice + freight - currentCouponDiscount.value - pointsDiscount).toFixed(2)))
+  const memberDiscount = memberDiscountCents.value / 100
+  return Math.max(0, Number((goodsPrice + freight - currentCouponDiscount.value - pointsDiscount - memberDiscount).toFixed(2)))
+})
+const displayDiscountTotal = computed(() => Number((currentCouponDiscount.value + offsetPoints.value / 100 + memberDiscountCents.value / 100).toFixed(2)))
+const giftOriginalTotal = computed(() => {
+  if (!isMemberGiftOrder.value)
+    return 0
+  return Number((Number(orderInfo.value?.price || 0) + Number(orderInfo.value?.transfee || 0)).toFixed(2))
 })
-const displayDiscountTotal = computed(() => Number((currentCouponDiscount.value + offsetPoints.value / 100).toFixed(2)))
 
 onLoad((options: any) => {
   orderInfo.value = JSON.parse(options.data)
-  couponList.value = orderInfo.value?.orderCouponItemDTOS || []
-  initialCouponId.value = orderInfo.value?.allowanceId
-  confirmedCouponId.value = initialCouponId.value
-  draftCouponId.value = initialCouponId.value
+  console.log(orderInfo.value, '===商品数据===')
+  syncCouponState()
+  deliveryType.value = current.value === '自提' ? 2 : 3
+  // model.value1 = userInfo.value?.nickName || ''
+  model.value2 = userInfo.value?.mobile || ''
 })
 onShow(() => {
   useUserStore().getuserAddresslist()
-  if (selectedAddress.value) {
-    getDevryList()
+  if (orderInfo.value && current.value === '即时配送' && (isSingleSkuOrder.value || isMemberGiftOrder.value)) {
+    getConfirmOrder()
+  }
+})
+
+watch(current, async (value) => {
+  deliveryType.value = value === '自提' ? 2 : 3
+  if (orderInfo.value && (isSingleSkuOrder.value || isMemberGiftOrder.value)) {
+    await getConfirmOrder()
   }
 })
 
@@ -84,16 +129,70 @@ function getCouponDisplayName(coupon?: Partial<Api.AppMemberCouponVO> & Record<s
   return coupon?.activityName || coupon?.couponName || ''
 }
 
-async function getDevryList() {
-  const res = await Apis.xsb.delivery({
-    data: {
-      memberId: userInfo.value.id,
-      shopId: Number(orderInfo.value?.skuList[0].shopId || SelectShopInfo.value?.shopId || 2),
-      addressId: selectedAddress.value?.id,
-    },
+function syncCouponState() {
+  couponList.value = orderInfo.value?.orderCouponItemDTOS || []
+  initialCouponId.value = orderInfo.value?.allowanceId
+  confirmedCouponId.value = initialCouponId.value
+  draftCouponId.value = initialCouponId.value
+}
+
+function getOrderConfirmParams() {
+  const firstSku = orderInfo.value?.skuList?.[0]
+  return {
+    skuId: firstSku?.skuId,
+    num: Number(firstSku?.num || 1),
+    channelId: userInfo.value?.channelId,
+    shopId: Number(firstSku?.shopId || SelectShopInfo.value?.shopId || 2),
+    dvyType: deliveryType.value,
+  }
+}
+
+async function getConfirmOrder() {
+  const params: Record<string, any> = getOrderConfirmParams()
+  if (!params.skuId) {
+    return
+  }
+  if (isSelfPickup.value) {
+    if (!Location.value.latitude || !Location.value.longitude) {
+      useGlobalToast().show('暂无定位缓存,无法计算自提点距离')
+    }
+    else {
+      params.latitude = Location.value.latitude
+      params.longitude = Location.value.longitude
+    }
+  }
+  const res = await Apis.xsb.skuOrderConfirm({
+    data: params,
+  })
+  if (isMemberGiftOrder.value) {
+    // 赠品订单仅更新配送费和店铺地址信息,保留原始商品数据
+    orderInfo.value = {
+      ...orderInfo.value,
+      transfee: res.data.transfee ?? orderInfo.value?.transfee ?? 0,
+      shopAddressDTO: res.data.shopAddressDTO ?? orderInfo.value?.shopAddressDTO,
+    } as ConfirmOrderInfo
+  }
+  else {
+    const originalSku = orderInfo.value?.skuList?.[0]
+    const skuList = res.data.sku
+      ? [{ ...res.data.sku, id: originalSku?.id, num: params.num, shopId: params.shopId }]
+      : (orderInfo.value?.skuList || [])
+    orderInfo.value = {
+      ...orderInfo.value,
+      ...res.data,
+      skuList,
+    } as ConfirmOrderInfo
+    syncCouponState()
+  }
+}
+
+function openShopLocation() {
+  uni.openLocation({
+    latitude: Number(shopAddressInfo.value?.shopLat) || 0,
+    longitude: Number(shopAddressInfo.value?.shopLng) || 0,
+    name: shopAddressInfo.value?.shopName,
+    address: shopAddressInfo.value?.shopAddress,
   })
-  deliveryType.value = res.data.deliveryType
-  console.log(res)
 }
 
 async function openCouponPopup() {
@@ -119,7 +218,7 @@ function confirmCoupon() {
 }
 
 async function handlePay() {
-  if (!selectedAddress.value) {
+  if (!isSelfPickup.value && !selectedAddress.value) {
     useGlobalToast().show({ msg: '请选择收货地址' })
     return
   }
@@ -127,8 +226,33 @@ async function handlePay() {
     useGlobalToast().show({ msg: '网络异常!请联系客服' })
     return
   }
+  if (isSelfPickup.value) {
+    if (!model.value1) {
+      useGlobalToast().show({ msg: '请填写联系人' })
+      return
+    }
+    if (!mobilePattern.test(model.value2)) {
+      useGlobalToast().show({ msg: '请输入正确的手机号' })
+      return
+    }
+  }
   isPay.value = true
   try {
+    if (isMemberGiftOrder.value) {
+      console.log('=====赠品订单')
+      if (!selectedAddress.value) {
+        useGlobalToast().show({ msg: '请选择收货地址' })
+        return
+      }
+      await Apis.sys.giftsReceive({
+        data: {
+          addressId: selectedAddress.value.id,
+          items: orderInfo.value.memberGiftItems,
+        },
+      })
+      await useUserStore().paySuccess('xsb-order', 'subPack-xsb/commonTab/index')
+      return
+    }
     const orderItemList = orderInfo.value?.skuList.map((it) => {
       return {
         prodCount: it.num,
@@ -144,9 +268,16 @@ async function handlePay() {
       orderItemList,
       unref(remarks),
       confirmedCouponId.value,
+      isSelfPickup.value
+        ? {
+            consigneeName: model.value1,
+            consigneeMobile: model.value2,
+          }
+        : undefined,
     )
     // #ifdef MP-WEIXIN
     const res = await useUserStore().handleCommonPayMent(orderNumber)
+    console.log(orderInfo.value, '=====订单信息')
     await useUserStore().clearCart(orderInfo.value.skuList)
     totalProduct.value = null
     if (res.payType !== 1) {
@@ -177,8 +308,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">
@@ -210,6 +343,51 @@ async function handlePay() {
       </view>
     </view>
 
+    <view v-else class="my20rpx rounded-16rpx bg-white p24rpx">
+      <view class="flex items-center gap-50rpx">
+        <view class="flex-1">
+          <view class="text-28rpx font-semibold">
+            自提点:{{ shopAddressInfo?.shopName || orderInfo?.shopName || '暂无门店信息' }}
+          </view>
+          <view class="mt-20rpx text-24rpx text-#AAAAAA">
+            {{ shopAddressInfo?.shopAddress || '暂无门店地址' }}
+          </view>
+        </view>
+        <view class="flex-shrink-0" @click="openShopLocation">
+          <view v-if="shopDistanceText" class="mb-20rpx text-24rpx text-#AAAAAA">
+            {{ shopDistanceText }}
+          </view>
+          <wd-icon name="location" size="22px" color="#9ED605" />
+        </view>
+      </view>
+      <view>
+        <view class="mt-20rpx flex items-center">
+          <view class="w100rpx text-28rpx">
+            联系人:
+          </view>
+          <wd-input
+            v-model="model.value1"
+            prop="value1"
+            clearable
+            placeholder="请输入联系人"
+            :rules="[{ required: true, message: '请填写联系人' }]"
+          />
+        </view>
+        <view class="mt-20rpx flex items-center">
+          <view class="w140rpx text-28rpx">
+            预留电话:
+          </view>
+          <wd-input
+            v-model="model.value2"
+            prop="value2"
+            clearable
+            placeholder="请输入预留电话"
+            :rules="mobileRules"
+          />
+        </view>
+      </view>
+    </view>
+
     <view class="rounded-16rpx bg-white p24rpx">
       <view class="flex items-center text-28rpx font-semibold">
         {{ orderInfo?.shopName }}
@@ -223,6 +401,9 @@ async function handlePay() {
           <view class="flex-1">
             <view class="w-full flex items-center justify-between font-semibold">
               <view class="text-28rpx">
+                <text v-if="isMemberGiftOrder" class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
+                  赠品
+                </text>
                 {{ item.skuName }}
               </view>
               <view class="text-32rpx text-#FF4D3A">
@@ -253,11 +434,20 @@ async function handlePay() {
         <view v-if="deliveryType == 1">
           快递
         </view>
+        <view v-if="deliveryType == 2">
+          自提
+        </view>
         <view class="text-#FF4D3A font-semibold">
           ¥{{ orderInfo?.transfee }}
         </view>
       </view>
-      <view class="mb28rpx flex items-center justify-between text-28rpx" @click="openCouponPopup">
+      <view v-if="!isMemberGiftOrder && userMemberInfo.active" class="mb28rpx flex items-center justify-between text-28rpx">
+        <view>{{ orderInfo?.memberBenefitDesc }}</view>
+        <view class="text-#FF4D3A font-semibold">
+          -¥{{ orderInfo?.memberDiscountAmount }}
+        </view>
+      </view>
+      <view v-if="!isMemberGiftOrder" class="mb28rpx flex items-center justify-between text-28rpx" @click="openCouponPopup">
         <view>优惠券</view>
         <view class="flex items-center">
           <view v-if="currentCouponDiscount > 0" class="text-[#FF4D3A] font-semibold">
@@ -269,7 +459,7 @@ async function handlePay() {
           <wd-icon name="arrow-right" size="18px" color="#aaa" class="ml10rpx" />
         </view>
       </view>
-      <view class="flex items-center justify-between text-28rpx">
+      <view v-if="!isMemberGiftOrder" class="flex items-center justify-between text-28rpx">
         <view>积分({{ offsetPoints }})</view>
         <view class="text-#FF4D3A font-semibold">
           - ¥{{ offsetPoints / 100 }}
@@ -280,17 +470,31 @@ async function handlePay() {
         <view class="font-semibold">
           总计:
         </view>
-        <view class="text-#FF4D3A font-semibold">
+        <view v-if="isMemberGiftOrder" class="flex items-center">
+          <text class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
+            赠品
+          </text>
+          <text class="text-#AAAAAA line-through">
+            ¥{{ giftOriginalTotal }}
+          </text>
+        </view>
+        <view v-else class="text-#FF4D3A font-semibold">
           ¥ {{ displayTotalPrice }}
         </view>
       </view>
     </view>
+    <view v-if="isMemberGiftOrder" class="mt20rpx flex items-center gap-20rpx rounded-16rpx bg-white p24rpx">
+      <wd-icon name="warning" size="16px" color="#FF4D3A" />
+      <text class="text-24rpx">
+        本商品为会员权益赠品,购买后不支持售后
+      </text>
+    </view>
     <view class="mt20rpx flex items-center rounded-16rpx bg-white p24rpx">
       <view class="w80rpx">
         备注
       </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" />
@@ -369,9 +573,17 @@ 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 v-if="isMemberGiftOrder" class="flex items-center">
+          <text class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
+            赠品
+          </text>
+          <text class="text-32rpx text-#AAAAAA line-through">
+            ¥{{ giftOriginalTotal }}
+          </text>
+        </view>
+        <view v-else class="flex items-center text-#FF4D3A">
           <view class="font-semibold10 flex items-baseline text-36rpx">
             <text class="text-24rpx">

+ 5 - 0
src/subPack-xsb/coupon/index.vue

@@ -12,6 +12,7 @@ const tabList = [
 
 const activeTab = ref(0)
 const activeCoupon = ref(null)
+const routeType = ref('')
 
 const { data: couponList, isLastPage, page, reload } = usePagination(
   (pageNum, pageSize) => Apis.xsb.memberCouponPage({
@@ -32,6 +33,9 @@ const { data: couponList, isLastPage, page, reload } = usePagination(
 )
 onLoad((options: any) => {
   console.log(options)
+  if (options.type) {
+    routeType.value = options.type
+  }
   if (options.couponId) {
     activeCoupon.value = options.couponId
     switchTab(Number(options.activeTab))
@@ -69,6 +73,7 @@ onReachBottom(() => {
           <CouponItem
             :itemcoupon="item"
             :show-use-btn="item.useStatus === 2"
+            :route-type="routeType"
           />
         </view>
       </view>

+ 13 - 1
src/subPack-xsb/goods/index.vue

@@ -119,6 +119,7 @@ async function handleConfimOrder() {
         skuId: specId.value,
         num: SelectGoodsNum.value,
         channelId: unref(userInfo).channelId,
+        dvyType: 3,
         shopId: unref(goodsInfo)?.shopId || 2,
       },
     })
@@ -175,7 +176,18 @@ function handleClick() {
       </wd-swiper>
       <view class="view-0 header relative z-3 rounded-t-32rpx px24rpx pt24rpx -mt30rpx">
         <view class="flex items-center justify-between">
-          <view class="flex items-end text-#FF4D3A font-semibold">
+          <view v-if="goodsInfo?.isMember" class="flex items-end text-#FF4D3A font-semibold">
+            <view class="text-24rpx">
+              ¥
+            </view>
+            <view class="text-36rpx line-height-[36rpx]">
+              {{ goodsInfo?.memberPrice }}
+            </view>
+            <view class="ml-14rpx text-24rpx text-#AAA line-through">
+              ¥{{ goodsInfo?.channelProdPrice }}
+            </view>
+          </view>
+          <view v-else class="flex items-end text-#FF4D3A font-semibold">
             <view class="text-24rpx">
             </view>

+ 1 - 0
src/subPack-xsb/order/index.vue

@@ -13,6 +13,7 @@ const navTabTypeList = [
   { name: '全部', value: 0 },
   { name: '配送(外卖)', value: 3 },
   { name: '快递', value: 1 },
+  { name: '自提', value: 2 },
 ]
 
 const orderStatusList = [

+ 88 - 28
src/subPack-xsb/orderDetaile/index.vue

@@ -40,7 +40,6 @@ const mapTextShop = {
   [OrderStatus.OrderDelivering]: orderInfo.value?.dvyType === 3 ? '骑手配送中' : '待收货',
   [OrderStatus.OrderArrived]: '已送达',
 }
-
 const mapLation = computed(() => {
   const lation = {
     latitude: mapInfo.value?.shopLatitude,
@@ -252,6 +251,15 @@ async function handleMarkerTap(e: UniHelper.MapOnMarkertapEvent) {
     }
   }
 }
+function openShopLocation() {
+  uni.openLocation({
+    latitude: orderInfo.value?.latitude || 0,
+    longitude: orderInfo.value?.longitude || 0,
+    name: orderInfo.value?.shopName,
+    address: orderInfo.value?.consigneeAddress,
+  })
+}
+
 async function handleReceive() {
   await useUserStore().handleCommonOrderReceive(orderInfo.value as Api.xsbOrderList)
   getDetail(String(unref(orderInfo)?.orderNumber))
@@ -319,7 +327,7 @@ function handleRefundDetail(item: any) {
               商家拣货中
             </view>
             <view v-if="orderInfo.hbOrderStatus === OrderStatus.OrderWaitDelivery" class="mr-10rpx">
-              订单待配送
+              {{ orderInfo.dvyType === 2 ? '订单待自提' : '订单待配送' }}
             </view>
             <view v-if="orderInfo.hbOrderStatus === OrderStatus.OrderDelivering" class="mr-10rpx">
               订单配送中
@@ -382,7 +390,7 @@ function handleRefundDetail(item: any) {
             </Zcontact>
           </view>
           <view
-            v-if="orderInfo.refundStatus != 2 && [OrderStatus.OrderWaitDelivery, OrderStatus.OrderAccepted].includes(orderInfo.hbOrderStatus)"
+            v-if="!orderInfo?.giftOrder && orderInfo.refundStatus != 2 && [OrderStatus.OrderWaitDelivery, OrderStatus.OrderAccepted].includes(orderInfo.hbOrderStatus)"
             class="flex flex-col items-center" @click="handleAfterSale"
           >
             <image :src="`${StaticUrl}/orderDetaile-shou.png`" class="h-40rpx w-40rpx" />
@@ -411,7 +419,19 @@ function handleRefundDetail(item: any) {
         </view> -->
         </view>
       </view>
-      <view class="mt-20rpx rounded-16rpx bg-white p-24rpx">
+      <view v-if="orderInfo?.dvyType === 2" class="mt-20rpx flex flex-col items-center rounded-16rpx bg-white p-24rpx text-center">
+        <QCode class="mb-20rpx rounded-16rpx" :text="orderInfo?.selfPickCode" :qwidth="80" qr-key="0" />
+        <view class="text-28rpx font-semibold">
+          {{ orderInfo?.selfPickCode }}
+        </view>
+        <view class="text-28rpx" :class="orderInfo?.isWriteOff === 1 ? '' : 'line-through'">
+          {{ orderInfo?.isWriteOff === 1 ? '(未核销)' : '(已核销)' }}
+        </view>
+        <view class="mt-20rpx text-24rpx text-#AAA">
+          {{ orderInfo?.completeTime ? `核销时间:${orderInfo?.completeTime}` : '出示该二维码进行核销确认' }}
+        </view>
+      </view>
+      <view v-if="orderInfo?.dvyType === 3" class="mt-20rpx rounded-16rpx bg-white p-24rpx">
         <view class="flex items-center">
           <i class="iconfont text-40rpx text-[var(--them-color)]">&#xe654;</i>
           <!-- <image :src="`${StaticUrl}/orderDetaile-user.png`" class="mr-20rpx h-40rpx w-40rpx" /> -->
@@ -423,6 +443,27 @@ function handleRefundDetail(item: any) {
           {{ orderInfo?.consigneeAddress }}
         </view>
       </view>
+      <view v-if="orderInfo?.dvyType === 2" class="mt-20rpx rounded-16rpx bg-white p-24rpx">
+        <view class="flex items-center gap-50rpx">
+          <view class="flex-1">
+            <view class="text-28rpx font-semibold">
+              自提点:{{ orderInfo?.shopName }}
+            </view>
+            <view class="mt-20rpx text-24rpx text-#AAAAAA">
+              {{ orderInfo?.consigneeAddress }}
+            </view>
+          </view>
+          <view class="flex-shrink-0" @click="openShopLocation">
+            <wd-icon name="location" size="24px" color="#9ED605" />
+          </view>
+        </view>
+        <view class="mt-20rpx text-26rpx text-#AAA">
+          <view>联系人:{{ orderInfo?.consigneeName }}</view>
+          <view class="mt-20rpx">
+            预留电话:{{ orderInfo?.consigneeMobile }}
+          </view>
+        </view>
+      </view>
       <view class="mt-20rpx rounded-16rpx bg-white p-24rpx">
         <view class="flex items-center">
           <image :src="`${StaticUrl}/order-icon.png`" class="h-36rpx w-36rpx" />
@@ -439,6 +480,9 @@ function handleRefundDetail(item: any) {
             <view class="flex-1">
               <view class="w-full flex items-center justify-between font-semibold">
                 <view class="text-28rpx">
+                  <text v-if="orderInfo?.giftOrder" class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
+                    赠品
+                  </text>
                   {{ item.skuName }}
                 </view>
                 <view class="text-32rpx text-[#FF4D3A]">
@@ -464,42 +508,52 @@ function handleRefundDetail(item: any) {
             ¥{{ orderInfo?.total }}
           </view>
         </view>
-        <view class="mt-24rpx flex items-center justify-between">
-          <view v-if="orderInfo.dvyType == 3">
+        <view v-if="orderInfo.dvyType != 2" class="mt-24rpx flex items-center justify-between">
+          <view v-if="orderInfo.dvyType == 3" class="text-28rpx">
             配送费(即时配送)
           </view>
-          <view v-if="orderInfo.dvyType == 1">
+          <view v-if="orderInfo.dvyType == 1" class="text-28rpx">
             快递
           </view>
           <view class="text-[#FF4A39] font-semibold">
             ¥{{ orderInfo?.freightAmount }}
           </view>
         </view>
-        <view class="mt-24rpx flex items-center justify-between">
-          <view class="text-28rpx">
-            优惠券
-          </view>
-          <view class="text-[#FF4A39] font-semibold">
-            -¥{{ Number(orderInfo?.couponBaseInfoDTO?.discountMoney) || 0 }}
-          </view>
-        </view>
-        <view v-if="orderInfo.refundOrderList && orderInfo.refundOrderList.some((it) => it.refundOrderStatus == 1) " class="mt10rpx rounded-16rpx bg-#ccc p24rpx text-24rpx">
-          <view v-if="orderInfo?.isAll">
-            已退还优惠券:{{ orderInfo.couponBaseInfoDTO?.activityName }}
-            <view>优惠券已退回您的账户,可在“我的-优惠券”中查看</view>
+        <template v-if="!orderInfo?.giftOrder">
+          <view v-if="orderInfo?.memberDiscountDesc && orderInfo?.memberDiscountAmount" class="mt-24rpx flex items-center justify-between">
+            <view class="text-28rpx">
+              {{ orderInfo?.memberDiscountDesc || '-' }}
+            </view>
+            <view class="text-[#FF4A39] font-semibold">
+              -¥{{ orderInfo?.memberDiscountAmount }}
+            </view>
           </view>
-          <view v-else>
-            注:部分退款不退还优惠券
+          <view class="mt-24rpx flex items-center justify-between">
+            <view class="text-28rpx">
+              优惠券
+            </view>
+            <view class="text-[#FF4A39] font-semibold">
+              -¥{{ Number(orderInfo?.couponBaseInfoDTO?.discountMoney) || 0 }}
+            </view>
           </view>
-        </view>
-        <view class="mt-24rpx flex items-center justify-between">
-          <view class="text-28rpx">
-            积分
+          <view v-if="orderInfo.refundOrderList && orderInfo.refundOrderList.some((it) => it.refundOrderStatus == 1) " class="mt10rpx rounded-16rpx bg-#ccc p24rpx text-24rpx">
+            <view v-if="orderInfo?.isAll">
+              已退还优惠券:{{ orderInfo.couponBaseInfoDTO?.activityName }}
+              <view>优惠券已退回您的账户,可在“我的-优惠券”中查看</view>
+            </view>
+            <view v-else>
+              注:部分退款不退还优惠券
+            </view>
           </view>
-          <view class="text-[#FF4A39] font-semibold">
-            -¥{{ Number(orderInfo?.offsetPoints) / 100 }}
+          <view class="mt-24rpx flex items-center justify-between">
+            <view class="text-28rpx">
+              积分
+            </view>
+            <view class="text-[#FF4A39] font-semibold">
+              -¥{{ Number(orderInfo?.offsetPoints) / 100 }}
+            </view>
           </view>
-        </view>
+        </template>
         <view class="my-24rpx h-2rpx w-full bg-[#F0F0F0]" />
         <view class="flex items-center justify-end">
           <view class="text-28rpx">
@@ -532,6 +586,12 @@ function handleRefundDetail(item: any) {
           </view>
         </view>
       </view>
+      <view v-if="orderInfo?.giftOrder" class="mt20rpx flex items-center gap-20rpx rounded-16rpx bg-white p24rpx">
+        <wd-icon name="warning" size="16px" color="#FF4D3A" />
+        <text class="text-24rpx">
+          本商品为会员权益赠品,购买后不支持售后
+        </text>
+      </view>
       <view class="mt-20rpx rounded-16rpx bg-white p-24rpx">
         <view class="mb-24rpx text-28rpx font-semibold">
           订单信息

+ 12 - 1
src/subPack-xsb/search/index.vue

@@ -167,7 +167,18 @@ function handleSearchText(text: string) {
             <view class="text-32rpx font-semibold">
               {{ item.prodName }}
             </view>
-            <view class="mt14rpx text-36rpx text-#FF4A39 font-semibold">
+            <view v-if="item.isMember" class="mt14rpx flex items-center gap-16rpx">
+              <view class="text-36rpx text-#FF4A39 font-semibold">
+                ¥{{ item.memberPrice }}
+              </view>
+              <view class="rounded-8rpx bg-#FF4A39 px-8rpx py-4rpx text-22rpx text-#FFF">
+                会员价
+              </view>
+              <view class="text-24rpx text-#AAA line-through">
+                ¥{{ item.channelProdPrice }}
+              </view>
+            </view>
+            <view v-else class="mt14rpx text-36rpx text-#FF4A39 font-semibold">
               ¥{{ item.channelProdPrice }}
             </view>
           </view>

+ 2 - 0
src/uni-pages.d.ts

@@ -28,7 +28,9 @@ interface NavigateToOptions {
        "/subPack-common/threePayRes/index" |
        "/subPack-common/user-center/index" |
        "/subPack-smqjh/bannerDetaile/index" |
+       "/subPack-smqjh/giveawaysVip/giveawaysVip" |
        "/subPack-smqjh/order/index" |
+       "/subPack-smqjh/userVip/userVip" |
        "/subPack-film/choose-film/index" |
        "/subPack-film/choose-seat/index" |
        "/subPack-film/index/index" |