cb-biz-ui 1.1.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 (76) hide show
  1. package/README.md +44 -0
  2. package/components/cb-address-list/cb-address-list.vue +133 -0
  3. package/components/cb-cart-bar/cb-cart-bar.vue +52 -0
  4. package/components/cb-cart-bar-button/cb-cart-bar-button.vue +36 -0
  5. package/components/cb-cart-bar-icon/cb-cart-bar-icon.vue +48 -0
  6. package/components/cb-category/cb-category.vue +163 -0
  7. package/components/cb-delivery-address/cb-delivery-address.vue +48 -0
  8. package/components/cb-discount-coupon/cb-discount-coupon.vue +124 -0
  9. package/components/cb-discount-coupon/interface.d.ts +32 -0
  10. package/components/cb-discount-coupon/utils.ts +23 -0
  11. package/components/cb-drag-list/cb-drag-list.vue +868 -0
  12. package/components/cb-drag-list/drag.wxs +366 -0
  13. package/components/cb-form-classify/cb-form-classify.vue +208 -0
  14. package/components/cb-form-select/cb-form-select.vue +250 -0
  15. package/components/cb-goods-card/cb-goods-card.vue +251 -0
  16. package/components/cb-goods-sku/cb-goods-sku.vue +270 -0
  17. package/components/cb-header/cb-header.vue +113 -0
  18. package/components/cb-inventory/cb-inventory.vue +161 -0
  19. package/components/cb-manage-goods-item/cb-manage-goods-item.vue +95 -0
  20. package/components/cb-money-input/cb-money-input.vue +90 -0
  21. package/components/cb-offline-stores-coupon/cb-offline-stores-coupon.vue +96 -0
  22. package/components/cb-offline-stores-coupon/interface.d.ts +29 -0
  23. package/components/cb-offline-stores-coupon/utils.ts +10 -0
  24. package/components/cb-order-card/cb-order-card.vue +187 -0
  25. package/components/cb-order-goods/cb-order-goods.vue +64 -0
  26. package/components/cb-order-info/cb-order-info.vue +112 -0
  27. package/components/cb-order-remark/cb-order-remark.vue +121 -0
  28. package/components/cb-shipping-coupon/cb-shipping-coupon.vue +112 -0
  29. package/components/cb-shipping-coupon/interface.d.ts +32 -0
  30. package/components/cb-shipping-coupon/utils.ts +23 -0
  31. package/components/cb-shopping-cart/cb-shopping-cart.vue +230 -0
  32. package/components/cb-shopping-cart-tabbar/cb-shopping-cart-tabbar.vue +147 -0
  33. package/components/cb-sort-icon/cb-sort-icon.vue +70 -0
  34. package/components/cb-store-location/cb-store-location.vue +85 -0
  35. package/components/cb-unit-select/cb-unit-select.vue +161 -0
  36. package/components/cb-vertical-nav/cb-vertical-nav.vue +102 -0
  37. package/components/interface/types.d.ts +246 -0
  38. package/index.js +39 -0
  39. package/index.scss +23 -0
  40. package/libs/config/index.js +20 -0
  41. package/libs/css/address-list.scss +143 -0
  42. package/libs/css/cart-bar-icon.scss +34 -0
  43. package/libs/css/category.scss +83 -0
  44. package/libs/css/common.scss +0 -0
  45. package/libs/css/delivery-address.scss +46 -0
  46. package/libs/css/discount-coupon.scss +237 -0
  47. package/libs/css/form-classify.scss +98 -0
  48. package/libs/css/form-select.scss +98 -0
  49. package/libs/css/global/color.scss +156 -0
  50. package/libs/css/global/common.scss +0 -0
  51. package/libs/css/global/style.h5.scss +8 -0
  52. package/libs/css/global/style.mp.scss +0 -0
  53. package/libs/css/global/style.nvue.scss +3 -0
  54. package/libs/css/global/style.vue.scss +0 -0
  55. package/libs/css/goods-card.scss +154 -0
  56. package/libs/css/inventory.scss +74 -0
  57. package/libs/css/manage-goods-item.scss +76 -0
  58. package/libs/css/offline-stores-coupon.scss +133 -0
  59. package/libs/css/order-goods.scss +63 -0
  60. package/libs/css/order-info.scss +89 -0
  61. package/libs/css/order-remark.scss +68 -0
  62. package/libs/css/shipping-coupon.scss +151 -0
  63. package/libs/css/shopping-cart.scss +50 -0
  64. package/libs/css/sort-icon.scss +34 -0
  65. package/libs/css/store-location.scss +66 -0
  66. package/libs/css/theme.json +10 -0
  67. package/libs/css/unit-select.scss +62 -0
  68. package/libs/css/vertical-nav.scss +27 -0
  69. package/libs/utils/deep-clone.js +36 -0
  70. package/libs/utils/deep-merge.js +37 -0
  71. package/libs/utils/guid.js +42 -0
  72. package/libs/utils/index.js +6 -0
  73. package/libs/utils/time-format.js +54 -0
  74. package/libs/utils/validate.js +238 -0
  75. package/package.json +24 -0
  76. package/theme.scss +39 -0
