Browse Source

Merge branch 'master' of https://gitee.com/yudaocode/yudao-mall-uniapp into develop

# Conflicts:
#	pages/goods/index.vue
#	pages/order/addressSelection.vue
#	pages/order/confirm.vue
#	sheep/components/s-goods-column/s-goods-column.vue
YunaiV 11 months ago
parent
commit
f03fcf1373
72 changed files with 3203 additions and 2019 deletions
  1. 2 1
      .env
  2. 4 3
      manifest.json
  3. 12 0
      pages.json
  4. 44 22
      pages/activity/groupon/detail.vue
  5. 2 2
      pages/app/sign.vue
  6. 5 5
      pages/chat/components/messageList.vue
  7. 35 30
      pages/chat/components/messageListItem.vue
  8. 125 118
      pages/commission/components/commission-menu.vue
  9. 1 1
      pages/commission/goods.vue
  10. 27 6
      pages/commission/team.vue
  11. 48 12
      pages/commission/withdraw.vue
  12. 0 1
      pages/coupon/list.vue
  13. 149 104
      pages/goods/comment/add.vue
  14. 2 1
      pages/goods/comment/list.vue
  15. 0 3
      pages/goods/components/detail/detail-activity-tip.vue
  16. 27 9
      pages/goods/groupon.vue
  17. 110 263
      pages/goods/index.vue
  18. 2 6
      pages/index/cart.vue
  19. 6 5
      pages/index/category.vue
  20. 64 49
      pages/order/addressSelection.vue
  21. 132 79
      pages/order/confirm.vue
  22. 30 8
      pages/order/detail.vue
  23. 2 2
      pages/order/express/log.vue
  24. 261 0
      pages/order/pickUpVerify.vue
  25. 6 0
      pages/pay/index.vue
  26. 0 1
      pages/pay/result.vue
  27. 1 1
      pages/public/faq.vue
  28. 12 3
      pages/user/address/list.vue
  29. 282 0
      pages/user/goods_details_store/index.vue
  30. 1 1
      pages/user/wallet/score.vue
  31. 0 14
      sheep/api/migration/chat.js
  32. 1 1
      sheep/api/promotion/activity.js
  33. 13 11
      sheep/api/promotion/combination.js
  34. 0 17
      sheep/api/promotion/coupon.js
  35. 15 4
      sheep/api/promotion/seckill.js
  36. 16 0
      sheep/api/system/dict.js
  37. 19 1
      sheep/api/trade/delivery.js
  38. 10 0
      sheep/api/trade/order.js
  39. 19 11
      sheep/components/s-auth-modal/s-auth-modal.vue
  40. 5 5
      sheep/components/s-block-item/s-block-item.vue
  41. 162 138
      sheep/components/s-coupon-block/s-coupon-block.vue
  42. 24 1
      sheep/components/s-coupon-card/s-coupon-card.vue
  43. 6 16
      sheep/components/s-coupon-list/s-coupon-list.vue
  44. 20 9
      sheep/components/s-coupon-select/s-coupon-select.vue
  45. 19 8
      sheep/components/s-custom-navbar/s-custom-navbar.vue
  46. 17 8
      sheep/components/s-goods-card/s-goods-card.vue
  47. 180 206
      sheep/components/s-goods-column/s-goods-column.vue
  48. 241 70
      sheep/components/s-groupon-block/s-groupon-block.vue
  49. 2 2
      sheep/components/s-live-block/s-live-block.vue
  50. 306 326
      sheep/components/s-menu-button/s-menu-button.vue
  51. 93 71
      sheep/components/s-menu-grid/s-menu-grid.vue
  52. 26 2
      sheep/components/s-order-card/s-order-card.vue
  53. 238 73
      sheep/components/s-seckill-block/s-seckill-block.vue
  54. 49 13
      sheep/components/s-select-groupon-sku/s-select-groupon-sku.vue
  55. 1 5
      sheep/components/s-select-seckill-sku/s-select-seckill-sku.vue
  56. 1 1
      sheep/components/s-share-modal/canvas-poster/index.vue
  57. 5 5
      sheep/components/s-share-modal/canvas-poster/poster/groupon.js
  58. 92 84
      sheep/components/s-title-block/s-title-block.vue
  59. 166 148
      sheep/components/s-user-card/s-user-card.vue
  60. 28 2
      sheep/components/s-wallet-card/s-wallet-card.vue
  61. 1 1
      sheep/helper/index.js
  62. 5 1
      sheep/helper/utils.js
  63. 1 1
      sheep/hooks/useModal.js
  64. 8 6
      sheep/libs/sdk-h5-weixin.js
  65. 0 1
      sheep/platform/provider/wechat/miniProgram.js
  66. 1 2
      sheep/platform/provider/wechat/officialAccount.js
  67. 3 2
      sheep/platform/share.js
  68. 2 4
      sheep/request/index.js
  69. 7 1
      sheep/store/cart.js
  70. 9 12
      sheep/util/const.js
  71. BIN
      static/images/line.png
  72. BIN
      static/images/writeOff.png

+ 2 - 1
.env

@@ -18,7 +18,8 @@ SHOPRO_WEBSOCKET_PATH = /infra/ws
 SHOPRO_DEV_PORT = 3000
 SHOPRO_DEV_PORT = 3000
 
 
 # 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地  |  http(s)://xxx.xxx=自定义静态资源地址前缀
 # 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地  |  http(s)://xxx.xxx=自定义静态资源地址前缀
-SHOPRO_STATIC_URL = https://file.sheepjs.com
+SHOPRO_STATIC_URL = http://test.yudao.iocoder.cn
+### SHOPRO_STATIC_URL = https://file.sheepjs.com
 
 
 # 是否开启直播  1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启)
 # 是否开启直播  1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启)
 SHOPRO_MPLIVE_ON = 0
 SHOPRO_MPLIVE_ON = 0

+ 4 - 3
manifest.json

@@ -3,7 +3,7 @@
   "appid": "__UNI__460BC4C",
   "appid": "__UNI__460BC4C",
   "description": "基于 uni-app + Vue3 技术驱动的在线商城系统,内含诸多功能与丰富的活动,期待您的使用和反馈。",
   "description": "基于 uni-app + Vue3 技术驱动的在线商城系统,内含诸多功能与丰富的活动,期待您的使用和反馈。",
   "versionName": "2.1.0",
   "versionName": "2.1.0",
-  "versionCode": 183,
+  "versionCode": "183",
   "transformPx": false,
   "transformPx": false,
   "app-plus": {
   "app-plus": {
     "usingComponents": true,
     "usingComponents": true,
@@ -188,7 +188,8 @@
     "setting": {
     "setting": {
       "urlCheck": false,
       "urlCheck": false,
       "minified": true,
       "minified": true,
-      "postcss": true
+      "postcss": false,
+      "es6": false
     },
     },
     "optimization": {
     "optimization": {
       "subPackages": true
       "subPackages": true
@@ -216,7 +217,7 @@
   "h5": {
   "h5": {
     "template": "index.html",
     "template": "index.html",
     "router": {
     "router": {
-      "mode": "hash",
+      "mode": "history",
       "base": "./"
       "base": "./"
     },
     },
     "sdkConfigs": {
     "sdkConfigs": {

+ 12 - 0
pages.json

@@ -307,6 +307,18 @@
 						"title": "编辑地址"
 						"title": "编辑地址"
 					}
 					}
 				},
 				},
+                {
+                  "path": "goods_details_store/index",
+                  "style": {
+                    "navigationBarTitleText": "自提门店"
+                  },
+                  "meta": {
+                    "auth": true,
+                    "sync": true,
+                    "title": "地址管理",
+                    "group": "用户中心"
+                  }
+                },
 				{
 				{
 					"path": "wallet/money",
 					"path": "wallet/money",
 					"style": {
 					"style": {

+ 44 - 22
pages/activity/groupon/detail.vue

@@ -181,11 +181,11 @@
         </view>
         </view>
       </view>
       </view>
 
 
-      <!-- TODO 芋艿:这里暂时没接入 -->
-      <view v-if="state.data.goods">
+      <view v-if="!isEmpty(state.goodsInfo)">
+        <!-- 规格与数量弹框 -->
         <s-select-groupon-sku
         <s-select-groupon-sku
           :show="state.showSelectSku"
           :show="state.showSelectSku"
-          :goodsInfo="state.data.goods"
+          :goodsInfo="state.goodsInfo"
           :grouponAction="state.grouponAction"
           :grouponAction="state.grouponAction"
           :grouponNum="state.grouponNum"
           :grouponNum="state.grouponNum"
           @buy="onBuy"
           @buy="onBuy"
@@ -193,6 +193,7 @@
           @close="state.showSelectSku = false"
           @close="state.showSelectSku = false"
         />
         />
       </view>
       </view>
+
     </view>
     </view>
 
 
     <s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
     <s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
@@ -203,25 +204,28 @@
   import { computed, reactive } from 'vue';
   import { computed, reactive } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import { onLoad } from '@dcloudio/uni-app';
   import { onLoad } from '@dcloudio/uni-app';
-  import { useDurationTime } from '@/sheep/hooks/useGoods';
+  import { fen2yuan, useDurationTime } from '@/sheep/hooks/useGoods';
   import { showShareModal } from '@/sheep/hooks/useModal';
   import { showShareModal } from '@/sheep/hooks/useModal';
   import { isEmpty } from 'lodash-es';
   import { isEmpty } from 'lodash-es';
   import CombinationApi from '@/sheep/api/promotion/combination';
   import CombinationApi from '@/sheep/api/promotion/combination';
+  import SpuApi from '@/sheep/api/product/spu';
 
 
   const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
   const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
   const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
   const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
   const state = reactive({
   const state = reactive({
     data: {}, // 拼团详情
     data: {}, // 拼团详情
-    loading: true,
-    grouponAction: 'create',
-    showSelectSku: false,
-    grouponNum: 0,
-    number: 0,
-    activity: {},
+    goodsId: 0, // 商品ID
+    goodsInfo: {}, // 商品信息
+    showSelectSku: false, // 显示规格弹框
+    selectedSkuPrice: {}, // 选中的规格价格
+    activity: {}, // 团购活动
+    grouponId: 0, // 团购ID
+    grouponNum: 0, // 团购人数
+    grouponAction: 'create', // 团购操作
     combinationHeadId: null, // 拼团团长编号
     combinationHeadId: null, // 拼团团长编号
+    loading: true,
   });
   });
 
 
-  // todo 芋艿:分享要再接下
   const shareInfo = computed(() => {
   const shareInfo = computed(() => {
     if (isEmpty(state.data)) return {};
     if (isEmpty(state.data)) return {};
     return sheep.$platform.share.getShareInfo(
     return sheep.$platform.share.getShareInfo(
@@ -231,15 +235,14 @@
         desc: state.data.goods?.subtitle,
         desc: state.data.goods?.subtitle,
         params: {
         params: {
           page: '5',
           page: '5',
-          query: state.data.id,
+          query: state.data.headRecord.id,
         },
         },
       },
       },
       {
       {
         type: 'groupon', // 邀请拼团海报
         type: 'groupon', // 邀请拼团海报
         title: state.data.headRecord.spuName, // 商品标题
         title: state.data.headRecord.spuName, // 商品标题
         image: sheep.$url.cdn(state.data.headRecord.picUrl), // 商品主图
         image: sheep.$url.cdn(state.data.headRecord.picUrl), // 商品主图
-        price: state.data.goods?.price, // 商品价格
-        original_price: state.data.goods?.original_price, // 商品原价
+        price: fen2yuan(state.data.headRecord.combinationPrice), // 商品价格
       },
       },
     );
     );
   });
   });
@@ -251,33 +254,33 @@
     });
     });
   }
   }
 
 
-  // 去开团 TODO 芋艿:这里没接入
+  // 去开团
   function onCreateGroupon() {
   function onCreateGroupon() {
     state.grouponAction = 'create';
     state.grouponAction = 'create';
     state.grouponId = 0;
     state.grouponId = 0;
     state.showSelectSku = true;
     state.showSelectSku = true;
   }
   }
 
 
-  // 规格变更 TODO 芋艿:这里没接入
+  // 规格变更
   function onSkuChange(e) {
   function onSkuChange(e) {
     state.selectedSkuPrice = e;
     state.selectedSkuPrice = e;
   }
   }
 
 
-  // 立即参团 TODO 芋艿:这里没接入
+  // 立即参团
   function onJoinGroupon() {
   function onJoinGroupon() {
     state.grouponAction = 'join';
     state.grouponAction = 'join';
-    state.grouponId = state.data.activityId;
-    state.combinationHeadId = state.data.id;
-    state.grouponNum = state.data.num;
+    state.grouponId = state.data.headRecord.activityId;
+    state.combinationHeadId = state.data.headRecord.id;
+    state.grouponNum = state.data.headRecord.userSize;
     state.showSelectSku = true;
     state.showSelectSku = true;
   }
   }
 
 
-  // 立即购买 TODO 芋艿:这里没接入
+  // 立即购买
   function onBuy(sku) {
   function onBuy(sku) {
     sheep.$router.go('/pages/order/confirm', {
     sheep.$router.go('/pages/order/confirm', {
       data: JSON.stringify({
       data: JSON.stringify({
         order_type: 'goods',
         order_type: 'goods',
-        combinationActivityId: state.data.activity.id,
+        combinationActivityId: state.activity.id,
         combinationHeadId: state.combinationHeadId,
         combinationHeadId: state.combinationHeadId,
         items: [
         items: [
           {
           {
@@ -306,6 +309,25 @@
         data.headRecord.activityId,
         data.headRecord.activityId,
       );
       );
       state.activity = activity;
       state.activity = activity;
+      state.grouponNum = activity.userSize;
+      // 加载商品信息
+      const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
+      state.goodsId = spu.id;
+      // 默认显示最低价
+      activity.products.forEach((product) => {
+        spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
+      });
+      state.goodsInfo = spu;
+      // 价格、库存使用活动的
+      spu.skus.forEach((sku) => {
+        const product = activity.products.find((product) => product.skuId === sku.id);
+        if (product) {
+          sku.price = product.combinationPrice;
+        } else {
+          // 找不到可能是没配置,则不能发起秒杀
+          sku.stock = 0;
+        }
+      });
     } else {
     } else {
       state.data = null;
       state.data = null;
     }
     }

+ 2 - 2
pages/app/sign.vue

@@ -62,7 +62,7 @@
         </view>
         </view>
       </view>
       </view>
 
 
-      <!-- 签到说明 TODO @科举:这里改成【已累计签到】 -->
+      <!-- 签到说明 TODO @芋艿:【签到】这里改成【已累计签到】;改版,接入 sheepjs  -->
       <view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40">
       <view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40">
         <view class="activity-title ss-m-b-30">签到说明</view>
         <view class="activity-title ss-m-b-30">签到说明</view>
         <view class="activity-des">1、已累计签到{{state.signInfo.totalDay}}天</view>
         <view class="activity-des">1、已累计签到{{state.signInfo.totalDay}}天</view>
@@ -110,7 +110,7 @@
     signInfo: {}, // 签到信息
     signInfo: {}, // 签到信息
 
 
     signConfigList: [], // 签到配置列表
     signConfigList: [], // 签到配置列表
-    maxDay: 0, // 最大的签到天数 
+    maxDay: 0, // 最大的签到天数
 
 
     showModel: false, // 签到弹框
     showModel: false, // 签到弹框
     signResult: {}, // 签到结果
     signResult: {}, // 签到结果

+ 5 - 5
pages/chat/components/messageList.vue

@@ -7,7 +7,7 @@
             @scrolltoupper="onScrollToUpper" @query="queryList">
             @scrolltoupper="onScrollToUpper" @query="queryList">
     <template #top>
     <template #top>
       <!-- 撑一下顶部导航 -->
       <!-- 撑一下顶部导航 -->
-      <view style="height: 45px"></view>
+      <view :style="{ height: sys_navBar + 'px' }"></view>
     </template>
     </template>
     <!-- style="transform: scaleY(-1)"必须写,否则会导致列表倒置!!! -->
     <!-- style="transform: scaleY(-1)"必须写,否则会导致列表倒置!!! -->
     <!-- 注意不要直接在chat-item组件标签上设置style,因为在微信小程序中是无效的,请包一层view -->
     <!-- 注意不要直接在chat-item组件标签上设置style,因为在微信小程序中是无效的,请包一层view -->
@@ -33,7 +33,9 @@
   import { reactive, ref } from 'vue';
   import { reactive, ref } from 'vue';
   import KeFuApi from '@/sheep/api/promotion/kefu';
   import KeFuApi from '@/sheep/api/promotion/kefu';
   import { isEmpty } from '@/sheep/helper/utils';
   import { isEmpty } from '@/sheep/helper/utils';
-
+  import sheep from '@/sheep';
+  
+  const sys_navBar = sheep.$platform.navbar;
   const messageList = ref([]); // 消息列表
   const messageList = ref([]); // 消息列表
   const showNewMessageTip = ref(false); // 显示有新消息提示
   const showNewMessageTip = ref(false); // 显示有新消息提示
   const backToTopStyle = reactive({
   const backToTopStyle = reactive({
@@ -67,7 +69,7 @@
   };
   };
   /** 刷新消息列表 */
   /** 刷新消息列表 */
   const refreshMessageList = (message = undefined) => {
   const refreshMessageList = (message = undefined) => {
-    if (queryParams.pageNo != 1 && message !== undefined) {
+    if (message !== undefined) {
       showNewMessageTip.value = true;
       showNewMessageTip.value = true;
       // 追加数据
       // 追加数据
       pagingRef.value.addChatRecordData([message], false);
       pagingRef.value.addChatRecordData([message], false);
@@ -87,8 +89,6 @@
       return;
       return;
     }
     }
     showNewMessageTip.value = false;
     showNewMessageTip.value = false;
-    // 到底重置消息列表
-    refreshMessageList();
   };
   };
   defineExpose({ getMessageList, refreshMessageList });
   defineExpose({ getMessageList, refreshMessageList });
 </script>
 </script>

+ 35 - 30
pages/chat/components/messageListItem.vue

@@ -4,12 +4,20 @@
     <view class="message-item ss-flex-col scroll-item">
     <view class="message-item ss-flex-col scroll-item">
       <view class="ss-flex ss-row-center ss-col-center">
       <view class="ss-flex ss-row-center ss-col-center">
         <!-- 日期 -->
         <!-- 日期 -->
-        <view v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(message, messageIndex)"
-              class="date-message">
+        <view
+          v-if="
+            message.contentType !== KeFuMessageContentTypeEnum.SYSTEM &&
+            showTime(message, messageIndex)
+          "
+          class="date-message"
+        >
           {{ formatDate(message.createTime) }}
           {{ formatDate(message.createTime) }}
         </view>
         </view>
         <!-- 系统消息 -->
         <!-- 系统消息 -->
-        <view v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM" class="system-message">
+        <view
+          v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM"
+          class="system-message"
+        >
           {{ message.content }}
           {{ message.content }}
         </view>
         </view>
       </view>
       </view>
@@ -18,32 +26,35 @@
         v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"
         v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"
         class="ss-flex ss-col-top"
         class="ss-flex ss-col-top"
         :class="[
         :class="[
-              message.senderType === UserTypeEnum.ADMIN
-                ? `ss-row-left`
-                : message.senderType === UserTypeEnum.MEMBER
-                ? `ss-row-right`
-                : '',
-            ]"
+          message.senderType === UserTypeEnum.ADMIN
+            ? `ss-row-left`
+            : message.senderType === UserTypeEnum.MEMBER
+            ? `ss-row-right`
+            : '',
+        ]"
       >
       >
         <!-- 客服头像 -->
         <!-- 客服头像 -->
         <image
         <image
           v-show="message.senderType === UserTypeEnum.ADMIN"
           v-show="message.senderType === UserTypeEnum.ADMIN"
           class="chat-avatar ss-m-r-24"
           class="chat-avatar ss-m-r-24"
           :src="
           :src="
-                sheep.$url.cdn(message.senderAvatar) ||
-                sheep.$url.static('/static/img/shop/chat/default.png')
-              "
+            sheep.$url.cdn(message.senderAvatar) ||
+            sheep.$url.static('/static/img/shop/chat/default.png')
+          "
           mode="aspectFill"
           mode="aspectFill"
         ></image>
         ></image>
         <!-- 内容 -->
         <!-- 内容 -->
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
-          <view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}">
+          <view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
             <mp-html :content="replaceEmoji(message.content)" />
             <mp-html :content="replaceEmoji(message.content)" />
           </view>
           </view>
         </template>
         </template>
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">
-          <view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}"
-                :style="{ width: '200rpx' }">
+          <view
+            class="message-box"
+            :class="{ admin: message.senderType === UserTypeEnum.ADMIN }"
+            :style="{ width: '200rpx' }"
+          >
             <su-image
             <su-image
               class="message-img"
               class="message-img"
               isPreview
               isPreview
@@ -59,29 +70,23 @@
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
           <GoodsItem
           <GoodsItem
             :goodsData="getMessageContent(message)"
             :goodsData="getMessageContent(message)"
-            @tap="
-                    sheep.$router.go('/pages/goods/index', {
-                      id: getMessageContent(message).id,
-                    })
-                  "
+            @tap="sheep.$router.go('/pages/goods/index', { id: getMessageContent(message).spuId })"
           />
           />
         </template>
         </template>
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">
         <template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">
           <OrderItem
           <OrderItem
             :orderData="getMessageContent(message)"
             :orderData="getMessageContent(message)"
-            @tap="
-                  sheep.$router.go('/pages/order/detail', {
-                    id: getMessageContent(message).id,
-                  })
-                "
+            @tap="sheep.$router.go('/pages/order/detail', { id: getMessageContent(message).id })"
           />
           />
         </template>
         </template>
         <!-- user头像 -->
         <!-- user头像 -->
         <image
         <image
           v-if="message.senderType === UserTypeEnum.MEMBER"
           v-if="message.senderType === UserTypeEnum.MEMBER"
           class="chat-avatar ss-m-l-24"
           class="chat-avatar ss-m-l-24"
-          :src="sheep.$url.cdn(message.senderAvatar) ||
-                sheep.$url.static('/static/img/shop/chat/default.png')"
+          :src="
+            sheep.$url.cdn(message.senderAvatar) ||
+            sheep.$url.static('/static/img/shop/chat/default.png')
+          "
           mode="aspectFill"
           mode="aspectFill"
         >
         >
         </image>
         </image>
@@ -104,7 +109,7 @@
     // 消息
     // 消息
     message: {
     message: {
       type: Object,
       type: Object,
-      default: ()=>({}),
+      default: () => ({}),
     },
     },
     // 消息索引
     // 消息索引
     messageIndex: {
     messageIndex: {
@@ -112,10 +117,10 @@
       default: 0,
       default: 0,
     },
     },
     // 消息列表
     // 消息列表
-    messageList:{
+    messageList: {
       type: Array,
       type: Array,
       default: () => [],
       default: () => [],
-    }
+    },
   });
   });
   const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // 解析消息内容
   const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // 解析消息内容
 
 

+ 125 - 118
pages/commission/components/commission-menu.vue

@@ -1,138 +1,145 @@
 <!-- 分销:商菜单栏 -->
 <!-- 分销:商菜单栏 -->
 <template>
 <template>
-	<view class="menu-box ss-flex-col">
-		<view class="header-box">
-			<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
-			<view class="ss-flex header-title">
-				<view class="title">功能专区</view>
-				<text class="cicon-forward"></text>
-			</view>
-		</view>
-		<view class="menu-list ss-flex ss-flex-wrap">
-			<view v-for="(item, index) in state.menuList" :key="index" class="item-box ss-flex-col ss-col-center"
-				@tap="sheep.$router.go(item.path)">
-				<image class="menu-icon ss-m-b-10" :src="sheep.$url.static(item.img)" mode="aspectFill"></image>
-				<view>{{ item.title }}</view>
-			</view>
-		</view>
-	</view>
+  <view class="menu-box ss-flex-col">
+    <view class="header-box">
+      <image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
+      <view class="ss-flex header-title">
+        <view class="title">功能专区</view>
+        <text class="cicon-forward"></text>
+      </view>
+    </view>
+    <view class="menu-list ss-flex ss-flex-wrap">
+      <view
+        v-for="(item, index) in state.menuList"
+        :key="index"
+        class="item-box ss-flex-col ss-col-center"
+        @tap="sheep.$router.go(item.path)"
+      >
+        <image
+          class="menu-icon ss-m-b-10"
+          :src="sheep.$url.static(item.img)"
+          mode="aspectFill"
+        ></image>
+        <view>{{ item.title }}</view>
+      </view>
+    </view>
+  </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	import sheep from '@/sheep';
-	import { reactive } from 'vue';
+  import sheep from '@/sheep';
+  import { reactive } from 'vue';
 
 
-	const state = reactive({
-		menuList: [{
-				img: '/static/img/shop/commission/commission_icon1.png',
-				title: '我的团队',
-				path: '/pages/commission/team',
-			},
-			{
-				img: '/static/img/shop/commission/commission_icon2.png',
-				title: '佣金明细',
-				path: '/pages/commission/wallet',
-			},
-			{
-				img: '/static/img/shop/commission/commission_icon3.png',
-				title: '分销订单',
-				path: '/pages/commission/order',
-			},
-			{
-				img: '/static/img/shop/commission/commission_icon4.png',
-				title: '推广商品',
-				path: '/pages/commission/goods',
-			},
-			// {
-			//   img: '/static/img/shop/commission/commission_icon5.png',
-			//   title: '我的资料',
-			//   path: '/pages/commission/apply',
-			//   isAgentFrom: true,
-			// },
-			// todo @芋艿:邀请海报需要登录后的个人数据
-			{
-				img: '/static/img/shop/commission/commission_icon7.png',
-				title: '邀请海报',
-				path: 'action:showShareModal',
-			},
-      // TODO @芋艿:缺少 icon
+  const state = reactive({
+    menuList: [
       {
       {
-				// img: '/static/img/shop/commission/commission_icon7.png',
-				title: '推广排行',
-				path: '/pages/commission/promoter',
-			},
+        img: '/static/img/shop/commission/commission_icon1.png',
+        title: '我的团队',
+        path: '/pages/commission/team',
+      },
       {
       {
-				// img: '/static/img/shop/commission/commission_icon7.png',
-				title: '佣金排行',
-				path: '/pages/commission/commission-ranking',
-			}
-		],
-	});
+        img: '/static/img/shop/commission/commission_icon2.png',
+        title: '佣金明细',
+        path: '/pages/commission/wallet',
+      },
+      {
+        img: '/static/img/shop/commission/commission_icon3.png',
+        title: '分销订单',
+        path: '/pages/commission/order',
+      },
+      {
+        img: '/static/img/shop/commission/commission_icon4.png',
+        title: '推广商品',
+        path: '/pages/commission/goods',
+      },
+      // {
+      //   img: '/static/img/shop/commission/commission_icon5.png',
+      //   title: '我的资料',
+      //   path: '/pages/commission/apply',
+      //   isAgentFrom: true,
+      // },
+      {
+        img: '/static/img/shop/commission/commission_icon7.png',
+        title: '邀请海报',
+        path: 'action:showShareModal',
+      },
+      {
+        img: '/static/img/shop/commission/commission_icon8.png',
+        title: '推广排行',
+        path: '/pages/commission/promoter',
+      },
+      {
+        img: '/static/img/shop/commission/commission_icon9.png',
+        title: '佣金排行',
+        path: '/pages/commission/commission-ranking',
+      },
+    ],
+  });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	.menu-box {
-		margin: 0 auto;
-		width: 690rpx;
-		margin-bottom: 20rpx;
-		margin-top: 20rpx;
-		border-radius: 12rpx;
-		z-index: 3;
-		position: relative;
-	}
+  .menu-box {
+    margin: 0 auto;
+    width: 690rpx;
+    margin-bottom: 20rpx;
+    margin-top: 20rpx;
+    border-radius: 12rpx;
+    z-index: 3;
+    position: relative;
+  }
 
 
-	.header-box {
-		width: 690rpx;
-		height: 76rpx;
-		position: relative;
+  .header-box {
+    width: 690rpx;
+    height: 76rpx;
+    position: relative;
 
 
-		.header-bg {
-			width: 690rpx;
-			height: 76rpx;
-		}
+    .header-bg {
+      width: 690rpx;
+      height: 76rpx;
+    }
 
 
-		.header-title {
-			position: absolute;
-			left: 20rpx;
-			top: 24rpx;
-		}
+    .header-title {
+      position: absolute;
+      left: 20rpx;
+      top: 24rpx;
+    }
 
 
-		.title {
-			font-size: 28rpx;
-			font-weight: 500;
-			color: #ffffff;
-			line-height: 30rpx;
-		}
+    .title {
+      font-size: 28rpx;
+      font-weight: 500;
+      color: #ffffff;
+      line-height: 30rpx;
+    }
 
 
-		.cicon-forward {
-			font-size: 30rpx;
-			font-weight: 400;
-			color: #ffffff;
-			line-height: 30rpx;
-		}
-	}
+    .cicon-forward {
+      font-size: 30rpx;
+      font-weight: 400;
+      color: #ffffff;
+      line-height: 30rpx;
+    }
+  }
 
 
-	.menu-list {
-		padding: 50rpx 0 10rpx 0;
-		background: #fdfae9;
-		border-radius: 0 0 12rpx 12rpx;
-	}
+  .menu-list {
+    padding: 50rpx 0 10rpx 0;
+    background: #fdfae9;
+    border-radius: 0 0 12rpx 12rpx;
+  }
 
 
-	.item-box {
-		width: 25%;
-		margin-bottom: 40rpx;
-	}
+  .item-box {
+    width: 25%;
+    margin-bottom: 40rpx;
+  }
 
 
-	.menu-icon {
-		width: 68rpx;
-		height: 68rpx;
-		background: #ffffff;
-		border-radius: 50%;
-	}
+  .menu-icon {
+    width: 68rpx;
+    height: 68rpx;
+    background: #ffffff;
+    border-radius: 50%;
+  }
 
 
-	.menu-title {
-		font-size: 26rpx;
-		font-weight: 500;
-		color: #ffffff;
-	}
-</style>
+  .menu-title {
+    font-size: 26rpx;
+    font-weight: 500;
+    color: #ffffff;
+  }
+</style>

+ 1 - 1
pages/commission/goods.vue

@@ -76,7 +76,7 @@
     shareInfo: {},
     shareInfo: {},
   });
   });
 
 
