vhall-mini-sdk 0.4.1 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/components/gift/gift-display/gift-display.js +118 -0
  2. package/dist/components/gift/gift-display/gift-display.json +3 -0
  3. package/dist/components/gift/gift-display/gift-display.wxml +16 -0
  4. package/dist/components/gift/gift-display/gift-display.wxss +1 -0
  5. package/dist/components/gift/gift-sender/gift-sender.js +63 -0
  6. package/dist/components/gift/gift-sender/gift-sender.json +6 -0
  7. package/dist/components/gift/gift-sender/gift-sender.wxml +19 -0
  8. package/dist/components/gift/gift-sender/gift-sender.wxss +1 -0
  9. package/dist/components/lottery/lottery-accept/index.js +249 -0
  10. package/dist/components/lottery/lottery-accept/index.json +4 -0
  11. package/dist/components/lottery/lottery-accept/index.wxml +49 -0
  12. package/dist/components/lottery/lottery-accept/index.wxss +1 -0
  13. package/dist/components/lottery/lottery-history/index.js +36 -0
  14. package/dist/components/lottery/lottery-history/index.json +3 -0
  15. package/dist/components/lottery/lottery-history/index.wxml +28 -0
  16. package/dist/components/lottery/lottery-history/index.wxss +1 -0
  17. package/dist/components/lottery/lottery-shake/lottery-shake.js +328 -0
  18. package/dist/components/lottery/lottery-shake/lottery-shake.json +1 -0
  19. package/dist/components/lottery/lottery-shake/lottery-shake.wxml +52 -0
  20. package/dist/components/lottery/lottery-shake/lottery-shake.wxss +1 -0
  21. package/dist/components/lottery/lottery-slot/lottery-slot.js +230 -0
  22. package/dist/components/lottery/lottery-slot/lottery-slot.json +1 -0
  23. package/dist/components/lottery/lottery-slot/lottery-slot.wxml +62 -0
  24. package/dist/components/lottery/lottery-slot/lottery-slot.wxss +1 -0
  25. package/dist/components/lottery/lottery-wheel/lottery-wheel.js +153 -0
  26. package/dist/components/lottery/lottery-wheel/lottery-wheel.json +4 -0
  27. package/dist/components/lottery/lottery-wheel/lottery-wheel.wxml +91 -0
  28. package/dist/components/lottery/lottery-wheel/lottery-wheel.wxss +1 -0
  29. package/dist/components/lottery/lottery-winners/index.js +101 -0
  30. package/dist/components/lottery/lottery-winners/index.json +4 -0
  31. package/dist/components/lottery/lottery-winners/index.wxml +39 -0
  32. package/dist/components/lottery/lottery-winners/index.wxss +1 -0
  33. package/dist/components/lottery/lottery.js +388 -0
  34. package/dist/components/lottery/lottery.json +11 -0
  35. package/dist/components/lottery/lottery.wxml +78 -0
  36. package/dist/components/lottery/lottery.wxss +1 -0
  37. package/dist/components/lottery/wheel.json +49 -0
  38. package/dist/components/mall-reward/common/reward-card.wxss +0 -0
  39. package/dist/components/mall-reward/duration-icon/index.js +101 -0
  40. package/dist/components/mall-reward/duration-icon/index.json +3 -0
  41. package/dist/components/mall-reward/duration-icon/index.wxml +7 -0
  42. package/dist/components/mall-reward/duration-icon/index.wxss +1 -0
  43. package/dist/components/mall-reward/f-count-down/index.js +61 -0
  44. package/dist/components/mall-reward/f-count-down/index.json +3 -0
  45. package/dist/components/mall-reward/f-count-down/index.wxml +9 -0
  46. package/dist/components/mall-reward/f-count-down/index.wxss +1 -0
  47. package/dist/components/mall-reward/f-empty/index.js +11 -0
  48. package/dist/components/mall-reward/f-empty/index.json +3 -0
  49. package/dist/components/mall-reward/f-empty/index.wxml +8 -0
  50. package/dist/components/mall-reward/f-empty/index.wxss +1 -0
  51. package/dist/components/mall-reward/f-history/index.js +84 -0
  52. package/dist/components/mall-reward/f-history/index.json +4 -0
  53. package/dist/components/mall-reward/f-history/index.wxml +38 -0
  54. package/dist/components/mall-reward/f-history/index.wxss +1 -0
  55. package/dist/components/mall-reward/f-open/index.js +36 -0
  56. package/dist/components/mall-reward/f-open/index.json +3 -0
  57. package/dist/components/mall-reward/f-open/index.wxml +10 -0
  58. package/dist/components/mall-reward/f-open/index.wxss +1 -0
  59. package/dist/components/mall-reward/f-receive/index.js +36 -0
  60. package/dist/components/mall-reward/f-receive/index.json +3 -0
  61. package/dist/components/mall-reward/f-receive/index.wxml +9 -0
  62. package/dist/components/mall-reward/f-receive/index.wxss +1 -0
  63. package/dist/components/mall-reward/index.js +374 -0
  64. package/dist/components/mall-reward/index.json +8 -0
  65. package/dist/components/mall-reward/index.wxml +4 -0
  66. package/dist/components/mall-reward/index.wxss +0 -0
  67. package/dist/components/mall-reward/main-popup/index.js +46 -0
  68. package/dist/components/mall-reward/main-popup/index.json +12 -0
  69. package/dist/components/mall-reward/main-popup/index.wxml +16 -0
  70. package/dist/components/mall-reward/main-popup/index.wxss +1 -0
  71. package/dist/components/praise/praise.js +150 -0
  72. package/dist/components/praise/praise.json +5 -0
  73. package/dist/components/praise/praise.wxml +17 -0
  74. package/dist/components/praise/praise.wxss +1 -0
  75. package/dist/components/product/product-card/product-card.js +109 -0
  76. package/dist/components/product/product-card/product-card.json +3 -0
  77. package/dist/components/product/product-card/product-card.wxml +47 -0
  78. package/dist/components/product/product-card/product-card.wxss +1 -0
  79. package/dist/components/product/product-detail/product-detail.js +127 -0
  80. package/dist/components/product/product-detail/product-detail.json +3 -0
  81. package/dist/components/product/product-detail/product-detail.wxml +57 -0
  82. package/dist/components/product/product-detail/product-detail.wxss +1 -0
  83. package/dist/components/product/product-item/product-item.js +56 -0
  84. package/dist/components/product/product-item/product-item.json +3 -0
  85. package/dist/components/product/product-item/product-item.wxml +35 -0
  86. package/dist/components/product/product-item/product-item.wxss +1 -0
  87. package/dist/components/product/product-list/product-list.js +67 -0
  88. package/dist/components/product/product-list/product-list.json +6 -0
  89. package/dist/components/product/product-list/product-list.wxml +16 -0
  90. package/dist/components/product/product-list/product-list.wxss +1 -0
  91. package/dist/components/product/product-order/product-order.js +394 -0
  92. package/dist/components/product/product-order/product-order.json +3 -0
  93. package/dist/components/product/product-order/product-order.wxml +75 -0
  94. package/dist/components/product/product-order/product-order.wxss +1 -0
  95. package/dist/pubComponents/popup/popup.wxss +1 -0
  96. package/dist/sdk/config/index.js +1 -0
  97. package/dist/sdk/plugins/InteractServer.js +1 -0
  98. package/dist/sdk/plugins/LotteryServer.js +1 -0
  99. package/dist/sdk/plugins/MallRewardServer.js +1 -0
  100. package/dist/sdk/plugins/ProductServer.js +1 -0
  101. package/lib/components/live-landscape/live-landscape.js +2 -2
  102. package/lib/components/live-portrait/live-portrait.js +2 -2
  103. package/lib/components/player/components/controls/controls.wxml +6 -3
  104. package/lib/components/player/components/controls/controls.wxss +1 -1
  105. package/lib/components/player/player.wxml +26 -24
  106. package/lib/components/player/player.wxss +1 -1
  107. package/lib/components/product/product-card/product-card.wxml +1 -1
  108. package/lib/sdk/main/index.js +2 -2
  109. package/lib/shared/mpUtils.js +1 -1
  110. package/package.json +1 -1