@@ -0,0 +1,250 @@
1
+ <template>
2
+ <view
3
+ class="form-select"
4
+ :style="{
5
+ padding: getPadding,
6
+ background: getBgColor
7
+ }"
8
+ >
9
+ <view class="form-select_center" @tap="popup">
10
+ <view class="content">
11
+ <view
12
+ class="label"
13
+ :style="{
14
+ width: labelCenter ? labelWidth + 'rpx' : ''
15
+ }"
16
+ >{{ label }}
17
+
18
+ <view
19
+ class="asterisk"
20
+ v-if="asterisk"
21
+ :style="{ color: '#EB0909', right: asteriskRight + 'rpx' }"
22
+ >*</view
23
+ >
24
+ </view>
25
+ <view class="placeholder" v-if="!getValue()">{{ placeholder }}</view>
26
+ <view class="form-value" v-else>{{ getValue() }}</view></view
27
+ >
28
+ <view
29
+ class="ui-cell__arrow"
30
+ :style="{ borderColor: getArrowColor, right: arrowRight + 'rpx' }"
31
+ v-if="arrow"
32
+ ></view>
33
+ </view>
34
+ <view
35
+ v-if="bottomBorder"
36
+ :style="{
37
+ background: getBorderColor,
38
+ left: left + 'rpx',
39
+ right: right + 'rpx'
40
+ }"
41
+ class="border-bottom"
42
+ ></view>
43
+ <ui-bottom-popup
44
+ :radius="false"
45
+ :zIndex="1002"
46
+ :maskZIndex="1001"
47
+ :show="popupShow"
48
+ @close="popup"
49
+ >
50
+ <view class="popup-box">
51
+ <view class="title">{{ placeholder }}</view>
52
+ <ui-radio-group @change="radioChange">
53
+ <ui-label v-for="item in copyList" :key="item.value">
54
+ <ui-list-cell>
55
+ <view class="radio-center">
56
+ <ui-radio
57
+ :checked="item.checked"
58
+ :value="item.value"
59
+ color="#07C160"
60
+ borderColor="#6D7278"
61
+ >
62
+ </ui-radio>
63
+ <text class="text" v-if="!item.itemValue">{{
64
+ item.label
65
+ }}</text>
66
+ <view class="item-value" v-else>
67
+ <ui-input
68
+ :placeholder="item.itemValue.startPlaceholder"
69
+ v-model="item.itemValue.start"
70
+ ></ui-input>
71
+ <text class="icon">-</text>
72
+ <ui-input
73
+ :placeholder="item.itemValue.endPlaceholder"
74
+ v-model="item.itemValue.end"
75
+ ></ui-input>
76
+ </view>
77
+ </view>
78
+ </ui-list-cell>
79
+ </ui-label>
80
+ </ui-radio-group>
81
+ <view class="tools">
82
+ <ui-form-button
83
+ width="200rpx"
84
+ height="70rpx"
85
+ color="#07C160"
86
+ background="rgba(0, 0, 0, 0.05)"
87
+ size="30"
88
+ borderWidth="0"
89
+ @click="close"
90
+ >取消</ui-form-button
91
+ >
92
+ <view style="width: 32rpx"></view>
93
+ <ui-form-button
94
+ width="200rpx"
95
+ height="70rpx"
96
+ color="#fff"
97
+ background="#07C160"
98
+ size="30"
99
+ borderWidth="0"
100
+ @click="confirm"
101
+ >完成</ui-form-button
102
+ >
103
+ </view>
104
+ </view>
105
+ </ui-bottom-popup>
106
+ </view>
107
+ </template>
108
+ <script setup lang="ts">
109
+ import { computed, reactive, ref, watch } from 'vue';
110
+ import { loopGetObjectValue } from '../../libs/utils';
111
+ interface listType {
112
+ label: string;
113
+ value: string | number;
114
+ checked: boolean;
115
+ itemValue?: { start: string; end: string };
116
+ }
117
+ interface IProps {
118
+ label: string;
119
+ placeholder: string;
120
+ arrowColor?: string;
121
+ arrow?: boolean;
122
+ arrowRight?: number | string;
123
+ padding?: string;
124
+ background?: string;
125
+ asterisk?: boolean;
126
+ asteriskRight?: number;
127
+ labelCenter?: boolean;
128
+ labelWidth?: number | string;
129
+ bottomBorder?: boolean;
130
+ borderColor?: string;
131
+ left?: number | string;
132
+ right?: number | string;
133
+ list: listType[];
134
+ value?: string | number;
135
+ disabled?: boolean;
136
+ }
137
+ const props = withDefaults(defineProps<IProps>(), {
138
+ label: '',
139
+ placeholder: '请选择',
140
+ arrow: true,
141
+ arrowColor: '',
142
+ arrowRight: 30,
143
+ asterisk: false,
144
+ asteriskRight: 6,
145
+ labelCenter: false,
146
+ labelWidth: 160,
147
+ bottomBorder: true,
148
+ borderColor: '',
149
+ left: 30,
150
+ right: 0,
151
+ list: [],
152
+ disabled: false
153
+ });
154
+ const emit = defineEmits<{
155
+ (e: 'confirm', item: listType, list: listType[]): void;
156
+ }>();
157
+
158
+ const copyList = ref(JSON.parse(JSON.stringify(props.list || [])));
159
+ const popupShow = ref(false);
160
+
161
+ const getArrowColor = computed(() => {
162
+ return (
163
+ props.arrowColor ||
164
+ loopGetObjectValue(['uiListCell', 'arrowColor'], uni.$ui) ||
165
+ '#c0c0c0'
166
+ );
167
+ });
168
+ const getPadding = computed(() => {
169
+ return (
170
+ props.padding ||
171
+ loopGetObjectValue(['uiFormItem', 'padding'], uni.$ui) ||
172
+ '26rpx 30rpx'
173
+ );
174
+ });
175
+ const getBgColor = computed(() => {
176
+ return (
177
+ props.background ||
178
+ loopGetObjectValue(['uiFormItem', 'background'], uni.$ui) ||
179
+ '#fff'
180
+ );
181
+ });
182
+ const getBorderColor = computed(() => {
183
+ return (
184
+ props.borderColor ||
185
+ loopGetObjectValue(['uiFormItem', 'borderColor'], uni.$ui) ||
186
+ '#eaeef1'
187
+ );
188
+ });
189
+
190
+ const popup = () => {
191
+ if (props.disabled) return;
192
+ popupShow.value = !popupShow.value;
193
+ };
194
+ const close = () => {
195
+ popupShow.value = false;
196
+ };
197
+
198
+ const confirm = () => {
199
+ const item = copyList.value.find((v) => v.checked);
200
+ if (!item) {
201
+ uni.showToast({
202
+ title: '请选择',
203
+ icon: 'none'
204
+ });
205
+ return;
206
+ }
207
+ if (item.itemValue) {
208
+ if (!item.itemValue.start || !item.itemValue.end) {
209
+ uni.showToast({
210
+ title: '请输入完整内容',
211
+ icon: 'none'
212
+ });
213
+ return;
214
+ }
215
+ }
216
+ console.log(item);
217
+ emit('confirm', item, JSON.parse(JSON.stringify(copyList.value)));
218
+ close();
219
+ };
220
+
221
+ const radioChange = (e) => {
222
+ const { value } = e.detail;
223
+ copyList.value.forEach((v) => {
224
+ if (v.value === value) {
225
+ v.checked = true;
226
+ } else {
227
+ v.checked = false;
228
+ }
229
+ });
230
+ };
231
+ const getValue = () => {
232
+ if (props?.value?.itemValue) {
233
+ return props?.value?.itemValue?.start + '-' + props?.value?.itemValue?.end;
234
+ }
235
+ if (props?.value?.label) {
236
+ return props?.value?.label;
237
+ }
238
+ return '';
239
+ };
240
+
241
+ watch(
242
+ () => props.list,
243
+ (value, oldValue) => {
244
+ copyList.value = JSON.parse(JSON.stringify(value));
245
+ }
246
+ );
247
+ </script>
248
+ <style scoped lang="scss">
249
+ @import '../../libs/css/form-select.scss';
250
+ </style>
@@ -0,0 +1,251 @@
1
+ <template>
2
+ <view class="goods-card bottom-border" @tap="itemTap">
3
+ <view class="goods-card_image">
4
+ <ui-lazyload-img
5
+ :width="imgWidth"
6
+ :height="imgHeight"
7
+ radius="8rpx"
8
+ :draggable="false"
9
+ :placeholder="imagePlaceholder"
10
+ backgroundColor="#f9f9f9"
11
+ :mode="imageMode"
12
+ :src="entity.image || ''"
13
+ ></ui-lazyload-img>
14
+ <!-- <view
15
+ :style="{
16
+ width: imgWidth,
17
+ height: imgHeight,
18
+ }"
19
+ v-if="errStatusText"
20
+ class="goods-status_error"
21
+ >{{ errStatusText }}</view
22
+ > -->
23
+ </view>
24
+ <view class="goods-card_info">
25
+ <view class="goods-card_info_title">
26
+ <ui-overflow-hidden size="24rpx">
27
+ <text class="text" :style="{ fontSize: textFontSize.title }">{{
28
+ entity.name
29
+ }}</text>
30
+ </ui-overflow-hidden>
31
+ </view>
32
+ <view class="goods-card_info_tag" v-if="entity.hasDiscount">
33
+ <ui-tag
34
+ type="danger"
35
+ padding="6rpx 10rpx"
36
+ :size="textFontSize.tag"
37
+ plain
38
+ ><view class="tag-box">
39
+ <image
40
+ class="icon icon_yh"
41
+ src="https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/5131a04c08bf4c80b73291f82186ce46.png"
42
+ />
43
+
44
+ <text>{{ getDiscount(entity.discount) }}</text>
45
+ </view></ui-tag
46
+ >
47
+ </view>
48
+ <view class="goods-card_info_sales-volume">
49
+ <text
50
+ class="goods-card_info_sales-volume_text"
51
+ :style="{ fontSize: textFontSize.salesVolume }"
52
+ >销量{{ ` ` }}{{ entity.saleCnt || 0 }}
53
+ </text>
54
+ </view>
55
+ <view class="goods-card_info_price">
56
+ <text
57
+ class="goods-card_info_price_preferential-price"
58
+ :style="{ fontSize: textFontSize.preferentialPrice }"
59
+ >
60
+ ¥{{ price }}/{{ entity?.unitTitle || '件' }}
61
+ </text>
62
+ <text
63
+ class="goods-card_info_price_price"
64
+ v-if="entity.hasDiscount"
65
+ :style="{ fontSize: textFontSize.price }"
66
+ >
67
+ ¥{{ entity.marketPriceShow }}/{{ entity.unitTitle || '件' }}
68
+ </text>
69
+ </view>
70
+ <view class="goods-card_info_status" v-if="errStatusText">
71
+ <text class="goods-card_info_status_text">{{ errStatusText }}</text>
72
+ </view>
73
+ <view class="goods-card_info_add" v-else>
74
+ <view
75
+ @tap.stop="addClick"
76
+ v-if="!goodsCount"
77
+ class="goods-card_info_add_icon"
78
+ >
79
+ <ui-icon name="add" :size="19" color="red"></ui-icon>
80
+ </view>
81
+ <view v-else class="number-box" @tap.stop="() => {}">
82
+ <ui-numberbox
83
+ :value="goodsCount"
84
+ :min="0"
85
+ :max="
86
+ entity.unlimitedInventory
87
+ ? 99999
88
+ : entity.inventoryCapacity || 100
89
+ "
90
+ @change="change"
91
+ @triggerMax="triggerMax"
92
+ :border="true"
93
+ :width="65"
94
+ :iconSize="19"
95
+ :size="22"
96
+ :step="1"
97
+ :backgroundColor="textFontSize.numberBoxBg"
98
+ iconColor="#C7C7CC"
99
+ ></ui-numberbox>
100
+ </view>
101
+ <ui-cubic-bezier
102
+ v-if="bezier"
103
+ right="0"
104
+ bottom="0"
105
+ :windowWidth="state.windowWidth"
106
+ :windowHeight="state.windowHeight"
107
+ :position="{ right: 110, bottom: 15 }"
108
+ direction="down"
109
+ :index="0"
110
+ @click="addClick"
111
+ ></ui-cubic-bezier>
112
+ </view>
113
+ </view>
114
+ </view>
115
+ </template>
116
+
117
+ <script setup lang="ts">
118
+ import { onMounted, reactive, computed } from 'vue';
119
+ import type { GoodsDataType, changeValueType } from '../interface/types';
120
+
121
+ interface IProps {
122
+ entity: GoodsDataType;
123
+ goodsCount: number;
124
+ imgWidth?: string;
125
+ imgHeight?: string;
126
+ bezier?: boolean;
127
+ goodMin?: number;
128
+ imagePlaceholder?: string;
129
+ imageMode?:
130
+ | 'scaleToFill'
131
+ | 'aspectFit'
132
+ | 'aspectFill'
133
+ | 'widthFix'
134
+ | 'top'
135
+ | 'bottom'
136
+ | 'center'
137
+ | 'left'
138
+ | 'right'
139
+ | 'top left'
140
+ | 'top right'
141
+ | 'bottom left'
142
+ | 'bottom right';
143
+ textFontSize?: {
144
+ title: string;
145
+ tag: string;
146
+ salesVolume: string;
147
+ preferentialPrice: string;
148
+ price: string;
149
+ numberBoxBg?: string;
150
+ };
151
+ }
152
+ const props = withDefaults(defineProps<IProps>(), {
153
+ imgWidth: '225rpx',
154
+ imgHeight: '225rpx',
155
+ goodMin: 0,
156
+ goodsCount: 0,
157
+ bezier: true,
158
+ imagePlaceholder:
159
+ 'https://shop-cdn.cbyzx.com/shop23n05y18abcd/img/3544375090854cd099d72edb09dce492.png',
160
+ imageMode: 'aspectFill',
161
+ textFontSize: {
162
+ title: '24rpx',
163
+ tag: '18rpx',
164
+ salesVolume: '20rpx',
165
+ preferentialPrice: '24rpx',
166
+ price: '20rpx',
167
+ numberBoxBg: '#fff'
168
+ },
169
+ entity: {
170
+ goodSrc: '',
171
+ title: '',
172
+ preferentialPrice: 0,
173
+ status: 0,
174
+ unit: '份'
175
+ }
176
+ });
177
+
178
+ const emit = defineEmits<{
179
+ (e: 'countChange', value: changeValueType, entity: GoodsDataType): void;
180
+ (e: 'handleClick', entity: GoodsDataType): void;
181
+ }>();
182
+
183
+ const price = computed(() => {
184
+ return props.entity.hasDiscount
185
+ ? props.entity.platformPriceShow
186
+ : props.entity.marketPriceShow;
187
+ });
188
+ const errStatusText = computed(() => {
189
+ if (props.entity.saleStatus === 20) {
190
+ return '已失效';
191
+ }
192
+ if (!props.entity.existInventory) {
193
+ return '无货';
194
+ }
195
+ });
196
+
197
+ const state = reactive({
198
+ windowWidth: 375,
199
+ windowHeight: 667
200
+ });
201
+
202
+ const getDiscount = (discount: number | string) => {
203
+ // if (discount === '' || discount === null || discount === undefined) return ''
204
+ // const value = Number(discount) * 10
205
+ return `${discount} 折`;
206
+ };
207
+
208
+ const change = (val: changeValueType) => {
209
+ // if (val.value > item.skuInfo.inventoryCapacity) {
210
+ // uni.showToast({
211
+ // title: '库存不足,最大库存为' + item.skuInfo.inventoryCapacity,
212
+ // icon: 'none',
213
+ // })
214
+ // }
215
+ emit('countChange', val, props.entity);
216
+ };
217
+
218
+ const triggerMax = () => {
219
+ uni.showModal({
220
+ title: '提示',
221
+ content: '库存不足,最大库存为' + props.entity.inventoryCapacity,
222
+ showCancel: false
223
+ });
224
+ };
225
+
226
+ const load = () => {
227
+ let sys = uni.getSystemInfoSync();
228
+ state.windowWidth = sys.windowWidth;
229
+ state.windowHeight = sys.windowHeight;
230
+ };
231
+
232
+ const itemTap = () => {
233
+ emit('handleClick', props.entity);
234
+ };
235
+
236
+ onMounted(() => {
237
+ load();
238
+ });
239
+
240
+ const addClick = () => {
241
+ change({
242
+ value: props.goodsCount + 1,
243
+ type: 'plus',
244
+ index: 0,
245
+ custom: {}
246
+ });
247
+ };
248
+ </script>
249
+ <style scoped lang="scss">
250
+ @import '../../libs/css/goods-card.scss';
251
+ </style>