-  // TODO 芋艿:分享的接入
+  // TODO @puhui999:【分享】接入
   function onShareGoods(goodsInfo) {
   function onShareGoods(goodsInfo) {
     state.shareInfo = $share.getShareInfo(
     state.shareInfo = $share.getShareInfo(
       {
       {

+ 27 - 6
pages/commission/team.vue

@@ -1,8 +1,29 @@
 <!-- 页面 TODO 芋艿:该页面的实现代码需要优化,包括 js 和 css,以及相关的样式设计 -->
 <!-- 页面 TODO 芋艿:该页面的实现代码需要优化,包括 js 和 css,以及相关的样式设计 -->
 <template>
 <template>
   <s-layout title="我的团队" :class="state.scrollTop ? 'team-wrap' : ''" navbar="inner">
   <s-layout title="我的团队" :class="state.scrollTop ? 'team-wrap' : ''" navbar="inner">
+  <view
+	    class="header-box"
+	    :style="[
+	      {
+	        marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
+	        paddingTop: Number(statusBarHeight + 108) + 'rpx',
+	      },
+	    ]"
+	  >
+	    <!-- 推广数据总览 -->
+	    <view class="team-data-box ss-flex ss-col-center ss-row-between" style="width: 100%">
+	      <view class="data-card" style="width: 100%">
+	        <view class="total-item" style="width: 100%">
+	          <view class="item-title" style="text-align: center">推广人数</view>
+	          <view class="total-num" style="text-align: center">
+	            {{ state.summary.firstBrokerageUserCount + state.summary.secondBrokerageUserCount || 0 }}
+	          </view>
+	        </view>
+	      </view>
+	    </view>
+	  </view>
     <view class="promoter-list">
     <view class="promoter-list">
-      <view
+      <!--<view
         class="promoterHeader bg-color"
         class="promoterHeader bg-color"
         style="backgroundcolor: #e93323 !important; height: 218rpx; color: #fff"
         style="backgroundcolor: #e93323 !important; height: 218rpx; color: #fff"
       >
       >
@@ -21,9 +42,9 @@
           </view>
           </view>
           <view class="iconfont icon-tuandui" />
           <view class="iconfont icon-tuandui" />
         </view>
         </view>
-      </view>
-      <view style="padding: 0 30rpx">
-        <view class="nav acea-row row-around l1">
+      </view>-->
+      <view style="padding: 0 20rpx">
+        <view class="nav acea-row row-around l1" style="margin-top:20rpx;">
           <view :class="state.level == 1 ? 'item on' : 'item'" @click="setType(1)">
           <view :class="state.level == 1 ? 'item on' : 'item'" @click="setType(1)">
             一级({{ state.summary.firstBrokerageUserCount || 0 }})
             一级({{ state.summary.firstBrokerageUserCount || 0 }})
           </view>
           </view>
@@ -152,7 +173,7 @@
             </view>
             </view>
           </block>
           </block>
           <block v-if="state.pagination.list.length === 0">
           <block v-if="state.pagination.list.length === 0">
-            <view style="text-align: center">暂无推广人数</view>
+            <view style="text-align: center;margin-top:30rpx;">暂无推广人数</view>
           </block>
           </block>
         </view>
         </view>
       </view>
       </view>
@@ -456,7 +477,7 @@
   .promoter-list .nav .item.on {
   .promoter-list .nav .item.on {
     border-bottom: 5rpx solid;
     border-bottom: 5rpx solid;
     // $theme-color
     // $theme-color
-    color: red;
+    color: var(--ui-BG-Main);
     // $theme-color
     // $theme-color
   }
   }
 
 

+ 48 - 12
pages/commission/withdraw.vue

@@ -15,7 +15,10 @@
         <view class="num-title">可提现金额(元)</view>
         <view class="num-title">可提现金额(元)</view>
         <view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view>
         <view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view>
       </view>
       </view>
-      <button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })">
+      <button
+        class="ss-reset-button log-btn"
+        @tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })"
+      >
         提现记录
         提现记录
       </button>
       </button>
     </view>
     </view>
@@ -98,12 +101,23 @@
         v-show="state.accountInfo.type === '2'"
         v-show="state.accountInfo.type === '2'"
       >
       >
         <view class="unit" />
         <view class="unit" />
-        <uni-easyinput
-          :inputBorder="false"
-          class="ss-flex-1 ss-p-l-10"
-          v-model="state.accountInfo.bankName"
-          placeholder="请输入提现银行"
-        />
+        <!--银行改为下拉选择-->
+        <picker
+          @change="bankChange"
+          :value="state.bankListSelectedIndex"
+          :range="state.bankList"
+          range-key="label"
+          style="width: 100%"
+        >
+          <uni-easyinput
+            :inputBorder="false"
+            :value="state.accountInfo.bankName"
+            placeholder="请选择银行"
+            suffixIcon="right"
+            disabled
+            :styles="{ disableColor: '#fff', borderColor: '#fff', color: '#333!important' }"
+          />
+        </picker>
       </view>
       </view>
       <!-- 开户地址 -->
       <!-- 开户地址 -->
       <view class="card-title" v-show="state.accountInfo.type === '2'">开户地址</view>
       <view class="card-title" v-show="state.accountInfo.type === '2'">开户地址</view>
@@ -152,6 +166,7 @@
   import { fen2yuan } from '@/sheep/hooks/useGoods';
   import { fen2yuan } from '@/sheep/hooks/useGoods';
   import TradeConfigApi from '@/sheep/api/trade/config';
   import TradeConfigApi from '@/sheep/api/trade/config';
   import BrokerageApi from '@/sheep/api/trade/brokerage';
   import BrokerageApi from '@/sheep/api/trade/brokerage';
+  import DictApi from '@/sheep/api/system/dict';
 
 
   const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
   const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
   const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
   const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
@@ -176,6 +191,8 @@
     frozenDays: 0, // 冻结天数
     frozenDays: 0, // 冻结天数
     minPrice: 0, // 最低提现金额
     minPrice: 0, // 最低提现金额
     withdrawTypes: [], // 提现方式
     withdrawTypes: [], // 提现方式
+    bankList: [], // 银行字典数据
+    bankListSelectedIndex: '', // 选中银行 bankList 的 index
   });
   });
 
 
   // 打开提现方式的弹窗
   // 打开提现方式的弹窗
@@ -186,7 +203,7 @@
   // 提交提现
   // 提交提现
   const onConfirm = async () => {
   const onConfirm = async () => {
     // 参数校验
     // 参数校验
-    debugger;
+    //debugger;
     if (
     if (
       !state.accountInfo.price ||
       !state.accountInfo.price ||
       state.accountInfo.price > state.brokerageInfo.price ||
       state.accountInfo.price > state.brokerageInfo.price ||
@@ -215,12 +232,12 @@
       confirmText: '查看记录',
       confirmText: '查看记录',
       success: (res) => {
       success: (res) => {
         if (res.confirm) {
         if (res.confirm) {
-          sheep.$router.go('/pages/commission/wallet', { type: 2 })
+          sheep.$router.go('/pages/commission/wallet', { type: 2 });
           return;
           return;
         }
         }
         getBrokerageUser();
         getBrokerageUser();
         state.accountInfo = {};
         state.accountInfo = {};
-      }
+      },
     });
     });
   };
   };
 
 
@@ -245,10 +262,29 @@
     }
     }
   }
   }
 
 
+  // 获取提现银行配置字典
+  async function getDictDataListByType() {
+    let { code, data } = await DictApi.getDictDataListByType('brokerage_bank_name');
+    if (code !== 0) {
+      return;
+    }
+    if (data && data.length > 0) {
+      state.bankList = data;
+    }
+  }
+
+  // 银行选择
+  function bankChange(e) {
+    const value = e.detail.value;
+    state.bankListSelectedIndex = value;
+    state.accountInfo.bankName = state.bankList[value].label;
+  }
+
   onBeforeMount(() => {
   onBeforeMount(() => {
     getWithdrawRules();
     getWithdrawRules();
-    getBrokerageUser()
-  })
+    getBrokerageUser();
+    getDictDataListByType(); //获取银行字典数据
+  });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>

+ 0 - 1
pages/coupon/list.vue

@@ -107,7 +107,6 @@
     },
     },
   ];
   ];
 
 
