cb-biz-ui 1.7.6 → 1.7.8
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view class="goods-card bottom-border" @tap="itemTap">
|
|
3
3
|
<view class="goods-card_image">
|
|
4
|
-
<ui-lazyload-img
|
|
4
|
+
<!-- <ui-lazyload-img
|
|
5
5
|
:width="imgWidth"
|
|
6
6
|
:height="imgHeight"
|
|
7
7
|
radius="8rpx"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
:mode="imageMode"
|
|
12
12
|
:src="goodsImage"
|
|
13
13
|
sizeType="previewImage"
|
|
14
|
-
></ui-lazyload-img>
|
|
14
|
+
></ui-lazyload-img> -->
|
|
15
15
|
<!-- <view
|
|
16
16
|
:style="{
|
|
17
17
|
width: imgWidth,
|
|
@@ -21,77 +21,59 @@
|
|
|
21
21
|
class="goods-status_error"
|
|
22
22
|
>{{ errStatusText }}</view
|
|
23
23
|
> -->
|
|
24
|
+
<image
|
|
25
|
+
:mode="imageMode"
|
|
26
|
+
:draggable="false"
|
|
27
|
+
:src="goodsImage"
|
|
28
|
+
:style="{ width: imgWidth, height: imgHeight, borderRadius: '8rpx' }"
|
|
29
|
+
/>
|
|
24
30
|
</view>
|
|
25
31
|
<view class="goods-card_info">
|
|
26
32
|
<view class="goods-card_info_title">
|
|
27
33
|
<ui-overflow-hidden size="24rpx">
|
|
28
|
-
<text class="text" :style="{ fontSize: textFontSize.title }"
|
|
29
|
-
>{{ entity.name }}
|
|
34
|
+
<text class="text" :style="{ fontSize: textFontSize.title }">{{ entity.name }}
|
|
30
35
|
</text>
|
|
31
36
|
</ui-overflow-hidden>
|
|
32
37
|
</view>
|
|
33
38
|
<view class="rebate-box" v-if="entity.rebateGold">
|
|
34
39
|
<view class="rebate-box_title"> 购买返利 </view>
|
|
35
40
|
<view class="rebate-box_content">
|
|
36
|
-
<text class="rebate-box_content_text"
|
|
37
|
-
>约¥{{ entity.rebateMoney || 0 }}</text
|
|
38
|
-
>
|
|
41
|
+
<text class="rebate-box_content_text">约¥{{ entity.rebateMoney || 0 }}</text>
|
|
39
42
|
<view class="rebate-box_content_icon">
|
|
40
43
|
(
|
|
41
44
|
<text class="rebate-box_content_icon_text">{{
|
|
42
45
|
entity.rebateGold
|
|
43
46
|
}}</text>
|
|
44
|
-
<image
|
|
45
|
-
|
|
46
|
-
src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/21f285a66453412e8cd0046ed31aa222@.png"
|
|
47
|
-
/>
|
|
47
|
+
<image class="rebate-icon"
|
|
48
|
+
src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/21f285a66453412e8cd0046ed31aa222@.png" />
|
|
48
49
|
)
|
|
49
50
|
</view>
|
|
50
51
|
</view>
|
|
51
52
|
</view>
|
|
52
53
|
<view class="goods-card_info_sales-specification" v-if="entity.attrValue && entity.attrUnitValue">
|
|
53
|
-
<text
|
|
54
|
-
|
|
55
|
-
:style="{ fontSize: '22rpx' }"
|
|
56
|
-
>{{ entity.attrValue + '/' + entity.attrUnitValue }}
|
|
54
|
+
<text class="goods-card_info_sales-specification_text" :style="{ fontSize: '22rpx' }">{{ entity.attrValue + '/'
|
|
55
|
+
+ entity.attrUnitValue }}
|
|
57
56
|
</text>
|
|
58
57
|
</view>
|
|
59
58
|
<view class="goods-card_info_sales-volume" v-if="entity.saleCnt">
|
|
60
|
-
<text
|
|
61
|
-
|
|
62
|
-
:style="{ fontSize: textFontSize.salesVolume }"
|
|
63
|
-
>销量{{ ` ` }}{{ entity.saleCnt || 0 }}
|
|
59
|
+
<text class="goods-card_info_sales-volume_text" :style="{ fontSize: textFontSize.salesVolume }">销量{{ ` ` }}{{
|
|
60
|
+
entity.saleCnt || 0 }}
|
|
64
61
|
</text>
|
|
65
62
|
</view>
|
|
66
|
-
<view class="goods-card_info_tag" v-if="entity.hasDiscount">
|
|
67
|
-
<ui-tag
|
|
68
|
-
type="danger"
|
|
69
|
-
padding="6rpx 10rpx"
|
|
70
|
-
:size="textFontSize.tag"
|
|
71
|
-
plain
|
|
72
|
-
>
|
|
63
|
+
<view class="goods-card_info_tag" v-if="entity.hasDiscount || entity.purchaseLimitNum > 0">
|
|
64
|
+
<ui-tag type="danger" padding="6rpx 10rpx" :size="textFontSize.tag" plain>
|
|
73
65
|
<view class="tag-box">
|
|
74
|
-
<image
|
|
75
|
-
|
|
76
|
-
src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/5131a04c08bf4c80b73291f82186ce46.png"
|
|
77
|
-
/>
|
|
66
|
+
<image class="icon icon_yh"
|
|
67
|
+
src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/5131a04c08bf4c80b73291f82186ce46.png" />
|
|
78
68
|
|
|
79
69
|
<text>{{ getDiscount(entity.discount) }}</text>
|
|
80
70
|
</view>
|
|
81
71
|
</ui-tag>
|
|
82
72
|
<view v-if="entity.purchaseLimitNum > 0" style="margin-left: 10rpx">
|
|
83
|
-
<ui-tag
|
|
84
|
-
type="danger"
|
|
85
|
-
padding="6rpx 10rpx"
|
|
86
|
-
:size="textFontSize.tag"
|
|
87
|
-
plain
|
|
88
|
-
>
|
|
73
|
+
<ui-tag type="danger" padding="6rpx 10rpx" :size="textFontSize.tag" plain>
|
|
89
74
|
<view class="tag-box">
|
|
90
|
-
<image
|
|
91
|
-
|
|
92
|
-
style="width: 28rpx"
|
|
93
|
-
src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/0eb08f3800884600bde0cd670aecc869@.png@.webp"
|
|
94
|
-
/>
|
|
75
|
+
<image class="icon icon_yh" style="width: 28rpx"
|
|
76
|
+
src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/0eb08f3800884600bde0cd670aecc869@.png@.webp" />
|
|
95
77
|
|
|
96
78
|
<text>每人限{{ entity.purchaseLimitNum }}份</text>
|
|
97
79
|
</view>
|
|
@@ -99,17 +81,10 @@
|
|
|
99
81
|
</view>
|
|
100
82
|
</view>
|
|
101
83
|
<view class="goods-card_info_price">
|
|
102
|
-
<text
|
|
103
|
-
class="goods-card_info_price_preferential-price"
|
|
104
|
-
:style="{ fontSize: textFontSize.preferentialPrice }"
|
|
105
|
-
>
|
|
84
|
+
<text class="goods-card_info_price_preferential-price" :style="{ fontSize: textFontSize.preferentialPrice }">
|
|
106
85
|
¥{{ price }}
|
|
107
86
|
</text>
|
|
108
|
-
<text
|
|
109
|
-
class="goods-card_info_price_price"
|
|
110
|
-
v-if="entity.hasDiscount"
|
|
111
|
-
:style="{ fontSize: textFontSize.price }"
|
|
112
|
-
>
|
|
87
|
+
<text class="goods-card_info_price_price" v-if="entity.hasDiscount" :style="{ fontSize: textFontSize.price }">
|
|
113
88
|
¥{{ entity.marketPriceShow }}
|
|
114
89
|
</text>
|
|
115
90
|
</view>
|
|
@@ -117,14 +92,10 @@
|
|
|
117
92
|
<text class="goods-card_info_status_text">{{ errStatusText }}</text>
|
|
118
93
|
</view>
|
|
119
94
|
<view class="goods-card_info_add" v-else>
|
|
120
|
-
<view
|
|
121
|
-
@tap.stop="addClick"
|
|
122
|
-
v-if="!goodsCount"
|
|
123
|
-
class="goods-card_info_add_icon"
|
|
124
|
-
>
|
|
95
|
+
<view @tap.stop="addClick" v-if="!goodsCount" class="goods-card_info_add_icon">
|
|
125
96
|
<ui-icon name="add" :size="19" :color="addBtnBgColor"></ui-icon>
|
|
126
97
|
</view>
|
|
127
|
-
<view v-else class="number-box" @tap.stop="() => {}">
|
|
98
|
+
<view v-else class="number-box" @tap.stop="() => { }">
|
|
128
99
|
<!-- <uni-number-box
|
|
129
100
|
:value="goodsCount"
|
|
130
101
|
:min="0"
|
|
@@ -137,37 +108,15 @@
|
|
|
137
108
|
@change="change"
|
|
138
109
|
></uni-number-box> -->
|
|
139
110
|
|
|
140
|
-
<ui-numberbox
|
|
141
|
-
|
|
142
|
-
:
|
|
143
|
-
:
|
|
144
|
-
|
|
145
|
-
? 99999
|
|
146
|
-
: entity.inventoryCapacity || 100
|
|
147
|
-
"
|
|
148
|
-
@change="change"
|
|
149
|
-
@triggerMax="triggerMax"
|
|
150
|
-
:border="true"
|
|
151
|
-
:width="65"
|
|
152
|
-
:iconSize="19"
|
|
153
|
-
:size="22"
|
|
154
|
-
:step="1"
|
|
155
|
-
:backgroundColor="textFontSize.numberBoxBg"
|
|
156
|
-
iconColor="#C7C7CC"
|
|
157
|
-
></ui-numberbox>
|
|
111
|
+
<ui-numberbox :value="goodsCount" :min="0" :max="entity.unlimitedInventory
|
|
112
|
+
? 99999
|
|
113
|
+
: entity.inventoryCapacity || 100
|
|
114
|
+
" @change="change" @triggerMax="triggerMax" :border="true" :width="65" :iconSize="19" :size="22" :step="1"
|
|
115
|
+
:backgroundColor="textFontSize.numberBoxBg" iconColor="#C7C7CC"></ui-numberbox>
|
|
158
116
|
</view>
|
|
159
|
-
<ui-cubic-bezier
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
bottom="0"
|
|
163
|
-
:backgroundColor="addBtnBgColor"
|
|
164
|
-
:windowWidth="state.windowWidth"
|
|
165
|
-
:windowHeight="state.windowHeight"
|
|
166
|
-
:position="{ right: 110, bottom: 15 }"
|
|
167
|
-
direction="down"
|
|
168
|
-
:index="0"
|
|
169
|
-
@click="addClick"
|
|
170
|
-
></ui-cubic-bezier>
|
|
117
|
+
<ui-cubic-bezier v-if="bezier" right="0" bottom="0" :backgroundColor="addBtnBgColor"
|
|
118
|
+
:windowWidth="state.windowWidth" :windowHeight="state.windowHeight" :position="{ right: 110, bottom: 15 }"
|
|
119
|
+
direction="down" :index="0" @click="addClick"></ui-cubic-bezier>
|
|
171
120
|
</view>
|
|
172
121
|
</view>
|
|
173
122
|
</view>
|
|
@@ -176,6 +125,7 @@
|
|
|
176
125
|
<script setup lang="ts">
|
|
177
126
|
import { onMounted, reactive, computed } from 'vue';
|
|
178
127
|
import type { GoodsDataType, changeValueType } from '../interface/types';
|
|
128
|
+
import imageJSsdk from './new-sdk';
|
|
179
129
|
|
|
180
130
|
interface IProps {
|
|
181
131
|
entity: GoodsDataType;
|
|
@@ -186,19 +136,19 @@ interface IProps {
|
|
|
186
136
|
goodMin?: number;
|
|
187
137
|
imagePlaceholder?: string;
|
|
188
138
|
imageMode?:
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
139
|
+
| 'scaleToFill'
|
|
140
|
+
| 'aspectFit'
|
|
141
|
+
| 'aspectFill'
|
|
142
|
+
| 'widthFix'
|
|
143
|
+
| 'top'
|
|
144
|
+
| 'bottom'
|
|
145
|
+
| 'center'
|
|
146
|
+
| 'left'
|
|
147
|
+
| 'right'
|
|
148
|
+
| 'top left'
|
|
149
|
+
| 'top right'
|
|
150
|
+
| 'bottom left'
|
|
151
|
+
| 'bottom right';
|
|
202
152
|
textFontSize?: {
|
|
203
153
|
title: string;
|
|
204
154
|
tag: string;
|
|
@@ -210,6 +160,7 @@ interface IProps {
|
|
|
210
160
|
addBtnBgColor: string;
|
|
211
161
|
}
|
|
212
162
|
|
|
163
|
+
|
|
213
164
|
const props = withDefaults(defineProps<IProps>(), {
|
|
214
165
|
imgWidth: '225rpx',
|
|
215
166
|
imgHeight: '225rpx',
|
|
@@ -260,7 +211,7 @@ const goodsImage = computed(() => {
|
|
|
260
211
|
if (props?.entity?.image?.includes('static.tanshuapi.com')) {
|
|
261
212
|
return urlConversion(props?.entity?.image || '');
|
|
262
213
|
}
|
|
263
|
-
return props?.entity?.image || '';
|
|
214
|
+
return imageJSsdk.getWebpUrl(props?.entity?.image || '', 'previewImage');
|
|
264
215
|
});
|
|
265
216
|
|
|
266
217
|
function urlConversion(path) {
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
class ImageJSsdk {
|
|
2
|
+
// 支持的图片扩展名
|
|
3
|
+
imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp'];
|
|
4
|
+
|
|
5
|
+
// 图片尺寸映射表
|
|
6
|
+
imageSizeMap = {
|
|
7
|
+
listImage: '@h240',
|
|
8
|
+
previewImage: '@h480',
|
|
9
|
+
detailsImage: ''
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 手动解析URL为协议和路径(适配微信小程序)
|
|
14
|
+
* @param url 完整URL字符串
|
|
15
|
+
* @returns 包含协议和路径的对象,无效URL返回null
|
|
16
|
+
*/
|
|
17
|
+
parseUrl(url) {
|
|
18
|
+
if (!url) return null;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// 匹配协议部分 (http:, https: 等)
|
|
22
|
+
const protocolMatch = url.match(/^([a-zA-Z]+:)/);
|
|
23
|
+
if (!protocolMatch) {
|
|
24
|
+
console.error('URL缺少协议部分');
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const protocol = protocolMatch[1];
|
|
28
|
+
|
|
29
|
+
// 移除协议部分后处理路径
|
|
30
|
+
const pathStart =
|
|
31
|
+
url.indexOf('//') === -1 ? protocol.length : url.indexOf('//') + 2;
|
|
32
|
+
const pathname = url.substring(pathStart);
|
|
33
|
+
|
|
34
|
+
return { protocol, pathname };
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.error('URL解析错误:', err);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 判断URL是否为图片
|
|
43
|
+
* @param urlObj 解析后的URL对象
|
|
44
|
+
* @returns 是否为图片的布尔值
|
|
45
|
+
*/
|
|
46
|
+
isImageUrl(urlObj) {
|
|
47
|
+
if (!urlObj) return false;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const lastDotIndex = urlObj.pathname.lastIndexOf('.');
|
|
51
|
+
if (lastDotIndex === -1) return false;
|
|
52
|
+
|
|
53
|
+
// 提取并转换为小写扩展名
|
|
54
|
+
const extension = urlObj.pathname.slice(lastDotIndex + 1).toLowerCase();
|
|
55
|
+
return this.imageExtensions.includes(extension);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error('判断图片类型错误:', err);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 获取URL信息
|
|
64
|
+
* @param urlObj 解析后的URL对象
|
|
65
|
+
* @returns 包含路径、扩展名和是否为新URL格式的对象
|
|
66
|
+
*/
|
|
67
|
+
getUrlInfo(urlObj) {
|
|
68
|
+
// 处理无效URL情况
|
|
69
|
+
if (!urlObj || !this.isImageUrl(urlObj)) {
|
|
70
|
+
return { pathname: '', ext: '', isNewUrl: false };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const lastDotIndex = urlObj.pathname.lastIndexOf('.');
|
|
74
|
+
const ext =
|
|
75
|
+
lastDotIndex !== -1
|
|
76
|
+
? urlObj.pathname.slice(lastDotIndex + 1).toLowerCase()
|
|
77
|
+
: '';
|
|
78
|
+
const atSymbolCount = (urlObj.pathname.match(/@/g) || []).length;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
pathname: urlObj.pathname,
|
|
82
|
+
ext,
|
|
83
|
+
isNewUrl: urlObj.pathname.includes('@.') && atSymbolCount === 1
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 获取WebP格式的图片URL
|
|
89
|
+
* @param url 原始图片URL
|
|
90
|
+
* @param sizeType 尺寸类型,对应imageSizeMap
|
|
91
|
+
* @returns 处理后的WebP图片URL
|
|
92
|
+
*/
|
|
93
|
+
getWebpUrl(url, sizeType = 'detailsImage') {
|
|
94
|
+
if (!url) return '';
|
|
95
|
+
|
|
96
|
+
const urlObj = this.parseUrl(url);
|
|
97
|
+
if (!urlObj) return url;
|
|
98
|
+
|
|
99
|
+
const urlInfo = this.getUrlInfo(urlObj);
|
|
100
|
+
const sizeStr = this.imageSizeMap[sizeType] || '';
|
|
101
|
+
|
|
102
|
+
if (!urlInfo.isNewUrl) {
|
|
103
|
+
return url;
|
|
104
|
+
}
|
|
105
|
+
// 处理已为webp格式的URL
|
|
106
|
+
if (urlInfo.ext === 'webp') {
|
|
107
|
+
// 避免重复添加尺寸参数
|
|
108
|
+
return url.includes(sizeStr) ? url : `${url}${sizeStr}.webp`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!this.imageExtensions.includes(urlInfo.ext)) {
|
|
112
|
+
return url;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 处理其他格式转换为webp
|
|
116
|
+
const hasSize = sizeStr && !url.includes(sizeStr);
|
|
117
|
+
return hasSize
|
|
118
|
+
? `${url}${sizeStr}.webp`
|
|
119
|
+
: `${url}${sizeStr ? '' : '@'}.webp`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 单例导出
|
|
125
|
+
const imageJSsdk = new ImageJSsdk();
|
|
126
|
+
export default imageJSsdk;
|