@@ -0,0 +1,109 @@
1
+ import { appendParamsToPath } from '../../../shared/utils.js';
2
+
3
+ Component({
4
+ properties: {
5
+ // SDK实例
6
+ sdkInstance: {
7
+ type: Object,
8
+ value: null,
9
+ observer: function(newVal) {
10
+ if (newVal) {
11
+ this.initStoreListener();
12
+ // 初始加载商品数据
13
+ const productServer = newVal.get('productServer');
14
+ if (productServer) {
15
+ productServer.getProductList();
16
+ }
17
+ }
18
+ }
19
+ }
20
+ },
21
+ data: {
22
+ // 商品列表数据
23
+ products: []
24
+ },
25
+ lifetimes: {
26
+ attached() {
27
+ },
28
+ detached() {
29
+ // 组件卸载时移除store监听
30
+ if (this.unsub) {
31
+ this.unsub();
32
+ }
33
+ }
34
+ },
35
+ methods: {
36
+ // 初始化store监听
37
+ initStoreListener() {
38
+ if (this.unsub) {
39
+ this.unsub();
40
+ }
41
+
42
+ this.unsub = this.properties.sdkInstance.store.get({
43
+ productList: (val) => {
44
+ if (val) {
45
+ // 只显示 push_status == 1 的商品
46
+ const filteredProducts = val.filter(product => product.push_status === 1);
47
+ // 最多显示3个商品卡片
48
+ const products = filteredProducts.slice(0, 3);
49
+ this.setData({
50
+ products: products
51
+ });
52
+ }
53
+ }
54
+ });
55
+ },
56
+ // 点击商品卡片(打开详情)
57
+ onCardClick(e) {
58
+ const index = parseInt(e.currentTarget.dataset.index);
59
+ const product = this.data.products[index];
60
+ if (product) {
61
+ this.triggerEvent('cardClick', product);
62
+ }
63
+ },
64
+ // 点击购买按钮(走购买逻辑)
65
+ onBuyClick(e) {
66
+ const index = parseInt(e.currentTarget.dataset.index);
67
+ const product = this.data.products[index];
68
+ if (!product) {
69
+ console.error('商品数据不存在');
70
+ return;
71
+ }
72
+
73
+ // 检查是否已抢光或待开价
74
+ if (product.sale_status === 0 || product.covered_status === 1) {
75
+ return;
76
+ }
77
+
78
+ // 检查 buy_type
79
+ if (product.buy_type === 4 && product?.mini_program_config?.mini_program_path) {
80
+ // 跳转到小程序路径
81
+ const webinarId = this.properties.sdkInstance.store.get('webinarId');
82
+ console.log("跳转小程序路径:", appendParamsToPath(product?.mini_program_config?.mini_program_path, { webinarId }))
83
+ wx.navigateTo({
84
+ url: appendParamsToPath(product?.mini_program_config?.mini_program_path, { webinarId })
85
+ });
86
+ } else if (product.buy_type === 1) {
87
+ // 触发购买事件,由父组件显示下单弹窗
88
+ this.triggerEvent('buyClick', product);
89
+ } else {
90
+ // 提示无法购买
91
+ wx.showToast({
92
+ title: '无法购买,请联系主办方',
93
+ icon: 'none',
94
+ duration: 2000
95
+ });
96
+ }
97
+ },
98
+ // 点击关闭按钮(通过改变本地数据关闭卡片)
99
+ onCloseCard(e) {
100
+ const productId = e.currentTarget.dataset.productId;
101
+
102
+ // 从本地数据中移除该商品
103
+ const updatedProducts = this.data.products.filter(product => product.goods_id !== productId);
104
+ this.setData({
105
+ products: updatedProducts
106
+ });
107
+ }
108
+ }
109
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "component": true
3
+ }
@@ -0,0 +1,47 @@
1
+ <view class="product-card-container">
2
+ <block wx:for="{{products}}" wx:key="{{item.goods_id}}">
3
+ <view
4
+ class="product-card {{(item.sale_status === 0 || item.covered_status === 1) ? 'product-card-disabled' : ''}} {{products.length > 1 ? 'product-card-small' : ''}}"
5
+ >
6
+ <!-- 讲解中徽章 -->
7
+ <view class="product-card-badge">
8
+ <image class="product-card-badge-icon" src="https://cnstatic01.e.vhall.com/common-static/saas-wap/static/img/live.b07d13f4.gif" mode="heightFix"></image>
9
+ 讲解中
10
+ </view>
11
+
12
+ <!-- 关闭按钮 -->
13
+ <view class="product-card-close" bindtap="onCloseCard" data-product-id="{{item.goods_id}}">x</view>
14
+
15
+ <!-- 商品图片(点击打开详情) -->
16
+ <view class="product-card-image" bindtap="onCardClick" data-index="{{index}}">
17
+ <image class="product-card-img"
18
+ src="{{item.cover_img || 'https://cnstatic01.e.vhall.com/common-static/images/default_avatar.png'}}"
19
+ mode="aspectFill"
20
+ ></image>
21
+ <!-- 已抢光遮罩层 -->
22
+ <view wx:if="{{item.sale_status === 0}}" class="product-card-mask">
23
+ <text class="product-card-mask-text">已抢光</text>
24
+ </view>
25
+ </view>
26
+
27
+ <!-- 商品信息 -->
28
+ <view class="product-card-info">
29
+ <!-- 商品名称(点击打开详情) -->
30
+ <text class="product-card-title" bindtap="onCardClick" data-index="{{index}}">{{item.name || '商品名称'}}</text>
31
+
32
+ <!-- 价格和购买按钮 -->
33
+ <view class="product-card-price-container" bindtap="onBuyClick" data-index="{{index}}">
34
+
35
+ <block wx:if="{{item.covered_status === 1}}">
36
+ <text class="product-card-price">¥?</text>
37
+ </block>
38
+ <block wx:else>
39
+ <text class="product-card-price">¥{{item.discount_price || item.price || 0}}</text>
40
+ </block>
41
+
42
+ <image class="buy-icon" src="//cnstatic01.e.vhall.com/common-static/saas-wap/static/img/rob.4306d2b5.png" mode="heightFix" ></image>
43
+ </view>
44
+ </view>
45
+ </view>
46
+ </block>
47
+ </view>
@@ -0,0 +1 @@
1
+ .product-card-container{align-items:flex-end;bottom:180rpx;display:flex;flex-direction:column;gap:16rpx;position:fixed;right:20rpx;z-index:999}.product-card{animation:slideIn .3s ease-out forwards;background-color:#fff;border-radius:12rpx;box-shadow:0 4rpx 12rpx rgba(0,0,0,.15);opacity:0;overflow:hidden;position:relative;transform:translateX(100%);width:240rpx}.product-card:first-child{animation-delay:0s}.product-card:nth-child(2){animation-delay:.1s}.product-card:nth-child(3){animation-delay:.2s}@keyframes slideIn{0%{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}.product-card-badge{background-color:rgba(0,0,0,.6);border-radius:30rpx;color:#fff;font-size:.71rem;left:8rpx;padding:4rpx 20rpx;position:absolute;top:8rpx;z-index:10}.product-card-badge .product-card-badge-icon{height:20rpx}.product-card-close{color:#fff;font-size:1.14rem;padding:0 14rpx;position:absolute;right:0rpx;top:0rpx;z-index:10}.product-card-image{height:240rpx;position:relative;width:100%}.product-card-image .product-card-img{height:100%;object-fit:cover;width:100%}.product-card-info{padding:12rpx}.product-card-title{color:#333;display:block;font-size:.86rem;font-weight:500;margin-bottom:12rpx;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.product-card-price-container{align-items:center;background:#fb2626;border-radius:8rpx;color:#fff;display:flex;height:50rpx;justify-content:space-between;margin-top:12rpx;padding-left:10rpx}.product-card-buy{background-color:#ff4d4f;border-radius:6rpx;color:#fff;cursor:pointer;font-size:.71rem;padding:8rpx 16rpx}.product-card-mask{align-items:center;background-color:rgba(0,0,0,.4);bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}.product-card-mask-text{border-radius:20rpx;color:#fff;font-size:.86rem;padding:8rpx 16rpx}.product-card-disabled{opacity:.7}.product-card-disabled .product-card-price{color:#fff}.product-card-disabled .product-card-price-container{opacity:.6}.buy-icon{display:block;height:100%}.product-card-small{width:180rpx}.product-card-small .product-card-image{height:180rpx}.product-card-small .product-card-price-container{height:40rpx}.product-card-small .product-card-badge{font-size:.64rem;padding:3rpx 16rpx}.product-card-small .product-card-close{font-size:1rem;padding:0 10rpx}.product-card-small .buy-icon{display:none}
@@ -0,0 +1,127 @@
1
+ import { appendParamsToPath } from '../../../shared/utils.js';
2
+ Component({
3
+ properties: {
4
+ // 商品数据
5
+ product: {
6
+ type: Object,
7
+ value: {}
8
+ },
9
+ // 是否显示
10
+ show: {
11
+ type: Boolean,
12
+ value: false
13
+ },
14
+ // SDK实例
15
+ sdkInstance: {
16
+ type: Object,
17
+ value: null,
18
+ observer: function(newVal) {
19
+ if (newVal) {
20
+ this.initStoreListener();
21
+ }
22
+ }
23
+ }
24
+ },
25
+ data: {
26
+ // 当前显示的图片索引
27
+ currentImageIndex: 0
28
+ },
29
+ lifetimes: {
30
+ attached() {
31
+ // 组件挂载时初始化store监听
32
+ if (this.properties.sdkInstance) {
33
+ this.initStoreListener();
34
+ }
35
+ },
36
+ detached() {
37
+ // 组件卸载时移除store监听
38
+ if (this.unsub) {
39
+ this.unsub();
40
+ }
41
+ }
42
+ },
43
+ observers: {
44
+ // 监听显示状态变化
45
+ show: function(show) {
46
+ if (show) {
47
+ // 重置数据
48
+ this.setData({
49
+ currentImageIndex: 0
50
+ });
51
+ }
52
+ }
53
+ },
54
+ methods: {
55
+ // 初始化store监听
56
+ initStoreListener() {
57
+ if (this.unsub) {
58
+ this.unsub();
59
+ }
60
+
61
+ this.unsub = this.properties.sdkInstance.store.get({
62
+ productList: (val) => {
63
+ if (val && this.properties.product && this.properties.product.goods_id) {
64
+ // 检查当前商品是否在列表中
65
+ const currentProduct = val.find(item => item.goods_id === this.properties.product.goods_id);
66
+ if (currentProduct) {
67
+ // 如果商品在列表中,更新商品数据
68
+ this.setData({
69
+ product: currentProduct
70
+ });
71
+ }
72
+ }
73
+ }
74
+ });
75
+ },
76
+ // 关闭商品详情
77
+ closeDetail() {
78
+ this.setData({
79
+ show: false
80
+ });
81
+ this.triggerEvent('close');
82
+ },
83
+ // 购买商品
84
+ buyProduct() {
85
+ const product = this.data.product;
86
+
87
+ if (!product) {
88
+ console.error('商品数据不存在');
89
+ return;
90
+ }
91
+
92
+ // 检查是否已抢光或待开价
93
+ if (product.sale_status === 0 || product.covered_status === 1) {
94
+ return;
95
+ }
96
+
97
+ // 检查 buy_type
98
+ if (product.buy_type === 4 && product?.mini_program_config?.mini_program_path) {
99
+ // 跳转到小程序路径
100
+ const webinarId = this.properties.sdkInstance.store.get('webinarId');
101
+ console.log("跳转小程序路径:", appendParamsToPath(product?.mini_program_config?.mini_program_path, { webinarId }))
102
+ wx.navigateTo({
103
+ url: appendParamsToPath(product?.mini_program_config?.mini_program_path, { webinarId })
104
+ });
105
+ this.closeDetail();
106
+ } else if (product.buy_type === 1) {
107
+ // 先关闭详情弹框
108
+ this.closeDetail();
109
+ // 触发购买事件,由父组件显示下单弹窗
110
+ this.triggerEvent('buy', product);
111
+ } else {
112
+ // 提示无法购买
113
+ wx.showToast({
114
+ title: '无法购买,请联系主办方',
115
+ icon: 'none',
116
+ duration: 2000
117
+ });
118
+ }
119
+ },
120
+ // 图片滑动切换
121
+ bindchange(e) {
122
+ this.setData({
123
+ currentImageIndex: e.detail.current
124
+ });
125
+ }
126
+ }
127
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "component": true
3
+ }
@@ -0,0 +1,57 @@
1
+ <view wx:if="{{show}}" class="product-detail-container">
2
+ <view class="product-detail-content">
3
+ <!-- 图片轮播 -->
4
+ <view class="product-images">
5
+ <view class="close-btn" bindtap="closeDetail">×</view>
6
+ <swiper
7
+ class="swiper"
8
+ current="{{currentImageIndex}}"
9
+ bindchange="bindchange"
10
+ indicator-dots="false"
11
+ autoplay="false"
12
+ circular="true"
13
+ >
14
+ <block wx:for="{{product.images}}" wx:key="{{index}}">
15
+ <swiper-item class="swiper-item">
16
+ <view class="product-image">
17
+ <image class="product-detail-img" src="{{item.img_url}}" mode="aspectFill"></image>
18
+ </view>
19
+ </swiper-item>
20
+ </block>
21
+ </swiper>
22
+ <view class="image-indicator">
23
+ {{currentImageIndex + 1}}/{{product.images ? product.images.length : 1}}
24
+ </view>
25
+ </view>
26
+
27
+ <!-- 商品信息 -->
28
+ <view class="product-info">
29
+ <!-- 价格 -->
30
+ <block wx:if="{{product.covered_status === 1}}">
31
+ <text class="covered-price">¥?待开价</text>
32
+ </block>
33
+ <block wx:else>
34
+ <view class="price-container">
35
+ <text class="discount-price">¥{{product.discount_price || product.price || 0}}</text>
36
+ <text wx:if="{{product.discount_price && product.price && product.discount_price !== product.price}}" class="original-price">¥{{product.price}}</text>
37
+ </view>
38
+ </block>
39
+
40
+ <!-- 商品名称 -->
41
+ <text class="product-title">{{product.name || '商品名称'}}</text>
42
+
43
+ <!-- 商品描述 -->
44
+ <text class="product-desc">{{product.description || ''}}</text>
45
+
46
+
47
+
48
+ <!-- 购买按钮 -->
49
+ <view
50
+ class="buy-btn {{product.sale_status === 0 || product.covered_status === 1 ? 'disabled' : ''}}"
51
+ bindtap="buyProduct"
52
+ >
53
+ {{product.sale_status === 0 ? '已抢光' : product.covered_status === 1 ? '待开价' : '购买'}}
54
+ </view>
55
+ </view>
56
+ </view>
57
+ </view>
@@ -0,0 +1 @@
1
+ .product-detail-container{align-items:flex-end;background-color:rgba(0,0,0,.5);bottom:0;display:flex;left:0;position:fixed;right:0;top:0;z-index:9999}.product-detail-content{background-color:#fff;border-radius:20rpx 20rpx 0 0;max-height:90vh;overflow:hidden;width:100%}.product-images{background-color:#f5f5f5;height:750rpx;position:relative}.swiper{height:100%}.swiper-item{align-items:center;display:flex;height:100%;justify-content:center}.product-image{height:100%;width:100%}.product-image .product-detail-img{height:100%;object-fit:contain;width:100%}.image-indicator{border-radius:20rpx;bottom:20rpx;font-size:.86rem;padding:8rpx 16rpx}.close-btn,.image-indicator{background-color:rgba(0,0,0,.6);color:#fff;position:absolute;right:20rpx}.close-btn{align-items:center;border-radius:50%;display:flex;font-size:1.29rem;height:60rpx;justify-content:center;top:20rpx;width:60rpx;z-index:10}.product-info{padding:30rpx}.price-container{align-items:baseline;display:flex;margin-bottom:30rpx}.discount-price{color:#fb2626;font-size:1.43rem;margin-right:20rpx}.original-price{color:#999;font-size:1rem;text-decoration:line-through}.product-title{-webkit-line-clamp:2;color:#333;font-size:1.14rem;font-weight:700;line-height:1.71rem;margin-bottom:20rpx}.product-desc,.product-title{-webkit-box-orient:vertical;display:block;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.product-desc{-webkit-line-clamp:3;color:#666;font-size:1rem;line-height:1.43rem;margin-bottom:30rpx}.covered-price{color:#999;font-size:1.14rem;margin-bottom:30rpx}.buy-btn{align-items:center;background-color:#fb2626;border-radius:45rpx;color:#fff;display:flex;font-size:1.14rem;font-weight:700;height:90rpx;justify-content:center;margin-top:20rpx;width:100%}.buy-btn.disabled{background-color:#ccc;color:#999;cursor:not-allowed}
@@ -0,0 +1,56 @@
1
+ import { appendParamsToPath } from '../../../shared/utils.js';
2
+ Component({
3
+ properties: {
4
+ // 商品数据
5
+ product: {
6
+ type: Object,
7
+ value: {}
8
+ },
9
+ // 商品序号
10
+ index: {
11
+ type: Number,
12
+ value: 0
13
+ },
14
+ webinarId: {
15
+ type: String,
16
+ value: 0
17
+ }
18
+ },
19
+ data: {
20
+ // 组件内部数据
21
+ },
22
+ methods: {
23
+ // 点击商品
24
+ onProductClick() {
25
+ this.triggerEvent('openDetail', this.properties.product);
26
+ },
27
+ // 点击购买按钮
28
+ onBuyClick(e) {
29
+ const product = this.properties.product;
30
+ // 检查是否已抢光或待开价
31
+ if (product.sale_status === 0 || product.covered_status === 1) {
32
+ return;
33
+ }
34
+
35
+ // 检查 buy_type
36
+ if (product.buy_type === 4 && product?.mini_program_config?.mini_program_path) {
37
+ // 跳转到小程序路径
38
+ const webinarId = this.properties.webinarId;
39
+ console.log("跳转小程序路径:", appendParamsToPath(product?.mini_program_config?.mini_program_path, { webinarId }))
40
+ wx.navigateTo({
41
+ url: appendParamsToPath(product?.mini_program_config?.mini_program_path, { webinarId })
42
+ });
43
+ } else if (product.buy_type === 1) {
44
+ // 触发购买事件,由父组件显示下单弹窗
45
+ this.triggerEvent('buyClick', product);
46
+ } else {
47
+ // 提示无法购买
48
+ wx.showToast({
49
+ title: '无法购买,请联系主办方',
50
+ icon: 'none',
51
+ duration: 2000
52
+ });
53
+ }
54
+ }
55
+ }
56
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "component": true
3
+ }
@@ -0,0 +1,35 @@
1
+ <view class="product-item" bindtap="onProductClick">
2
+ <view class="product-image">
3
+ <view class="product-index">{{index + 1}}</view>
4
+ <image src="{{product.cover_img || 'https://cnstatic01.e.vhall.com/common-static/images/default_avatar.png'}}" mode="aspectFill"></image>
5
+ <view wx:if="{{product.sale_status === 0}}" class="product-mask">
6
+ <text class="product-mask-text">已抢光</text>
7
+ </view>
8
+ <!-- 讲解中标识 -->
9
+ <view wx:if="{{product.push_status === 1}}" class="product-badge">
10
+ <image src="https://cnstatic01.e.vhall.com/common-static/saas-wap/static/img/live.b07d13f4.gif" mode="heightFix" style="height: 20rpx; margin-right: 8rpx;"></image>
11
+ <text class="product-badge-text">讲解中</text>
12
+ </view>
13
+ </view>
14
+ <view class="product-info">
15
+ <view>
16
+ <text class="product-name">{{product.name }}</text>
17
+ <text class="product-desc">{{product.description }}</text>
18
+ </view>
19
+ <!-- 价格显示逻辑 -->
20
+ <block wx:if="{{product.covered_status === 1}}">
21
+ <text class="covered-price">¥?待开价</text>
22
+ </block>
23
+ <block wx:else>
24
+ <view wx:if="{{product.discount_price && product.price && product.discount_price !== product.price}}" class="price-container">
25
+ <text class="product-discount-price">¥{{product.discount_price}}</text>
26
+ <text class="product-original-price">¥{{product.price}}</text>
27
+ </view>
28
+ <text wx:else class="product-price">¥{{product.discount_price || product.price || 0}}</text>
29
+ </block>
30
+ </view>
31
+ <!-- 购买按钮 -->
32
+ <view class="{{['buy-btn',(product.sale_status === 0 || product.covered_status === 1) ? 'disabled' : '']}}" catchtap="onBuyClick">
33
+ 购买
34
+ </view>
35
+ </view>
@@ -0,0 +1 @@
1
+ .product-image{border-radius:10rpx;height:180rpx;margin-right:20rpx;overflow:hidden;position:relative;width:180rpx}.product-index{border-radius:8rpx 0 8rpx 0;color:#fff;font-size:1rem;height:40rpx;padding:0 16rpx;z-index:1}.product-index,.product-mask{align-items:center;background-color:rgba(0,0,0,.6);display:flex;justify-content:center;left:0;position:absolute;top:0}.product-mask{bottom:0;right:0;z-index:2}.product-mask-text{color:#fff;font-size:1rem}.buy-btn.disabled{cursor:not-allowed;opacity:.6}.covered-price{color:#999;font-size:1rem;margin-bottom:10rpx}.product-image image{height:100%;object-fit:cover;width:100%}.product-info{display:flex;flex:1;flex-direction:column;justify-content:space-between;width:0}.product-name{color:#333;font-size:1.12rem;line-height:1.43rem}.product-desc,.product-name{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden;text-overflow:ellipsis}.product-desc{color:#666;font-size:.9rem}.price-container{align-items:baseline;display:flex}.product-discount-price{color:#fb2626;font-size:1.14rem}.product-original-price{color:#999;font-size:.86rem;text-decoration:line-through}.product-price{color:#fb2626;font-size:1.14rem}.buy-btn{background-color:#fb2626;border-radius:40rpx;bottom:20rpx;color:#fff;font-size:.86rem;padding:10rpx 32rpx;position:absolute;right:20rpx}.product-item{border-bottom:1rpx solid #f0f0f0;cursor:pointer;display:flex;padding:20rpx 0;position:relative}.product-item:last-child{border-bottom:none}.product-sales{color:#999;font-size:.86rem}.product-badge{align-items:center;background-color:rgba(0,0,0,.6);bottom:0;color:#fff;display:flex;font-size:.71rem;justify-content:center;left:0;padding:8rpx;position:absolute;right:0;text-align:center;z-index:5}.product-badge-text{display:inline-block}
@@ -0,0 +1,67 @@
1
+ Component({
2
+ properties: {
3
+ sdkInstance: {
4
+ type: Object,
5
+ value: null,
6
+ observer: function(newVal) {
7
+ if (newVal) {
8
+ this.initStoreListener();
9
+ }
10
+ }
11
+ },
12
+ },
13
+ data: {
14
+ // 组件内部数据
15
+ productList: [],
16
+ webinarId: ''
17
+ },
18
+ lifetimes: {
19
+ created() {
20
+ // 组件创建时
21
+ },
22
+ attached() {
23
+ // 组件挂载时
24
+ if (this.properties.sdkInstance) {
25
+ this.initStoreListener();
26
+ this.setData({
27
+ webinarId: this.properties.sdkInstance.store.get('webinarId'),
28
+ });
29
+ // // 初始加载商品数据
30
+ // const productServer = this.properties.sdkInstance.get('productServer');
31
+ // if (productServer) {
32
+ // productServer.getProductList();
33
+ // }
34
+ }
35
+ },
36
+ detached() {
37
+ // 组件卸载时
38
+ if (this.unsub) {
39
+ this.unsub();
40
+ }
41
+ }
42
+ },
43
+ methods: {
44
+ // 初始化store监听
45
+ initStoreListener() {
46
+ if (this.unsub) {
47
+ this.unsub();
48
+ }
49
+
50
+ this.unsub = this.properties.sdkInstance.store.get({
51
+ productList: (val) => {
52
+ if (val) {
53
+ this.setData({ productList: val });
54
+ }
55
+ }
56
+ });
57
+ },
58
+ // 打开商品详情
59
+ openProductDetail(e) {
60
+ this.triggerEvent('productClick', e.detail);
61
+ },
62
+ // 处理购买点击事件
63
+ onBuyClick(e) {
64
+ this.triggerEvent('buyClick', e.detail);
65
+ },
66
+ },
67
+ });
@@ -0,0 +1,6 @@
1
+ {
2
+ "component": true,
3
+ "usingComponents": {
4
+ "product-item": "../product-item/product-item"
5
+ }
6
+ }
@@ -0,0 +1,16 @@
1
+ <view class="product-container">
2
+ <view class="product-list">
3
+ <view wx:if="{{productList.length === 0}}" class="product-empty">暂无商品</view>
4
+ <view wx:else>
5
+ <product-item
6
+ webinarId="{{webinarId}}"
7
+ wx:for="{{productList}}"
8
+ wx:key="{{item.id}}"
9
+ index="{{index}}"
10
+ product="{{item}}"
11
+ bind:openDetail="openProductDetail"
12
+ bind:buyClick="onBuyClick"
13
+ />
14
+ </view>
15
+ </view>
16
+ </view>
@@ -0,0 +1 @@
1
+ .product-container{height:100%}.product-list{box-sizing:border-box;height:100%;overflow-y:auto;padding:20rpx;width:100%}.product-empty{color:#999;font-size:1rem;padding:40rpx 0;text-align:center}