-  // TODO yunai:
   function onTabsChange(e) {
   function onTabsChange(e) {
     state.currentTab = e.index;
     state.currentTab = e.index;
     state.type = e.value;
     state.type = e.value;

+ 149 - 104
pages/goods/comment/add.vue

@@ -1,89 +1,130 @@
 <!-- 评价  -->
 <!-- 评价  -->
 <template>
 <template>
-	<s-layout title="评价">
-		<view>
-			<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
-				<view>
-					<view class="commont-from-wrap">
-						<!-- 评价商品 -->
-						<s-goods-item
+  <s-layout title="评价">
+    <view>
+      <view v-for="(item, index) in state.orderInfo.items" :key="item.id">
+        <view>
+          <view class="commont-from-wrap">
+            <!-- 评价商品 -->
+            <s-goods-item
               :img="item.picUrl"
               :img="item.picUrl"
               :title="item.spuName"
               :title="item.spuName"
               :skuText="item.properties.map((property) => property.valueName).join(' ')"
               :skuText="item.properties.map((property) => property.valueName).join(' ')"
-							:price="item.payPrice"
+              :price="item.payPrice"
               :num="item.count"
               :num="item.count"
             />
             />
-					</view>
-
-					<view class="form-item">
-						<!-- 评分 -->
-						<view class="star-box ss-flex ss-col-center">
-							<view class="star-title ss-m-r-40">商品质量</view>
-							<uni-rate v-model="state.commentList[index].descriptionScores" />
-						</view>
-						<view class="star-box ss-flex ss-col-center">
-							<view class="star-title ss-m-r-40">服务态度</view>
-							<uni-rate v-model="state.commentList[index].benefitScores" />
-						</view>
-						<!-- 评价 -->
-						<view class="area-box">
-							<uni-easyinput :inputBorder="false" type="textarea" maxlength="120" autoHeight
-								v-model="state.commentList[index].content"
-								placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" />
-              <!-- TODO 芋艿:文件上传 -->
-							<view class="img-box">
-								<s-uploader v-model:url="state.commentList[index].images" fileMediatype="image"
-									limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" />
-							</view>
-						</view>
-					</view>
-				</view>
-			</view>
-		</view>
-    <!-- TODO 芋艿:是否匿名 -->
-
-		<su-fixed bottom placeholder>
-			<view class="foot_box ss-flex ss-row-center ss-col-center">
-				<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
-					发布
-				</button>
-			</view>
-		</su-fixed>
-	</s-layout>
+          </view>
+
+          <view class="form-item">
+            <!-- 评分 -->
+            <view class="star-box ss-flex ss-col-center">
+              <view class="star-title ss-m-r-40">商品质量</view>
+              <uni-rate v-model="state.commentList[index].descriptionScores" />
+            </view>
+            <view class="star-box ss-flex ss-col-center">
+              <view class="star-title ss-m-r-40">服务态度</view>
+              <uni-rate v-model="state.commentList[index].benefitScores" />
+            </view>
+            <!-- 评价 -->
+            <view class="area-box">
+              <uni-easyinput
+                :inputBorder="false"
+                type="textarea"
+                maxlength="120"
+                autoHeight
+                v-model="state.commentList[index].content"
+                placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~"
+              />
+              <view class="img-box">
+                <s-uploader
+                  v-model:url="state.commentList[index].images"
+                  fileMediatype="image"
+                  limit="9"
+                  mode="grid"
+                  :imageStyles="{ width: '168rpx', height: '168rpx' }"
+                  @success="(payload) => uploadSuccess(payload, index)"
+                />
+              </view>
+            </view>
+            <view class="checkbox-container">
+              <checkbox-group @change="(event) => toggleAnonymous(index, event)">
+                <label>
+                  <checkbox value="anonymousChecked" />
+                  匿名评论
+                </label>
+              </checkbox-group>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+    <su-fixed bottom placeholder>
+      <view class="foot_box ss-flex ss-row-center ss-col-center">
+        <button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
+          发布
+        </button>
+      </view>
+    </su-fixed>
+  </s-layout>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	import sheep from '@/sheep';
-	import { onLoad } from '@dcloudio/uni-app';
-	import { reactive } from 'vue';
+  import sheep from '@/sheep';
+  import { onLoad } from '@dcloudio/uni-app';
+  import { reactive, ref } from 'vue';
   import OrderApi from '@/sheep/api/trade/order';
   import OrderApi from '@/sheep/api/trade/order';
 
 
-	const state = reactive({
-		orderInfo: {},
-		commentList: [],
-		id: null
-	});
+  const state = reactive({
+    orderInfo: {},
+    commentList: [],
+    id: null,
+  });
+
+  /**
+   * 切换是否匿名
+   *
+   * @param commentIndex  当前评论下标
+   * @param event 复选框事件
+   */
+  function toggleAnonymous(commentIndex, event) {
+    state.commentList[commentIndex].anonymous = event.detail.value[0] === 'anonymousChecked';
+  }
 
 
-	async function onSubmit() {
+  /**
+   * 发布评论
+   *
+   * @returns {Promise<void>}
+   */
+  async function onSubmit() {
     // 顺序提交评论
     // 顺序提交评论
     for (const comment of state.commentList) {
     for (const comment of state.commentList) {
       await OrderApi.createOrderItemComment(comment);
       await OrderApi.createOrderItemComment(comment);
     }
     }
     // 都评论好,返回
     // 都评论好,返回
     sheep.$router.back();
     sheep.$router.back();
-	}
+  }
 
 
-	onLoad(async (options) => {
+  /**
+   * 图片添加到表单
+   *
+   * @param payload 上传成功后的回调数据
+   * @param commentIndex  当前评论的下标
+   */
+  function uploadSuccess(payload, commentIndex) {
+    state.commentList[commentIndex].picUrls = state.commentList[commentIndex].images;
+  }
+
+  onLoad(async (options) => {
     if (!options.id) {
     if (!options.id) {
       sheep.$helper.toast(`缺少订单信息,请检查`);
       sheep.$helper.toast(`缺少订单信息,请检查`);
-      return
+      return;
     }
     }
-		state.id = options.id;
+    state.id = options.id;
 
 
-		const { code, data } = await OrderApi.getOrder(state.id);
+    const { code, data } = await OrderApi.getOrder(state.id);
     if (code !== 0) {
     if (code !== 0) {
       sheep.$helper.toast('无待评价订单');
       sheep.$helper.toast('无待评价订单');
-      return
+      return;
     }
     }
     // 处理评论
     // 处理评论
     data.items.forEach((item) => {
     data.items.forEach((item) => {
@@ -93,53 +134,57 @@
         descriptionScores: 5,
         descriptionScores: 5,
         benefitScores: 5,
         benefitScores: 5,
         content: '',
         content: '',
-        picUrls: []
+        picUrls: [],
       });
       });
     });
     });
     state.orderInfo = data;
     state.orderInfo = data;
-	});
+  });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	// 评价商品
-	.goods-card {
-		margin: 10rpx 0;
-		padding: 20rpx;
-		background: #fff;
-	}
-
-	// 评论,选择图片
-	.form-item {
-		background: #fff;
-
-		.star-box {
-			height: 100rpx;
-			padding: 0 25rpx;
-		}
-
-		.star-title {
-			font-weight: 600;
-		}
-	}
-
-	.area-box {
-		width: 690rpx;
-		min-height: 306rpx;
-		background: rgba(249, 250, 251, 1);
-		border-radius: 20rpx;
-		padding: 28rpx;
-		margin: auto;
-
-		.img-box {
-			margin-top: 20rpx;
-		}
-	}
-
-	.post-btn {
-		width: 690rpx;
-		line-height: 80rpx;
-		border-radius: 40rpx;
-		color: rgba(#fff, 0.9);
-		margin-bottom: 20rpx;
-	}
-</style>
+  // 评价商品
+  .goods-card {
+    margin: 10rpx 0;
+    padding: 20rpx;
+    background: #fff;
+  }
+
+  // 评论,选择图片
+  .form-item {
+    background: #fff;
+
+    .star-box {
+      height: 100rpx;
+      padding: 0 25rpx;
+    }
+
+    .star-title {
+      font-weight: 600;
+    }
+  }
+
+  .area-box {
+    width: 690rpx;
+    min-height: 306rpx;
+    background: rgba(249, 250, 251, 1);
+    border-radius: 20rpx;
+    padding: 28rpx;
+    margin: auto;
+
+    .img-box {
+      margin-top: 20rpx;
+    }
+  }
+
+  .checkbox-container {
+    padding: 10rpx;
+  }
+
+  .post-btn {
+    width: 690rpx;
+    line-height: 80rpx;
+    border-radius: 40rpx;
+    color: rgba(#fff, 0.9);
+    margin-bottom: 20rpx;
+  }
+</style>

+ 2 - 1
pages/goods/comment/list.vue

@@ -1,6 +1,6 @@
 <!-- 商品评论的分页 -->
 <!-- 商品评论的分页 -->
 <template>
 <template>
-  <s-layout title="全部评">
+  <s-layout title="全部评">
     <su-tabs
     <su-tabs
       :list="state.type"
       :list="state.type"
       :scrollable="false"
       :scrollable="false"
@@ -16,6 +16,7 @@
     <s-empty v-if="state.pagination.total === 0" text="暂无数据" icon="/static/data-empty.png" />
     <s-empty v-if="state.pagination.total === 0" text="暂无数据" icon="/static/data-empty.png" />
     <!-- 下拉 -->
     <!-- 下拉 -->
     <uni-load-more
     <uni-load-more
+      icon-type="auto"
       v-if="state.pagination.total > 0"
       v-if="state.pagination.total > 0"
       :status="state.loadStatus"
       :status="state.loadStatus"
       :content-text="{
       :content-text="{

+ 0 - 3
pages/goods/components/detail/detail-activity-tip.vue

@@ -2,7 +2,6 @@
   <su-fixed bottom placeholder :val="44">
   <su-fixed bottom placeholder :val="44">
     <view>
     <view>
       <view v-for="activity in props.activityList" :key="activity.id">
       <view v-for="activity in props.activityList" :key="activity.id">
-        <!-- TODO 芋艿:拼团 -->
         <view
         <view
           class="activity-box ss-p-x-38 ss-flex ss-row-between ss-col-center"
           class="activity-box ss-p-x-38 ss-flex ss-row-between ss-col-center"
           :class="activity.type === 1 ? 'seckill-box' : 'groupon-box'"
           :class="activity.type === 1 ? 'seckill-box' : 'groupon-box'"
@@ -14,7 +13,6 @@
                 :src="sheep.$url.static('/static/img/shop/goods/seckill-icon.png')"
                 :src="sheep.$url.static('/static/img/shop/goods/seckill-icon.png')"
                 class="activity-icon"
                 class="activity-icon"
               />
               />
-              <!-- TODO 芋艿:拼团 -->
               <image
               <image
                 v-else-if="activity.type === 3"
                 v-else-if="activity.type === 3"
                 :src="sheep.$url.static('/static/img/shop/goods/groupon-icon.png')"
                 :src="sheep.$url.static('/static/img/shop/goods/groupon-icon.png')"
@@ -33,7 +31,6 @@
 <script setup>
 <script setup>
   import sheep from '@/sheep';
   import sheep from '@/sheep';
 
 
-  // TODO 芋艿:这里要迁移下;
   const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
   const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
   const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
   const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
 
 

+ 27 - 9
pages/goods/groupon.vue

@@ -54,7 +54,7 @@
                 <view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
                 <view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
                   单买价:
                   单买价:
                   <view class="origin-price-text">
                   <view class="origin-price-text">
-                    {{ fen2yuan(state.goodsInfo.price) }}
+                    {{ fen2yuan(state.goodsInfo.marketPrice) }}
                   </view>
                   </view>
                 </view>
                 </view>
               </view>
               </view>
@@ -80,7 +80,7 @@
         <!-- 功能卡片 -->
         <!-- 功能卡片 -->
         <view class="detail-cell-card detail-card ss-flex-col">
         <view class="detail-cell-card detail-card ss-flex-col">
           <!-- 规格 -->
           <!-- 规格 -->
-          <detail-cell-sku :sku="state.selectedSkuPrice" @tap="state.showSelectSku = true" />
+          <detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
         </view>
         </view>
 
 
         <!-- 参团列表 -->
         <!-- 参团列表 -->
@@ -104,7 +104,6 @@
       <detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
       <detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
 
 
       <!-- 商品tabbar -->
       <!-- 商品tabbar -->
-      <!-- TODO: 已售罄、预热 判断 设计-->
       <detail-tabbar v-model="state.goodsInfo">
       <detail-tabbar v-model="state.goodsInfo">
         <view class="buy-box ss-flex ss-col-center ss-p-r-20">
         <view class="buy-box ss-flex ss-col-center ss-p-r-20">
           <button
           <button
@@ -125,7 +124,12 @@
             :disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0"
             :disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0"
           >
           >
             <view class="btn-price">{{
             <view class="btn-price">{{
-              fen2yuan(state.activity.price || state.goodsInfo.price)
+              fen2yuan(
+                state.selectedSku.price * state.selectedSku.count ||
+                  state.activity.price * state.selectedSku.count ||
+                  state.goodsInfo.price * state.selectedSku.count ||
+                  state.goodsInfo.price,
+              )
             }}</view>
             }}</view>
             <view v-if="state.activity.startTime > new Date().getTime()">未开始</view>
             <view v-if="state.activity.startTime > new Date().getTime()">未开始</view>
             <view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view>
             <view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view>
@@ -168,7 +172,7 @@
     goodsInfo: {}, // 商品信息
     goodsInfo: {}, // 商品信息
     goodsSwiper: [], // 商品轮播图
     goodsSwiper: [], // 商品轮播图
     showSelectSku: false, // 显示规格弹框
     showSelectSku: false, // 显示规格弹框
-    selectedSkuPrice: {}, // 选中的规格价格
+    selectedSku: {}, // 选中的规格属性
     activity: {}, // 团购活动
     activity: {}, // 团购活动
     grouponId: 0, // 团购ID
     grouponId: 0, // 团购ID
     grouponNum: 0, // 团购人数
     grouponNum: 0, // 团购人数
@@ -183,7 +187,7 @@
 
 
   // 规格变更
   // 规格变更
   function onSkuChange(e) {
   function onSkuChange(e) {
-    state.selectedSkuPrice = e;
+    state.selectedSku = e;
   }
   }
 
 
   function onSkuClose() {
   function onSkuClose() {
@@ -199,6 +203,7 @@
 
 
   /**
   /**
    * 去参团
    * 去参团
+   *
    * @param record 团长的团购记录
    * @param record 团长的团购记录
    */
    */
   function onJoinGroupon(record) {
   function onJoinGroupon(record) {
@@ -227,7 +232,6 @@
   }
   }
 
 
   // 分享信息
   // 分享信息
-  // TODO @芋艿:分享的接入
   const shareInfo = computed(() => {
   const shareInfo = computed(() => {
     if (isEmpty(state.activity)) return {};
     if (isEmpty(state.activity)) return {};
     return sheep.$platform.share.getShareInfo(
     return sheep.$platform.share.getShareInfo(
@@ -262,9 +266,23 @@
     // 加载商品信息
     // 加载商品信息
     const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
     const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
     state.goodsId = spu.id;
     state.goodsId = spu.id;
-    activity.products.forEach((product) => {
-      spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
+
+    // 默认显示最低价
+    spu.price = activity.products.reduce((min, product) => {
+      return Math.min(min, product.combinationPrice || Infinity);
+    }, Infinity);
+
+    // 价格、库存使用活动的
+    spu.skus.forEach((sku) => {
+      const product = activity.products.find((product) => product.skuId === sku.id);
+      if (product) {
+        sku.price = product.combinationPrice;
+      } else {
+        // 找不到可能是没配置,则不能发起秒杀
+        sku.stock = 0;
+      }
     });
     });
+
     // 关闭骨架屏
     // 关闭骨架屏
     state.skeletonLoading = false;
     state.skeletonLoading = false;
     if (code === 0) {
     if (code === 0) {

+ 110 - 263
pages/goods/index.vue

@@ -7,47 +7,30 @@
       <!-- 骨架屏 -->
       <!-- 骨架屏 -->
       <detailSkeleton v-if="state.skeletonLoading" />
       <detailSkeleton v-if="state.skeletonLoading" />
       <!-- 下架/售罄提醒 -->
       <!-- 下架/售罄提醒 -->
-      <s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction
-               actionText="再逛逛" actionUrl="/pages/goods/list" />
+      <s-empty
+        v-else-if="state.goodsInfo === null"
+        text="商品不存在或已下架"
+        icon="/static/soldout-empty.png"
+        showAction
+        actionText="再逛逛"
+        actionUrl="/pages/goods/list"
+      />
       <block v-else>
       <block v-else>
         <view class="detail-swiper-selector">
         <view class="detail-swiper-selector">
           <!-- 商品轮播图  -->
           <!-- 商品轮播图  -->
-          <su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
-                     otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" />
-          <!-- 限时折扣 -->
-          <view class="discount" v-if="setShow">
-            <image class="disImg" src="../../static/images/dis.png"></image>
-            <view class="discountCont">
-              <view class="disContT">
-                <view class="disContT1">
-                  <view class="disContT1P">
-                    ¥{{fen2yuan(settleData.price)}}
-                  </view>
-                  <view class="disContT1End">
-                    直降¥{{fen2yuan( state.goodsInfo.price - settleData.price)}}
-                  </view>
-                </view>
-                <view class="disContT2">
-                  限时折扣
-                </view>
-              </view>
-              <view class="disContB">
-                <view class="disContB1">
-                  价格:¥{{fen2yuan(state.goodsInfo.price)}} 丨 剩余:{{settleData.stock}}
-                </view>
-                <view class="disContB2">
-                  距结束仅剩
-                  <countDown :tipText="' '" :bgColor="bgColor" :dayText="':'" :hourText="':'"
-                             :minuteText="':'" :secondText="' '" :datatime="settleData.endTime / 1000"
-                             :isDay="false" />
-                </view>
-              </view>
-            </view>
-          </view>
-          <!-- 限时折扣 -->
+          <su-swiper
+            class="ss-m-b-14"
+            isPreview
+            :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
+            otStyle="tag"
+            imageMode="widthFix"
+            dotCur="bg-mask-40"
+            :seizeHeight="750"
+          />
+
           <!-- 价格+标题 -->
           <!-- 价格+标题 -->
           <view class="title-card detail-card ss-p-y-40 ss-p-x-20">
           <view class="title-card detail-card ss-p-y-40 ss-p-x-20">
-            <view class="ss-flex ss-row-between ss-col-center ss-m-b-26" v-if="!setShow">
+            <view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
               <view class="price-box ss-flex ss-col-bottom">
               <view class="price-box ss-flex ss-col-bottom">
                 <view class="price-text ss-m-r-16">
                 <view class="price-text ss-m-r-16">
                   {{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
                   {{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
@@ -64,16 +47,23 @@
               <!-- 满减送/限时折扣活动的提示 -->
               <!-- 满减送/限时折扣活动的提示 -->
               <div class="tag-content">
               <div class="tag-content">
                 <view class="tag-box ss-flex">
                 <view class="tag-box ss-flex">
-                  <view class="tag ss-m-r-10" v-for="promos in state.activityInfo" :key="promos.id"
-                        @tap="onActivity">
+                  <view
+                    class="tag ss-m-r-10"
+                    v-for="promos in state.activityInfo"
+                    :key="promos.id"
+                    @tap="onActivity"
+                  >
                     {{ promos.name }}
                     {{ promos.name }}
                   </view>
                   </view>
                 </view>
                 </view>
               </div>
               </div>
 
 
-              <!-- 优惠劵@tap="state.showModel = true" -->
-              <view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="onActivity"
-                    v-if="state.couponInfo.length">
+              <!-- 优惠劵 -->
+              <view
+                class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
+                @tap="state.showModel = true"
+                v-if="state.couponInfo.length"
+              >
                 <view class="discounts-title ss-m-r-8">领券</view>
                 <view class="discounts-title ss-m-r-8">领券</view>
                 <text class="cicon-forward"></text>
                 <text class="cicon-forward"></text>
               </view>
               </view>
@@ -84,30 +74,51 @@
 
 
           <!-- 功能卡片 -->
           <!-- 功能卡片 -->
           <view class="detail-cell-card detail-card ss-flex-col">
           <view class="detail-cell-card detail-card ss-flex-col">
-            <detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
-                             @tap="state.showSelectSku = true" />
+            <detail-cell-sku
+              v-model="state.selectedSku.goods_sku_text"
+              :sku="state.selectedSku"
+              @tap="state.showSelectSku = true"
+            />
           </view>
           </view>
 
 
           <!-- 规格与数量弹框 -->
           <!-- 规格与数量弹框 -->
-          <s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
-                        @buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
+          <s-select-sku
+            :goodsInfo="state.goodsInfo"
+            :show="state.showSelectSku"
+            @addCart="onAddCart"
+            @buy="onBuy"
+            @change="onSkuChange"
+            @close="state.showSelectSku = false"
+          />
         </view>
         </view>
 
 
         <!-- 评价 -->
         <!-- 评价 -->
         <detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
         <detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
         <!-- 详情 -->
         <!-- 详情 -->
-        <detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
+        <detail-content-card
+          class="detail-content-selector"
+          :content="state.goodsInfo.description"
+        />
 
 
         <!-- 活动跳转:拼团/秒杀/砍价活动 -->
         <!-- 活动跳转:拼团/秒杀/砍价活动 -->
-        <detail-activity-tip v-if="state.activityList.length > 0" :activity-list="state.activityList" />
+        <detail-activity-tip
+          v-if="state.activityList.length > 0"
+          :activity-list="state.activityList"
+        />
 
 
         <!-- 详情 tabbar -->
         <!-- 详情 tabbar -->
         <detail-tabbar v-model="state.goodsInfo">
         <detail-tabbar v-model="state.goodsInfo">
           <view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
           <view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
-            <button class="ss-reset-button add-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
+            <button
+              class="ss-reset-button add-btn ui-Shadow-Main"
+              @tap="state.showSelectSku = true"
+            >
               加入购物车
               加入购物车
             </button>
             </button>
-            <button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
+            <button
+              class="ss-reset-button buy-btn ui-Shadow-Main"
+              @tap="state.showSelectSku = true"
+            >
               立即购买
               立即购买
             </button>
             </button>
           </view>
           </view>
@@ -117,38 +128,32 @@
         </detail-tabbar>
         </detail-tabbar>
 
 
         <!-- 优惠劵弹窗 -->
         <!-- 优惠劵弹窗 -->
-        <!-- <s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
-          @get="onGet" /> -->
+        <s-coupon-get
+          v-model="state.couponInfo"
+          :show="state.showModel"
+          @close="state.showModel = false"
+          @get="onGet"
+        />
 
 
         <!-- 满减送/限时折扣活动弹窗 -->
         <!-- 满减送/限时折扣活动弹窗 -->
-        <s-activity-pop v-model="state" :show="state.showActivityModel"
-                        @close="state.showActivityModel = false" @get="onGet" />
+        <s-activity-pop
+          v-model="state.activityInfo"
+          :show="state.showActivityModel"
+          @close="state.showActivityModel = false"
+        />
       </block>
       </block>
     </s-layout>
     </s-layout>
   </view>
   </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import {
-    reactive,
-    computed,
-    ref
-  } from 'vue';
-  import {
-    onLoad,
-    onPageScroll
-  } from '@dcloudio/uni-app';
+  import { reactive, computed } from 'vue';
+  import { onLoad, onPageScroll } from '@dcloudio/uni-app';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import CouponApi from '@/sheep/api/promotion/coupon';
   import CouponApi from '@/sheep/api/promotion/coupon';
   import ActivityApi from '@/sheep/api/promotion/activity';
   import ActivityApi from '@/sheep/api/promotion/activity';
   import FavoriteApi from '@/sheep/api/product/favorite';
   import FavoriteApi from '@/sheep/api/product/favorite';
-  import {
-    formatSales,
-    formatGoodsSwiper,
-    fen2yuan,
-    handList,
-    handListPrice
-  } from '@/sheep/hooks/useGoods';
+  import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
   import detailNavbar from './components/detail/detail-navbar.vue';
   import detailNavbar from './components/detail/detail-navbar.vue';
   import detailCellSku from './components/detail/detail-cell-sku.vue';
   import detailCellSku from './components/detail/detail-cell-sku.vue';
   import detailTabbar from './components/detail/detail-tabbar.vue';
   import detailTabbar from './components/detail/detail-tabbar.vue';
@@ -156,22 +161,11 @@
   import detailCommentCard from './components/detail/detail-comment-card.vue';
   import detailCommentCard from './components/detail/detail-comment-card.vue';
   import detailContentCard from './components/detail/detail-content-card.vue';
   import detailContentCard from './components/detail/detail-content-card.vue';
   import detailActivityTip from './components/detail/detail-activity-tip.vue';
   import detailActivityTip from './components/detail/detail-activity-tip.vue';
-  import {
-    isEmpty
-  } from 'lodash-es';
+  import { isEmpty } from 'lodash-es';
   import SpuApi from '@/sheep/api/product/spu';
   import SpuApi from '@/sheep/api/product/spu';
 
 
-  onPageScroll(() => {
-  });
-  import countDown from '@/sheep/components/countDown/index.vue'
-
-  const bgColor = {
-    'bgColor': '#E93323',
-    'Color': '#fff',
-    'width': '44rpx',
-    'timeTxtwidth': '16rpx',
-    'isDay': true
-  }
+  onPageScroll(() => {});
+
   const isLogin = computed(() => sheep.$store('user').isLogin);
   const isLogin = computed(() => sheep.$store('user').isLogin);
   const state = reactive({
   const state = reactive({
     goodsId: 0,
     goodsId: 0,
@@ -182,19 +176,13 @@
     showModel: false, // 是否展示 Coupon 优惠劵的弹窗
     showModel: false, // 是否展示 Coupon 优惠劵的弹窗
     couponInfo: [], // 可领取的 Coupon 优惠劵的列表
     couponInfo: [], // 可领取的 Coupon 优惠劵的列表
     showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
     showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
-    activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表
+    activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表 TODO 芋艿:正在接入中
     activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
     activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
   });
   });
 
 
   // 规格变更
   // 规格变更
   function onSkuChange(e) {
   function onSkuChange(e) {
-    if (e.type == 4) {
-      settleData.value = e
-      setShow.value = true
-    } else {
-      state.selectedSku = e;
-      setShow.value = false
-    }
+    state.selectedSku = e;
   }
   }
 
 
   // 添加购物车
   // 添加购物车
@@ -208,17 +196,19 @@
 
 
   // 立即购买
   // 立即购买
   function onBuy(e) {
   function onBuy(e) {
-    if (!e.id) {
+    if (!state.selectedSku.id) {
       sheep.$helper.toast('请选择商品规格');
       sheep.$helper.toast('请选择商品规格');
       return;
       return;
     }
     }
     sheep.$router.go('/pages/order/confirm', {
     sheep.$router.go('/pages/order/confirm', {
       data: JSON.stringify({
       data: JSON.stringify({
-        items: [{
-          skuId: e.id,
-          count: e.goods_num,
-          categoryId: state.goodsInfo.categoryId
-        }]
+        items: [
+          {
+            skuId: e.id,
+            count: e.goods_num,
+            categoryId: state.goodsInfo.categoryId,
+          },
+        ],
       }),
       }),
     });
     });
   }
   }
@@ -230,9 +220,7 @@
 
 
   // 立即领取
   // 立即领取
   async function onGet(id) {
   async function onGet(id) {
-    const {
-      code
-    } = await CouponApi.takeCoupon(id);
+    const { code } = await CouponApi.takeCoupon(id);
     if (code !== 0) {
     if (code !== 0) {
       return;
       return;
     }
     }
@@ -244,69 +232,35 @@
     }, 1000);
     }, 1000);
   }
   }
 
 
-  //  TODO 芋艿:待测试
   const shareInfo = computed(() => {
   const shareInfo = computed(() => {
     if (isEmpty(state.goodsInfo)) return {};
     if (isEmpty(state.goodsInfo)) return {};
-    return sheep.$platform.share.getShareInfo({
-      title: state.goodsInfo.name,
-      image: sheep.$url.cdn(state.goodsInfo.picUrl),
-      desc: state.goodsInfo.introduction,
-      params: {
-        page: '2',
-        query: state.goodsInfo.id,
+    return sheep.$platform.share.getShareInfo(
+      {
+        title: state.goodsInfo.name,
+        image: sheep.$url.cdn(state.goodsInfo.picUrl),
+        desc: state.goodsInfo.introduction,
+        params: {
+          page: '2',
+          query: state.goodsInfo.id,
+        },
       },
       },
-    }, {
-      type: 'goods', // 商品海报
-      title: state.goodsInfo.name, // 商品名称
-      image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
-      price: fen2yuan(state.goodsInfo.price), // 商品价格
-      original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
-    });
+      {
+        type: 'goods', // 商品海报
+        title: state.goodsInfo.name, // 商品名称
+        image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
+        price: fen2yuan(state.goodsInfo.price), // 商品价格
+        original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
+      },
+    );
   });
   });
 
 
   async function getCoupon() {
   async function getCoupon() {
-    const {
-      code,
-      data
-    } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
+    const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
     if (code === 0) {
     if (code === 0) {
       state.couponInfo = data;
       state.couponInfo = data;
     }
     }
   }
   }
 
 
-  //获取结算信息
-  const setShow = ref(false)
-  const settleData = ref()
-
-  async function getSettlementByIds(ids) {
-    const { data } = await SpuApi.getSettlementProduct(ids);
-    settleData.value = handle(data)
-    state.goodsInfo.skus = handListPrice(state.goodsInfo.skus, data[0].skus)
-  }
-
-  //判断是否有限时折扣信息
-  function handle(array) {
-    let setList = {}
-    array.some(item => {
-      return item.skus.some(items => {
-        if (items.type === 4) {
-          setShow.value = true;
-          setList = items;
-          return true; // 返回true以结束some循环
-        }
-        return false; // 继续遍历
-      });
-    });
-    // 将库存信息加入
-    state.goodsInfo.skus.forEach(item => {
-      if (item.id == setList.skuId) {
-        setList.stock = item.stock
-      }
-    })
-
-    return setList
-  }
-
   onLoad((options) => {
   onLoad((options) => {
     // 非法参数
     // 非法参数
     if (!options.id) {
     if (!options.id) {
@@ -324,6 +278,7 @@
       // 加载到商品
       // 加载到商品
       state.skeletonLoading = false;
       state.skeletonLoading = false;
       state.goodsInfo = res.data;
       state.goodsInfo = res.data;
+
       // 加载是否收藏
       // 加载是否收藏
       if (isLogin.value) {
       if (isLogin.value) {
         FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
         FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
@@ -338,24 +293,13 @@
     // 2. 加载优惠劵信息
     // 2. 加载优惠劵信息
     getCoupon();
     getCoupon();
 
 
-    // 3. 加载营销活动信息
+    // 3. 获得单个商品,进行中的拼团、秒杀、砍价活动信息
     ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
     ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
       if (res.code !== 0) {
       if (res.code !== 0) {
         return;
         return;
       }
       }
-      let activData = handList(res.data)
-      activData.forEach(activity => {
-        if ([1, 2, 3].includes(activity.type)) { // 情况一:拼团/秒杀/砍价
-          state.activityList.push(activity);
-        } else if (activity.type === 5) { // 情况二:满减送
-          state.activityInfo.push(activity);
-        } else { // 情况三:限时折扣 TODO 芋艿
-          // console.log('待实现!优先级不高');
-        }
-      })
+      state.activityList = res.data;
     });
     });
-    //获取结算信息
-    getSettlementByIds(state.goodsId)
   });
   });
 </script>
 </script>
 
 
@@ -504,101 +448,4 @@
       color: #333333;
       color: #333333;
     }
     }
   }
   }
-
-  // 限时折扣
-  .discount {
-    width: 750rpx;
-    height: 100rpx;
-    // background-color: red;
-    overflow: hidden;
-    position: relative;
-  }
-
-  .disImg {
-    width: 750rpx;
-    height: 100rpx;
-    position: absolute;
-    top: 0;
-    z-index: -1;
-  }
-
-  .discountCont {
-    width: 680rpx;
-    height: 90rpx;
-    margin: 10rpx auto 0 auto;
-    // background-color: gold;
-  }
-
-  .disContT {
-    width: 680rpx;
-    height: 50rpx;
-    display: flex;
-    justify-content: space-between;
-  }
-
-  .disContT1 {
-    width: 400rpx;
-    height: 50rpx;
-    // background-color: green;
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
-  }
-
-  .disContT2 {
-    width: 200rpx;
-    height: 50rpx;
-    line-height: 50rpx;
-    // background-color: gold;
-    font-size: 30rpx;
-    text-align: end;
-    color: white;
-    font-weight: bolder;
-    font-style: oblique 20deg;
-    letter-spacing: .1rem;
-  }
-
-  .disContT1P {
-    color: white;
-    font-weight: bold;
-    font-size: 28rpx;
-  }
-
-  .disContT1End {
-    // width: 180rpx;
-    padding: 0 10rpx;
-    height: 30rpx;
-    line-height: 28rpx;
-    text-align: center;
-    font-weight: bold;
-    background-color: white;
-    color: #ff3000;
-    font-size: 23rpx;
-    border-radius: 20rpx;
-    margin-left: 10rpx;
-  }
-
-  .disContB {
-    width: 680rpx;
-    height: 40rpx;
-    display: flex;
-    justify-content: space-between;
-    font-size: 20rpx;
-    color: white;
-    align-items: center;
-  }
-
-  .disContB1 {
-    width: 300rpx;
-    height: 40rpx;
-    line-height: 40rpx;
-  }
-
-  .disContB2 {
-    width: 300rpx;
-    height: 40rpx;
-    line-height: 40rpx;
-    display: flex;
-    justify-content: flex-end;
-  }
-</style>
+</style>

+ 2 - 6
pages/index/cart.vue

@@ -107,6 +107,7 @@
 				skuId: item.sku.id,
 				skuId: item.sku.id,
 				count: item.count,
 				count: item.count,
 				cartId: item.id,
 				cartId: item.id,
+				categoryId: item.spu.categoryId
 			})
 			})
 			goods_list.push({
 			goods_list.push({
 				// goods_id: item.goods_id,
 				// goods_id: item.goods_id,
@@ -124,12 +125,7 @@
 		}
 		}
 		sheep.$router.go('/pages/order/confirm', {
 		sheep.$router.go('/pages/order/confirm', {
 			data: JSON.stringify({
 			data: JSON.stringify({
-				// order_type: 'goods',
-				// goods_list,
-				items,
-				// from: 'cart',
-				deliveryType: 1,
-				pointStatus: false,
+				items
 			}),
 			}),
 		});
 		});
 	}
 	}

+ 6 - 5
pages/index/category.vue

@@ -131,12 +131,13 @@
     getGoodsList();
     getGoodsList();
   }
   }
 
 
-  onLoad(async () => {
+  onLoad(async (params) => {
     await getList();
     await getList();
-    // 如果是 first 风格,需要加载商品分页
-    if (state.style === 'first_one' || state.style === 'first_two') {
-      onMenu(0);
-    }
+
+    // 首页点击分类的处理:查找满足条件的分类
+    const foundCategory = state.categoryList.find(category => category.id === params.id);
+    // 如果找到则调用 onMenu 自动勾选相应分类,否则调用 onMenu(0) 勾选第一个分类
+    onMenu(foundCategory ? state.categoryList.indexOf(foundCategory) : 0);
   });
   });
 
 
   onReachBottom(() => {
   onReachBottom(() => {

+ 64 - 49
pages/order/addressSelection.vue

@@ -1,52 +1,69 @@
 <!-- 下单界面,收货地址 or 自提门店的选择组件 -->
 <!-- 下单界面,收货地址 or 自提门店的选择组件 -->
 <template>
 <template>
-  <view class="allAddress" :style="state.isPickUp ? '':'padding-top:10rpx;'">
+  <view class="allAddress" :style="state.isPickUp ? '' : 'padding-top:10rpx;'">
     <view class="nav flex flex-wrap">
     <view class="nav flex flex-wrap">
-      <view class="item font-color" :class="state.deliveryType === 1 ? 'on' : 'on2'"
-            @tap="switchDeliveryType(1)" v-if='state.isPickUp' />
-      <view class="item font-color" :class="state.deliveryType === 2 ? 'on' : 'on2'"
-            @tap="switchDeliveryType(2)" v-if='state.isPickUp' />
+      <view
+        class="item font-color"
+        :class="state.deliveryType === 1 ? 'on' : 'on2'"
+        @tap="switchDeliveryType(1)"
+        v-if="state.isPickUp"
+      />
+      <view
+        class="item font-color"
+        :class="state.deliveryType === 2 ? 'on' : 'on2'"
+        @tap="switchDeliveryType(2)"
+        v-if="state.isPickUp"
+      />
     </view>
     </view>
     <!-- 情况一:收货地址的选择 -->
     <!-- 情况一:收货地址的选择 -->
-    <view class='address flex flex-wrap flex-center ss-row-between' @tap='onSelectAddress' v-if='state.deliveryType === 1'
-          :style="state.isPickUp ? '':'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'">
-      <view class='addressCon' v-if="state.addressInfo.name">
-        <view class='name'>{{ state.addressInfo.name }}
-          <text class='phone'>{{ state.addressInfo.mobile }}</text>
+    <view
+      class="address flex flex-wrap flex-center ss-row-between"
+      @tap="onSelectAddress"
+      v-if="state.deliveryType === 1"
+      :style="state.isPickUp ? '' : 'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'"
+    >
+      <view class="addressCon" v-if="state.addressInfo.name">
+        <view class="name"
+          >{{ state.addressInfo.name }}
+          <text class="phone">{{ state.addressInfo.mobile }}</text>
         </view>
         </view>
         <view class="flex flex-wrap">
         <view class="flex flex-wrap">
-          <text class='default font-color' v-if="state.addressInfo.defaultStatus">[默认]</text>
-          <text class="line2">{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text>
+          <text class="default font-color" v-if="state.addressInfo.defaultStatus">[默认]</text>
+          <text class="line2"
+            >{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text
+          >
         </view>
         </view>
       </view>
       </view>
-      <view class='addressCon' v-else>
-        <view class='setaddress'>设置收货地址</view>
+      <view class="addressCon" v-else>
+        <view class="setaddress">设置收货地址</view>
       </view>
       </view>
-      <view class='iconfont'>
+      <view class="iconfont">
         <view class="ss-rest-button">
         <view class="ss-rest-button">
           <text class="_icon-forward" />
           <text class="_icon-forward" />
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
     <!-- 情况二:门店的选择 -->
     <!-- 情况二:门店的选择 -->
-    <view class='address flex flex-wrap flex-center ss-row-between' v-else @tap="onSelectAddress">
-      <view class='addressCon' v-if="state.pickUpInfo.name">
-        <view class='name'>{{ state.pickUpInfo.name }}
-          <text class='phone'>{{ state.pickUpInfo.phone }}</text>
+    <view class="address flex flex-wrap flex-center ss-row-between" v-else @tap="onSelectAddress">
+      <view class="addressCon" v-if="state.pickUpInfo.name">
+        <view class="name"
+          >{{ state.pickUpInfo.name }}
+          <text class="phone">{{ state.pickUpInfo.phone }}</text>
         </view>
         </view>
-        <view class="line1"> {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
+        <view class="line1">
+          {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
         </view>
         </view>
       </view>
       </view>
-      <view class='addressCon' v-else>
-        <view class='setaddress'>选择自提门店</view>
+      <view class="addressCon" v-else>
+        <view class="setaddress">选择自提门店</view>
       </view>
       </view>
-      <view class='iconfont'>
+      <view class="iconfont">
         <view class="ss-rest-button">
         <view class="ss-rest-button">
           <text class="_icon-forward" />
           <text class="_icon-forward" />
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
-    <view class='line'>
+    <view class="line">
       <image :src="sheep.$url.static('/static/images/line.png', 'local')" />
       <image :src="sheep.$url.static('/static/images/line.png', 'local')" />
     </view>
     </view>
   </view>
   </view>
@@ -61,13 +78,13 @@
     modelValue: {
     modelValue: {
       type: Object,
       type: Object,
       default() {},
       default() {},
-    }
+    },
   });
   });
-  const emits = defineEmits(['update:modelValue','change']);
+  const emits = defineEmits(['update:modelValue']);
 
 
   // computed 解决父子组件双向数据同步
   // computed 解决父子组件双向数据同步
   const state = computed({
   const state = computed({
-    get(){
+    get() {
       return new Proxy(props.modelValue, {
       return new Proxy(props.modelValue, {
         set(obj, name, val) {
         set(obj, name, val) {
           emits('update:modelValue', {
           emits('update:modelValue', {
@@ -75,21 +92,21 @@
             [name]: val,
             [name]: val,
           });
           });
           return true;
           return true;
-        }
-      })
+        },
+      });
     },
     },
-    set(val){
+    set(val) {
       emits('update:modelValue', val);
       emits('update:modelValue', val);
-    }
-  })
+    },
+  });
 
 
   // 选择地址
   // 选择地址
   function onSelectAddress() {
   function onSelectAddress() {
-    let emitName = 'SELECT_ADDRESS'
+    let emitName = 'SELECT_ADDRESS';
     let addressPage = '/pages/user/address/list?type=select';
     let addressPage = '/pages/user/address/list?type=select';
-    if (state.value.deliveryType === 2){
-      emitName = 'SELECT_PICK_UP_INFO'
-      addressPage = '/pages/user/goods_details_store/index'
+    if (state.value.deliveryType === 2) {
+      emitName = 'SELECT_PICK_UP_INFO';
+      addressPage = '/pages/user/goods_details_store/index';
     }
     }
     uni.$once(emitName, (e) => {
     uni.$once(emitName, (e) => {
       changeConsignee(e.addressInfo);
       changeConsignee(e.addressInfo);
@@ -100,28 +117,26 @@
   // 更改收货人地址&计算订单信息
   // 更改收货人地址&计算订单信息
   async function changeConsignee(addressInfo = {}) {
   async function changeConsignee(addressInfo = {}) {
     if (!isEmpty(addressInfo)) {
     if (!isEmpty(addressInfo)) {
-      if (state.value.deliveryType === 1){
+      if (state.value.deliveryType === 1) {
         state.value.addressInfo = addressInfo;
         state.value.addressInfo = addressInfo;
       }
       }
-      if (state.value.deliveryType === 2){
+      if (state.value.deliveryType === 2) {
         state.value.pickUpInfo = addressInfo;
         state.value.pickUpInfo = addressInfo;
       }
       }
-      emits('change')
     }
     }
   }
   }
 
 
   // 收货方式切换
   // 收货方式切换
-  const switchDeliveryType = (type) =>{
+  const switchDeliveryType = (type) => {
     state.value.deliveryType = type;
     state.value.deliveryType = type;
-    emits('change')
-  }
+  };
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
-  .allAddress .font-color{
-    color: #E93323!important
+  .allAddress .font-color {
+    color: #e93323 !important;
   }
   }
-  .line2{
+  .line2 {
     width: 504rpx;
     width: 504rpx;
   }
   }
   .textR {
   .textR {
@@ -204,7 +219,7 @@
   .allAddress .nav .item.on::before {
   .allAddress .nav .item.on::before {
     position: absolute;
     position: absolute;
     bottom: 0;
     bottom: 0;
-    content: "快递配送";
+    content: '快递配送';
     font-size: 28rpx;
     font-size: 28rpx;
     display: block;
     display: block;
     height: 0;
     height: 0;
@@ -219,7 +234,7 @@
   }
   }
 
 
   .allAddress .nav .item:nth-of-type(2).on::before {
   .allAddress .nav .item:nth-of-type(2).on::before {
-    content: "到店自提";
+    content: '到店自提';
     border-width: 0 0 80rpx 20rpx;
     border-width: 0 0 80rpx 20rpx;
     border-radius: 36rpx 14rpx 0 0;
     border-radius: 36rpx 14rpx 0 0;
   }
   }
@@ -231,7 +246,7 @@
   .allAddress .nav .item.on2::before {
   .allAddress .nav .item.on2::before {
     position: absolute;
     position: absolute;
     bottom: 0;
     bottom: 0;
-    content: "到店自提";
+    content: '到店自提';
     font-size: 28rpx;
     font-size: 28rpx;
     display: block;
     display: block;
     height: 0;
     height: 0;
@@ -245,7 +260,7 @@
   }
   }
 
 
   .allAddress .nav .item:nth-of-type(1).on2::before {
   .allAddress .nav .item:nth-of-type(1).on2::before {
-    content: "快递配送";
+    content: '快递配送';
     border-width: 0 60rpx 60rpx 0;
     border-width: 0 60rpx 60rpx 0;
     border-radius: 14rpx 36rpx 0 0;
     border-radius: 14rpx 36rpx 0 0;
   }
   }

+ 132 - 79
pages/order/confirm.vue

@@ -1,18 +1,30 @@
 <template>
 <template>
   <s-layout title="确认订单">
   <s-layout title="确认订单">
     <!-- 头部地址选择【配送地址】【自提地址】 -->
     <!-- 头部地址选择【配送地址】【自提地址】 -->
-    <AddressSelection v-model="addressState" @change="getOrderInfo()" />
+    <AddressSelection v-model="addressState" />
 
 
     <!-- 商品信息 -->
     <!-- 商品信息 -->
     <view class="order-card-box ss-m-b-14">
     <view class="order-card-box ss-m-b-14">
-      <s-goods-item v-for="item in state.orderInfo.items" :key="item.skuId" :img="item.picUrl"
-                    :title="item.spuName" :skuText="item.properties.map((property) => property.valueName).join(' ')"
-                    :price="item.price" :num="item.count" marginBottom="10" />
+      <s-goods-item
+        v-for="item in state.orderInfo.items"
+        :key="item.skuId"
+        :img="item.picUrl"
+        :title="item.spuName"
+        :skuText="item.properties.map((property) => property.valueName).join(' ')"
+        :price="item.price"
+        :num="item.count"
+        marginBottom="10"
+      />
       <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
       <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
         <view class="item-title">订单备注</view>
         <view class="item-title">订单备注</view>
         <view class="ss-flex ss-col-center">
         <view class="ss-flex ss-col-center">
-          <uni-easyinput maxlength="20" placeholder="建议留言前先与商家沟通" v-model="state.orderPayload.remark"
-                         :inputBorder="false" :clearable="false" />
+          <uni-easyinput
+            maxlength="20"
+            placeholder="建议留言前先与商家沟通"
+            v-model="state.orderPayload.remark"
+            :inputBorder="false"
+            :clearable="false"
+          />
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
@@ -28,71 +40,121 @@
             </text>
             </text>
           </view>
           </view>
         </view>
         </view>
-        <view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0">
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="state.orderInfo.type === 0"
+        >
           <view class="item-title">积分抵扣</view>
           <view class="item-title">积分抵扣</view>
           <view class="ss-flex ss-col-center">
           <view class="ss-flex ss-col-center">
             {{ state.pointStatus ? '剩余积分' : '当前积分' }}
             {{ state.pointStatus ? '剩余积分' : '当前积分' }}
-            <image :src="sheep.$url.static('/static/img/shop/goods/score1.svg')" class="score-img" />
+            <image
+              :src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
+              class="score-img"
+            />
             <text class="item-value ss-m-r-24">
             <text class="item-value ss-m-r-24">
-              {{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
+              {{
+                state.pointStatus
+                  ? state.orderInfo.totalPoint - state.orderInfo.usePoint
+                  : state.orderInfo.totalPoint || 0
+              }}
             </text>
             </text>
             <checkbox-group @change="changeIntegral">
             <checkbox-group @change="changeIntegral">
-              <checkbox :checked='state.pointStatus'
-                        :disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
+              <checkbox
+                :checked="state.pointStatus"
+                :disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0"
+              />
             </checkbox-group>
             </checkbox-group>
           </view>
           </view>
         </view>
         </view>
         <!-- 快递配置时,信息的展示 -->
         <!-- 快递配置时,信息的展示 -->
-        <view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 1'>
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="addressState.deliveryType === 1"
+        >
           <view class="item-title">运费</view>
           <view class="item-title">运费</view>
           <view class="ss-flex ss-col-center">
           <view class="ss-flex ss-col-center">
             <text class="item-value ss-m-r-24" v-if="state.orderInfo.price.deliveryPrice > 0">
             <text class="item-value ss-m-r-24" v-if="state.orderInfo.price.deliveryPrice > 0">
               +¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
               +¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
             </text>
             </text>
-            <view class='item-value ss-m-r-24' v-else>免运费</view>
+            <view class="item-value ss-m-r-24" v-else>免运费</view>
           </view>
           </view>
         </view>
         </view>
         <!-- 门店自提时,需要填写姓名和手机号 -->
         <!-- 门店自提时,需要填写姓名和手机号 -->
-        <view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="addressState.deliveryType === 2"
+        >
           <view class="item-title">联系人</view>
           <view class="item-title">联系人</view>
           <view class="ss-flex ss-col-center">
           <view class="ss-flex ss-col-center">
-            <uni-easyinput maxlength="20" placeholder="请填写您的联系姓名" v-model="addressState.receiverName"
-                           :inputBorder="false" :clearable="false" />
+            <uni-easyinput
+              maxlength="20"
+              placeholder="请填写您的联系姓名"
+              v-model="addressState.receiverName"
+              :inputBorder="false"
+              :clearable="false"
+            />
           </view>
           </view>
         </view>
         </view>
-        <view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="addressState.deliveryType === 2"
+        >
           <view class="item-title">联系电话</view>
           <view class="item-title">联系电话</view>
           <view class="ss-flex ss-col-center">
           <view class="ss-flex ss-col-center">
-            <uni-easyinput maxlength="20" placeholder="请填写您的联系电话" v-model="addressState.receiverMobile"
-                           :inputBorder="false" :clearable="false" />
+            <uni-easyinput
+              maxlength="20"
+              placeholder="请填写您的联系电话"
+              v-model="addressState.receiverMobile"
+              :inputBorder="false"
+              :clearable="false"
+            />
           </view>
           </view>
         </view>
         </view>
         <!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
         <!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
-        <view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0">
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="state.orderInfo.type === 0"
+        >
           <view class="item-title">优惠券</view>
           <view class="item-title">优惠券</view>
           <view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
           <view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
             <text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
             <text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
               -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
               -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
             </text>
             </text>
-            <text class="item-value" :class="couponNumber > 0 ? 'text-red' : 'text-disabled'" v-else>
+            <text
+              class="item-value"
+              :class="
+                state.couponInfo.filter((coupon) => coupon.match).length > 0
+                  ? 'text-red'
+                  : 'text-disabled'
+              "
+              v-else
+            >
               {{
               {{
-                couponNumber > 0 ? couponNumber + ' 张可用' : '暂无可用优惠券'
+                state.couponInfo.filter((coupon) => coupon.match).length > 0
+                  ? state.couponInfo.filter((coupon) => coupon.match).length + ' 张可用'
+                  : '暂无可用优惠券'
               }}
               }}
             </text>
             </text>
             <text class="_icon-forward item-icon" />
             <text class="_icon-forward item-icon" />
           </view>
           </view>
         </view>
         </view>
-        <view class="order-item ss-flex ss-col-center ss-row-between"
-              v-if="state.orderInfo.price.discountPrice > 0">
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="state.orderInfo.price.discountPrice > 0"
+        >
           <view class="item-title">活动优惠</view>
           <view class="item-title">活动优惠</view>
-          <view class="ss-flex ss-col-center" @tap="state.showDiscount = true">
+          <view class="ss-flex ss-col-center">
+            <!--                @tap="state.showDiscount = true" TODO puhui999:【折扣】后续要把优惠信息打进去 -->
             <text class="item-value text-red">
             <text class="item-value text-red">
               -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
               -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
             </text>
             </text>
             <text class="_icon-forward item-icon" />
             <text class="_icon-forward item-icon" />
           </view>
           </view>
         </view>
         </view>
-        <view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.price.vipPrice > 0">
+        <view
+          class="order-item ss-flex ss-col-center ss-row-between"
+          v-if="state.orderInfo.price.vipPrice > 0"
+        >
           <view class="item-title">会员优惠</view>
           <view class="item-title">会员优惠</view>
           <view class="ss-flex ss-col-center">
           <view class="ss-flex ss-col-center">
             <text class="item-value text-red">
             <text class="item-value text-red">
@@ -111,11 +173,19 @@
     </view>
     </view>
 
 
     <!-- 选择优惠券弹框 -->
     <!-- 选择优惠券弹框 -->
-    <s-coupon-select v-model="state.couponInfo" :show="state.showCoupon" @confirm="onSelectCoupon"
-                     @close="state.showCoupon = false" />
-
-    <!-- 满额折扣弹框 TODO 芋艿:后续要把优惠信息打进去 -->
-    <s-discount-list v-model="state.orderInfo" :show="state.showDiscount" @close="state.showDiscount = false" />
+    <s-coupon-select
+      v-model="state.couponInfo"
+      :show="state.showCoupon"
+      @confirm="onSelectCoupon"
+      @close="state.showCoupon = false"
+    />
+
+    <!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
+    <s-discount-list
+      v-model="state.orderInfo"
+      :show="state.showDiscount"
+      @close="state.showDiscount = false"
+    />
 
 
     <!-- 底部 -->
     <!-- 底部 -->
     <su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
     <su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
@@ -125,7 +195,10 @@
             ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
             ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
           </view>
           </view>
         </view>
         </view>
-        <button class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main" @tap="onConfirm">
+        <button
+          class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
+          @tap="onConfirm"
+        >
           提交订单
           提交订单
         </button>
         </button>
       </view>
       </view>
@@ -134,20 +207,13 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import {
-    reactive,
-    ref
-  } from 'vue';
-  import {
-    onLoad
-  } from '@dcloudio/uni-app';
+  import { reactive, ref, watch } from 'vue';
+  import { onLoad } from '@dcloudio/uni-app';
   import AddressSelection from '@/pages/order/addressSelection.vue';
   import AddressSelection from '@/pages/order/addressSelection.vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import OrderApi from '@/sheep/api/trade/order';
   import OrderApi from '@/sheep/api/trade/order';
-  import CouponApi from '@/sheep/api/promotion/coupon';
-  import {
-    fen2yuan
-  } from '@/sheep/hooks/useGoods';
+  import TradeConfigApi from '@/sheep/api/trade/config';
+  import { fen2yuan } from '@/sheep/hooks/useGoods';
 
 
   const state = reactive({
   const state = reactive({
     orderPayload: {},
     orderPayload: {},
@@ -164,8 +230,8 @@
 
 
   const addressState = ref({
   const addressState = ref({
     addressInfo: {}, // 选择的收货地址
     addressInfo: {}, // 选择的收货地址
-    deliveryType: 1, // 收货方式 1 - 快递配送;2 - 门店自提
-    isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
+    deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
+    isPickUp: true, // 门店自提是否开启
     pickUpInfo: {}, // 选择的自提门店信息
     pickUpInfo: {}, // 选择的自提门店信息
     receiverName: '', // 收件人名称
     receiverName: '', // 收件人名称
     receiverMobile: '', // 收件人手机
     receiverMobile: '', // 收件人手机
@@ -182,7 +248,7 @@
 
 
   // 选择优惠券
   // 选择优惠券
   async function onSelectCoupon(couponId) {
   async function onSelectCoupon(couponId) {
-    state.orderPayload.couponId = couponId || 0;
+    state.orderPayload.couponId = couponId;
     await getOrderInfo();
     await getOrderInfo();
     state.showCoupon = false;
     state.showCoupon = false;
   }
   }
@@ -216,10 +282,7 @@
 
 
   // 创建订单&跳转
   // 创建订单&跳转
   async function submitOrder() {
   async function submitOrder() {
-    const {
-      code,
-      data
-    } = await OrderApi.createOrder({
+    const { code, data } = await OrderApi.createOrder({
       items: state.orderPayload.items,
       items: state.orderPayload.items,
       couponId: state.orderPayload.couponId,
       couponId: state.orderPayload.couponId,
       remark: state.orderPayload.remark,
       remark: state.orderPayload.remark,
@@ -250,10 +313,7 @@
   // 检查库存 & 计算订单价格
   // 检查库存 & 计算订单价格
   async function getOrderInfo() {
   async function getOrderInfo() {
     // 计算价格
     // 计算价格
-    const {
-      data,
-      code
-    } = await OrderApi.settlementOrder({
+    const { data, code } = await OrderApi.settlementOrder({
       items: state.orderPayload.items,
       items: state.orderPayload.items,
       couponId: state.orderPayload.couponId,
       couponId: state.orderPayload.couponId,
       deliveryType: addressState.value.deliveryType,
       deliveryType: addressState.value.deliveryType,
@@ -267,38 +327,16 @@
       seckillActivityId: state.orderPayload.seckillActivityId,
       seckillActivityId: state.orderPayload.seckillActivityId,
     });
     });
     if (code !== 0) {
     if (code !== 0) {
-      setTimeout(() => {
-        uni.navigateBack({
-          delta: 1
-        })
-      }, 1500)
       return;
       return;
     }
     }
     state.orderInfo = data;
     state.orderInfo = data;
+    state.couponInfo = data.coupons;
     // 设置收货地址
     // 设置收货地址
     if (state.orderInfo.address) {
     if (state.orderInfo.address) {
       addressState.value.addressInfo = state.orderInfo.address;
       addressState.value.addressInfo = state.orderInfo.address;
     }
     }
   }
   }
 
 
-  // 获取可用优惠券
-  let couponNumber = ref(0)
-  async function getCoupons() {
-    const {
-      code,
-      data
-    } = await CouponApi.getMatchCouponList(
-      state.orderInfo.price.payPrice,
-      state.orderInfo.items.map((item) => item.spuId),
-      state.orderPayload.items.map((item) => item.skuId),
-      state.orderPayload.items.map((item) => item.categoryId),
-    );
-    if (code === 0) {
-      state.couponInfo = data;
-      couponNumber.value = state.couponInfo.filter(item => item.match).length;
-    }
-  }
-
   onLoad(async (options) => {
   onLoad(async (options) => {
     if (!options.data) {
     if (!options.data) {
       sheep.$helper.toast('参数不正确,请检查!');
       sheep.$helper.toast('参数不正确,请检查!');
@@ -306,7 +344,22 @@
     }
     }
     state.orderPayload = JSON.parse(options.data);
     state.orderPayload = JSON.parse(options.data);
     await getOrderInfo();
     await getOrderInfo();
-    await getCoupons();
+    // 获取交易配置
+    const { data, code } = await TradeConfigApi.getTradeConfig();
+    if (code === 0) {
+      addressState.value.isPickUp = data.deliveryPickUpEnabled;
+    }
+  });
+
+  // 使用 watch 监听地址和配送方式的变化
+  watch(addressState, async (newAddress, oldAddress) => {
+    // 如果收货地址或配送方式有变化,则重新计算价格
+    if (
+      newAddress.addressInfo.id !== oldAddress.addressInfo.id ||
+      newAddress.deliveryType !== oldAddress.deliveryType
+    ) {
+      await getOrderInfo();
+    }
   });
   });
 </script>
 </script>
 
 
@@ -429,4 +482,4 @@
     font-size: 36rpx;
     font-size: 36rpx;
     color: #999999;
     color: #999999;
   }
   }
-</style>
+</style>

+ 30 - 8
pages/order/detail.vue

@@ -45,9 +45,9 @@
         </image>
         </image>
         <view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
         <view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
       </view>
       </view>
-      <view class="ss-font-26 ss-m-x-20 ss-m-b-70">{{
-        formatOrderStatusDescription(state.orderInfo)
-      }}</view>
+      <view class="ss-font-26 ss-m-x-20 ss-m-b-70">
+        {{ formatOrderStatusDescription(state.orderInfo) }}
+      </view>
     </view>
     </view>
 
 
     <!-- 收货地址 -->
     <!-- 收货地址 -->
@@ -126,6 +126,9 @@
       </view>
       </view>
     </view>
     </view>
 
 
+    <!--  自提核销  -->
+    <PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
+
     <!-- 订单信息 -->
     <!-- 订单信息 -->
     <view class="notice-box">
     <view class="notice-box">
       <view class="notice-box__content">
       <view class="notice-box__content">
@@ -167,11 +170,14 @@
         <text class="title">运费</text>
         <text class="title">运费</text>
         <text class="detail">¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
         <text class="detail">¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
       </view>
       </view>
-      <!-- TODO 芋艿:优惠劵抵扣、积分抵扣 -->
       <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
       <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
         <text class="title">优惠劵金额</text>
         <text class="title">优惠劵金额</text>
         <text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
         <text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
       </view>
       </view>
+      <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
+        <text class="title">积分抵扣</text>
+        <text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
+      </view>
       <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
       <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
         <text class="title">活动优惠</text>
         <text class="title">活动优惠</text>
         <text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
         <text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
@@ -251,7 +257,7 @@
 <script setup>
 <script setup>
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import { onLoad } from '@dcloudio/uni-app';
   import { onLoad } from '@dcloudio/uni-app';
-  import { reactive } from 'vue';
+  import { reactive, ref } from 'vue';
   import { isEmpty } from 'lodash-es';
   import { isEmpty } from 'lodash-es';
   import {
   import {
     fen2yuan,
     fen2yuan,
@@ -260,6 +266,8 @@
     handleOrderButtons,
     handleOrderButtons,
   } from '@/sheep/hooks/useGoods';
   } from '@/sheep/hooks/useGoods';
   import OrderApi from '@/sheep/api/trade/order';
   import OrderApi from '@/sheep/api/trade/order';
+  import DeliveryApi from '@/sheep/api/trade/delivery';
+  import PickUpVerify from '@/pages/order/pickUpVerify.vue';
 
 
   const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
   const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
   const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
   const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
@@ -270,6 +278,9 @@
     comeinType: '', // 进入订单详情的来源类型
     comeinType: '', // 进入订单详情的来源类型
   });
   });
 
 
+  // ========== 门店自提(核销) ==========
+  const systemStore = ref({}); // 门店信息
+
   // 复制
   // 复制
   const onCopy = () => {
   const onCopy = () => {
     sheep.$helper.copyText(state.orderInfo.no);
     sheep.$helper.copyText(state.orderInfo.no);
@@ -294,7 +305,7 @@
     uni.showModal({
     uni.showModal({
       title: '提示',
       title: '提示',
       content: '确定要取消订单吗?',
       content: '确定要取消订单吗?',
-      success: async function (res) {
+      success: async function(res) {
         if (!res.confirm) {
         if (!res.confirm) {
           return;
           return;
         }
         }
@@ -313,7 +324,7 @@
     });
     });
   }
   }
 
 
-  // 确认收货 TODO 芋艿:待测试
+  // 确认收货
   async function onConfirm(orderId, ignore = false) {
   async function onConfirm(orderId, ignore = false) {
     // 需开启确认收货组件
     // 需开启确认收货组件
     // todo: 芋艿:待接入微信
     // todo: 芋艿:待接入微信
@@ -366,6 +377,7 @@
       },
       },
     });
     });
   }
   }
+
   // #endif
   // #endif
 
 
   // 评价
   // 评价
@@ -375,6 +387,8 @@
     });
     });
   }
   }
 
 
+  const pickUpVerifyRef = ref();
+
   async function getOrderDetail(id) {
   async function getOrderDetail(id) {
     // 对详情数据进行适配
     // 对详情数据进行适配
     let res;
     let res;
@@ -389,6 +403,14 @@
     if (res.code === 0) {
     if (res.code === 0) {
       state.orderInfo = res.data;
       state.orderInfo = res.data;
       handleOrderButtons(state.orderInfo);
       handleOrderButtons(state.orderInfo);
+      // 配送方式:门店自提
+      if (res.data.pickUpStoreId) {
+        const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
+        systemStore.value = data || {};
+      }
+      if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
+        pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
+      }
     } else {
     } else {
       sheep.$router.back();
       sheep.$router.back();
     }
     }
@@ -429,7 +451,7 @@
     color: rgba(#fff, 0.9);
     color: rgba(#fff, 0.9);
     width: 100%;
     width: 100%;
     background: v-bind(headerBg) no-repeat,
     background: v-bind(headerBg) no-repeat,
-      linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
+    linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
     background-size: 750rpx 100%;
     background-size: 750rpx 100%;
     box-sizing: border-box;
     box-sizing: border-box;
 
 

+ 2 - 2
pages/order/express/log.vue

@@ -12,7 +12,7 @@
           </swiper>
           </swiper>
         </uni-swiper-dot>
         </uni-swiper-dot>
         <view class="log-card-msg">
         <view class="log-card-msg">
-          <!-- TODO 芋艿:优化点:展示状态 -->
+          <!-- TODO 芋艿:【物流】优化点:展示状态 -->
 <!--          <view class="ss-flex ss-m-b-8">-->
 <!--          <view class="ss-flex ss-m-b-8">-->
 <!--            <view>物流状态:</view>-->
 <!--            <view>物流状态:</view>-->
 <!--            <view class="warning-color">{{ state.info.status_text }}</view>-->
 <!--            <view class="warning-color">{{ state.info.status_text }}</view>-->
@@ -34,7 +34,7 @@
             <view v-if="state.tracks.length - 1 !== index" class="line" />
             <view v-if="state.tracks.length - 1 !== index" class="line" />
           </view>
           </view>
           <view class="log-content-msg">
           <view class="log-content-msg">
-            <!-- TODO 芋艿:优化点:展示状态 -->
+            <!-- TODO 芋艿:【物流】优化点:展示状态 -->
 <!--            <view class="log-msg-title ss-m-b-20">-->
 <!--            <view class="log-msg-title ss-m-b-20">-->
 <!--              {{ item.status_text }}-->
 <!--              {{ item.status_text }}-->
 <!--            </view>-->
 <!--            </view>-->

+ 261 - 0
pages/order/pickUpVerify.vue

@@ -0,0 +1,261 @@
+<template>
+  <view class='order-details'>
+    <!--  自提商品核销  -->
+    <view v-if="orderInfo.deliveryType === 2 && orderInfo.payStatus" class="writeOff borRadius14">
+      <view class="title">核销信息</view>
+      <view class="grayBg flex-center">
+        <view class="pictrue">
+          <image
+            v-if="!!painterImageUrl"
+            :src="painterImageUrl"
+            :style="{width: `${state.qrcodeSize}px`, height: `${state.qrcodeSize}px`}"
+            :show-menu-by-longpress="true"
+          />
+        </view>
+      </view>
+      <view class="gear">
+        <image :src="sheep.$url.static('/static/images/writeOff.png', 'local')"></image>
+      </view>
+      <view class="num">{{ orderInfo.pickUpVerifyCode }}</view>
+      <view class="rules">
+        <!-- TODO puhui999: 需要后端放回:使用 receiveTime 即可 -->
+<!--        <view class="item">-->
+<!--          <view class="rulesTitle flex flex-wrap align-center">-->
+<!--            核销时间-->
+<!--          </view>-->
+<!--          <view class="info">-->
+<!--            每日:-->
+<!--            <text class="time">2020-2-+52</text>-->
+<!--          </view>-->
+<!--        </view>-->
+        <view class="item">
+          <view class="rulesTitle flex flex-wrap align-center">
+            <text class="iconfont icon-shuoming1"></text>
+            使用说明
+          </view>
+          <view class="info">可将二维码出示给店员扫描或提供数字核销码</view>
+        </view>
+      </view>
+    </view>
+    <view v-if="orderInfo.deliveryType === 2" class="map flex flex-wrap align-center ss-row-between borRadius14">
+      <view>自提地址信息</view>
+      <view class="place cart-color flex flex-wrap flex-center" @tap="showMaoLocation">
+        查看位置
+      </view>
+    </view>
+    <!--  海报画板:默认隐藏只用来生成海报。生成方式为主动调用  -->
+    <l-painter
+      v-if="showPainter"
+      isCanvasToTempFilePath
+      pathType="url"
+      @success="setPainterImageUrl"
+      hidden
+      ref="painterRef"
+    />
+  </view>
+</template>
+
+<script setup>
+  import sheep from '@/sheep';
+  import { reactive, ref } from 'vue';
+
+  const props = defineProps({
+    orderInfo: {
+      type: Object,
+      default() {},
+    },
+    systemStore:{
+      type: Object,
+      default() {},
+    }
+  });
+  const state = reactive({
+    qrcodeSize: 145
+  })
+
+  /**
+   * 打开地图
+   */
+  const showMaoLocation = () => {
+    console.log(props.systemStore);
+    if (!props.systemStore.latitude || !props.systemStore.longitude) {
+      sheep.$helper.toast('缺少经纬度信息无法查看地图!');
+      return
+    }
+    uni.openLocation({
+      latitude: props.systemStore.latitude,
+      longitude: props.systemStore.longitude,
+      scale: 8,
+      name: props.systemStore.name,
+      address: props.systemStore.areaName + props.systemStore.detailAddress,
+    });
+  }
+  /**
+   * 拨打电话
+   */
+  const makePhone = () => {
+    uni.makePhoneCall({
+      phoneNumber: props.systemStore.phone
+    })
+  }
+
+  const painterRef = ref(); // 海报画板
+  const painterImageUrl = ref(); // 海报 url
+  const showPainter = ref(true)
+  // 渲染海报
+  const renderPoster = async (poster) => {
+    await painterRef.value.render(poster);
+  };
+  // 获得生成的图片
+  const setPainterImageUrl = (path) => {
+    painterImageUrl.value = path;
+    showPainter.value = false
+  };
+  /**
+   * 生成核销二维码
+   */
+  const markCode = (text) => {
+    renderPoster({
+      css: {
+        width: `${state.qrcodeSize}px`,
+        height: `${state.qrcodeSize}px`
+      },
+      views:[
+        {
+          type: 'qrcode',
+          text: text,
+          css: {
+            width: `${state.qrcodeSize}px`,
+            height: `${state.qrcodeSize}px`
+          }
+        }
+      ]
+    })
+  }
+  defineExpose({
+    markCode
+  })
+</script>
+
+<style scoped lang="scss">
+  // TODO puhui999: 样式需要调整有 bug
+  .borRadius14 {
+    border-radius: 14rpx !important;
+  }
+  .cart-color {
+    color: #E93323 !important;
+    border: 1px solid #E93323 !important
+  }
+  .order-details{
+    border-radius: 10rpx;
+    margin: 0 20rpx 20rpx 20rpx;
+  }
+  .order-details .writeOff {
+    background-color: #fff;
+    margin-top: 15rpx;
+    padding-bottom: 50rpx;
+  }
+
+  .order-details .writeOff .title {
+    font-size: 30rpx;
+    color: #282828;
+    height: 87rpx;
+    border-bottom: 1px solid #f0f0f0;
+    padding: 0 24rpx;
+    line-height: 87rpx;
+  }
+
+  .order-details .writeOff .grayBg {
+    background-color: #f2f5f7;
+    width: 590rpx;
+    height: 384rpx;
+    border-radius: 20rpx 20rpx 0 0;
+    margin: 50rpx auto 0 auto;
+    padding-top: 55rpx;
+  }
+
+  .order-details .writeOff .grayBg .pictrue {
+    width: 290rpx;
+    height: 290rpx;
+  }
+
+  .order-details .writeOff .grayBg .pictrue image {
+    width: 100%;
+    height: 100%;
+  }
+
+  .order-details .writeOff .gear {
+    width: 590rpx;
+    height: 30rpx;
+    margin: 0 auto;
+  }
+
+  .order-details .writeOff .gear image {
+    width: 100%;
+    height: 100%;
+  }
+
+  .order-details .writeOff .num {
+    background-color: #f0c34c;
+    width: 590rpx;
+    height: 84rpx;
+    color: #282828;
+    font-size: 48rpx;
+    margin: 0 auto;
+    border-radius: 0 0 20rpx 20rpx;
+    text-align: center;
+    padding-top: 4rpx;
+  }
+
+  .order-details .writeOff .rules {
+    margin: 46rpx 30rpx 0 30rpx;
+    border-top: 1px solid #f0f0f0;
+    padding-top: 10rpx;
+  }
+
+  .order-details .writeOff .rules .item {
+    margin-top: 20rpx;
+  }
+
+  .order-details .writeOff .rules .item .rulesTitle {
+    font-size: 28rpx;
+    color: #282828;
+  }
+
+  .order-details .writeOff .rules .item .rulesTitle .iconfont {
+    font-size: 30rpx;
+    color: #333;
+    margin-right: 8rpx;
+    margin-top: 5rpx;
+  }
+
+  .order-details .writeOff .rules .item .info {
+    font-size: 28rpx;
+    color: #999;
+    margin-top: 7rpx;
+  }
+
+  .order-details .writeOff .rules .item .info .time {
+    margin-left: 20rpx;
+  }
+
+  .order-details .map {
+    height: 86rpx;
+    font-size: 30rpx;
+    color: #282828;
+    line-height: 86rpx;
+    border-bottom: 1px solid #f0f0f0;
+    margin-top: 15rpx;
+    background-color: #fff;
+    padding: 0 24rpx;
+  }
+
+  .order-details .map .place {
+    font-size: 26rpx;
+    width: 176rpx;
+    height: 50rpx;
+    border-radius: 25rpx;
+    line-height: 50rpx;
+    text-align: center;
+  }
+</style>

+ 6 - 0
pages/pay/index.vue

@@ -174,6 +174,12 @@
       return
       return
     }
     }
     state.payMethods = getPayMethods(data)
     state.payMethods = getPayMethods(data)
+    state.payMethods.find(item => {
+      if (item.value && !item.disabled) {
+        state.payment = item.value;
+        return true;
+      }
+    });
   }
   }
 
 
   onLoad((options) => {
   onLoad((options) => {

+ 0 - 1
pages/pay/result.vue

@@ -39,7 +39,6 @@
         <button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder">
         <button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder">
           查看订单
           查看订单
         </button>
         </button>
-        <!-- TODO 芋艿:拼团接入 -->
         <button
         <button
           class="check-btn ss-reset-button"
           class="check-btn ss-reset-button"
           v-if="payResult === 'success' && state.tradeOrder.type === 3"
           v-if="payResult === 'success' && state.tradeOrder.type === 3"

+ 1 - 1
pages/public/faq.vue

@@ -49,7 +49,7 @@
     }
     }
   }
   }
   onLoad(() => {
   onLoad(() => {
-    // TODO 芋艿:目前简单做,使用营销文章,作为 faq
+    // TODO 芋艿:【文章】目前简单做,使用营销文章,作为 faq
     if (true) {
     if (true) {
       sheep.$router.go('/pages/public/richtext', {
       sheep.$router.go('/pages/public/richtext', {
         title: '常见问题',
         title: '常见问题',

+ 12 - 3
pages/user/address/list.vue

@@ -39,8 +39,8 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import { reactive, onBeforeMount } from 'vue';
-  import { onShow } from '@dcloudio/uni-app';
+  import { onBeforeMount, reactive } from 'vue';
+  import { onShow, onLoad } from '@dcloudio/uni-app';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import { isEmpty } from 'lodash-es';
   import { isEmpty } from 'lodash-es';
   import AreaApi from '@/sheep/api/system/area';
   import AreaApi from '@/sheep/api/system/area';
@@ -49,10 +49,14 @@
   const state = reactive({
   const state = reactive({
     list: [], // 地址列表
     list: [], // 地址列表
     loading: true,
     loading: true,
+    openType: '', // 页面打开类型
   });
   });
 
 
   // 选择收货地址
   // 选择收货地址
   const onSelect = (addressInfo) => {
   const onSelect = (addressInfo) => {
+    if (state.openType !== 'select'){ // 不作为选择组件时阻断操作
+      return
+    }
     uni.$emit('SELECT_ADDRESS', {
     uni.$emit('SELECT_ADDRESS', {
       addressInfo,
       addressInfo,
     });
     });
@@ -60,7 +64,6 @@
   };
   };
 
 
   // 导入微信地址
   // 导入微信地址
-  // TODO 芋艿:未测试
   function importWechatAddress() {
   function importWechatAddress() {
     let wechatAddress = {};
     let wechatAddress = {};
     // #ifdef MP
     // #ifdef MP
@@ -110,6 +113,12 @@
     // #endif
     // #endif
   }
   }
 
 
+  onLoad((option) => {
+    if (option.type) {
+      state.openType = option.type;
+    }
+  });
+
   onShow(async () => {
   onShow(async () => {
     state.list = (await AddressApi.getAddressList()).data;
     state.list = (await AddressApi.getAddressList()).data;
     state.loading = false;
     state.loading = false;

+ 282 - 0
pages/user/goods_details_store/index.vue

@@ -0,0 +1,282 @@
+<template>
+  <s-layout title="选择自提门店" :bgStyle="{ color: '#FFF' }">
+    <view class="storeBox" ref="container">
+      <view
+        class="storeBox-box"
+        v-for="(item, index) in state.storeList"
+        :key="index"
+        @tap="checked(item)"
+      >
+        <view class="store-img">
+          <image :src="item.logo" class="img" />
+        </view>
+        <view class="store-cent-left">
+          <view class="store-name">{{ item.name }}</view>
+          <view class="store-address line1">
+            {{ item.areaName }}{{ ', ' + item.detailAddress }}
+          </view>
+        </view>
+        <view class="row-right ss-flex-col ss-col-center">
+          <view>
+            <!-- #ifdef H5 -->
+            <a class="store-phone" :href="'tel:' + item.phone">
+              <view class="iconfont">
+                <view class="ss-rest-button">
+                  <text class="_icon-forward" />
+                </view>
+              </view>
+            </a>
+            <!-- #endif -->
+            <!-- #ifdef MP -->
+            <view class="store-phone" @click="call(item.phone)">
+              <view class="iconfont">
+                <view class="ss-rest-button">
+                  <text class="_icon-forward" />
+                </view>
+              </view>
+            </view>
+            <!-- #endif -->
+          </view>
+          <view class="store-distance ss-flex ss-row-center" @tap.stop="showMaoLocation(item)">
+            <text class="addressTxt" v-if="item.distance">
+              距离{{ item.distance.toFixed(2) }}千米
+            </text>
+            <text class="addressTxt" v-else>查看地图</text>
+            <view class="iconfont">
+              <view class="ss-rest-button">
+                <text class="_icon-forward" />
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </s-layout>
+</template>
+
+<script setup>
+  import DeliveryApi from '@/sheep/api/trade/delivery';
+  import { onMounted, reactive } from 'vue';
+  import { onLoad } from '@dcloudio/uni-app';
+  import sheep from '@/sheep';
+
+  const LONGITUDE = 'user_longitude';
+  const LATITUDE = 'user_latitude';
+  const state = reactive({
+    loaded: false,
+    loading: false,
+    storeList: [],
+    system_store: {},
+    locationShow: false,
+    user_latitude: 0,
+    user_longitude: 0,
+  });
+
+  const call = (phone) => {
+    uni.makePhoneCall({
+      phoneNumber: phone,
+    });
+  };
+  const selfLocation = () => {
+    // #ifdef H5
+    const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
+    if (jsWxSdk.isWechat()) {
+      jsWxSdk.getLocation((res) => {
+        state.user_latitude = res.latitude;
+        state.user_longitude = res.longitude;
+        uni.setStorageSync(LATITUDE, res.latitude);
+        uni.setStorageSync(LONGITUDE, res.longitude);
+        getList();
+      });
+    } else {
+      // #endif
+      uni.getLocation({
+        type: 'gcj02',
+        success: (res) => {
+          try {
+            state.user_latitude = res.latitude;
+            state.user_longitude = res.longitude;
+            uni.setStorageSync(LATITUDE, res.latitude);
+            uni.setStorageSync(LONGITUDE, res.longitude);
+          } catch (e) {
+            console.error(e);
+          }
+          getList();
+        },
+        complete: () => {
+          getList();
+        },
+      });
+      // #ifdef H5
+    }
+    // #endif
+  };
+  const showMaoLocation = (e) => {
+    // #ifdef H5
+    const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
+    if (jsWxSdk.isWechat()) {
+      jsWxSdk.openLocation({
+        latitude: Number(e.latitude),
+        longitude: Number(e.longitude),
+        name: e.name,
+        address: `${e.areaName}-${e.detailAddress}`,
+      });
+    } else {
+      // #endif
+      uni.openLocation({
+        latitude: Number(e.latitude),
+        longitude: Number(e.longitude),
+        name: e.name,
+        address: `${e.areaName}-${e.detailAddress}`,
+        success: function () {
+          console.log('success');
+        },
+      });
+      // #ifdef H5
+    }
+    // #endif
+  };
+
+  /**
+   * 选中门店
+   */
+  const checked = (addressInfo) => {
+    uni.$emit('SELECT_PICK_UP_INFO', {
+      addressInfo,
+    });
+    sheep.$router.back();
+  };
+
+  /**
+   * 获取门店列表数据
+   */
+  const getList = async () => {
+    if (state.loading || state.loaded) {
+      return;
+    }
+    state.loading = true;
+    const { data, code } = await DeliveryApi.getDeliveryPickUpStoreList({
+      latitude: state.user_latitude,
+      longitude: state.user_longitude,
+    });
+    if (code !== 0) {
+      return;
+    }
+    state.loading = false;
+    state.storeList = data;
+  };
+
+  onMounted(() => {
+    if (state.user_latitude && state.user_longitude) {
+      getList();
+    } else {
+      selfLocation();
+      getList();
+    }
+  });
+  onLoad(() => {
+    try {
+      state.user_latitude = uni.getStorageSync(LATITUDE);
+      state.user_longitude = uni.getStorageSync(LONGITUDE);
+    } catch (e) {
+      console.error(e);
+    }
+  });
+</script>
+<style lang="scss" scoped>
+  .line1 {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+
+  .geoPage {
+    position: fixed;
+    width: 100%;
+    height: 100%;
+    top: 0;
+    z-index: 10000;
+  }
+
+  .storeBox {
+    width: 100%;
+    background-color: #fff;
+    padding: 0 30rpx;
+  }
+
+  .storeBox-box {
+    width: 100%;
+    height: auto;
+    display: flex;
+    align-items: center;
+    padding: 23rpx 0;
+    justify-content: space-between;
+    border-bottom: 1px solid #eee;
+  }
+
+  .store-cent {
+    display: flex;
+    align-items: center;
+    width: 80%;
+  }
+
+  .store-cent-left {
+    //width: 45%;
+    flex: 2;
+  }
+
+  .store-img {
+    flex: 1;
+    width: 120rpx;
+    height: 120rpx;
+    border-radius: 6rpx;
+    margin-right: 22rpx;
+  }
+
+  .store-img .img {
+    width: 100%;
+    height: 100%;
+  }
+
+  .store-name {
+    color: #282828;
+    font-size: 30rpx;
+    margin-bottom: 22rpx;
+    font-weight: 800;
+  }
+
+  .store-address {
+    color: #666666;
+    font-size: 24rpx;
+  }
+
+  .store-phone {
+    width: 50rpx;
+    height: 50rpx;
+    color: #fff;
+    border-radius: 50%;
+    display: block;
+    text-align: center;
+    line-height: 48rpx;
+    background-color: #e83323;
+    margin-bottom: 22rpx;
+    text-decoration: none;
+  }
+
+  .store-distance {
+    font-size: 22rpx;
+    color: #e83323;
+  }
+
+  .iconfont {
+    font-size: 20rpx;
+  }
+
+  .row-right {
+    flex: 2;
+    //display: flex;
+    //flex-direction: column;
+    //align-items: flex-end;
+    //width: 33.5%;
+  }
+</style>

+ 1 - 1
pages/user/wallet/score.vue

@@ -36,7 +36,7 @@
           </button>
           </button>
         </uni-datetime-picker>
         </uni-datetime-picker>
 
 
-        <!-- TODO 芋艿:优化 -->
+        <!-- TODO 芋艿:【钱包】可优化 -->
         <!--				<view class="total-box">-->
         <!--				<view class="total-box">-->
         <!--					<view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
         <!--					<view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
         <!--					<view>总支出¥{{ -state.pagination.expense }}</view>-->
         <!--					<view>总支出¥{{ -state.pagination.expense }}</view>-->

+ 0 - 14
sheep/api/migration/chat.js

@@ -1,14 +0,0 @@
-import request from '@/sheep/request';
-
-// TODO 芋艿:暂不支持 socket 聊天
-export default {
-  // 获取聊天token
-  unifiedToken: () =>
-    request({
-      url: 'unifiedToken',
-      custom: {
-        showError: false,
-        showLoading: false,
-      },
-    }),
-};

+ 1 - 1
sheep/api/promotion/activity.js

@@ -1,7 +1,7 @@
 import request from '@/sheep/request';
 import request from '@/sheep/request';
 
 
 const ActivityApi = {
 const ActivityApi = {
-  // 获得单个商品,近期参与的每个活动
+  // 获得单个商品,进行中的拼团、秒杀、砍价活动信息
   getActivityListBySpuId: (spuId) => {
   getActivityListBySpuId: (spuId) => {
     return request({
     return request({
       url: '/promotion/activity/list-by-spu-id',
       url: '/promotion/activity/list-by-spu-id',

+ 13 - 11
sheep/api/promotion/combination.js

@@ -2,15 +2,6 @@ import request from '@/sheep/request';
 
 
 // 拼团 API
 // 拼团 API
 const CombinationApi = {
 const CombinationApi = {
-  // 获得拼团活动列表
-  getCombinationActivityList: (count) => {
-    return request({
-      url: '/promotion/combination-activity/list',
-      method: 'GET',
-      params: { count },
-    });
-  },
-
   // 获得拼团活动分页
   // 获得拼团活动分页
   getCombinationActivityPage: (params) => {
   getCombinationActivityPage: (params) => {
     return request({
     return request({
@@ -31,6 +22,17 @@ const CombinationApi = {
     });
     });
   },
   },
 
 
+  // 获得拼团活动列表,基于活动编号数组
+  getCombinationActivityListByIds: (ids) => {
+    return request({
+      url: '/promotion/combination-activity/list-by-ids',
+      method: 'GET',
+      params: {
+        ids,
+      },
+    });
+  },
+
   // 获得最近 n 条拼团记录(团长发起的)
   // 获得最近 n 条拼团记录(团长发起的)
   getHeadCombinationRecordList: (activityId, status, count) => {
   getHeadCombinationRecordList: (activityId, status, count) => {
     return request({
     return request({
@@ -47,9 +49,9 @@ const CombinationApi = {
   // 获得我的拼团记录分页
   // 获得我的拼团记录分页
   getCombinationRecordPage: (params) => {
   getCombinationRecordPage: (params) => {
     return request({
     return request({
-      url: "/promotion/combination-record/page",
+      url: '/promotion/combination-record/page',
       method: 'GET',
       method: 'GET',
-      params
+      params,
     });
     });
   },
   },
 
 

+ 0 - 17
sheep/api/promotion/coupon.js

@@ -79,23 +79,6 @@ const CouponApi = {
       },
       },
     });
     });
   },
   },
-  // 获得匹配指定商品的优惠劵列表
-  getMatchCouponList: (price, spuIds, skuIds, categoryIds) => {
-    return request({
-      url: '/promotion/coupon/match-list',
-      method: 'GET',
-      params: {
-        price,
-        spuIds: spuIds.join(','),
-        skuIds: skuIds.join(','),
-        categoryIds: categoryIds.join(','),
-      },
-      custom: {
-        showError: false,
-        showLoading: false, // 避免影响 settlementOrder 结算的结果
-      },
-    });
-  }
 };
 };
 
 
 export default CouponApi;
 export default CouponApi;

+ 15 - 4
sheep/api/promotion/seckill.js

@@ -1,4 +1,4 @@
-import request from "@/sheep/request";
+import request from '@/sheep/request';
 
 
 const SeckillApi = {
 const SeckillApi = {
   // 获得秒杀时间段列表
   // 获得秒杀时间段列表
@@ -16,6 +16,17 @@ const SeckillApi = {
     return request({ url: 'promotion/seckill-activity/page', method: 'GET', params });
     return request({ url: 'promotion/seckill-activity/page', method: 'GET', params });
   },
   },
 
 
+  // 获得秒杀活动列表,基于活动编号数组
+  getSeckillActivityListByIds: (ids) => {
+    return request({
+      url: '/promotion/seckill-activity/list-by-ids',
+      method: 'GET',
+      params: {
+        ids,
+      },
+    });
+  },
+
   /**
   /**
    * 获得秒杀活动明细
    * 获得秒杀活动明细
    * @param {number} id 秒杀活动编号
    * @param {number} id 秒杀活动编号
@@ -25,9 +36,9 @@ const SeckillApi = {
     return request({
     return request({
       url: 'promotion/seckill-activity/get-detail',
       url: 'promotion/seckill-activity/get-detail',
       method: 'GET',
       method: 'GET',
-      params: { id }
+      params: { id },
     });
     });
-  }
-}
+  },
+};
 
 
 export default SeckillApi;
 export default SeckillApi;

+ 16 - 0
sheep/api/system/dict.js

@@ -0,0 +1,16 @@
+import request from '@/sheep/request';
+
+const DictApi = {
+  // 根据字典类型查询字典数据信息
+  getDictDataListByType: (type) => {
+    return request({
+      url: `/system/dict-data/type`,
+      method: 'GET',
+      params: {
+        type,
+      },
+    });
+  },
+};
+
+export default DictApi;

+ 19 - 1
sheep/api/trade/delivery.js

@@ -7,7 +7,25 @@ const DeliveryApi = {
       url: `/trade/delivery/express/list`,
       url: `/trade/delivery/express/list`,
       method: 'get',
       method: 'get',
     });
     });
-  }
+  },
+  // 获得自提门店列表
+  getDeliveryPickUpStoreList: (params) => {
+    return request({
+      url: `/trade/delivery/pick-up-store/list`,
+      method: 'GET',
+      params,
+    });
+  },
+  // 获得自提门店
+  getDeliveryPickUpStore: (id) => {
+    return request({
+      url: `/trade/delivery/pick-up-store/get`,
+      method: 'GET',
+      params: {
+        id,
+      },
+    });
+  },
 };
 };
 
 
 export default DeliveryApi;
 export default DeliveryApi;

+ 10 - 0
sheep/api/trade/order.js

@@ -1,4 +1,5 @@
 import request from '@/sheep/request';
 import request from '@/sheep/request';
+import { isEmpty } from '@/sheep/helper/utils';
 
 
 const OrderApi = {
 const OrderApi = {
   // 计算订单信息
   // 计算订单信息
@@ -13,6 +14,15 @@ const OrderApi = {
     if (!(data.addressId > 0)) {
     if (!(data.addressId > 0)) {
       delete data2.addressId;
       delete data2.addressId;
     }
     }
+    if (!(data.pickUpStoreId > 0)) {
+      delete data2.pickUpStoreId;
+    }
+    if (isEmpty(data.receiverName)) {
+      delete data2.receiverName;
+    }
+    if (isEmpty(data.receiverMobile)) {
+      delete data2.receiverMobile;
+    }
     if (!(data.combinationActivityId > 0)) {
     if (!(data.combinationActivityId > 0)) {
       delete data2.combinationActivityId;
       delete data2.combinationActivityId;
     }
     }

+ 19 - 11
sheep/components/s-auth-modal/s-auth-modal.vue

@@ -10,7 +10,11 @@
       />
       />
 
 
       <!-- 2. 短信登录  smsLogin -->
       <!-- 2. 短信登录  smsLogin -->
-      <sms-login v-if="authType === 'smsLogin'" :agreeStatus="state.protocol" @onConfirm="onConfirm" />
+      <sms-login
+        v-if="authType === 'smsLogin'"
+        :agreeStatus="state.protocol"
+        @onConfirm="onConfirm"
+      />
 
 
       <!-- 3. 忘记密码 resetPassword-->
       <!-- 3. 忘记密码 resetPassword-->
       <reset-password v-if="authType === 'resetPassword'" />
       <reset-password v-if="authType === 'resetPassword'" />
@@ -32,7 +36,11 @@
         <!-- 7.1 微信小程序的快捷登录 -->
         <!-- 7.1 微信小程序的快捷登录 -->
         <view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box">
         <view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box">
           <view class="register-title">还没有账号?</view>
           <view class="register-title">还没有账号?</view>
-          <button class="ss-reset-button login-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
+          <button
+            class="ss-reset-button login-btn"
+            open-type="getPhoneNumber"
+            @getphonenumber="getPhoneNumber"
+          >
             快捷登录
             快捷登录
           </button>
           </button>
           <view class="circle" />
           <view class="circle" />
@@ -81,17 +89,13 @@
           />
           />
           <view class="agreement-text ss-flex ss-col-center ss-m-l-8">
           <view class="agreement-text ss-flex ss-col-center ss-m-l-8">
             我已阅读并遵守
             我已阅读并遵守
-            <view class="tcp-text" @tap.stop="onProtocol('用户协议')">
-              《用户协议》
-            </view>
+            <view class="tcp-text" @tap.stop="onProtocol('用户协议')"> 《用户协议》 </view>
             <view class="agreement-text">与</view>
             <view class="agreement-text">与</view>
-            <view class="tcp-text" @tap.stop="onProtocol('隐私协议')">
-              《隐私协议》
-            </view>
+            <view class="tcp-text" @tap.stop="onProtocol('隐私协议')"> 《隐私协议》 </view>
           </view>
           </view>
         </label>
         </label>
       </view>
       </view>
-      <view class="safe-box"/>
+      <view class="safe-box" />
     </view>
     </view>
   </su-popup>
   </su-popup>
 </template>
 </template>
@@ -107,8 +111,6 @@
   import mpAuthorization from './components/mp-authorization.vue';
   import mpAuthorization from './components/mp-authorization.vue';
   import { closeAuthModal, showAuthModal } from '@/sheep/hooks/useModal';
   import { closeAuthModal, showAuthModal } from '@/sheep/hooks/useModal';
 
 
-  const appInfo = computed(() => sheep.$store('app').info);
-
   const modalStore = sheep.$store('modal');
   const modalStore = sheep.$store('modal');
   // 授权弹窗类型
   // 授权弹窗类型
   const authType = computed(() => modalStore.auth);
   const authType = computed(() => modalStore.auth);
@@ -152,7 +154,13 @@
     }
     }
     const loginRes = await sheep.$platform.useProvider(provider).login();
     const loginRes = await sheep.$platform.useProvider(provider).login();
     if (loginRes) {
     if (loginRes) {
+      const userInfo = await sheep.$store('user').getInfo();
       closeAuthModal();
       closeAuthModal();
+      // 如果用户已经有头像和昵称,不需要再次授权
+      if (userInfo.avatar && userInfo.nickname) {
+        return;
+      }
+
       // 触发小程序授权信息弹框
       // 触发小程序授权信息弹框
       // #ifdef MP-WEIXIN
       // #ifdef MP-WEIXIN
       showAuthModal('mpAuthorization');
       showAuthModal('mpAuthorization');

+ 5 - 5
sheep/components/s-block-item/s-block-item.vue

@@ -9,7 +9,7 @@
     <!-- 基础组件:列表导航 -->
     <!-- 基础组件:列表导航 -->
     <s-menu-list v-if="type === 'MenuList'" :data="data" />
     <s-menu-list v-if="type === 'MenuList'" :data="data" />
     <!-- 基础组件:宫格导航 -->
     <!-- 基础组件:宫格导航 -->
-    <s-menu-grid v-if="type === 'MenuGrid'" :data="data" />
+    <s-menu-grid v-if="type === 'MenuGrid'" :data="data" :styles="styles" />
     <!-- 基础组件:弹窗广告 -->
     <!-- 基础组件:弹窗广告 -->
     <s-popup-image v-if="type === 'Popover'" :data="data" />
     <s-popup-image v-if="type === 'Popover'" :data="data" />
     <!-- 基础组件:悬浮按钮 -->
     <!-- 基础组件:悬浮按钮 -->
@@ -47,13 +47,13 @@
     <s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" />
     <s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" />
 
 
     <!-- 用户组件:用户卡片 -->
     <!-- 用户组件:用户卡片 -->
-    <s-user-card v-if="type === 'UserCard'" />
+    <s-user-card v-if="type === 'UserCard'" :data="data" :styles="styles" />
     <!-- 用户组件:用户订单 -->
     <!-- 用户组件:用户订单 -->
-    <s-order-card v-if="type === 'UserOrder'" :data="data" />
+    <s-order-card v-if="type === 'UserOrder'" :data="data" :styles="styles" />
     <!-- 用户组件:用户资产 -->
     <!-- 用户组件:用户资产 -->
-    <s-wallet-card v-if="type === 'UserWallet'" />
+    <s-wallet-card v-if="type === 'UserWallet'" :data="data" :styles="styles" />
     <!-- 用户组件:用户卡券 -->
     <!-- 用户组件:用户卡券 -->
-    <s-coupon-card v-if="type === 'UserCoupon'" />
+    <s-coupon-card v-if="type === 'UserCoupon'" :data="data" :styles="styles" />
   </view>
   </view>
 </template>
 </template>
 
 

+ 162 - 138
sheep/components/s-coupon-block/s-coupon-block.vue

@@ -1,152 +1,176 @@
 <!-- 装修营销组件:优惠券  -->
 <!-- 装修营销组件:优惠券  -->
 <template>
 <template>
-  <scroll-view class="scroll-box" scroll-x scroll-anchoring>
-    <view class="coupon-box ss-flex">
-      <view
-        class="coupon-item"
-        :style="[couponBg, { marginLeft: `${data.space}px` }]"
-        v-for="(item, index) in couponList"
-        :key="index"
-      >
-        <su-coupon
-          :size="SIZE_LIST[columns - 1]"
-          :textColor="data.textColor"
-          background=""
-          :couponId="item.id"
-          :title="item.name"
-          :type="formatCouponDiscountType(item)"
-          :value="formatCouponDiscountValue(item)"
-          :sellBy="formatValidityType(item)"
-        >
-          <template v-slot:btn>
-            <!-- 两列时,领取按钮坚排 -->
-            <button
-              v-if="columns === 2"
-              @click.stop="onGetCoupon(item.id)"
-              class="ss-reset-button card-btn vertical"
-              :style="[btnStyles]"
-            >
-              <view class="btn-text">立即领取</view>
-            </button>
-            <button
-              v-else
-              class="ss-reset-button card-btn"
-              :style="[btnStyles]"
-              @click.stop="onGetCoupon(item.id)"
-            >
-              立即领取
-            </button>
-          </template>
-        </su-coupon>
-      </view>
-    </view>
-  </scroll-view>
+	<scroll-view class="scroll-box" scroll-x scroll-anchoring :style="[bgStyle, { marginLeft: `${data.space}px` }]">
+		<view class="coupon-box ss-flex" :style="couponList.length === 2 ? couponBoxStyleTwo : couponBoxStyleNormal">
+			<view class="coupon-item" :style="[couponBg, { marginLeft: `${data.space}px` }]"
+				v-for="(item, index) in couponList" :key="index">
+				<su-coupon :size="SIZE_LIST[columns - 1]" :textColor="data.textColor" background="" :couponId="item.id"
+					:title="item.name" :type="formatCouponDiscountType(item)" :value="formatCouponDiscountValue(item)"
+					:sellBy="formatValidityType(item)">
+					<template v-slot:btn>
+						<!-- 两列时,领取按钮坚排 -->
+						<button v-if="columns === 2" @click.stop="onGetCoupon(item.id)"
+							class="ss-reset-button card-btn vertical" :style="[btnStyles]">
+							<view class="btn-text">立即领取</view>
+						</button>
+						<button v-else class="ss-reset-button card-btn" :style="[btnStyles]"
+							@click.stop="onGetCoupon(item.id)">
+							立即领取
+						</button>
+					</template>
+				</su-coupon>
+			</view>
+		</view>
+	</scroll-view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import sheep from '@/sheep';
-  import CouponApi from '@/sheep/api/promotion/coupon';
-  import { ref, onMounted } from 'vue';
-  import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from "@/sheep/util/const";
-  import { floatToFixed2, formatDate } from "@/sheep/util";
+	import sheep from '@/sheep';
+	import CouponApi from '@/sheep/api/promotion/coupon';
+	import {
+		ref,
+		onMounted,
+		computed
+	} from 'vue';
+	import {
+		CouponTemplateValidityTypeEnum,
+		PromotionDiscountTypeEnum
+	} from "@/sheep/util/const";
+	import {
+		floatToFixed2,
+		formatDate
+	} from "@/sheep/util";
 
 
-  const props = defineProps({
-    data: {
-      type: Object,
-      default: () => ({}),
-    },
-    styles: {
-      type: Object,
-      default: () => ({}),
-    },
-  });
-  const { columns, button } = props.data;
-  const SIZE_LIST = ['lg', 'md', 'xs']
-  const couponBg = {
-    background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
-  };
-  const btnStyles = {
-    background: button.bgColor,
-    color: button.color,
-  };
+	const props = defineProps({
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+	});
+	const {
+		columns,
+		button
+	} = props.data;
+	const SIZE_LIST = ['lg', 'md', 'xs']
+	const couponBg = {
+		background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
+	};
+	const btnStyles = {
+		background: button.bgColor,
+		color: button.color,
+	};
+	// 两列优惠券时的排版方式
+	const couponBoxStyleNormal = {
+		'display': 'flex',
+		'justify-content': 'space-between'
+	};
+	// 非两列优惠券时的排版方式
+	const couponBoxStyleTwo = {
+		'display': 'flex',
+		'justify-content': 'space-around'
+	};
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
 
-  // 格式化【折扣类型】
-  const formatCouponDiscountType = (coupon) => {
-    if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
-      return 'reduce'
-    }
-    if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
-      return 'percent'
-    }
-    return `未知【${coupon.discountType}】`
-  }
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
+	// 格式化【折扣类型】
+	const formatCouponDiscountType = (coupon) => {
+		if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
+			return 'reduce'
+		}
+		if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
+			return 'percent'
+		}
+		return `未知【${coupon.discountType}】`
+	}
 
 
-  // 格式化【折扣】
-  const formatCouponDiscountValue = (coupon) => {
-    if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
-      return floatToFixed2(coupon.discountPrice)
-    }
-    if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
-      return coupon.discountPercent
-    }
-    return `未知【${coupon.discountType}】`
-  }
+	// 格式化【折扣】
+	const formatCouponDiscountValue = (coupon) => {
+		if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
+			return floatToFixed2(coupon.discountPrice)
+		}
+		if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
+			return coupon.discountPercent
+		}
+		return `未知【${coupon.discountType}】`
+	}
 
 
-  // 格式化【有效期限】
-  const formatValidityType = (row) => {
-    if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
-      return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
-    }
-    if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
-      return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
-    }
-    return '未知【' + row.validityType + '】'
-  }
+	// 格式化【有效期限】
+	const formatValidityType = (row) => {
+		if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
+			return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
+		}
+		if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
+			return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
+		}
+		return '未知【' + row.validityType + '】'
+	}
 
 
-  const couponList = ref([]);
-  // 立即领取优惠券
-  async function onGetCoupon(id) {
-    const { error, msg } = await CouponApi.takeCoupon(id);
-    if (error === 0) {
-      uni.showToast({
-        title: msg,
-        icon: 'none',
-      });
-      return
-    }
-    await getCouponTemplateList()
-  }
-  const getCouponTemplateList = async () => {
-    const { data } = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
-    couponList.value = data;
-  }
-  onMounted(() => {
-    getCouponTemplateList()
-  });
+	const couponList = ref([]);
+	// 立即领取优惠券
+	async function onGetCoupon(id) {
+		const {
+			error,
+			msg
+		} = await CouponApi.takeCoupon(id);
+		if (error === 0) {
+			uni.showToast({
+				title: msg,
+				icon: 'none',
+			});
+			return
+		}
+		await getCouponTemplateList()
+	}
+	const getCouponTemplateList = async () => {
+		const {
+			data
+		} = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
+		couponList.value = data;
+	}
+	onMounted(() => {
+		getCouponTemplateList()
+	});
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  .card-btn {
-    width: 140rpx;
-    height: 50rpx;
-    border-radius: 25rpx;
-    font-size: 24rpx;
-    line-height: 50rpx;
-    &.vertical {
-      width: 50rpx;
-      height: 140rpx;
-      margin: auto 20rpx auto 0;
+	.card-btn {
+		width: 140rpx;
+		height: 50rpx;
+		border-radius: 25rpx;
+		font-size: 24rpx;
+		line-height: 50rpx;
 
 
-      .btn-text {
-        font-size: 24rpx;
-        text-align: center;
-        writing-mode: vertical-lr;
-      }
-    }
-  }
-  .coupon-item {
-    &:nth-of-type(1) {
-      margin-left: 0 !important;
-    }
-  }
-</style>
+		&.vertical {
+			width: 50rpx;
+			height: 140rpx;
+			margin: auto 20rpx auto 0;
+
+			.btn-text {
+				font-size: 24rpx;
+				text-align: center;
+				writing-mode: vertical-lr;
+			}
+		}
+	}
+
+	.coupon-item {
+		&:nth-of-type(1) {
+			margin-left: 0 !important;
+		}
+	}
+</style>

+ 24 - 1
sheep/components/s-coupon-card/s-coupon-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户卡券 -->
 <!-- 装修用户组件:用户卡券 -->
 <template>
 <template>
-	<view class="ss-coupon-menu-wrap ss-flex ss-col-center">
+	<view class="ss-coupon-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
 		<view class="menu-item ss-flex-col ss-row-center ss-col-center" v-for="item in props.list" :key="item.title"
 		<view class="menu-item ss-flex-col ss-row-center ss-col-center" v-for="item in props.list" :key="item.title"
 			@tap="sheep.$router.go(item.path, { type: item.type })"
 			@tap="sheep.$router.go(item.path, { type: item.type })"
 			:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'">
 			:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'">
@@ -15,6 +15,7 @@
 	 * 装修组件 - 优惠券菜单
 	 * 装修组件 - 优惠券菜单
 	 */
 	 */
 	import sheep from '@/sheep';
 	import sheep from '@/sheep';
+	import { computed } from 'vue';
 
 
 	// 接收参数
 	// 接收参数
 	const props = defineProps({
 	const props = defineProps({
@@ -52,6 +53,28 @@
 				];
 				];
 			},
 			},
 		},
 		},
+		// 装修数据
+		data: {
+		  type: Object,
+		  default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+		  type: Object,
+		  default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+	  // 直接从 props.styles 解构
+	  const { bgType, bgImg, bgColor } = props.styles; 
+	
+	  // 根据 bgType 返回相应的样式
+	  return {
+		background: bgType === 'img'
+			? `url(${bgImg}) no-repeat top center / 100% 100%`
+			: bgColor
+		};
 	});
 	});
 </script>
 </script>
 
 

+ 6 - 16
sheep/components/s-coupon-list/s-coupon-list.vue

@@ -37,30 +37,22 @@
         <view class="ss-flex ss-row-between ss-m-t-16">
         <view class="ss-flex ss-row-between ss-m-t-16">
           <view
           <view
             class="sellby-text"
             class="sellby-text"
-            :class=" isDisable ? 'disabled-color' : 'subtitle-color'"
+            :class="isDisable ? 'disabled-color' : 'subtitle-color'"
             v-if="data.validityType === 2"
             v-if="data.validityType === 2"
           >
           >
             有效期:领取后 {{ data.fixedEndTerm }} 天内可用
             有效期:领取后 {{ data.fixedEndTerm }} 天内可用
           </view>
           </view>
-          <view
-            class="sellby-text"
-            :class=" isDisable ? 'disabled-color' : 'subtitle-color'"
-            v-else
-          >
+          <view class="sellby-text" :class="isDisable ? 'disabled-color' : 'subtitle-color'" v-else>
             有效期: {{ sheep.$helper.timeFormat(data.validStartTime, 'yyyy-mm-dd') }} 至
             有效期: {{ sheep.$helper.timeFormat(data.validStartTime, 'yyyy-mm-dd') }} 至
             {{ sheep.$helper.timeFormat(data.validEndTime, 'yyyy-mm-dd') }}
             {{ sheep.$helper.timeFormat(data.validEndTime, 'yyyy-mm-dd') }}
           </view>
           </view>
-          <view
-            class="value-enough"
-            :class="isDisable ? 'disabled-color' : 'subtitle-color'"
-          >
+          <view class="value-enough" :class="isDisable ? 'disabled-color' : 'subtitle-color'">
             满 {{ fen2yuan(data.usePrice) }} 可用
             满 {{ fen2yuan(data.usePrice) }} 可用
           </view>
           </view>
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
 
 
-    <!-- TODO 芋艿:可优化,增加优惠劵的描述 -->
     <view class="desc ss-flex ss-row-between">
     <view class="desc ss-flex ss-row-between">
       <view>
       <view>
         <view class="desc-title">{{ data.description }}</view>
         <view class="desc-title">{{ data.description }}</view>
@@ -76,17 +68,15 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import { computed, reactive } from 'vue';
+  import { computed } from 'vue';
   import { fen2yuan } from '../../hooks/useGoods';
   import { fen2yuan } from '../../hooks/useGoods';
   import sheep from '../../index';
   import sheep from '../../index';
 
 
-  const state = reactive({});
-
   const isDisable = computed(() => {
   const isDisable = computed(() => {
     if (props.type === 'coupon') {
     if (props.type === 'coupon') {
       return false;
       return false;
     }
     }
-    return props.data.status !== 1;
+    return props.disabled;
   });
   });
 
 
   // 接受参数
   // 接受参数
@@ -202,4 +192,4 @@
   .price-text {
   .price-text {
     color: #ff0000;
     color: #ff0000;
   }
   }
-</style>
+</style>

+ 20 - 9
sheep/components/s-coupon-select/s-coupon-select.vue

@@ -16,8 +16,12 @@
         :scroll-with-animation="false"
         :scroll-with-animation="false"
         :enable-back-to-top="true"
         :enable-back-to-top="true"
       >
       >
+        <!--可使用的优惠券区域-->
         <view class="subtitle ss-m-l-20">可使用优惠券</view>
         <view class="subtitle ss-m-l-20">可使用优惠券</view>
-        <view v-for="(item, index) in state.couponInfo" :key="index">
+        <view
+          v-for="(item, index) in state.couponInfo.filter((coupon) => coupon.match)"
+          :key="index"
+        >
           <s-coupon-list :data="item" type="user" :disabled="false">
           <s-coupon-list :data="item" type="user" :disabled="false">
             <template #default>
             <template #default>
               <label class="ss-flex ss-col-center" @tap="radioChange(item.id)">
               <label class="ss-flex ss-col-center" @tap="radioChange(item.id)">
@@ -31,19 +35,18 @@
             </template>
             </template>
           </s-coupon-list>
           </s-coupon-list>
         </view>
         </view>
-        <!-- TODO 芋艿:未来接口需要支持下
+        <!--不可使用的优惠券区域-->
         <view class="subtitle ss-m-t-40 ss-m-l-20">不可使用优惠券</view>
         <view class="subtitle ss-m-t-40 ss-m-l-20">不可使用优惠券</view>
-        <view v-for="item in state.couponInfo.cannot_use" :key="item.id">
+        <view v-for="item in state.couponInfo.filter((coupon) => !coupon.match)" :key="item.id">
           <s-coupon-list :data="item" type="user" :disabled="true">
           <s-coupon-list :data="item" type="user" :disabled="true">
             <template v-slot:reason>
             <template v-slot:reason>
               <view class="ss-flex ss-m-t-24">
               <view class="ss-flex ss-m-t-24">
                 <view class="reason-title"> 不可用原因:</view>
                 <view class="reason-title"> 不可用原因:</view>
-                <view class="reason-desc">{{ item.cannot_use_msg }}</view>
+                <view class="reason-desc">{{ item.mismatchReason || '未达到使用门槛' }}</view>
               </view>
               </view>
             </template>
             </template>
           </s-coupon-list>
           </s-coupon-list>
         </view>
         </view>
-      -->
       </scroll-view>
       </scroll-view>
     </view>
     </view>
     <view class="modal-footer ss-flex">
     <view class="modal-footer ss-flex">
@@ -55,7 +58,8 @@
   import { computed, reactive } from 'vue';
   import { computed, reactive } from 'vue';
 
 
   const props = defineProps({
   const props = defineProps({
-    modelValue: { // 优惠劵列表
+    modelValue: {
+      // 优惠劵列表
       type: Object,
       type: Object,
       default() {},
       default() {},
     },
     },
@@ -69,13 +73,13 @@
 
 
   const state = reactive({
   const state = reactive({
     couponInfo: computed(() => props.modelValue), // 优惠劵列表
     couponInfo: computed(() => props.modelValue), // 优惠劵列表
-    couponId: 0, // 选中的优惠劵编号
+    couponId: undefined, // 选中的优惠劵编号
   });
   });
 
 
   // 选中优惠劵
   // 选中优惠劵
   function radioChange(couponId) {
   function radioChange(couponId) {
     if (state.couponId === couponId) {
     if (state.couponId === couponId) {
-      state.couponId = 0;
+      state.couponId = undefined;
     } else {
     } else {
       state.couponId = couponId;
       state.couponId = couponId;
     }
     }
@@ -84,7 +88,7 @@
   // 确认优惠劵
   // 确认优惠劵
   const onConfirm = () => {
   const onConfirm = () => {
     emits('confirm', state.couponId);
     emits('confirm', state.couponId);
-  }
+  };
 </script>
 </script>
 <style lang="scss" scoped>
 <style lang="scss" scoped>
   :deep() {
   :deep() {
@@ -96,25 +100,30 @@
   .model-box {
   .model-box {
     height: 60vh;
     height: 60vh;
   }
   }
+
   .title {
   .title {
     font-size: 36rpx;
     font-size: 36rpx;
     height: 80rpx;
     height: 80rpx;
     font-weight: bold;
     font-weight: bold;
     color: #333333;
     color: #333333;
   }
   }
+
   .subtitle {
   .subtitle {
     font-size: 26rpx;
     font-size: 26rpx;
     font-weight: 500;
     font-weight: 500;
     color: #333333;
     color: #333333;
   }
   }
+
   .model-content {
   .model-content {
     height: 54vh;
     height: 54vh;
   }
   }
+
   .modal-footer {
   .modal-footer {
     width: 100%;
     width: 100%;
     height: 120rpx;
     height: 120rpx;
     background: #fff;
     background: #fff;
   }
   }
+
   .confirm-btn {
   .confirm-btn {
     width: 710rpx;
     width: 710rpx;
     margin-left: 20rpx;
     margin-left: 20rpx;
@@ -123,12 +132,14 @@
     border-radius: 40rpx;
     border-radius: 40rpx;
     color: #fff;
     color: #fff;
   }
   }
+
   .reason-title {
   .reason-title {
     font-weight: 600;
     font-weight: 600;
     font-size: 20rpx;
     font-size: 20rpx;
     line-height: 26rpx;
     line-height: 26rpx;
     color: #ff0003;
     color: #ff0003;
   }
   }
+
   .reason-desc {
   .reason-desc {
     font-weight: 600;
     font-weight: 600;
     font-size: 20rpx;
     font-size: 20rpx;

+ 19 - 8
sheep/components/s-custom-navbar/s-custom-navbar.vue

@@ -44,9 +44,9 @@
    *
    *
    * @property {Number | String}  alwaysShow = [0,1]			    - 是否常驻
    * @property {Number | String}  alwaysShow = [0,1]			    - 是否常驻
    * @property {Number | String}  styleType = [inner]			   	- 是否沉浸式
    * @property {Number | String}  styleType = [inner]			   	- 是否沉浸式
-   * @property {String | Number} type 		 					- 标题背景模式
-   * @property {String} color 		 							- 页面背景色
-   * @property {String} src 		 								- 页面背景图片
+   * @property {String | Number} type              - 标题背景模式
+   * @property {String} color                  - 页面背景色
+   * @property {String} src                    - 页面背景图片
    */
    */
   import { computed, unref } from 'vue';
   import { computed, unref } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
@@ -77,7 +77,7 @@
   });
   });
   const navList = computed(() => {
   const navList = computed(() => {
     // #ifdef MP
     // #ifdef MP
-    return props.data.mapCells || [];
+    return props.data.mpCells || [];
     // #endif
     // #endif
     return props.data.otherCells || [];
     return props.data.otherCells || [];
   });
   });
@@ -117,11 +117,12 @@
   const bgStyles = computed(() => {
   const bgStyles = computed(() => {
     return {
     return {
       background:
       background:
-          props.data.bgType === 'img' && props.data.bgImg
+        props.data.bgType === 'img' && props.data.bgImg
           ? `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`
           ? `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`
-          : props.data.bgColor
+          : props.data.bgColor,
     };
     };
   });
   });
+
   // 左侧按钮:返回上一页或首页
   // 左侧按钮:返回上一页或首页
   function onClickLeft() {
   function onClickLeft() {
     if (hasHistory) {
     if (hasHistory) {
@@ -130,6 +131,7 @@
       sheep.$router.go('/pages/index/index');
       sheep.$router.go('/pages/index/index');
     }
     }
   }
   }
+
   // 右侧按钮:打开快捷菜单
   // 右侧按钮:打开快捷菜单
   function onClickRight() {
   function onClickRight() {
     showMenuTools();
     showMenuTools();
@@ -147,44 +149,53 @@
       top: 50%;
       top: 50%;
       transform: translateY(-50%);
       transform: translateY(-50%);
     }
     }
+
     .nav-icon {
     .nav-icon {
       position: absolute;
       position: absolute;
       top: 50%;
       top: 50%;
       transform: translateY(-50%);
       transform: translateY(-50%);
       left: 20rpx;
       left: 20rpx;
+
       .inner-icon-box {
       .inner-icon-box {
         border: 1px solid rgba(#fff, 0.4);
         border: 1px solid rgba(#fff, 0.4);
         background: none !important;
         background: none !important;
       }
       }
+
       .icon-box {
       .icon-box {
         background: #ffffff;
         background: #ffffff;
-        box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08),
-          0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);
+        box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08), 0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);
         border-radius: 30rpx;
         border-radius: 30rpx;
         width: 134rpx;
         width: 134rpx;
         height: 56rpx;
         height: 56rpx;
         margin-left: 8rpx;
         margin-left: 8rpx;
+
         .line {
         .line {
           width: 2rpx;
           width: 2rpx;
           height: 24rpx;
           height: 24rpx;
           background: #e5e5e7;
           background: #e5e5e7;
         }
         }
+
         .sicon-back {
         .sicon-back {
           font-size: 32rpx;
           font-size: 32rpx;
         }
         }
+
         .sicon-home {
         .sicon-home {
           font-size: 32rpx;
           font-size: 32rpx;
         }
         }
+
         .sicon-more {
         .sicon-more {
           font-size: 32rpx;
           font-size: 32rpx;
         }
         }
+
         .icon-button {
         .icon-button {
           width: 67rpx;
           width: 67rpx;
           height: 56rpx;
           height: 56rpx;
+
           &-left:hover {
           &-left:hover {
             background: rgba(0, 0, 0, 0.16);
             background: rgba(0, 0, 0, 0.16);
             border-radius: 30rpx 0px 0px 30rpx;
             border-radius: 30rpx 0px 0px 30rpx;
           }
           }
+
           &-right:hover {
           &-right:hover {
             background: rgba(0, 0, 0, 0.16);
             background: rgba(0, 0, 0, 0.16);
             border-radius: 0px 30rpx 30rpx 0px;
             border-radius: 0px 30rpx 30rpx 0px;

+ 17 - 8
sheep/components/s-goods-card/s-goods-card.vue

@@ -3,7 +3,10 @@
   <!-- 商品卡片 -->
   <!-- 商品卡片 -->
   <view>
   <view>
     <!-- 布局1. 单列大图(上图,下内容)-->
     <!-- 布局1. 单列大图(上图,下内容)-->
-    <view v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.goodsList.length" class="goods-sl-box">
+    <view
+      v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.goodsList.length"
+      class="goods-sl-box"
+    >
       <view
       <view
         class="goods-box"
         class="goods-box"
         v-for="item in state.goodsList"
         v-for="item in state.goodsList"
@@ -100,7 +103,10 @@
     </view>
     </view>
 
 
     <!-- 布局3. 单列小图(左图,右内容) -->
     <!-- 布局3. 单列小图(左图,右内容) -->
-    <view v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.goodsList.length" class="goods-lg-box">
+    <view
+      v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.goodsList.length"
+      class="goods-lg-box"
+    >
       <view
       <view
         class="goods-box"
         class="goods-box"
         :style="[{ marginBottom: data.space + 'px' }]"
         :style="[{ marginBottom: data.space + 'px' }]"
@@ -147,7 +153,7 @@
     TWO_COL: 'twoCol',
     TWO_COL: 'twoCol',
     // 单列小图
     // 单列小图
     ONE_COL_SMALL_IMG: 'oneColSmallImg',
     ONE_COL_SMALL_IMG: 'oneColSmallImg',
-  }
+  };
 
 
   const state = reactive({
   const state = reactive({
     goodsList: [],
     goodsList: [],
@@ -157,16 +163,16 @@
   const props = defineProps({
   const props = defineProps({
     data: {
     data: {
       type: Object,
       type: Object,
-      default() {},
+      default: () => ({}),
     },
     },
     styles: {
     styles: {
       type: Object,
       type: Object,
-      default() {},
+      default: () => ({}),
     },
     },
   });
   });
 
 
-  const { layoutType, btnBuy, spuIds } = props.data ?? {};
-  const { marginLeft, marginRight } = props.styles ?? {};
+  const { layoutType, btnBuy, spuIds } = props.data || {};
+  const { marginLeft, marginRight } = props.styles || {};
 
 
   // 购买按钮样式
   // 购买按钮样式
   const buyStyle = computed(() => {
   const buyStyle = computed(() => {
@@ -215,6 +221,7 @@
     // 计数
     // 计数
     count++;
     count++;
   }
   }
+
   //endregion
   //endregion
 
 
   /**
   /**
@@ -283,7 +290,7 @@
     settleData.value = await getSettlementByIds(spuIds.join(','))
     settleData.value = await getSettlementByIds(spuIds.join(','))
     state.goodsList = await enrichDataWithSkus(ms,settleData.value)
     state.goodsList = await enrichDataWithSkus(ms,settleData.value)
     // 只有双列布局时需要
     // 只有双列布局时需要
-    if (layoutType === LayoutTypeEnum.TWO_COL){
+    if (layoutType === LayoutTypeEnum.TWO_COL) {
       // 分列
       // 分列
       calculateGoodsColumn();
       calculateGoodsColumn();
     }
     }
@@ -298,11 +305,13 @@
   .goods-list-box {
   .goods-list-box {
     width: 50%;
     width: 50%;
     box-sizing: border-box;
     box-sizing: border-box;
+
     .left-list {
     .left-list {
       &:nth-last-child(1) {
       &:nth-last-child(1) {
         margin-bottom: 0 !important;
         margin-bottom: 0 !important;
       }
       }
     }
     }
+
     .right-list {
     .right-list {
       &:nth-last-child(1) {
       &:nth-last-child(1) {
         margin-bottom: 0 !important;
         margin-bottom: 0 !important;

+ 180 - 206
sheep/components/s-goods-column/s-goods-column.vue

@@ -2,29 +2,38 @@
 <template>
 <template>
   <view class="ss-goods-wrap">
   <view class="ss-goods-wrap">
     <!-- xs卡片:横向紧凑型,一行放两个,图片左内容右边  -->
     <!-- xs卡片:横向紧凑型,一行放两个,图片左内容右边  -->
-    <view v-if="size === 'xs'" class="xs-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @tap="onClick">
+    <view
+      v-if="size === 'xs'"
+      class="xs-goods-card ss-flex ss-col-stretch"
+      :style="[elStyles]"
+      @tap="onClick"
+    >
       <view v-if="tagStyle.show" class="tag-icon-box">
       <view v-if="tagStyle.show" class="tag-icon-box">
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
       </view>
       </view>
-      <image class="xs-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFit"></image>
-      <view v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
-            class="xs-goods-content ss-flex-col ss-row-around">
-        <view v-if="goodsFields.title?.show || goodsFields.name?.show" class="xs-goods-title ss-line-1"
-              :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
+      <image
+        class="xs-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFit"
+      ></image>
+      <view
+        v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
+        class="xs-goods-content ss-flex-col ss-row-around"
+      >
+        <view
+          v-if="goodsFields.title?.show || goodsFields.name?.show"
+          class="xs-goods-title ss-line-1"
+          :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
+        >
           {{ data.title || data.name }}
           {{ data.title || data.name }}
         </view>
         </view>
-        <!-- 这里是新加的会员价和限时优惠 -->
-        <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
-          <view class="card" v-if="iconShow">{{iconShow}}</view>
-          <view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
-        </view>
-        <!-- 这里是新加的会员价和限时优惠结束 -->
-        <view v-if="goodsFields.price?.show" class="xs-goods-price font-OPPOSANS"
-              :style="[{ color: goodsFields.price.color }]">
+        <view
+          v-if="goodsFields.price?.show"
+          class="xs-goods-price font-OPPOSANS"
+          :style="[{ color: goodsFields.price.color }]"
+        >
           <text class="price-unit ss-font-24">{{ priceUnit }}</text>
           <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-          <text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
-          <text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
-          <text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
+          {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
@@ -34,26 +43,30 @@
       <view v-if="tagStyle.show" class="tag-icon-box">
       <view v-if="tagStyle.show" class="tag-icon-box">
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
       </view>
       </view>
-      <image class="sm-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
-
-      <view v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
-            class="sm-goods-content" :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
-        <view v-if="goodsFields.title?.show || goodsFields.name?.show"
-              class="sm-goods-title ss-line-1 ss-m-b-16">
+      <image
+        class="sm-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFill"
+      ></image>
+
+      <view
+        v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
+        class="sm-goods-content"
+        :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
+      >
+        <view
+          v-if="goodsFields.title?.show || goodsFields.name?.show"
+          class="sm-goods-title ss-line-1 ss-m-b-16"
+        >
           {{ data.title || data.name }}
           {{ data.title || data.name }}
         </view>
         </view>
-        <!-- 这里是新加的会员价和限时优惠 -->
-        <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
-          <view class="card" v-if="iconShow">{{iconShow}}</view>
-          <view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
-        </view>
-        <!-- 这里是新加的会员价和限时优惠结束 -->
-        <view v-if="goodsFields.price?.show" class="sm-goods-price font-OPPOSANS"
-              :style="[{ color: goodsFields.price.color }]">
+        <view
+          v-if="goodsFields.price?.show"
+          class="sm-goods-price font-OPPOSANS"
+          :style="[{ color: goodsFields.price.color }]"
+        >
           <text class="price-unit ss-font-24">{{ priceUnit }}</text>
           <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-          <text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
-          <text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
-          <text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
+          {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
@@ -63,43 +76,58 @@
       <view v-if="tagStyle.show" class="tag-icon-box">
       <view v-if="tagStyle.show" class="tag-icon-box">
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
       </view>
       </view>
-      <image class="md-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="widthFix"></image>
-      <view class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16" :id="elId">
-        <view v-if="goodsFields.title?.show || goodsFields.name?.show" class="md-goods-title ss-line-1"
-              :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
+      <image
+        class="md-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="widthFix"
+      ></image>
+      <view
+        class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16"
+        :id="elId"
+      >
+        <view
+          v-if="goodsFields.title?.show || goodsFields.name?.show"
+          class="md-goods-title ss-line-1"
+          :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
+        >
           {{ data.title || data.name }}
           {{ data.title || data.name }}
         </view>
         </view>
-        <view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
-              class="md-goods-subtitle ss-m-t-16 ss-line-1"
-              :style="[{ color: subTitleColor, background: subTitleBackground }]">
+        <view
+          v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
+          class="md-goods-subtitle ss-m-t-16 ss-line-1"
+          :style="[{ color: subTitleColor, background: subTitleBackground }]"
+        >
           {{ data.subtitle || data.introduction }}
           {{ data.subtitle || data.introduction }}
         </view>
         </view>
         <slot name="activity">
         <slot name="activity">
           <view v-if="data.promos?.length" class="tag-box ss-flex-wrap ss-flex ss-col-center">
           <view v-if="data.promos?.length" class="tag-box ss-flex-wrap ss-flex ss-col-center">
-            <view class="activity-tag ss-m-r-10 ss-m-t-16" v-for="item in data.promos" :key="item.id">
+            <view
+              class="activity-tag ss-m-r-10 ss-m-t-16"
+              v-for="item in data.promos"
+              :key="item.id"
+            >
               {{ item.title }}
               {{ item.title }}
             </view>
             </view>
           </view>
           </view>
         </slot>
         </slot>
-        <!-- 这里是新加的会员价和限时优惠 -->
-        <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
-          <view class="card" v-if="iconShow">{{iconShow}}</view>
-          <view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
-        </view>
-        <!-- 这里是新加的会员价和限时优惠结束 -->
         <view class="ss-flex ss-col-bottom">
         <view class="ss-flex ss-col-bottom">
-          <view v-if="goodsFields.price?.show" class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
-                :style="[{ color: goodsFields.price.color }]">
+          <view
+            v-if="goodsFields.price?.show"
+            class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
+            :style="[{ color: goodsFields.price.color }]"
+          >
             <text class="price-unit ss-font-24">{{ priceUnit }}</text>
             <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-            <text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
-            <text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
-            <text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
+            {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
           </view>
           </view>
 
 
-          <view v-if="
+          <view
+            v-if="
               (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
               (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
               (data.original_price > 0 || data.marketPrice > 0)
               (data.original_price > 0 || data.marketPrice > 0)
-            " class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex" :style="[{ color: originPriceColor }]">
+            "
+            class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
+            :style="[{ color: originPriceColor }]"
+          >
             <text class="price-unit ss-font-20">{{ priceUnit }}</text>
             <text class="price-unit ss-font-20">{{ priceUnit }}</text>
             <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
             <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
           </view>
           </view>
@@ -118,24 +146,38 @@
     </view>
     </view>
 
 
     <!-- lg卡片:横向型,一行放一个,图片左内容右边  -->
     <!-- lg卡片:横向型,一行放一个,图片左内容右边  -->
-    <view v-if="size === 'lg'" class="lg-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @tap="onClick">
+    <view
+      v-if="size === 'lg'"
+      class="lg-goods-card ss-flex ss-col-stretch"
+      :style="[elStyles]"
+      @tap="onClick"
+    >
       <view v-if="tagStyle.show" class="tag-icon-box">
       <view v-if="tagStyle.show" class="tag-icon-box">
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
       </view>
       </view>
-      <view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center"> 秒杀 </view>
+      <view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center">秒杀</view>
       <view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
       <view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
         <view class="tag-icon">拼团</view>
         <view class="tag-icon">拼团</view>
       </view>
       </view>
-      <image class="lg-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
+      <image
+        class="lg-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFill"
+      ></image>
       <view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
       <view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
         <view>
         <view>
-          <view v-if="goodsFields.title?.show || goodsFields.name?.show" class="lg-goods-title ss-line-2"
-                :style="[{ color: titleColor }]">
+          <view
+            v-if="goodsFields.title?.show || goodsFields.name?.show"
+            class="lg-goods-title ss-line-2"
+            :style="[{ color: titleColor }]"
+          >
             {{ data.title || data.name }}
             {{ data.title || data.name }}
           </view>
           </view>
-          <view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
-                class="lg-goods-subtitle ss-m-t-10 ss-line-1"
-                :style="[{ color: subTitleColor, background: subTitleBackground }]">
+          <view
+            v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
+            class="lg-goods-subtitle ss-m-t-10 ss-line-1"
+            :style="[{ color: subTitleColor, background: subTitleBackground }]"
+          >
             {{ data.subtitle || data.introduction }}
             {{ data.subtitle || data.introduction }}
           </view>
           </view>
         </view>
         </view>
@@ -147,27 +189,25 @@
               </view>
               </view>
             </view>
             </view>
           </slot>
           </slot>
-          <!-- 这里是新加的会员价和限时优惠 -->
-          <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
-            <view class="card" v-if="iconShow">{{iconShow}}</view>
-            <view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
-          </view>
-          <!-- 这里是新加的会员价和限时优惠结束 -->
           <view class="ss-flex ss-col-bottom ss-m-t-10">
           <view class="ss-flex ss-col-bottom ss-m-t-10">
-            <view v-if="goodsFields.price?.show"
-                  class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
-                  :style="[{ color: goodsFields.price.color }]">
+            <view
+              v-if="goodsFields.price?.show"
+              class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
+              :style="[{ color: goodsFields.price.color }]"
+            >
               <text class="ss-font-24">{{ priceUnit }}</text>
               <text class="ss-font-24">{{ priceUnit }}</text>
               {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
               {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
             </view>
             </view>
-            <view v-if="
+            <view
+              v-if="
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (data.original_price > 0 || data.marketPrice > 0)
                 (data.original_price > 0 || data.marketPrice > 0)
-              " class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS" :style="[{ color: originPriceColor }]">
+              "
+              class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS"
+              :style="[{ color: originPriceColor }]"
+            >
               <text class="price-unit ss-font-20">{{ priceUnit }}</text>
               <text class="price-unit ss-font-20">{{ priceUnit }}</text>
-              <text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
-              <text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
-              <text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
+              <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
             </view>
             </view>
           </view>
           </view>
           <view class="ss-m-t-8 ss-flex ss-col-center ss-flex-wrap">
           <view class="ss-m-t-8 ss-flex ss-col-center ss-flex-wrap">
@@ -187,45 +227,54 @@
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
         <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
       </view>
       </view>
 
 
-      <image class="sl-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
+      <image
+        class="sl-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFill"
+      ></image>
 
 
       <view class="sl-goods-content">
       <view class="sl-goods-content">
         <view>
         <view>
-          <view v-if="goodsFields.title?.show || goodsFields.name?.show" class="sl-goods-title ss-line-1"
-                :style="[{ color: titleColor }]">
+          <view
+            v-if="goodsFields.title?.show || goodsFields.name?.show"
+            class="sl-goods-title ss-line-1"
+            :style="[{ color: titleColor }]"
+          >
             {{ data.title || data.name }}
             {{ data.title || data.name }}
           </view>
           </view>
-          <view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
-                class="sl-goods-subtitle ss-m-t-16"
-                :style="[{ color: subTitleColor, background: subTitleBackground }]">
+          <view
+            v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
+            class="sl-goods-subtitle ss-m-t-16"
+            :style="[{ color: subTitleColor, background: subTitleBackground }]"
+          >
             {{ data.subtitle || data.introduction }}
             {{ data.subtitle || data.introduction }}
           </view>
           </view>
         </view>
         </view>
         <view>
         <view>
           <slot name="activity">
           <slot name="activity">
             <view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center ss-flex-wrap">
             <view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center ss-flex-wrap">
-              <view class="activity-tag ss-m-r-10 ss-m-t-16" v-for="item in data.promos" :key="item.id">
+              <view
+                class="activity-tag ss-m-r-10 ss-m-t-16"
+                v-for="item in data.promos"
+                :key="item.id"
+              >
                 {{ item.title }}
                 {{ item.title }}
               </view>
               </view>
             </view>
             </view>
           </slot>
           </slot>
-          <!-- 这里是新加的会员价和限时优惠 -->
-          <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
-            <view class="card" v-if="iconShow">{{iconShow}}</view>
-            <view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
-          </view>
-          <!-- 这里是新加的会员价和限时优惠结束 -->
           <view v-if="goodsFields.price?.show" class="ss-flex ss-col-bottom font-OPPOSANS">
           <view v-if="goodsFields.price?.show" class="ss-flex ss-col-bottom font-OPPOSANS">
             <view class="sl-goods-price ss-m-r-12" :style="[{ color: goodsFields.price.color }]">
             <view class="sl-goods-price ss-m-r-12" :style="[{ color: goodsFields.price.color }]">
               <text class="price-unit ss-font-24">{{ priceUnit }}</text>
               <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-              <text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
-              <text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
-              <text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
+              {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
             </view>
             </view>
-            <view v-if="
+            <view
+              v-if="
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (data.original_price > 0 || data.marketPrice > 0)
                 (data.original_price > 0 || data.marketPrice > 0)
-              " class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex" :style="[{ color: originPriceColor }]">
+              "
+              class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
+              :style="[{ color: originPriceColor }]"
+            >
               <text class="price-unit ss-font-20">{{ priceUnit }}</text>
               <text class="price-unit ss-font-20">{{ priceUnit }}</text>
               <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
               <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
             </view>
             </view>
@@ -248,50 +297,36 @@
    * 商品卡片
    * 商品卡片
    *
    *
    * @property {Array} size = [xs | sm | md | lg | sl ] 			 	- 列表数据
    * @property {Array} size = [xs | sm | md | lg | sl ] 			 	- 列表数据
-   * @property {String} tag 											- md及以上才有
-   * @property {String} img 											- 图片
-   * @property {String} background 									- 背景色
-   * @property {String} topRadius 									- 上圆角
-   * @property {String} bottomRadius 									- 下圆角
-   * @property {String} title 										- 标题
-   * @property {String} titleColor 									- 标题颜色
+   * @property {String} tag                      - md及以上才有
+   * @property {String} img                      - 图片
+   * @property {String} background                  - 背景色
+   * @property {String} topRadius                  - 上圆角
+   * @property {String} bottomRadius                  - 下圆角
+   * @property {String} title                    - 标题
+   * @property {String} titleColor                  - 标题颜色
    * @property {Number} titleWidth = 0								- 标题宽度,默认0,单位rpx
    * @property {Number} titleWidth = 0								- 标题宽度,默认0,单位rpx
-   * @property {String} subTitle 										- 副标题
-   * @property {String} subTitleColor									- 副标题颜色
-   * @property {String} subTitleBackground 							- 副标题背景
-   * @property {String | Number} price 								- 价格
-   * @property {String} priceColor 									- 价格颜色
-   * @property {String | Number} originPrice 							- 原价/划线价
-   * @property {String} originPriceColor 								- 原价颜色
-   * @property {String | Number} sales 								- 销售数量
-   * @property {String} salesColor									- 销售数量颜色
+   * @property {String} subTitle                    - 副标题
+   * @property {String} subTitleColor                  - 副标题颜色
+   * @property {String} subTitleBackground              - 副标题背景
+   * @property {String | Number} price                - 价格
+   * @property {String} priceColor                  - 价格颜色
+   * @property {String | Number} originPrice              - 原价/划线价
+   * @property {String} originPriceColor                - 原价颜色
+   * @property {String | Number} sales                - 销售数量
+   * @property {String} salesColor                  - 销售数量颜色
    *
    *
    * @slots activity												 	- 活动插槽
    * @slots activity												 	- 活动插槽
    * @slots cart														- 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
    * @slots cart														- 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
    *
    *
-   * @event {Function()} click 										- 点击卡片
+   * @event {Function()} click                    - 点击卡片
    *
    *
    */
    */
-  import {
-    computed,
-    reactive,
-    getCurrentInstance,
-    onMounted,
-    nextTick,
-    ref
-  } from 'vue';
+  import { computed, reactive, getCurrentInstance, onMounted, nextTick } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
-  import {
-    fen2yuan,
-    formatSales
-  } from '@/sheep/hooks/useGoods';
-  import {
-    formatStock
-  } from '@/sheep/hooks/useGoods';
-  import goodsCollectVue from '@/pages/user/goods-collect.vue';
-  import {
-    isArray
-  } from 'lodash-es';
+  import { fen2yuan, formatSales } from '@/sheep/hooks/useGoods';
+  import { formatStock } from '@/sheep/hooks/useGoods';
+  import { isArray } from 'lodash-es';
+
   // 数据
   // 数据
   const state = reactive({});
   const state = reactive({});
 
 
@@ -299,42 +334,30 @@
   const props = defineProps({
   const props = defineProps({
     goodsFields: {
     goodsFields: {
       type: [Array, Object],
       type: [Array, Object],
-      default () {
+      default() {
         return {
         return {
           // 商品价格
           // 商品价格
-          price: {
-            show: true
-          },
+          price: { show: true },
           // 库存
           // 库存
-          stock: {
-            show: true
-          },
+          stock: { show: true },
           // 商品名称
           // 商品名称
-          name: {
-            show: true
-          },
+          name: { show: true },
           // 商品介绍
           // 商品介绍
-          introduction: {
-            show: true
-          },
+          introduction: { show: true },
           // 市场价
           // 市场价
-          marketPrice: {
-            show: true
-          },
+          marketPrice: { show: true },
           // 销量
           // 销量
-          salesCount: {
-            show: true
-          },
+          salesCount: { show: true },
         };
         };
       },
       },
     },
     },
     tagStyle: {
     tagStyle: {
       type: Object,
       type: Object,
-      default: {},
+      default: () => ({}),
     },
     },
     data: {
     data: {
       type: Object,
       type: Object,
-      default: {},
+      default: () => ({}),
     },
     },
     size: {
     size: {
       type: String,
       type: String,
@@ -393,25 +416,7 @@
       default: false,
       default: false,
     },
     },
   });
   });
-  //判断限时优惠和会员价标签内容暂时导致页面出错,又舍不得丢,等着把新的数据整合到商品信息中,也用起来
-  const iconShow = handle()
-
-  function handle() {
-    if (props.data.discountPrice === null && props.data.vipPrice === null) {
-      // 如果两个值都为 null,则不展示任何内容
-      return '';
-    } else if (props.data.discountPrice === null) {
-      // 如果 discountPrice 为 null,展示 vipPrice
-      return '会员价';
-    } else if (props.data.vipPrice === null) {
-      // 如果 vipPrice 为 null,展示 discountPrice
-      return '限时优惠';
-    } else if (props.data.discountPrice < props.data.vipPrice) {
-      return '限时优惠';
-    } else if (props.data.discountPrice > props.data.vipPrice) {
-      return '会员价';
-    }
-  }
+
   // 组件样式
   // 组件样式
   const elStyles = computed(() => {
   const elStyles = computed(() => {
     return {
     return {
@@ -443,18 +448,13 @@
   };
   };
 
 
   // 获取卡片实时高度
   // 获取卡片实时高度
-  const {
-    proxy
-  } = getCurrentInstance();
+  const { proxy } = getCurrentInstance();
   const elId = `sheep_${Math.ceil(Math.random() * 10e5).toString(36)}`;
   const elId = `sheep_${Math.ceil(Math.random() * 10e5).toString(36)}`;
 
 
   function getGoodsPriceCardWH() {
   function getGoodsPriceCardWH() {
     if (props.size === 'md') {
     if (props.size === 'md') {
       const view = uni.createSelectorQuery().in(proxy);
       const view = uni.createSelectorQuery().in(proxy);
-      view.select(`#${elId}`).fields({
-        size: true,
-        scrollOffset: true
-      });
+      view.select(`#${elId}`).fields({ size: true, scrollOffset: true });
       view.exec((data) => {
       view.exec((data) => {
         let totalHeight = 0;
         let totalHeight = 0;
         const goodsPriceCard = data[0];
         const goodsPriceCard = data[0];
@@ -469,6 +469,7 @@
       });
       });
     }
     }
   }
   }
+
   onMounted(() => {
   onMounted(() => {
     nextTick(() => {
     nextTick(() => {
       getGoodsPriceCardWH();
       getGoodsPriceCardWH();
@@ -762,31 +763,4 @@
       color: #ffffff;
       color: #ffffff;
     }
     }
   }
   }
-
-  .card {
-    width: fit-content;
-    height: fit-content;
-    padding: 2rpx 10rpx;
-    background-color: red;
-    color: #ffffff;
-    font-size: 24rpx;
-  }
-
-  .card2 {
-    width: fit-content;
-    height: fit-content;
-    padding: 2rpx 10rpx;
-    background-color: rgb(255, 242, 241);
-    color: #ff2621;
-    font-size: 24rpx;
-    margin-left: 5rpx;
-  }
-
-  .iconBox {
-    width: 100%;
-    height: fit-content;
-    margin-top: 10rpx;
-    display: flex;
-    justify-content: flex-start;
-  }
-</style>
+</style>

+ 241 - 70
sheep/components/s-groupon-block/s-groupon-block.vue

@@ -1,83 +1,166 @@
-<!-- 装修组件 - 拼团 -->
+<!-- 装修商品组件:【拼团】商品卡片 -->
 <template>
 <template>
+  <!-- 商品卡片 -->
   <view>
   <view>
+    <!-- 布局1. 单列大图(上图,下内容)-->
     <view
     <view
-      v-if="layoutType === 'threeCol'"
-      class="goods-sm-box ss-flex ss-flex-wrap"
-      :style="[{ margin: '-' + data.space + 'rpx' }]"
+      v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.spuList.length"
+      class="goods-sl-box"
     >
     >
       <view
       <view
-        v-for="product in productList"
-        :key="product.id"
-        class="goods-card-box"
-        :style="[
-          {
-            padding: data.space + 'rpx',
-          },
-        ]"
+        class="goods-box"
+        v-for="item in state.spuList"
+        :key="item.id"
+        :style="[{ marginBottom: data.space * 2 + 'rpx' }]"
       >
       >
         <s-goods-column
         <s-goods-column
-          class="goods-card"
-          size="sm"
+          class=""
+          size="sl"
           :goodsFields="data.fields"
           :goodsFields="data.fields"
-          :tagStyle="tagStyle"
-          :data="product"
+          :tagStyle="data.badge"
+          :data="item"
           :titleColor="data.fields.name?.color"
           :titleColor="data.fields.name?.color"
+          :subTitleColor="data.fields.introduction.color"
           :topRadius="data.borderRadiusTop"
           :topRadius="data.borderRadiusTop"
           :bottomRadius="data.borderRadiusBottom"
           :bottomRadius="data.borderRadiusBottom"
-          @click="
-            sheep.$router.go('/pages/goods/groupon', {
-              id: props.data.activityId,
-            })
-          "
-        ></s-goods-column>
+          @click="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
+        >
+          <!-- 购买按钮 -->
+          <template v-slot:cart>
+            <button class="ss-reset-button cart-btn" :style="[buyStyle]">
+              {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
+            </button>
+          </template>
+        </s-goods-column>
       </view>
       </view>
     </view>
     </view>
-    <!-- 样式2 一行一个 图片左 文案右 -->
-    <view class="goods-box" v-if="layoutType === 'oneCol'">
+
+    <!-- 布局2. 单列小图(左图,右内容) -->
+    <view
+      v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.spuList.length"
+      class="goods-lg-box"
+    >
       <view
       <view
-        class="goods-list"
-        v-for="(product, index) in productList"
-        :key="index"
-        :style="[{ marginBottom: space + 'px' }]"
+        class="goods-box"
+        :style="[{ marginBottom: data.space + 'px' }]"
+        v-for="item in state.spuList"
+        :key="item.id"
       >
       >
         <s-goods-column
         <s-goods-column
           class="goods-card"
           class="goods-card"
           size="lg"
           size="lg"
           :goodsFields="data.fields"
           :goodsFields="data.fields"
-          :tagStyle="tagStyle"
-          :data="product"
+          :data="item"
+          :tagStyle="data.badge"
           :titleColor="data.fields.name?.color"
           :titleColor="data.fields.name?.color"
-          :subTitleColor="data.fields.introduction?.color"
+          :subTitleColor="data.fields.introduction.color"
           :topRadius="data.borderRadiusTop"
           :topRadius="data.borderRadiusTop"
           :bottomRadius="data.borderRadiusBottom"
           :bottomRadius="data.borderRadiusBottom"
-          @click="
-            sheep.$router.go('/pages/goods/groupon', {
-              id: props.data.activityId,
-            })
-          "
+          @tap="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
         >
         >
+          <!-- 购买按钮 -->
           <template v-slot:cart>
           <template v-slot:cart>
             <button class="ss-reset-button cart-btn" :style="[buyStyle]">
             <button class="ss-reset-button cart-btn" :style="[buyStyle]">
-              {{ btnBuy?.type === 'text' ? btnBuy.text : '' }}
+              {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
             </button>
             </button>
           </template>
           </template>
         </s-goods-column>
         </s-goods-column>
       </view>
       </view>
     </view>
     </view>
+
+    <!-- 布局3. 双列(每一列:上图,下内容)-->
+    <view
+      v-if="layoutType === LayoutTypeEnum.TWO_COL && state.spuList.length"
+      class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top"
+    >
+      <view class="goods-list-box">
+        <view
+          class="left-list"
+          :style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]"
+          v-for="item in state.leftSpuList"
+          :key="item.id"
+        >
+          <s-goods-column
+            class="goods-md-box"
+            size="md"
+            :goodsFields="data.fields"
+            :tagStyle="data.badge"
+            :data="item"
+            :titleColor="data.fields.name?.color"
+            :subTitleColor="data.fields.introduction.color"
+            :topRadius="data.borderRadiusTop"
+            :bottomRadius="data.borderRadiusBottom"
+            :titleWidth="330 - marginLeft - marginRight"
+            @click="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
+            @getHeight="calculateGoodsColumn($event, 'left')"
+          >
+            <!-- 购买按钮 -->
+            <template v-slot:cart>
+              <button class="ss-reset-button cart-btn" :style="[buyStyle]">
+                {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
+              </button>
+            </template>
+          </s-goods-column>
+        </view>
+      </view>
+      <view class="goods-list-box">
+        <view
+          class="right-list"
+          :style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
+          v-for="item in state.rightSpuList"
+          :key="item.id"
+        >
+          <s-goods-column
+            class="goods-md-box"
+            size="md"
+            :goodsFields="data.fields"
+            :tagStyle="data.badge"
+            :data="item"
+            :titleColor="data.fields.name?.color"
+            :subTitleColor="data.fields.introduction.color"
+            :topRadius="data.borderRadiusTop"
+            :bottomRadius="data.borderRadiusBottom"
+            :titleWidth="330 - marginLeft - marginRight"
+            @click="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
+            @getHeight="calculateGoodsColumn($event, 'right')"
+          >
+            <!-- 购买按钮 -->
+            <template v-slot:cart>
+              <button class="ss-reset-button cart-btn" :style="[buyStyle]">
+                {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
+              </button>
+            </template>
+          </s-goods-column>
+        </view>
+      </view>
+    </view>
   </view>
   </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
   /**
   /**
-   * 拼团
+   * 商品卡片
    */
    */
-  import { computed, onMounted, ref } from 'vue';
+  import { computed, onMounted, reactive, ref } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
-  import SpuApi from "@/sheep/api/product/spu";
-  import CombinationApi from "@/sheep/api/promotion/combination";
+  import CombinationApi from '@/sheep/api/promotion/combination';
+  import SpuApi from '@/sheep/api/product/spu';
 
 
-  // 接收参数
+  // 布局类型
+  const LayoutTypeEnum = {
+    // 单列大图
+    ONE_COL_BIG_IMG: 'oneColBigImg',
+    // 双列
+    TWO_COL: 'twoCol',
+    // 单列小图
+    ONE_COL_SMALL_IMG: 'oneColSmallImg',
+  };
+
+  const state = reactive({
+    spuList: [],
+    leftSpuList: [],
+    rightSpuList: [],
+  });
   const props = defineProps({
   const props = defineProps({
     data: {
     data: {
       type: Object,
       type: Object,
@@ -89,19 +172,19 @@
     },
     },
   });
   });
 
 
-  let { layoutType, tagStyle, btnBuy, space } = props.data;
-  let { marginLeft, marginRight } = props.styles;
+  const { layoutType, btnBuy, activityIds } = props.data || {};
+  const { marginLeft, marginRight } = props.styles || {};
 
 
   // 购买按钮样式
   // 购买按钮样式
   const buyStyle = computed(() => {
   const buyStyle = computed(() => {
-    let btnBuy = props.data.btnBuy;
-    if (btnBuy?.type === 'text') {
+    if (btnBuy.type === 'text') {
+      // 文字按钮:线性渐变背景颜色
       return {
       return {
         background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
         background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
       };
       };
     }
     }
-
-    if (btnBuy?.type === 'img') {
+    if (btnBuy.type === 'img') {
+      // 图片按钮
       return {
       return {
         width: '54rpx',
         width: '54rpx',
         height: '54rpx',
         height: '54rpx',
@@ -111,21 +194,124 @@
     }
     }
   });
   });
 
 
-  const productList = ref([]);
+  //region 商品瀑布流布局
+  // 下一个要处理的商品索引
+  let count = 0;
+  // 左列的高度
+  let leftHeight = 0;
+  // 右列的高度
+  let rightHeight = 0;
+
+  /**
+   * 计算商品在左列还是右列
+   * @param height 商品的高度
+   * @param where 添加到哪一列
+   */
+  function calculateGoodsColumn(height = 0, where = 'left') {
+    // 处理完
+    if (!state.spuList[count]) return;
+    // 增加列的高度
+    if (where === 'left') leftHeight += height;
+    if (where === 'right') rightHeight += height;
+    // 添加到矮的一列
+    if (leftHeight <= rightHeight) {
+      state.leftSpuList.push(state.spuList[count]);
+    } else {
+      state.rightSpuList.push(state.spuList[count]);
+    }
+    // 计数
+    count++;
+  }
+
+  //endregion
+
+  /**
+   * 根据商品编号列表,获取商品列表
+   * @param ids 商品编号列表
+   * @return {Promise<undefined>} 商品列表
+   */
+  async function getCombinationActivityDetailList(ids) {
+    const { data } = await CombinationApi.getCombinationActivityListByIds(ids);
+    return data;
+  }
+
+  /**
+   * 根据商品编号,获取商品详情
+   * @param ids 商品编号列表
+   * @return {Promise<undefined>} 商品列表
+   */
+  async function getSpuDetail(ids) {
+    const { data: spu } = await SpuApi.getSpuDetail(ids);
+    return spu;
+  }
+
+  // 初始化
   onMounted(async () => {
   onMounted(async () => {
-    // todo:@owen 与Yudao结构不一致,待重构
-    const { data: activity } = await CombinationApi.getCombinationActivity(props.data.activityId);
-    const { data: spu } = await SpuApi.getSpuDetail(activity.spuId)
-    productList.value = [spu];
+    // 加载活动列表
+    const activityList = await getCombinationActivityDetailList(activityIds.join(','));
+    // 循环获取活动商品SPU详情并添加到spuList
+    for (const activity of activityList) {
+      state.spuList.push(await getSpuDetail(activity.spuId));
+    }
+
+    // 循环活动列表
+    activityList.forEach((activity) => {
+      // 提取活动价格
+      const combinationPrice = activity.combinationPrice || Infinity;
+      // 查找对应的 spu 并更新价格
+      const spu = state.spuList.find((spu) => activity.spuId === spu.id);
+      if (spu) {
+        // 赋值最低价格
+        spu.price = Math.min(combinationPrice, spu.price);
+        // 赋值活动ID,为了点击跳转详情页
+        spu.activityId = activity.id;
+      }
+    });
+
+    // 只有双列布局时需要
+    if (layoutType === LayoutTypeEnum.TWO_COL) {
+      // 分列
+      calculateGoodsColumn();
+    }
   });
   });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  .goods-list {
+  .goods-md-wrap {
+    width: 100%;
+  }
+
+  .goods-list-box {
+    width: 50%;
+    box-sizing: border-box;
+
+    .left-list {
+      &:nth-last-child(1) {
+        margin-bottom: 0 !important;
+      }
+    }
+
+    .right-list {
+      &:nth-last-child(1) {
+        margin-bottom: 0 !important;
+      }
+    }
+  }
+
+  .goods-box {
+    &:nth-last-of-type(1) {
+      margin-bottom: 0 !important;
+    }
+  }
+
+  .goods-md-box,
+  .goods-sl-box,
+  .goods-lg-box {
     position: relative;
     position: relative;
+
     .cart-btn {
     .cart-btn {
       position: absolute;
       position: absolute;
-      bottom: 10rpx;
+      bottom: 18rpx;
       right: 20rpx;
       right: 20rpx;
       z-index: 11;
       z-index: 11;
       height: 50rpx;
       height: 50rpx;
@@ -136,19 +322,4 @@
       color: #fff;
       color: #fff;
     }
     }
   }
   }
-  .goods-list {
-    &:nth-last-of-type(1) {
-      margin-bottom: 0 !important;
-    }
-  }
-  .goods-sm-box {
-    margin: 0 auto;
-    box-sizing: border-box;
-    .goods-card-box {
-      flex-shrink: 0;
-      overflow: hidden;
-      width: 33.3%;
-      box-sizing: border-box;
-    }
-  }
 </style>
 </style>

+ 2 - 2
sheep/components/s-live-block/s-live-block.vue

@@ -70,8 +70,8 @@
       default() {},
       default() {},
     },
     },
   });
   });
-  const { mode, goodsFields, mpliveIds } = props.data ?? {};
-  const { marginLeft, marginRight } = props.styles ?? {};
+  const { mode, goodsFields, mpliveIds } = props.data || {};
+  const { marginLeft, marginRight } = props.styles || {};
 
 
   async function getLiveListByIds(ids) {
   async function getLiveListByIds(ids) {
     const { data } = await sheep.$api.app.mplive.getRoomList(ids);
     const { data } = await sheep.$api.app.mplive.getRoomList(ids);

+ 306 - 326
sheep/components/s-menu-button/s-menu-button.vue

@@ -1,363 +1,343 @@
 <!-- 装修基础组件:菜单导航(金刚区) -->
 <!-- 装修基础组件:菜单导航(金刚区) -->
 <template>
 <template>
-  <!-- 包裹层 -->
-  <view
-    class="ui-swiper"
-    :class="[props.mode, props.bg, props.ui]"
-    :style="[{ height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]"
-  >
-    <!-- 轮播 -->
-    <swiper
-      :circular="props.circular"
-      :current="state.cur"
-      :autoplay="props.autoplay"
-      :interval="props.interval"
-      :duration="props.duration"
-      :style="[{ height: swiperHeight + 'rpx' }]"
-      @change="swiperChange"
-    >
-      <swiper-item
-        v-for="(arr, index) in menuList"
-        :key="index"
-        :class="{ cur: state.cur == index }"
-      >
-        <!-- 宫格 -->
-        <view class="grid-wrap">
-          <view
-            v-for="(item, index) in arr"
-            :key="index"
-            class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
-            :style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]"
-            hover-class="ss-hover-btn"
-            @tap="sheep.$router.go(item.url)"
-          >
-            <view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
-              <view
-                v-if="item.badge.show"
-                class="tag-box"
-                :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
-              >
-                {{ item.badge.text }}
-              </view>
-              <image
-                v-if="item.iconUrl"
-                class="menu-icon"
-                :style="[
+	<!-- 包裹层 -->
+	<view class="ui-swiper" :class="[props.mode, props.ui]"
+		:style="[bgStyle, { height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]">
+		<!-- 轮播 -->
+		<swiper :circular="props.circular" :current="state.cur" :autoplay="props.autoplay" :interval="props.interval"
+			:duration="props.duration" :style="[{ height: swiperHeight + 'rpx' }]" @change="swiperChange">
+			<swiper-item v-for="(arr, index) in menuList" :key="index" :class="{ cur: state.cur == index }">
+				<!-- 宫格 -->
+				<view class="grid-wrap">
+					<view v-for="(item, index) in arr" :key="index"
+						class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
+						:style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]" hover-class="ss-hover-btn"
+						@tap="sheep.$router.go(item.url)">
+						<view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
+							<view v-if="item.badge.show" class="tag-box"
+								:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
+								{{ item.badge.text }}
+							</view>
+							<image v-if="item.iconUrl" class="menu-icon" :style="[
                   {
                   {
                     width: props.iconSize + 'rpx',
                     width: props.iconSize + 'rpx',
                     height: props.iconSize + 'rpx',
                     height: props.iconSize + 'rpx',
                   },
                   },
-                ]"
-                :src="sheep.$url.cdn(item.iconUrl)"
-                mode="aspectFill"
-              ></image>
-              <view
-                v-if="data.layout === 'iconText'"
-                class="menu-title"
-                :style="[{ color: item.titleColor }]"
-              >
-                {{ item.title }}
-              </view>
-            </view>
-          </view>
-        </view>
-      </swiper-item>
-    </swiper>
-    <!-- 指示点 -->
-    <template v-if="menuList.length > 1">
-      <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
-        <view
-          class="line-box"
-          v-for="(item, index) in menuList.length"
-          :key="index"
-          :class="[state.cur == index ? 'cur' : '', props.dotCur]"
-        ></view>
-      </view>
-      <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
-        <view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
-          <view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
-        </view>
-      </view>
-    </template>
-  </view>
+                ]" :src="sheep.$url.cdn(item.iconUrl)" mode="aspectFill"></image>
+							<view v-if="data.layout === 'iconText'" class="menu-title"
+								:style="[{ color: item.titleColor }]">
+								{{ item.title }}
+							</view>
+						</view>
+					</view>
+				</view>
+			</swiper-item>
+		</swiper>
+		<!-- 指示点 -->
+		<template v-if="menuList.length > 1">
+			<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
+				<view class="line-box" v-for="(item, index) in menuList.length" :key="index"
+					:class="[state.cur == index ? 'cur' : '', props.dotCur]"></view>
+			</view>
+			<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
+				<view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
+					<view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
+				</view>
+			</view>
+		</template>
+	</view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  /**
-   * 轮播menu
-   *
-   * @property {Boolean} circular = false  		- 是否采用衔接滑动,即播放到末尾后重新回到开头
-   * @property {Boolean} autoplay = true  		- 是否自动切换
-   * @property {Number} interval = 5000  			- 自动切换时间间隔
-   * @property {Number} duration = 500  			- 滑动动画时长,app-nvue不支持
-   * @property {Array} list = [] 					- 轮播数据
-   * @property {String} ui = ''  					- 样式class
-   * @property {String} mode  					- 模式
-   * @property {String} dotStyle  				- 指示点样式
-   * @property {String} dotCur= 'ui-BG-Main' 		- 当前指示点样式,默认主题色
-   * @property {String} bg  						- 背景
-   *
-   * @property {String|Number} col = 4  			- 一行数量
-   *  @property {String|Number} row = 1 			- 几行
-   * @property {String} hasBorder 				- 是否有边框
-   * @property {String} borderColor 				- 边框颜色
-   * @property {String} background		  		- 背景
-   * @property {String} hoverClass 				- 按压样式类
-   * @property {String} hoverStayTime 		  	- 动画时间
-   *
-   * @property {Array} list 		  				- 导航列表
-   * @property {Number} iconSize 		  			- 图标大小
-   * @property {String} color 		  			- 标题颜色
-   *
-   */
+	/**
+	 * 轮播menu
+	 *
+	 * @property {Boolean} circular = false  		- 是否采用衔接滑动,即播放到末尾后重新回到开头
+	 * @property {Boolean} autoplay = true  		- 是否自动切换
+	 * @property {Number} interval = 5000  			- 自动切换时间间隔
+	 * @property {Number} duration = 500  			- 滑动动画时长,app-nvue不支持
+	 * @property {Array} list = [] 					- 轮播数据
+	 * @property {String} ui = ''  					- 样式class
+	 * @property {String} mode  					- 模式
+	 * @property {String} dotStyle  				- 指示点样式
+	 * @property {String} dotCur= 'ui-BG-Main' 		- 当前指示点样式,默认主题色
+	 * @property {String} bg  						- 背景
+	 *
+	 * @property {String|Number} col = 4  			- 一行数量
+	 * @property {String|Number} row = 1 			- 几行
+	 * @property {String} hasBorder 				- 是否有边框
+	 * @property {String} borderColor 				- 边框颜色
+	 * @property {String} background		  		- 背景
+	 * @property {String} hoverClass 				- 按压样式类
+	 * @property {String} hoverStayTime 		  	- 动画时间
+	 *
+	 * @property {Array} list 		  				- 导航列表
+	 * @property {Number} iconSize 		  			- 图标大小
+	 * @property {String} color 		  			- 标题颜色
+	 *
+	 */
 
 
-  import { reactive, computed } from 'vue';
-  import sheep from '@/sheep';
+	import {
+		reactive,
+		computed
+	} from 'vue';
+	import sheep from '@/sheep';
 
 
-  // 数据
-  const state = reactive({
-    cur: 0,
-  });
+	// 数据
+	const state = reactive({
+		cur: 0,
+	});
 
 
-  // 接收参数
+	// 接收参数
 
 
-  const props = defineProps({
-    data: {
-      type: Object,
-      default() {},
-    },
-    styles: {
-      type: Object,
-      default() {},
-    },
-    circular: {
-      type: Boolean,
-      default: true,
-    },
-    autoplay: {
-      type: Boolean,
-      default: false,
-    },
-    interval: {
-      type: Number,
-      default: 5000,
-    },
-    duration: {
-      type: Number,
-      default: 500,
-    },
+	const props = defineProps({
+		// 装修数据
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+		circular: {
+			type: Boolean,
+			default: true,
+		},
+		autoplay: {
+			type: Boolean,
+			default: false,
+		},
+		interval: {
+			type: Number,
+			default: 5000,
+		},
+		duration: {
+			type: Number,
+			default: 500,
+		},
+		ui: {
+			type: String,
+			default: '',
+		},
+		mode: {
+			//default
+			type: String,
+			default: 'default',
+		},
+		dotStyle: {
+			type: String,
+			default: 'long', //default long tag
+		},
+		dotCur: {
+			type: String,
+			default: 'ui-BG-Main',
+		},
+		height: {
+			type: Number,
+			default: 300,
+		},
+		// 是否有边框
+		hasBorder: {
+			type: Boolean,
+			default: true,
+		},
+		// 边框颜色
+		borderColor: {
+			type: String,
+			default: 'red',
+		},
+		background: {
+			type: String,
+			default: 'blue',
+		},
+		hoverClass: {
+			type: String,
+			default: 'ss-hover-class', //'none'为没有hover效果
+		},
+		// 一排宫格数
+		col: {
+			type: [Number, String],
+			default: 3,
+		},
+		iconSize: {
+			type: Number,
+			default: 80,
+		},
+		color: {
+			type: String,
+			default: '#000',
+		},
+	});
 
 
-    ui: {
-      type: String,
-      default: '',
-    },
-    mode: {
-      //default
-      type: String,
-      default: 'default',
-    },
-    dotStyle: {
-      type: String,
-      default: 'long', //default long tag
-    },
-    dotCur: {
-      type: String,
-      default: 'ui-BG-Main',
-    },
-    bg: {
-      type: String,
-      default: 'bg-none',
-    },
-    height: {
-      type: Number,
-      default: 300,
-    },
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
 
-    // 是否有边框
-    hasBorder: {
-      type: Boolean,
-      default: true,
-    },
-    // 边框颜色
-    borderColor: {
-      type: String,
-      default: 'red',
-    },
-    background: {
-      type: String,
-      default: 'blue',
-    },
-    hoverClass: {
-      type: String,
-      default: 'ss-hover-class', //'none'为没有hover效果
-    },
-    // 一排宫格数
-    col: {
-      type: [Number, String],
-      default: 3,
-    },
-    iconSize: {
-      type: Number,
-      default: 80,
-    },
-    color: {
-      type: String,
-      default: '#000',
-    },
-  });
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
 
 
-  // 生成数据
-  const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
-  const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
-  const windowWidth = sheep.$platform.device.windowWidth;
+	// 生成数据
+	const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
+	const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
+	const windowWidth = sheep.$platform.device.windowWidth;
 
 
-  // current 改变时会触发 change 事件
-  const swiperChange = (e) => {
-    state.cur = e.detail.current;
-  };
+	// current 改变时会触发 change 事件
+	const swiperChange = (e) => {
+		state.cur = e.detail.current;
+	};
 
 
-  // 重组数据
-  const splitData = (oArr = [], length = 1) => {
-    let arr = [];
-    let minArr = [];
-    oArr.forEach((c) => {
-      if (minArr.length === length) {
-        minArr = [];
-      }
-      if (minArr.length === 0) {
-        arr.push(minArr);
-      }
-      minArr.push(c);
-    });
+	// 重组数据
+	const splitData = (oArr = [], length = 1) => {
+		let arr = [];
+		let minArr = [];
+		oArr.forEach((c) => {
+			if (minArr.length === length) {
+				minArr = [];
+			}
+			if (minArr.length === 0) {
+				arr.push(minArr);
+			}
+			minArr.push(c);
+		});
 
 
-    return arr;
-  };
+		return arr;
+	};
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  .grid-wrap {
-    width: 100%;
-    display: flex;
-    position: relative;
-    box-sizing: border-box;
-    overflow: hidden;
-    flex-wrap: wrap;
-    align-items: center;
-  }
-  .menu-box {
-    position: relative;
-    z-index: 1;
-    transform: translate(0, 0);
+	.grid-wrap {
+		width: 100%;
+		display: flex;
+		position: relative;
+		box-sizing: border-box;
+		overflow: hidden;
+		flex-wrap: wrap;
+		align-items: center;
+	}
 
 
-    .tag-box {
-      position: absolute;
-      z-index: 2;
-      top: 0;
-      right: -6rpx;
-      font-size: 2em;
-      line-height: 1;
-      padding: 0.4em 0.6em 0.3em;
-      transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
-      transform-origin: 100% 0;
-      border-radius: 200rpx;
-      white-space: nowrap;
-    }
+	.menu-box {
+		position: relative;
+		z-index: 1;
+		transform: translate(0, 0);
 
 
-    .menu-icon {
-      transform: translate(0, 0);
-      width: 80rpx;
-      height: 80rpx;
-      padding-bottom: 10rpx;
-    }
+		.tag-box {
+			position: absolute;
+			z-index: 2;
+			top: 0;
+			right: -6rpx;
+			font-size: 2em;
+			line-height: 1;
+			padding: 0.4em 0.6em 0.3em;
+			transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
+			transform-origin: 100% 0;
+			border-radius: 200rpx;
+			white-space: nowrap;
+		}
 
 
-    .menu-title {
-      font-size: 24rpx;
-      color: #333;
-    }
-  }
+		.menu-icon {
+			transform: translate(0, 0);
+			width: 80rpx;
+			height: 80rpx;
+			padding-bottom: 10rpx;
+		}
 
 
-  ::v-deep(.ui-swiper) {
-    position: relative;
-    z-index: 1;
+		.menu-title {
+			font-size: 24rpx;
+			color: #333;
+		}
+	}
 
 
-    .ui-swiper-dot {
-      position: absolute;
-      width: 100%;
-      bottom: 20rpx;
-      height: 30rpx;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      z-index: 2;
+	::v-deep(.ui-swiper) {
+		position: relative;
+		z-index: 1;
 
 
-      &.default .line-box {
-        display: inline-flex;
-        border-radius: 50rpx;
-        width: 6px;
-        height: 6px;
-        border: 2px solid transparent;
-        margin: 0 10rpx;
-        opacity: 0.3;
-        position: relative;
-        justify-content: center;
-        align-items: center;
+		.ui-swiper-dot {
+			position: absolute;
+			width: 100%;
+			bottom: 20rpx;
+			height: 30rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			z-index: 2;
 
 
-        &.cur {
-          width: 8px;
-          height: 8px;
-          opacity: 1;
-          border: 0px solid transparent;
-        }
+			&.default .line-box {
+				display: inline-flex;
+				border-radius: 50rpx;
+				width: 6px;
+				height: 6px;
+				border: 2px solid transparent;
+				margin: 0 10rpx;
+				opacity: 0.3;
+				position: relative;
+				justify-content: center;
+				align-items: center;
 
 
-        &.cur::after {
-          content: '';
-          border-radius: 50rpx;
-          width: 4px;
-          height: 4px;
-          background-color: #fff;
-        }
-      }
+				&.cur {
+					width: 8px;
+					height: 8px;
+					opacity: 1;
+					border: 0px solid transparent;
+				}
 
 
-      &.long .line-box {
-        display: inline-block;
-        border-radius: 100rpx;
-        width: 6px;
-        height: 6px;
-        margin: 0 10rpx;
-        opacity: 0.3;
-        position: relative;
+				&.cur::after {
+					content: '';
+					border-radius: 50rpx;
+					width: 4px;
+					height: 4px;
+					background-color: #fff;
+				}
+			}
 
 
-        &.cur {
-          width: 24rpx;
-          opacity: 1;
-        }
+			&.long .line-box {
+				display: inline-block;
+				border-radius: 100rpx;
+				width: 6px;
+				height: 6px;
+				margin: 0 10rpx;
+				opacity: 0.3;
+				position: relative;
 
 
-        &.cur::after {
-        }
-      }
+				&.cur {
+					width: 24rpx;
+					opacity: 1;
+				}
 
 
-      &.line {
-        bottom: 20rpx;
+				&.cur::after {}
+			}
 
 
-        .line-box {
-          display: inline-block;
-          width: 30px;
-          height: 3px;
-          opacity: 0.3;
-          position: relative;
+			&.line {
+				bottom: 20rpx;
 
 
-          &.cur {
-            opacity: 1;
-          }
-        }
-      }
+				.line-box {
+					display: inline-block;
+					width: 30px;
+					height: 3px;
+					opacity: 0.3;
+					position: relative;
 
 
-      &.tag {
-        justify-content: flex-end;
-        position: absolute;
-        bottom: 20rpx;
-        right: 20rpx;
-      }
-    }
-  }
-</style>
+					&.cur {
+						opacity: 1;
+					}
+				}
+			}
+
+			&.tag {
+				justify-content: flex-end;
+				position: absolute;
+				bottom: 20rpx;
+				right: 20rpx;
+			}
+		}
+	}
+</style>

+ 93 - 71
sheep/components/s-menu-grid/s-menu-grid.vue

@@ -1,82 +1,104 @@
 <!-- 装修基础组件:宫格导航 -->
 <!-- 装修基础组件:宫格导航 -->
 <template>
 <template>
-  <uni-grid :showBorder="Boolean(data.border)" :column="data.column">
-    <uni-grid-item
-      v-for="(item, index) in data.list"
-      :key="index"
-      @tap="sheep.$router.go(item.url)"
-    >
-      <view class="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
-        <view class="img-box">
-          <view
-            class="tag-box"
-            v-if="item.badge.show"
-            :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
-          >
-            {{ item.badge.text }}
-          </view>
-          <image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
-        </view>
+	<view :style="[bgStyle, { marginLeft: `${data.space}px` }]">
+		<uni-grid :showBorder="Boolean(data.border)" :column="data.column">
+			<uni-grid-item v-for="(item, index) in data.list" :key="index" @tap="sheep.$router.go(item.url)">
+				<view class="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
+					<view class="img-box">
+						<view class="tag-box" v-if="item.badge.show"
+							:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
+							{{ item.badge.text }}
+						</view>
+						<image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
+					</view>
+
+					<view class="title-box ss-flex ss-flex-col ss-row-center ss-col-center">
+						<view class="grid-text" :style="[{ color: item.titleColor }]">
+							{{ item.title }}
+						</view>
+						<view class="grid-tip" :style="[{ color: item.subtitleColor }]">
+							{{ item.subtitle }}
+						</view>
+					</view>
+				</view>
+			</uni-grid-item>
+		</uni-grid>
+	</view>
 
 
-        <view class="title-box ss-flex ss-flex-col ss-row-center ss-col-center">
-          <view class="grid-text" :style="[{ color: item.titleColor }]">
-            {{ item.title }}
-          </view>
-          <view class="grid-tip" :style="[{ color: item.subtitleColor }]">
-            {{ item.subtitle }}
-          </view>
-        </view>
-      </view>
-    </uni-grid-item>
-  </uni-grid>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import sheep from '@/sheep';
+	import sheep from '@/sheep';
+	import {
+		computed
+	} from 'vue';
+
+	const props = defineProps({
+		// 装修数据
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
 
-  const props = defineProps({
-    data: {
-      type: Object,
-      default() {},
-    },
-  });
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  .menu-image {
-    width: 24px;
-    height: 24px;
-  }
-  .grid-item-box {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    height: 100%;
-    .img-box {
-      position: relative;
-      .tag-box {
-        position: absolute;
-        z-index: 2;
-        top: 0;
-        right: 0;
-        font-size: 2em;
-        line-height: 1;
-        padding: 0.4em 0.6em 0.3em;
-        transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
-        transform-origin: 100% 0;
-        border-radius: 200rpx;
-        white-space: nowrap;
-      }
-    }
+	.menu-image {
+		width: 24px;
+		height: 24px;
+	}
+
+	.grid-item-box {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		height: 100%;
+
+		.img-box {
+			position: relative;
+
+			.tag-box {
+				position: absolute;
+				z-index: 2;
+				top: 0;
+				right: 0;
+				font-size: 2em;
+				line-height: 1;
+				padding: 0.4em 0.6em 0.3em;
+				transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
+				transform-origin: 100% 0;
+				border-radius: 200rpx;
+				white-space: nowrap;
+			}
+		}
 
 
-    .title-box {
-      .grid-tip {
-        font-size: 24rpx;
-        white-space: nowrap;
-        text-align: center;
-      }
-    }
-  }
-</style>
+		.title-box {
+			.grid-tip {
+				font-size: 24rpx;
+				white-space: nowrap;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 26 - 2
sheep/components/s-order-card/s-order-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户订单 -->
 <!-- 装修用户组件:用户订单 -->
 <template>
 <template>
-  <view class="ss-order-menu-wrap ss-flex ss-col-center">
+  <view class="ss-order-menu-wrap ss-flex ss-col-center" :style="[style, { marginLeft: `${data.space}px` }]">
     <view
     <view
       class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
       class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
       v-for="item in orderMap"
       v-for="item in orderMap"
@@ -67,8 +67,32 @@
       path: '/pages/order/list',
       path: '/pages/order/list',
     },
     },
   ];
   ];
-
+  // 接收参数
+  const props = defineProps({
+  	// 装修数据
+  	data: {
+  	  type: Object,
+  	  default: () => ({}),
+  	},
+  	// 装修样式
+  	styles: {
+  	  type: Object,
+  	  default: () => ({}),
+  	},
+  });
+  // 设置角标
   const numData = computed(() => sheep.$store('user').numData);
   const numData = computed(() => sheep.$store('user').numData);
+  // 设置背景样式
+  const style = computed(() => {
+    // 直接从 props.styles 解构
+    const { bgType, bgImg, bgColor } = props.styles; 
+    // 根据 bgType 返回相应的样式
+    return {
+  		background: bgType === 'img'
+  			? `url(${bgImg}) no-repeat top center / 100% 100%`
+  			: bgColor
+  	};
+  });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>

+ 238 - 73
sheep/components/s-seckill-block/s-seckill-block.vue

@@ -1,86 +1,166 @@
-<!-- 装修组件 - 秒杀 -->
+<!-- 装修商品组件:【秒杀】商品卡片 -->
 <template>
 <template>
+  <!-- 商品卡片 -->
   <view>
   <view>
-    <!-- 样式一:三列 - 上图下文 -->
+    <!-- 布局1. 单列大图(上图,下内容)-->
     <view
     <view
-      v-if="layoutType === 'threeCol'"
-      class="goods-sm-box ss-flex ss-flex-wrap"
-      :style="[{ margin: '-' + data.space + 'rpx' }]"
+      v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.spuList.length"
+      class="goods-sl-box"
     >
     >
       <view
       <view
-        v-for="product in productList"
-        :key="product.id"
-        class="goods-card-box"
-        :style="[
-          {
-            padding: data.space + 'rpx',
-          },
-        ]"
+        class="goods-box"
+        v-for="item in state.spuList"
+        :key="item.id"
+        :style="[{ marginBottom: data.space * 2 + 'rpx' }]"
       >
       >
         <s-goods-column
         <s-goods-column
-          class="goods-card"
-          size="sm"
+          class=""
+          size="sl"
           :goodsFields="data.fields"
           :goodsFields="data.fields"
-          :tagStyle="tagStyle"
-          :data="product"
+          :tagStyle="data.badge"
+          :data="item"
           :titleColor="data.fields.name?.color"
           :titleColor="data.fields.name?.color"
+          :subTitleColor="data.fields.introduction.color"
           :topRadius="data.borderRadiusTop"
           :topRadius="data.borderRadiusTop"
           :bottomRadius="data.borderRadiusBottom"
           :bottomRadius="data.borderRadiusBottom"
-          @click="
-            sheep.$router.go('/pages/goods/seckill', {
-              id: props.data.activityId,
-            })
-          "
-        ></s-goods-column>
+          @click="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
+        >
+          <!-- 购买按钮 -->
+          <template v-slot:cart>
+            <button class="ss-reset-button cart-btn" :style="[buyStyle]">
+              {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
+            </button>
+          </template>
+        </s-goods-column>
       </view>
       </view>
     </view>
     </view>
-    <!-- 样式二:一列 - 左图右文 -->
-    <view class="goods-box" v-if="layoutType === 'oneCol'">
+
+    <!-- 布局2. 单列小图(左图,右内容) -->
+    <view
+      v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.spuList.length"
+      class="goods-lg-box"
+    >
       <view
       <view
-        class="goods-list"
-        v-for="(product, index) in productList"
-        :key="index"
-        :style="[{ marginBottom: space + 'px' }]"
+        class="goods-box"
+        :style="[{ marginBottom: data.space + 'px' }]"
+        v-for="item in state.spuList"
+        :key="item.id"
       >
       >
         <s-goods-column
         <s-goods-column
           class="goods-card"
           class="goods-card"
           size="lg"
           size="lg"
           :goodsFields="data.fields"
           :goodsFields="data.fields"
-          :tagStyle="tagStyle"
-          :data="product"
+          :data="item"
+          :tagStyle="data.badge"
           :titleColor="data.fields.name?.color"
           :titleColor="data.fields.name?.color"
-          :subTitleColor="data.fields.introduction?.color"
+          :subTitleColor="data.fields.introduction.color"
           :topRadius="data.borderRadiusTop"
           :topRadius="data.borderRadiusTop"
           :bottomRadius="data.borderRadiusBottom"
           :bottomRadius="data.borderRadiusBottom"
-          @click="
-            sheep.$router.go('/pages/goods/seckill', {
-              id: props.data.activityId,
-            })
-          "
+          @tap="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
         >
         >
+          <!-- 购买按钮 -->
           <template v-slot:cart>
           <template v-slot:cart>
             <button class="ss-reset-button cart-btn" :style="[buyStyle]">
             <button class="ss-reset-button cart-btn" :style="[buyStyle]">
-              {{ btnBuy?.type === 'text' ? btnBuy.text : '' }}
+              {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
             </button>
             </button>
           </template>
           </template>
         </s-goods-column>
         </s-goods-column>
       </view>
       </view>
     </view>
     </view>
+
+    <!-- 布局3. 双列(每一列:上图,下内容)-->
+    <view
+      v-if="layoutType === LayoutTypeEnum.TWO_COL && state.spuList.length"
+      class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top"
+    >
+      <view class="goods-list-box">
+        <view
+          class="left-list"
+          :style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]"
+          v-for="item in state.leftSpuList"
+          :key="item.id"
+        >
+          <s-goods-column
+            class="goods-md-box"
+            size="md"
+            :goodsFields="data.fields"
+            :tagStyle="data.badge"
+            :data="item"
+            :titleColor="data.fields.name?.color"
+            :subTitleColor="data.fields.introduction.color"
+            :topRadius="data.borderRadiusTop"
+            :bottomRadius="data.borderRadiusBottom"
+            :titleWidth="330 - marginLeft - marginRight"
+            @click="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
+            @getHeight="calculateGoodsColumn($event, 'left')"
+          >
+            <!-- 购买按钮 -->
+            <template v-slot:cart>
+              <button class="ss-reset-button cart-btn" :style="[buyStyle]">
+                {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
+              </button>
+            </template>
+          </s-goods-column>
+        </view>
+      </view>
+      <view class="goods-list-box">
+        <view
+          class="right-list"
+          :style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
+          v-for="item in state.rightSpuList"
+          :key="item.id"
+        >
+          <s-goods-column
+            class="goods-md-box"
+            size="md"
+            :goodsFields="data.fields"
+            :tagStyle="data.badge"
+            :data="item"
+            :titleColor="data.fields.name?.color"
+            :subTitleColor="data.fields.introduction.color"
+            :topRadius="data.borderRadiusTop"
+            :bottomRadius="data.borderRadiusBottom"
+            :titleWidth="330 - marginLeft - marginRight"
+            @click="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
+            @getHeight="calculateGoodsColumn($event, 'right')"
+          >
+            <!-- 购买按钮 -->
+            <template v-slot:cart>
+              <button class="ss-reset-button cart-btn" :style="[buyStyle]">
+                {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
+              </button>
+            </template>
+          </s-goods-column>
+        </view>
+      </view>
+    </view>
   </view>
   </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
   /**
   /**
-   * 秒杀商品列表
-   *
-   * @property {Array} list 商品列表
+   * 商品卡片
    */
    */
-  import { computed, onMounted, ref } from 'vue';
+  import { computed, onMounted, reactive, ref } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
-  import SeckillApi from "@/sheep/api/promotion/seckill";
-  import SpuApi from "@/sheep/api/product/spu";
+  import SeckillApi from '@/sheep/api/promotion/seckill';
+  import SpuApi from '@/sheep/api/product/spu';
 
 
-  // 接收参数
+  // 布局类型
+  const LayoutTypeEnum = {
+    // 单列大图
+    ONE_COL_BIG_IMG: 'oneColBigImg',
+    // 双列
+    TWO_COL: 'twoCol',
+    // 单列小图
+    ONE_COL_SMALL_IMG: 'oneColSmallImg',
+  };
+
+  const state = reactive({
+    spuList: [],
+    leftSpuList: [],
+    rightSpuList: [],
+  });
   const props = defineProps({
   const props = defineProps({
     data: {
     data: {
       type: Object,
       type: Object,
@@ -92,18 +172,19 @@
     },
     },
   });
   });
 
 
-  let { layoutType, tagStyle, btnBuy, space } = props.data;
-  let { marginLeft, marginRight } = props.styles;
+  const { layoutType, btnBuy, activityIds } = props.data || {};
+  const { marginLeft, marginRight } = props.styles || {};
 
 
   // 购买按钮样式
   // 购买按钮样式
   const buyStyle = computed(() => {
   const buyStyle = computed(() => {
-    let btnBuy = props.data.btnBuy;
-    if (btnBuy?.type === 'text') {
+    if (btnBuy.type === 'text') {
+      // 文字按钮:线性渐变背景颜色
       return {
       return {
         background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
         background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
       };
       };
     }
     }
-    if (btnBuy?.type === 'img') {
+    if (btnBuy.type === 'img') {
+      // 图片按钮
       return {
       return {
         width: '54rpx',
         width: '54rpx',
         height: '54rpx',
         height: '54rpx',
@@ -113,30 +194,124 @@
     }
     }
   });
   });
 
 
-  // 商品列表
-  const productList = ref([]);
-  // 查询秒杀活动商品
+  //region 商品瀑布流布局
+  // 下一个要处理的商品索引
+  let count = 0;
+  // 左列的高度
+  let leftHeight = 0;
+  // 右列的高度
+  let rightHeight = 0;
+
+  /**
+   * 计算商品在左列还是右列
+   * @param height 商品的高度
+   * @param where 添加到哪一列
+   */
+  function calculateGoodsColumn(height = 0, where = 'left') {
+    // 处理完
+    if (!state.spuList[count]) return;
+    // 增加列的高度
+    if (where === 'left') leftHeight += height;
+    if (where === 'right') rightHeight += height;
+    // 添加到矮的一列
+    if (leftHeight <= rightHeight) {
+      state.leftSpuList.push(state.spuList[count]);
+    } else {
+      state.rightSpuList.push(state.spuList[count]);
+    }
+    // 计数
+    count++;
+  }
+
+  //endregion
+
+  /**
+   * 根据商品编号列表,获取商品列表
+   * @param ids 商品编号列表
+   * @return {Promise<undefined>} 商品列表
+   */
+  async function getSeckillActivityDetailList(ids) {
+    const { data } = await SeckillApi.getSeckillActivityListByIds(ids);
+    return data;
+  }
+
+  /**
+   * 根据商品编号,获取商品详情
+   * @param ids 商品编号列表
+   * @return {Promise<undefined>} 商品列表
+   */
+  async function getSpuDetail(ids) {
+    const { data: spu } = await SpuApi.getSpuDetail(ids);
+    return spu;
+  }
+
+  // 初始化
   onMounted(async () => {
   onMounted(async () => {
-    // todo:@owen 与Yudao结构不一致,待重构
-    const { data: activity } = await SeckillApi.getSeckillActivity(props.data.activityId);
-    const { data: spu } = await SpuApi.getSpuDetail(activity.spuId)
-    productList.value = [spu];
+    // 加载活动列表
+    const activityList = await getSeckillActivityDetailList(activityIds.join(','));
+    // 循环获取活动商品SPU详情并添加到spuList
+    for (const activity of activityList) {
+      state.spuList.push(await getSpuDetail(activity.spuId));
+    }
+
+    // 循环活动列表
+    activityList.forEach((activity) => {
+      // 提取活动价格
+      const seckillPrice = activity.seckillPrice || Infinity;
+      // 查找对应的 spu 并更新价格
+      const spu = state.spuList.find((spu) => activity.spuId === spu.id);
+      if (spu) {
+        // 赋值最低价格
+        spu.price = Math.min(seckillPrice, spu.price);
+        // 赋值活动ID,为了点击跳转详情页
+        spu.activityId = activity.id;
+      }
+    });
+
+    // 只有双列布局时需要
+    if (layoutType === LayoutTypeEnum.TWO_COL) {
+      // 分列
+      calculateGoodsColumn();
+    }
   });
   });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  .header-box {
-    height: 100rpx;
+  .goods-md-wrap {
+    width: 100%;
   }
   }
 
 
-  .goods-list {
-    position: relative;
-    &:nth-last-child(1) {
+  .goods-list-box {
+    width: 50%;
+    box-sizing: border-box;
+
+    .left-list {
+      &:nth-last-child(1) {
+        margin-bottom: 0 !important;
+      }
+    }
+
+    .right-list {
+      &:nth-last-child(1) {
+        margin-bottom: 0 !important;
+      }
+    }
+  }
+
+  .goods-box {
+    &:nth-last-of-type(1) {
       margin-bottom: 0 !important;
       margin-bottom: 0 !important;
     }
     }
+  }
+
+  .goods-md-box,
+  .goods-sl-box,
+  .goods-lg-box {
+    position: relative;
+
     .cart-btn {
     .cart-btn {
       position: absolute;
       position: absolute;
-      bottom: 10rpx;
+      bottom: 18rpx;
       right: 20rpx;
       right: 20rpx;
       z-index: 11;
       z-index: 11;
       height: 50rpx;
       height: 50rpx;
@@ -147,14 +322,4 @@
       color: #fff;
       color: #fff;
     }
     }
   }
   }
-  .goods-sm-box {
-    margin: 0 auto;
-    box-sizing: border-box;
-    .goods-card-box {
-      flex-shrink: 0;
-      overflow: hidden;
-      width: 33.3%;
-      box-sizing: border-box;
-    }
-  }
 </style>
 </style>

+ 49 - 13
sheep/components/s-select-groupon-sku/s-select-groupon-sku.vue

@@ -5,7 +5,11 @@
     <view class="ss-modal-box bg-white ss-flex-col">
     <view class="ss-modal-box bg-white ss-flex-col">
       <view class="modal-header ss-flex ss-col-center">
       <view class="modal-header ss-flex ss-col-center">
         <view class="header-left ss-m-r-30">
         <view class="header-left ss-m-r-30">
-          <image class="sku-image" :src="sheep.$url.cdn(state.selectedSku.picUrl || goodsInfo.picUrl)" mode="aspectFill" />
+          <image
+            class="sku-image"
+            :src="sheep.$url.cdn(state.selectedSku.picUrl || goodsInfo.picUrl)"
+            mode="aspectFill"
+          />
         </view>
         </view>
         <view class="header-right ss-flex-col ss-row-between ss-flex-1">
         <view class="header-right ss-flex-col ss-row-between ss-flex-1">
           <view class="goods-title ss-line-2">
           <view class="goods-title ss-line-2">
@@ -22,7 +26,13 @@
             </view>
             </view>
           </view>
           </view>
           <view class="header-right-bottom ss-flex ss-col-center ss-row-between">
           <view class="header-right-bottom ss-flex ss-col-center ss-row-between">
-            <view class="price-text"> {{ fen2yuan(goodsInfo.price) }}</view>
+            <view class="price-text">
+              {{
+                fen2yuan(
+                  state.selectedSku.price || goodsInfo.price || state.selectedSku.marketPrice,
+                )
+              }}</view
+            >
 
 
             <view class="stock-text ss-m-l-20">
             <view class="stock-text ss-m-l-20">
               库存{{ state.selectedSku.stock || goodsInfo.stock }}件
               库存{{ state.selectedSku.stock || goodsInfo.stock }}件
@@ -35,22 +45,35 @@
           <view class="sku-item ss-m-b-20" v-for="property in propertyList" :key="property.id">
           <view class="sku-item ss-m-b-20" v-for="property in propertyList" :key="property.id">
             <view class="label-text ss-m-b-20">{{ property.name }}</view>
             <view class="label-text ss-m-b-20">{{ property.name }}</view>
             <view class="ss-flex ss-col-center ss-flex-wrap">
             <view class="ss-flex ss-col-center ss-flex-wrap">
-              <button class="ss-reset-button spec-btn" v-for="value in property.values" :class="[
+              <button
+                class="ss-reset-button spec-btn"
+                v-for="value in property.values"
+                :class="[
                   {
                   {
                     'checked-btn': state.currentPropertyArray[property.id] === value.id,
                     'checked-btn': state.currentPropertyArray[property.id] === value.id,
                   },
                   },
                   {
                   {
                     'disabled-btn': value.disabled === true,
                     'disabled-btn': value.disabled === true,
                   },
                   },
-                ]" :key="value.id" :disabled="value.disabled === true" @tap="onSelectSku(property.id, value.id)">
+                ]"
+                :key="value.id"
+                :disabled="value.disabled === true"
+                @tap="onSelectSku(property.id, value.id)"
+              >
                 {{ value.name }}
                 {{ value.name }}
               </button>
               </button>
             </view>
             </view>
           </view>
           </view>
           <view class="buy-num-box ss-flex ss-col-center ss-row-between">
           <view class="buy-num-box ss-flex ss-col-center ss-row-between">
             <view class="label-text">购买数量</view>
             <view class="label-text">购买数量</view>
-            <su-number-box :min="1" :max="state.selectedSku.stock" :step="1"
-                           v-model="state.selectedSku.count" @change="onNumberChange($event)" activity="groupon" />
+            <su-number-box
+              :min="1"
+              :max="state.selectedSku.stock"
+              :step="1"
+              v-model="state.selectedSku.count"
+              @change="onNumberChange($event)"
+              activity="groupon"
+            />
           </view>
           </view>
         </scroll-view>
         </scroll-view>
       </view>
       </view>
@@ -63,7 +86,16 @@
               <view class="btn-title">{{ grouponNum + '人团' }}</view>
               <view class="btn-title">{{ grouponNum + '人团' }}</view>
             </button>
             </button>
             <button class="ss-reset-button btn-tox ss-flex-col" @tap="onBuy">
             <button class="ss-reset-button btn-tox ss-flex-col" @tap="onBuy">
-              <view class="btn-price">{{ fen2yuan(goodsInfo.price) }}</view>
+              <view class="btn-price">
+                {{
+                  fen2yuan(
+                    state.selectedSku.price * state.selectedSku.count ||
+                      goodsInfo.price * state.selectedSku.count ||
+                      state.selectedSku.marketPrice * state.selectedSku.count ||
+                      goodsInfo.price,
+                  )
+                }}
+              </view>
               <view v-if="grouponAction === 'create'">立即开团</view>
               <view v-if="grouponAction === 'create'">立即开团</view>
               <view v-else-if="grouponAction === 'join'">参与拼团</view>
               <view v-else-if="grouponAction === 'join'">参与拼团</view>
             </button>
             </button>
@@ -77,7 +109,7 @@
 <script setup>
 <script setup>
   import { computed, reactive, watch } from 'vue';
   import { computed, reactive, watch } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
-  import {convertProductPropertyList, fen2yuan} from '@/sheep/hooks/useGoods';
+  import { convertProductPropertyList, fen2yuan } from '@/sheep/hooks/useGoods';
 
 
   const headerBg = sheep.$url.css('/static/img/shop/goods/groupon-btn-long.png');
   const headerBg = sheep.$url.css('/static/img/shop/goods/groupon-btn-long.png');
   const emits = defineEmits(['change', 'addCart', 'buy', 'close', 'ladder']);
   const emits = defineEmits(['change', 'addCart', 'buy', 'close', 'ladder']);
@@ -88,7 +120,7 @@
     },
     },
     goodsInfo: {
     goodsInfo: {
       type: Object,
       type: Object,
-      default () {},
+      default() {},
     },
     },
     grouponAction: {
     grouponAction: {
       type: String,
       type: String,
@@ -111,7 +143,7 @@
   const skuList = computed(() => {
   const skuList = computed(() => {
     let skuPrices = props.goodsInfo.skus;
     let skuPrices = props.goodsInfo.skus;
     for (let price of skuPrices) {
     for (let price of skuPrices) {
-      price.value_id_array = price.properties.map((item) => item.valueId)
+      price.value_id_array = price.properties.map((item) => item.valueId);
     }
     }
     return skuPrices;
     return skuPrices;
   });
   });
@@ -120,7 +152,8 @@
     () => state.selectedSku,
     () => state.selectedSku,
     (newVal) => {
     (newVal) => {
       emits('change', newVal);
       emits('change', newVal);
-    }, {
+    },
+    {
       immediate: true, // 立即执行
       immediate: true, // 立即执行
       deep: true, // 深度监听
       deep: true, // 深度监听
     },
     },
@@ -215,7 +248,7 @@
       // 如果当前 property id 不存在于有库存的 SKU 中,则禁用
       // 如果当前 property id 不存在于有库存的 SKU 中,则禁用
       for (let valueIndex in propertyList[propertyIndex]['values']) {
       for (let valueIndex in propertyList[propertyIndex]['values']) {
         propertyList[propertyIndex]['values'][valueIndex]['disabled'] =
         propertyList[propertyIndex]['values'][valueIndex]['disabled'] =
-            noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
+          noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
       }
       }
     }
     }
   }
   }
@@ -245,7 +278,10 @@
   function onSelectSku(propertyId, valueId) {
   function onSelectSku(propertyId, valueId) {
     // 清空已选择
     // 清空已选择
     let isChecked = true; // 选中 or 取消选中
     let isChecked = true; // 选中 or 取消选中
-    if (state.currentPropertyArray[propertyId] !== undefined && state.currentPropertyArray[propertyId] === valueId) {
+    if (
+      state.currentPropertyArray[propertyId] !== undefined &&
+      state.currentPropertyArray[propertyId] === valueId
+    ) {
       // 点击已被选中的,删除并填充 ''
       // 点击已被选中的,删除并填充 ''
       isChecked = false;
       isChecked = false;
       state.currentPropertyArray.splice(propertyId, 1, '');
       state.currentPropertyArray.splice(propertyId, 1, '');

+ 1 - 5
sheep/components/s-select-seckill-sku/s-select-seckill-sku.vue

@@ -5,7 +5,7 @@
     <!-- SKU 信息 -->
     <!-- SKU 信息 -->
     <view class="ss-modal-box bg-white ss-flex-col">
     <view class="ss-modal-box bg-white ss-flex-col">
       <view class="modal-header ss-flex ss-col-center">
       <view class="modal-header ss-flex ss-col-center">
-        <!-- 规格图 -->
+        <!-- 规格图 -->
         <view class="header-left ss-m-r-30">
         <view class="header-left ss-m-r-30">
           <image
           <image
             class="sku-image"
             class="sku-image"
@@ -125,10 +125,6 @@
     return skuPrices;
     return skuPrices;
   });
   });
 
 
-  if (!state.goodsInfo.is_sku) {
-    state.selectedSku = state.goodsInfo.skus[0];
-  }
-
   watch(
   watch(
     () => state.selectedSku,
     () => state.selectedSku,
     (newVal) => {
     (newVal) => {

+ 1 - 1
sheep/components/s-share-modal/canvas-poster/index.vue

@@ -66,7 +66,7 @@
     css: {
     css: {
       // 根节点若无尺寸,自动获取父级节点
       // 根节点若无尺寸,自动获取父级节点
       width: sheep.$platform.device.windowWidth * 0.9,
       width: sheep.$platform.device.windowWidth * 0.9,
-      height: 550,
+      height: 600,
     },
     },
     views: [],
     views: [],
   });
   });

+ 5 - 5
sheep/components/s-share-modal/canvas-poster/poster/groupon.js

@@ -82,12 +82,12 @@ const groupon = async (poster) => {
       type: 'text',
       type: 'text',
       text: '2人团',
       text: '2人团',
       css: {
       css: {
-        color: '#ff0000',
-        fontSize: 30,
+        color: '#fff',
+        fontSize: 12,
         fontFamily: 'OPPOSANS',
         fontFamily: 'OPPOSANS',
         position: 'fixed',
         position: 'fixed',
-        left: width * 0.3,
-        top: width * 1.32,
+        left: width * 0.84,
+        top: width * 1.3,
       },
       },
     },
     },
     // #ifndef MP-WEIXIN
     // #ifndef MP-WEIXIN
@@ -96,7 +96,7 @@ const groupon = async (poster) => {
       text: poster.shareInfo.link,
       text: poster.shareInfo.link,
       css: {
       css: {
         position: 'fixed',
         position: 'fixed',
-        left: width * 0.75,
+        left: width * 0.5,
         top: width * 1.3,
         top: width * 1.3,
         width: width * 0.2,
         width: width * 0.2,
         height: width * 0.2,
         height: width * 0.2,

+ 92 - 84
sheep/components/s-title-block/s-title-block.vue

@@ -1,100 +1,108 @@
 <!-- 装修商品组件:标题栏 -->
 <!-- 装修商品组件:标题栏 -->
 <template>
 <template>
-  <view
-    class="ss-title-wrap ss-flex ss-col-center"
-    :class="[state.typeMap[data.textAlign]]"
-    :style="[elStyles]"
-  >
-    <view class="title-content">
-      <!-- 主标题 -->
-      <view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
-      <!-- 副标题 -->
-      <view v-if="data.description" :style="[descStyles]" class="sub-title-text">{{ data.description }}</view>
-    </view>
-    <!-- 查看更多 -->
-    <view v-if="data.more?.show" class="more-box ss-flex ss-col-center" @tap="sheep.$router.go(data.more.url)"
-          :style="{color: data.descriptionColor}">
-      <view class="more-text" v-if="data.more.type !== 'icon'">{{ data.more.text }} </view>
-      <text class="_icon-forward" v-if="data.more.type !== 'text'"></text>
-    </view>
-  </view>
+	<view class="ss-title-wrap ss-flex ss-col-center" :class="[state.typeMap[data.textAlign]]" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
+		<view class="title-content">
+			<!-- 主标题 -->
+			<view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
+			<!-- 副标题 -->
+			<view v-if="data.description" :style="[descStyles]" class="sub-title-text">{{ data.description }}</view>
+		</view>
+		<!-- 查看更多 -->
+		<view v-if="data.more?.show" class="more-box ss-flex ss-col-center" @tap="sheep.$router.go(data.more.url)"
+			:style="{color: data.descriptionColor}">
+			<view class="more-text" v-if="data.more.type !== 'icon'">{{ data.more.text }} </view>
+			<text class="_icon-forward" v-if="data.more.type !== 'text'"></text>
+		</view>
+	</view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  /**
-   * 标题栏
-   */
-  import { reactive } from 'vue';
-  import sheep from '@/sheep';
+	/**
+	 * 标题栏
+	 */
+	import {
+		reactive,
+		computed
+	} from 'vue';
+	import sheep from '@/sheep';
 
 
-  // 数据
-  const state = reactive({
-    typeMap: {
-      left: 'ss-row-left',
-      center: 'ss-row-center',
-    },
-  });
+	// 数据
+	const state = reactive({
+		typeMap: {
+			left: 'ss-row-left',
+			center: 'ss-row-center',
+		},
+	});
 
 
-  // 接收参数
-  const props = defineProps({
-    data: {
-      type: Object,
-      default() {},
-    },
-    styles: {
-      type: Object,
-      default() {},
-    },
-  });
+	// 接收参数
+	const props = defineProps({
+		// 装修数据
+		data: {
+			type: Object,
+			default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+			type: Object,
+			default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+		// 直接从 props.styles 解构
+		const {
+			bgType,
+			bgImg,
+			bgColor
+		} = props.styles;
 
 
-  // 组件样式
-  const elStyles = {
-    background: `url(${sheep.$url.cdn(props.data.bgImgUrl)}) no-repeat top center / 100% auto`,
-    fontSize: `${props.data.titleSize}px`,
-    fontWeight: `${props.data.titleWeight}px`,
-  };
+		// 根据 bgType 返回相应的样式
+		return {
+			background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
+		};
+	});
 
 
-  // 标题样式
-  const titleStyles = {
-    color: props.data.titleColor,
-    fontSize: `${props.data.titleSize}px`,
-    textAlign: props.data.textAlign
-  };
+	// 标题样式
+	const titleStyles = {
+		color: props.data.titleColor,
+		fontSize: `${props.data.titleSize}px`,
+		textAlign: props.data.textAlign
+	};
 
 
-  // 副标题
-  const descStyles = {
-    color: props.data.descriptionColor,
-    textAlign: props.data.textAlign,
-    fontSize: `${props.data.descriptionSize}px`,
-    fontWeight: `${props.data.descriptionWeight}px`,
-  };
+	// 副标题
+	const descStyles = {
+		color: props.data.descriptionColor,
+		textAlign: props.data.textAlign,
+		fontSize: `${props.data.descriptionSize}px`,
+		fontWeight: `${props.data.descriptionWeight}px`,
+	};
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  .ss-title-wrap {
-    height: 80rpx;
-    position: relative;
+	.ss-title-wrap {
+		height: 80rpx;
+		position: relative;
 
 
-    .title-content {
-      .title-text {
-        font-size: 30rpx;
-        color: #333;
-      }
+		.title-content {
+			.title-text {
+				font-size: 30rpx;
+				color: #333;
+			}
 
 
-      .sub-title-text {
-        font-size: 22rpx;
-        color: #999;
-      }
-    }
+			.sub-title-text {
+				font-size: 22rpx;
+				color: #999;
+			}
+		}
 
 
-    .more-box {
-      white-space: nowrap;
-      font-size: 22rpx;
-      color: #999;
-      position: absolute;
-      top: 50%;
-      transform: translateY(-50%);
-      right: 20rpx;
-    }
-  }
-</style>
+		.more-box {
+			white-space: nowrap;
+			font-size: 22rpx;
+			color: #999;
+			position: absolute;
+			top: 50%;
+			transform: translateY(-50%);
+			right: 20rpx;
+		}
+	}
+</style>

+ 166 - 148
sheep/components/s-user-card/s-user-card.vue

@@ -1,167 +1,185 @@
 <!-- 装修用户组件:用户卡片 -->
 <!-- 装修用户组件:用户卡片 -->
 <template>
 <template>
-	<view class="ss-user-info-wrap ss-p-t-50">
-		<view class="ss-flex ss-col-center ss-row-between ss-m-b-20">
-			<view class="left-box ss-flex ss-col-center ss-m-l-36">
-				<view class="avatar-box ss-m-r-24">
-					<image class="avatar-img" :src="
+  <view class="ss-user-info-wrap ss-p-t-50" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
+    <view class="ss-flex ss-col-center ss-row-between ss-m-b-20">
+      <view class="left-box ss-flex ss-col-center ss-m-l-36">
+        <view class="avatar-box ss-m-r-24">
+          <image class="avatar-img" :src="
               isLogin
               isLogin
                 ? sheep.$url.cdn(userInfo.avatar)
                 ? sheep.$url.cdn(userInfo.avatar)
-                : sheep.$url.static('/static/img/shop/default_avatar.png')
-            " mode="aspectFill" @tap="sheep.$router.go('/pages/user/info')"></image>
-				</view>
-				<view>
-					<view class="nickname-box ss-flex ss-col-center">
-						<view class="nick-name ss-m-r-20">{{ userInfo?.nickname || nickname }}</view>
-					</view>
-				</view>
-			</view>
-			<view class="right-box ss-m-r-52">
-				<button class="ss-reset-button" @tap="showShareModal">
-					<text class="sicon-qrcode"></text>
-				</button>
-			</view>
-		</view>
-
-		<!-- 提示绑定手机号 先隐藏 yudao 需要再修改 -->
-		<view
+                : sheep.$url.static('/static/img/shop/default_avatar.png')"
+                 mode="aspectFill" @tap="sheep.$router.go('/pages/user/info')">
+          </image>
+        </view>
+        <view>
+          <view class="nickname-box ss-flex ss-col-center">
+            <view class="nick-name ss-m-r-20">{{ userInfo?.nickname || nickname }}</view>
+          </view>
+        </view>
+      </view>
+      <view class="right-box ss-m-r-52">
+        <button class="ss-reset-button" @tap="showShareModal">
+          <text class="sicon-qrcode"></text>
+        </button>
+      </view>
+    </view>
+
+    <!-- 提示绑定手机号 先隐藏 yudao 需要再修改 -->
+    <view
       class="bind-mobile-box ss-flex ss-row-between ss-col-center"
       class="bind-mobile-box ss-flex ss-row-between ss-col-center"
       v-if="isLogin && !userInfo.mobile"
       v-if="isLogin && !userInfo.mobile"
     >
     >
       <view class="ss-flex">
       <view class="ss-flex">
         <text class="cicon-mobile-o" />
         <text class="cicon-mobile-o" />
-        <view class="mobile-title ss-m-l-20"> 点击绑定手机号确保账户安全 </view>
+        <view class="mobile-title ss-m-l-20"> 点击绑定手机号确保账户安全</view>
       </view>
       </view>
       <button class="ss-reset-button bind-btn" @tap="onBind">去绑定</button>
       <button class="ss-reset-button bind-btn" @tap="onBind">去绑定</button>
     </view>
     </view>
-	</view>
+  </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	/**
-	 * 用户卡片
-	 *
-	 * @property {Number} leftSpace 									- 容器左间距
-	 * @property {Number} rightSpace 									- 容器右间距
-	 *
-	 * @property {String} avatar 					- 头像
-	 * @property {String} nickname 					- 昵称
-	 * @property {String} vip		  				- 等级
-	 * @property {String} collectNum 				- 收藏数
-	 * @property {String} likeNum 					- 点赞数
-	 *
-	 *
-	 */
-	import {
-		computed,
-		reactive
-	} from 'vue';
-	import sheep from '@/sheep';
-	import {
-		showShareModal,
-		showAuthModal
-	} from '@/sheep/hooks/useModal';
-
-	// 用户信息
-	const userInfo = computed(() => sheep.$store('user').userInfo);
-	console.log('用户信息', userInfo)
-
-	// 是否登录
-	const isLogin = computed(() => sheep.$store('user').isLogin);
-	// 接收参数
-	const props = defineProps({
-		background: {
-			type: String,
-			default: '',
-		},
-		// 头像
-		avatar: {
-			type: String,
-			default: '',
-		},
-		nickname: {
-			type: String,
-			default: '请先登录',
-		},
-		vip: {
-			type: [String, Number],
-			default: '1',
-		},
-		collectNum: {
-			type: [String, Number],
-			default: '1',
-		},
-		likeNum: {
-			type: [String, Number],
-			default: '1',
-		},
-	});
-
-	function onBind() {
-		showAuthModal('changeMobile');
-	}
+  /**
+   * 用户卡片
+   *
+   * @property {Number} leftSpace                  - 容器左间距
+   * @property {Number} rightSpace                  - 容器右间距
+   *
+   * @property {String} avatar          - 头像
+   * @property {String} nickname          - 昵称
+   * @property {String} vip              - 等级
+   * @property {String} collectNum        - 收藏数
+   * @property {String} likeNum          - 点赞数
+   *
+   *
+   */
+  import { computed } from 'vue';
+  import sheep from '@/sheep';
+  import {
+    showShareModal,
+    showAuthModal,
+  } from '@/sheep/hooks/useModal';
+
+  // 用户信息
+  const userInfo = computed(() => sheep.$store('user').userInfo);
+  console.log('用户信息', userInfo);
+
+  // 是否登录
+  const isLogin = computed(() => sheep.$store('user').isLogin);
+  // 接收参数
+  const props = defineProps({
+    // 装修数据
+    data: {
+      type: Object,
+      default: () => ({}),
+    },
+    // 装修样式
+    styles: {
+      type: Object,
+      default: () => ({}),
+    },
+    // 头像
+    avatar: {
+      type: String,
+      default: '',
+    },
+    nickname: {
+      type: String,
+      default: '请先登录',
+    },
+    vip: {
+      type: [String, Number],
+      default: '1',
+    },
+    collectNum: {
+      type: [String, Number],
+      default: '1',
+    },
+    likeNum: {
+      type: [String, Number],
+      default: '1',
+    },
+  });
+
+  // 设置背景样式
+  const bgStyle = computed(() => {
+    // 直接从 props.styles 解构
+    const { bgType, bgImg, bgColor } = props.styles;
+
+    // 根据 bgType 返回相应的样式
+    return {
+      background: bgType === 'img'
+        ? `url(${bgImg}) no-repeat top center / 100% 100%`
+        : bgColor,
+    };
+  });
+
+  // 绑定手机号
+  function onBind() {
+    showAuthModal('changeMobile');
+  }
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	.ss-user-info-wrap {
-		box-sizing: border-box;
-
-		.avatar-box {
-			width: 100rpx;
-			height: 100rpx;
-			border-radius: 50%;
-			overflow: hidden;
-
-			.avatar-img {
-				width: 100%;
-				height: 100%;
-			}
-		}
-
-		.nick-name {
-			font-size: 34rpx;
-			font-weight: 400;
-			color: #333333;
-			line-height: normal;
-		}
-
-		.vip-img {
-			width: 30rpx;
-			height: 30rpx;
-		}
-
-		.sicon-qrcode {
-			font-size: 40rpx;
-		}
-	}
-
-	.bind-mobile-box {
-		width: 100%;
-		height: 84rpx;
-		padding: 0 34rpx 0 44rpx;
-		box-sizing: border-box;
-		background: #ffffff;
-		box-shadow: 0px -8rpx 9rpx 0px rgba(#e0e0e0, 0.3);
-
-		.cicon-mobile-o {
-			font-size: 30rpx;
-			color: #ff690d;
-		}
-
-		.mobile-title {
-			font-size: 24rpx;
-			font-weight: 500;
-			color: #ff690d;
-		}
-
-		.bind-btn {
-			width: 100rpx;
-			height: 50rpx;
-			background: #ff6100;
-			border-radius: 25rpx;
-			font-size: 24rpx;
-			font-weight: 500;
-			color: #ffffff;
-		}
-	}
+  .ss-user-info-wrap {
+    box-sizing: border-box;
+
+    .avatar-box {
+      width: 100rpx;
+      height: 100rpx;
+      border-radius: 50%;
+      overflow: hidden;
+
+      .avatar-img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    .nick-name {
+      font-size: 34rpx;
+      font-weight: 400;
+      color: #333333;
+      line-height: normal;
+    }
+
+    .vip-img {
+      width: 30rpx;
+      height: 30rpx;
+    }
+
+    .sicon-qrcode {
+      font-size: 40rpx;
+    }
+  }
+
+  .bind-mobile-box {
+    width: 100%;
+    height: 84rpx;
+    padding: 0 34rpx 0 44rpx;
+    box-sizing: border-box;
+    background: #ffffff;
+    box-shadow: 0px -8rpx 9rpx 0px rgba(#e0e0e0, 0.3);
+
+    .cicon-mobile-o {
+      font-size: 30rpx;
+      color: #ff690d;
+    }
+
+    .mobile-title {
+      font-size: 24rpx;
+      font-weight: 500;
+      color: #ff690d;
+    }
+
+    .bind-btn {
+      width: 100rpx;
+      height: 50rpx;
+      background: #ff6100;
+      border-radius: 25rpx;
+      font-size: 24rpx;
+      font-weight: 500;
+      color: #ffffff;
+    }
+  }
 </style>
 </style>

+ 28 - 2
sheep/components/s-wallet-card/s-wallet-card.vue

@@ -1,6 +1,6 @@
 <!-- 装修用户组件:用户资产 -->
 <!-- 装修用户组件:用户资产 -->
 <template>
 <template>
-	<view class="ss-wallet-menu-wrap ss-flex ss-col-center">
+	<view class="ss-wallet-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
 		<view class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
 		<view class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
 			@tap="sheep.$router.go('/pages/user/wallet/money')">
 			@tap="sheep.$router.go('/pages/user/wallet/money')">
 			<view class="value-box ss-flex ss-col-bottom">
 			<view class="value-box ss-flex ss-col-bottom">
@@ -42,8 +42,34 @@
 	 */
 	 */
 	import { computed } from 'vue';
 	import { computed } from 'vue';
 	import sheep from '@/sheep';
 	import sheep from '@/sheep';
-  import { fen2yuan } from '../../hooks/useGoods';
+	import { fen2yuan } from '../../hooks/useGoods';
 
 
+	// 接收参数
+	const props = defineProps({
+		// 装修数据
+		data: {
+		  type: Object,
+		  default: () => ({}),
+		},
+		// 装修样式
+		styles: {
+		  type: Object,
+		  default: () => ({}),
+		},
+	});
+	// 设置背景样式
+	const bgStyle = computed(() => {
+	  // 直接从 props.styles 解构
+	  const { bgType, bgImg, bgColor } = props.styles; 
+	
+	  // 根据 bgType 返回相应的样式
+	  return {
+		background: bgType === 'img'
+			? `url(${bgImg}) no-repeat top center / 100% 100%`
+			: bgColor
+		};
+	});
+	
 	const userWallet = computed(() => sheep.$store('user').userWallet);
 	const userWallet = computed(() => sheep.$store('user').userWallet);
 	const userInfo = computed(() => sheep.$store('user').userInfo);
 	const userInfo = computed(() => sheep.$store('user').userInfo);
 	const numData = computed(() => sheep.$store('user').numData);
 	const numData = computed(() => sheep.$store('user').numData);

+ 1 - 1
sheep/helper/index.js

@@ -621,7 +621,7 @@ function setProperty(obj, key, value) {
 function page() {
 function page() {
   const pages = getCurrentPages();
   const pages = getCurrentPages();
   // 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
   // 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
-  return `/${pages[pages.length - 1]?.route ?? ''}`;
+  return `/${pages[pages.length - 1]?.route || ''}`;
 }
 }
 
 
 /**
 /**

+ 5 - 1
sheep/helper/utils.js

@@ -23,6 +23,10 @@ export function isString(value) {
 }
 }
 
 
 export function isEmpty(value) {
 export function isEmpty(value) {
+  if (value === '' || value === undefined || value === null){
+    return true;
+  }
+
   if (isArray(value)) {
   if (isArray(value)) {
     return value.length === 0;
     return value.length === 0;
   }
   }
@@ -31,7 +35,7 @@ export function isEmpty(value) {
     return Object.keys(value).length === 0;
     return Object.keys(value).length === 0;
   }
   }
 
 
-  return value === '' || value === undefined || value === null;
+  return false
 }
 }
 
 
 export function isBoolean(value) {
 export function isBoolean(value) {

+ 1 - 1
sheep/hooks/useModal.js

@@ -14,7 +14,7 @@ export function showAuthModal(type = 'smsLogin') {
       modal.$patch((state) => {
       modal.$patch((state) => {
         state.auth = type;
         state.auth = type;
       });
       });
-    }, 200);
+    }, 500);
     closeAuthModal();
     closeAuthModal();
   } else {
   } else {
     modal.$patch((state) => {
     modal.$patch((state) => {

+ 8 - 6
sheep/libs/sdk-h5-weixin.js

@@ -1,9 +1,10 @@
 /**
 /**
  * 本模块封装微信浏览器下的一些方法。
  * 本模块封装微信浏览器下的一些方法。
  * 更多微信网页开发sdk方法,详见:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
  * 更多微信网页开发sdk方法,详见:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
+ * 有 the permission value is offline verifying 报错请参考 @see https://segmentfault.com/a/1190000042289419 解决
  */
  */
 
 
-import jweixin, { ready } from 'weixin-js-sdk';
+import jweixin from 'weixin-js-sdk';
 import $helper from '@/sheep/helper';
 import $helper from '@/sheep/helper';
 import AuthUtil from '@/sheep/api/member/auth';
 import AuthUtil from '@/sheep/api/member/auth';
 
 
@@ -38,7 +39,7 @@ export default {
         timestamp: data.timestamp,
         timestamp: data.timestamp,
         nonceStr: data.nonceStr,
         nonceStr: data.nonceStr,
         signature: data.signature,
         signature: data.signature,
-        jsApiList: ['chooseWXPay'], // TODO 芋艿:后续可以设置更多权限;
+        jsApiList: ['chooseWXPay', 'openLocation', 'getLocation','updateTimelineShareData','scanQRCode'], // TODO 芋艿:后续可以设置更多权限;
         openTagList: data.openTagList
         openTagList: data.openTagList
       });
       });
     }
     }
@@ -77,7 +78,7 @@ export default {
     });
     });
   },
   },
 
 
-  //获取微信收货地址 TODO 芋艿:未测试
+  // 获取微信收货地址
   openAddress(callback) {
   openAddress(callback) {
     this.isReady(() => {
     this.isReady(() => {
       jweixin.openAddress({
       jweixin.openAddress({
@@ -137,9 +138,10 @@ export default {
   openLocation(data, callback) {
   openLocation(data, callback) {
     this.isReady(() => {
     this.isReady(() => {
       jweixin.openLocation({
       jweixin.openLocation({
-        //根据传入的坐标打开地图
-        latitude: data.latitude,
-        longitude: data.longitude,
+        ...data,
+        success: function (res) {
+          console.log(res);
+        }
       });
       });
     });
     });
   },
   },

+ 0 - 1
sheep/platform/provider/wechat/miniProgram.js

@@ -53,7 +53,6 @@ const mobileLogin = async (e) => {
     } else {
     } else {
       return resolve(false);
       return resolve(false);
     }
     }
-    // TODO 芋艿:shareInfo: uni.getStorageSync('shareLog') || {},
   });
   });
 };
 };
 
 

+ 1 - 2
sheep/platform/provider/wechat/officialAccount.js

@@ -24,7 +24,6 @@ async function login(code = '', state = '') {
     // 解密 code 发起登陆
     // 解密 code 发起登陆
     const loginResult = await AuthUtil.socialLogin(socialType, code, state);
     const loginResult = await AuthUtil.socialLogin(socialType, code, state);
     if (loginResult.code === 0) {
     if (loginResult.code === 0) {
-      // TODO 芋艿:shareLog
       setOpenid(loginResult.data.openid);
       setOpenid(loginResult.data.openid);
       return loginResult;
       return loginResult;
     }
     }
@@ -103,5 +102,5 @@ export default {
   unbind,
   unbind,
   getInfo,
   getInfo,
   getOpenid,
   getOpenid,
-  jssdk: $wxsdk,
+  jsWxSdk: $wxsdk,
 };
 };

+ 3 - 2
sheep/platform/share.js

@@ -178,7 +178,7 @@ const decryptSpm = (spm) => {
 };
 };
 
 
 // 绑定推广员
 // 绑定推广员
-const bindBrokerageUser = async (val= undefined) => {
+const bindBrokerageUser = async (val = undefined) => {
   try {
   try {
     const shareId = val || uni.getStorageSync('shareId');
     const shareId = val || uni.getStorageSync('shareId');
     if (!shareId) {
     if (!shareId) {
@@ -186,7 +186,8 @@ const bindBrokerageUser = async (val= undefined) => {
     }
     }
     await BrokerageApi.bindBrokerageUser({ bindUserId: shareId });
     await BrokerageApi.bindBrokerageUser({ bindUserId: shareId });
     uni.removeStorageSync('shareId');
     uni.removeStorageSync('shareId');
-  } catch {
+  } catch (e) {
+    console.error(e);
   }
   }
 };
 };
 
 

+ 2 - 4
sheep/request/index.js

@@ -9,7 +9,7 @@ import $store from '@/sheep/store';
 import $platform from '@/sheep/platform';
 import $platform from '@/sheep/platform';
 import { showAuthModal } from '@/sheep/hooks/useModal';
 import { showAuthModal } from '@/sheep/hooks/useModal';
 import AuthUtil from '@/sheep/api/member/auth';
 import AuthUtil from '@/sheep/api/member/auth';
-import { getTerminalEnumByUniPlatform } from '@/sheep/util/const';
+import { getTerminal } from '@/sheep/util/const';
 
 
 const options = {
 const options = {
 	// 显示操作成功消息 默认不显示
 	// 显示操作成功消息 默认不显示
@@ -94,9 +94,7 @@ http.interceptors.request.use(
 		if (token) {
 		if (token) {
 			config.header['Authorization'] = token;
 			config.header['Authorization'] = token;
 		}
 		}
-
-		const terminalType = uni.getSystemInfoSync().uniPlatform
-		config.header['terminal'] = getTerminalEnumByUniPlatform(terminalType);
+		config.header['terminal'] = getTerminal();
 
 
     config.header['Accept'] = '*/*';
     config.header['Accept'] = '*/*';
     config.header['tenant-id'] = tenantId;
     config.header['tenant-id'] = tenantId;

+ 7 - 1
sheep/store/cart.js

@@ -57,7 +57,13 @@ const cart = defineStore({
 
 
     // 移除购物车
     // 移除购物车
     async delete(ids) {
     async delete(ids) {
-      const { code } = await CartApi.deleteCart(ids.join(','));
+      let idsTemp = '';
+      if (Array.isArray(ids)) {
+        idsTemp = ids.join(',');
+      } else {
+        idsTemp = ids;
+      }
+      const { code } = await CartApi.deleteCart(idsTemp);
       if (code === 0) {
       if (code === 0) {
         await this.getList();
         await this.getList();
       }
       }

+ 9 - 12
sheep/util/const.js

@@ -12,26 +12,23 @@ export const TerminalEnum = {
 };
 };
 
 
 /**
 /**
- * 将Uniapp提供的平台转换为后端所需的Terminal值
- * @param platformType Uniapp提供的平台类型
+ * 将 uni-app 提供的平台转换为后端所需的 terminal值
+ *
+ * @return 终端
  */
  */
-export const getTerminalEnumByUniPlatform = (platformType) => {
-  let terminal;
+export const getTerminal = () => {
+  const platformType = uni.getSystemInfoSync().uniPlatform;
   // 与后端terminal枚举一一对应
   // 与后端terminal枚举一一对应
   switch (platformType) {
   switch (platformType) {
     case 'app':
     case 'app':
-      terminal = TerminalEnum.APP;
-      break;
+      return TerminalEnum.APP;
     case 'web':
     case 'web':
-      terminal = TerminalEnum.H5;
-      break;
+      return TerminalEnum.H5;
     case 'mp-weixin':
     case 'mp-weixin':
-      terminal = TerminalEnum.WECHAT_MINI_PROGRAM;
-      break;
+      return TerminalEnum.WECHAT_MINI_PROGRAM;
     default:
     default:
-      terminal = TerminalEnum.UNKNOWN;
+      return TerminalEnum.UNKNOWN;
   }
   }
-  return terminal;
 };
 };
 
 
 // ========== MALL - 营销模块 ==========
 // ========== MALL - 营销模块 ==========

BIN
static/images/line.png


BIN
static/images/writeOff.png