@ecolovo/uniapp-components 2.0.1 → 2.0.3
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.
- package/components/aspect/aspect.vue +4 -2
- package/components/badge/badge.scss +3 -1
- package/components/badge/badge.vue +15 -11
- package/components/button/button.vue +100 -27
- package/components/checkbox/checkbox.scss +1 -1
- package/components/checkbox/checkbox.vue +54 -23
- package/components/checkbox-group/checkbox-group.vue +11 -4
- package/components/checkbox-group2/checkbox-group2.vue +23 -8
- package/components/checkbox-group2/checkbox2.vue +11 -4
- package/components/data-list/data-list.vue +25 -5
- package/components/date-picker/date-picker-view.vue +45 -16
- package/components/date-picker/date-picker.vue +58 -18
- package/components/dialog/dialog-content.vue +39 -12
- package/components/dialog/dialog.vue +30 -19
- package/components/dropdown/dropdown.vue +29 -6
- package/components/empty/empty.vue +10 -3
- package/components/flex/flex.vue +16 -6
- package/components/form-item/form-item.vue +13 -4
- package/components/icon/icon.scss +9 -0
- package/components/icon/icon.vue +46 -8
- package/components/image/image.vue +13 -8
- package/components/index.d.ts +50 -0
- package/components/index.js +50 -0
- package/components/index.ts +50 -0
- package/components/input/input.vue +13 -3
- package/components/input/password-input.vue +2 -2
- package/components/list-page/list-page.vue +24 -6
- package/components/load-more/load-more.vue +7 -2
- package/components/loading/animations/loading-animation3.vue +10 -5
- package/components/loading/animations/loading-animation4.vue +65 -8
- package/components/loading/loading.vue +7 -6
- package/components/message-box/message-box.d.ts +18 -0
- package/components/message-box/message-box.js +1 -0
- package/components/message-box/message-box.ts +18 -0
- package/components/message-box/message-box.vue +53 -21
- package/components/number-dialog/number-dialog.vue +61 -21
- package/components/number-input/number-input.vue +53 -18
- package/components/numpad/numpad.vue +11 -5
- package/components/page/page-body.scss +1 -1
- package/components/page/page-body.vue +79 -11
- package/components/page/page-footer.vue +11 -5
- package/components/page/page-header.vue +49 -24
- package/components/page/page.scss +2 -1
- package/components/page/page.vue +74 -29
- package/components/picker/picker-popup.vue +96 -68
- package/components/picker/picker.vue +11 -5
- package/components/popover/popover-content.vue +59 -19
- package/components/popover/popover-mask.vue +18 -11
- package/components/popover/popover.vue +13 -3
- package/components/popup/popup-content.vue +35 -11
- package/components/popup/popup.vue +36 -17
- package/components/price/price.scss +1 -0
- package/components/price/price.vue +18 -7
- package/components/search/search.vue +24 -10
- package/components/searching/searching.scss +14 -0
- package/components/searching/searching.vue +17 -10
- package/components/selector/selector.vue +10 -3
- package/components/switch/switch.vue +31 -10
- package/components/tab/tab.vue +41 -8
- package/components/textarea/textarea.vue +55 -13
- package/composable/component-name.js +2 -1
- package/composable/component-name.ts +2 -1
- package/composable/message-box.d.ts +35 -0
- package/composable/message-box.js +56 -0
- package/composable/message-box.ts +98 -0
- package/configs/index.d.ts +8 -1
- package/configs/index.js +14 -3
- package/configs/index.ts +8 -1
- package/easyCom.js +10 -5
- package/easyCom.ts +10 -5
- package/globals.d.ts +36 -0
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/index.ts +5 -0
- package/package.json +14 -6
- package/styles/global.scss +123 -2
- package/styles/reset.scss +5 -0
- package/styles/utils/css-var.scss +11 -11
- package/styles/utils/index.scss +0 -1
- package/styles/var/component.scss +23 -20
- package/styles/var/theme.scss +3 -3
- package/utils/date.d.ts +7 -2
- package/utils/date.js +31 -10
- package/utils/date.ts +20 -6
- package/utils/price.d.ts +4 -1
- package/utils/price.js +12 -7
- package/utils/price.ts +8 -3
- package/utils/round.js +4 -1
- package/utils/round.ts +4 -1
- package/utils/windowInfo.d.ts +0 -1
- package/styles/utils/z-index.scss +0 -10
|
@@ -22,7 +22,7 @@ defineOptions({
|
|
|
22
22
|
const classNames = useClassNames('aspect');
|
|
23
23
|
|
|
24
24
|
type _Props = {
|
|
25
|
-
/**
|
|
25
|
+
/** 高与宽的比例,默认为 1,即宽高相等,2 表示高为宽的 2 倍 */
|
|
26
26
|
ratio?: string | number;
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -34,7 +34,9 @@ defineEmits<{
|
|
|
34
34
|
(event: 'click'): void;
|
|
35
35
|
}>();
|
|
36
36
|
|
|
37
|
-
const inlineStyle = computed(
|
|
37
|
+
const inlineStyle = computed(
|
|
38
|
+
() => `padding-top: ${100 * Number(props.ratio)}%;`
|
|
39
|
+
);
|
|
38
40
|
</script>
|
|
39
41
|
|
|
40
42
|
<style lang="css" module>
|
|
@@ -40,13 +40,18 @@ const props = withDefaults(defineProps<_Props>(), {
|
|
|
40
40
|
max: 99,
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
defineEmits<{
|
|
44
|
-
(event: 'click'): void;
|
|
45
|
-
}>();
|
|
46
|
-
|
|
47
43
|
const showValue = computed(() => {
|
|
44
|
+
if (!props.value) return '';
|
|
45
|
+
|
|
48
46
|
const numberValue = Number(props.value);
|
|
49
|
-
|
|
47
|
+
// 如果传入的值不可转为数字,则原样显示
|
|
48
|
+
if (Number.isNaN(numberValue)) return props.value;
|
|
49
|
+
|
|
50
|
+
return numberValue && numberValue > 0
|
|
51
|
+
? numberValue > props.max
|
|
52
|
+
? `${props.max}+`
|
|
53
|
+
: numberValue
|
|
54
|
+
: '';
|
|
50
55
|
});
|
|
51
56
|
</script>
|
|
52
57
|
|
|
@@ -56,7 +61,7 @@ const showValue = computed(() => {
|
|
|
56
61
|
|
|
57
62
|
// 定义外部变量
|
|
58
63
|
%external-vars {
|
|
59
|
-
@include UTILS__DEFINE_COMPONENT_VARS(
|
|
64
|
+
@include UTILS__DEFINE_COMPONENT_VARS('badge', $badge);
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
$__translate: UTILS__LOCAL_VAR(translate);
|
|
@@ -65,6 +70,7 @@ $__height: UTILS__LOCAL_VAR(height);
|
|
|
65
70
|
$__border: UTILS__LOCAL_VAR(border);
|
|
66
71
|
$__color: UTILS__LOCAL_VAR(color);
|
|
67
72
|
$__background: UTILS__LOCAL_VAR(background);
|
|
73
|
+
$__padding-x: UTILS__LOCAL_VAR(padding-x);
|
|
68
74
|
|
|
69
75
|
.Badge {
|
|
70
76
|
@extend %external-vars;
|
|
@@ -74,16 +80,14 @@ $__background: UTILS__LOCAL_VAR(background);
|
|
|
74
80
|
width: fit-content;
|
|
75
81
|
|
|
76
82
|
.Badge--box {
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
box-sizing: border-box;
|
|
79
84
|
position: absolute;
|
|
80
85
|
top: 0;
|
|
81
86
|
right: 0;
|
|
82
87
|
z-index: 1;
|
|
83
|
-
padding: 0
|
|
84
|
-
box-sizing: content-box;
|
|
88
|
+
padding: 0 $__padding-x;
|
|
85
89
|
text-align: center;
|
|
86
|
-
min-width:
|
|
90
|
+
min-width: $__height;
|
|
87
91
|
height: $__height;
|
|
88
92
|
line-height: $__height;
|
|
89
93
|
font-size: $__font-size;
|
|
@@ -20,12 +20,24 @@
|
|
|
20
20
|
},
|
|
21
21
|
buttonSize,
|
|
22
22
|
]"
|
|
23
|
+
:disabled="isNotClickable"
|
|
23
24
|
:hover-class="disabled ? 'none' : $style['Button--active']"
|
|
24
25
|
:style="inlineCssVar"
|
|
25
26
|
@click="onClick"
|
|
27
|
+
@getphonenumber="$emit('getphonenumber', $event)"
|
|
28
|
+
@getuserinfo="$emit('getuserinfo', $event)"
|
|
29
|
+
@error="$emit('error', $event)"
|
|
30
|
+
@opensetting="$emit('opensetting', $event)"
|
|
31
|
+
@launchapp="$emit('launchapp', $event)"
|
|
32
|
+
@contact="$emit('contact', $event)"
|
|
33
|
+
@chooseavatar="$emit('chooseavatar', $event)"
|
|
34
|
+
@agreeprivacyauthorization="$emit('agreeprivacyauthorization', $event)"
|
|
26
35
|
>
|
|
27
36
|
<!-- 线性按钮边框:仅在线性按钮且不是禁用态时显示 -->
|
|
28
|
-
<view
|
|
37
|
+
<view
|
|
38
|
+
v-if="!disabled && !text && plain"
|
|
39
|
+
:class="$style['Button--plain-border']"
|
|
40
|
+
></view>
|
|
29
41
|
<!-- 仅在配置了图标或文本按钮处于加载态(不能处于禁用态)时显示 -->
|
|
30
42
|
<template v-if="text">
|
|
31
43
|
<icon-cpn
|
|
@@ -46,9 +58,15 @@
|
|
|
46
58
|
<slot></slot>
|
|
47
59
|
</view>
|
|
48
60
|
<!-- 点击态样式:仅在非文本按钮且不是禁用态时显示 -->
|
|
49
|
-
<view
|
|
61
|
+
<view
|
|
62
|
+
v-if="!disabled && !text"
|
|
63
|
+
:class="$style['Button--active-mask']"
|
|
64
|
+
></view>
|
|
50
65
|
<!-- 加载态样式:仅在非文本按钮处于加载态(不能处于禁用态)时显示 -->
|
|
51
|
-
<view
|
|
66
|
+
<view
|
|
67
|
+
v-if="!disabled && !text && isLoading"
|
|
68
|
+
:class="$style['Button--loading-icon']"
|
|
69
|
+
>
|
|
52
70
|
<icon-cpn icon="loading-dot-spinner" spinning />
|
|
53
71
|
</view>
|
|
54
72
|
</button>
|
|
@@ -59,6 +77,13 @@ import { computed, ref, useCssModule } from 'vue';
|
|
|
59
77
|
import useClassNames from '../../composable/component-name';
|
|
60
78
|
import IconCpn from '../icon/icon.vue';
|
|
61
79
|
|
|
80
|
+
/**
|
|
81
|
+
* **组件使用说明:**
|
|
82
|
+
*
|
|
83
|
+
* 当 async 为 false 时,组件会按传入的 coolDown 控制两次点击之间的间隔
|
|
84
|
+
* 当 async 为 true 时,需要在父组件监听 click 事件的回调函数中调用传入的 resolve 或 reject 方法,否则按钮将持续处于 loading 状态
|
|
85
|
+
*/
|
|
86
|
+
|
|
62
87
|
defineOptions({
|
|
63
88
|
options: {
|
|
64
89
|
styleIsolation: 'shared',
|
|
@@ -77,7 +102,12 @@ type _Props = {
|
|
|
77
102
|
/** 按钮主题 */
|
|
78
103
|
type?: string;
|
|
79
104
|
/** 对应小程序的 openType */
|
|
80
|
-
openType?:
|
|
105
|
+
openType?:
|
|
106
|
+
| 'contact'
|
|
107
|
+
| 'getPhoneNumber'
|
|
108
|
+
| 'getUserInfo'
|
|
109
|
+
| 'chooseAvatar'
|
|
110
|
+
| 'agreePrivacyAuthorization';
|
|
81
111
|
/** 按钮冷却时间,单位毫秒,两次点击之间的最小间隔,为 `0` 时可连续点击 */
|
|
82
112
|
coolDown?: number;
|
|
83
113
|
/** 是否异步事件 */
|
|
@@ -115,7 +145,15 @@ const props = withDefaults(defineProps<_Props>(), {
|
|
|
115
145
|
});
|
|
116
146
|
|
|
117
147
|
const emit = defineEmits<{
|
|
118
|
-
(event: 'click', payload?:
|
|
148
|
+
(event: 'click', payload?: UniApp.PromiseResolvers<unknown>): void;
|
|
149
|
+
(event: 'getphonenumber', payload?: UniApp.GetPhoneNumberEvent): void;
|
|
150
|
+
(event: 'getuserinfo', payload?: unknown): void;
|
|
151
|
+
(event: 'error', payload?: unknown): void;
|
|
152
|
+
(event: 'opensetting', payload?: unknown): void;
|
|
153
|
+
(event: 'launchapp', payload?: unknown): void;
|
|
154
|
+
(event: 'contact', payload?: unknown): void;
|
|
155
|
+
(event: 'chooseavatar', payload?: unknown): void;
|
|
156
|
+
(event: 'agreeprivacyauthorization', payload?: unknown): void;
|
|
119
157
|
}>();
|
|
120
158
|
|
|
121
159
|
/** 按钮是否冷却中 */
|
|
@@ -123,19 +161,35 @@ const isCoolingDown = ref(false);
|
|
|
123
161
|
/** 按钮是否处于请求状态 */
|
|
124
162
|
const isAsyncLoading = ref(false);
|
|
125
163
|
|
|
126
|
-
/**
|
|
127
|
-
const inlineCssVar = computed(
|
|
164
|
+
/** 按钮主题样式 */
|
|
165
|
+
const inlineCssVar = computed(
|
|
166
|
+
() => `--theme-from-prop: var(--button-theme-${props.type});`
|
|
167
|
+
);
|
|
128
168
|
/** 按钮尺寸样式 */
|
|
129
169
|
const buttonSize = computed(() => {
|
|
130
170
|
if (props.text) {
|
|
131
|
-
return props.large
|
|
171
|
+
return props.large
|
|
172
|
+
? $style['Button--text-large']
|
|
173
|
+
: props.small
|
|
174
|
+
? $style['Button--text-small']
|
|
175
|
+
: '';
|
|
132
176
|
}
|
|
133
|
-
return props.large
|
|
177
|
+
return props.large
|
|
178
|
+
? $style['Button--block-large']
|
|
179
|
+
: props.small
|
|
180
|
+
? $style['Button--block-small']
|
|
181
|
+
: '';
|
|
134
182
|
});
|
|
135
|
-
/**
|
|
183
|
+
/** 按钮是否处于 loading 状态 */
|
|
136
184
|
const isLoading = computed(() => props.loading || isAsyncLoading.value);
|
|
137
|
-
/**
|
|
138
|
-
const isNotClickable = computed(
|
|
185
|
+
/** 按钮是否可被点击 */
|
|
186
|
+
const isNotClickable = computed(
|
|
187
|
+
() =>
|
|
188
|
+
props.disabled ||
|
|
189
|
+
props.forbidClick ||
|
|
190
|
+
isLoading.value ||
|
|
191
|
+
isCoolingDown.value
|
|
192
|
+
);
|
|
139
193
|
|
|
140
194
|
/** 进入冷却 */
|
|
141
195
|
const $_coolDown = () => {
|
|
@@ -147,8 +201,9 @@ const $_coolDown = () => {
|
|
|
147
201
|
}, props.coolDown);
|
|
148
202
|
}
|
|
149
203
|
};
|
|
204
|
+
|
|
150
205
|
/** 点击按钮响应 */
|
|
151
|
-
const onClick =
|
|
206
|
+
const onClick = () => {
|
|
152
207
|
if (isNotClickable.value) {
|
|
153
208
|
return;
|
|
154
209
|
}
|
|
@@ -161,7 +216,13 @@ const onClick = async () => {
|
|
|
161
216
|
}
|
|
162
217
|
|
|
163
218
|
isAsyncLoading.value = true;
|
|
164
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
219
|
+
// const { promise, resolve, reject } = Promise.withResolvers();
|
|
220
|
+
let resolve: UniApp.PromiseResolver<unknown>,
|
|
221
|
+
reject: UniApp.PromiseRejector<unknown>;
|
|
222
|
+
const promise = new Promise((res, rej) => {
|
|
223
|
+
resolve = res;
|
|
224
|
+
reject = rej;
|
|
225
|
+
});
|
|
165
226
|
promise.finally(() => {
|
|
166
227
|
isAsyncLoading.value = false;
|
|
167
228
|
});
|
|
@@ -180,7 +241,7 @@ const onClick = async () => {
|
|
|
180
241
|
|
|
181
242
|
// 定义外部变量
|
|
182
243
|
%external-vars {
|
|
183
|
-
@include UTILS__DEFINE_COMPONENT_VARS(
|
|
244
|
+
@include UTILS__DEFINE_COMPONENT_VARS('button', $button);
|
|
184
245
|
}
|
|
185
246
|
|
|
186
247
|
%button-themes {
|
|
@@ -228,6 +289,25 @@ $button-sizes: (
|
|
|
228
289
|
.Button {
|
|
229
290
|
@extend %external-vars;
|
|
230
291
|
@extend %button-themes;
|
|
292
|
+
--button-color: #{UTILS__LOCAL_VAR(text-color)};
|
|
293
|
+
--button-background: #{UTILS__LOCAL_VAR(theme)};
|
|
294
|
+
color: var(--button-color);
|
|
295
|
+
background: var(--button-background);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.Button[disabled]:not([type]),
|
|
299
|
+
.Button[disabled][type='default'] {
|
|
300
|
+
color: var(--button-color);
|
|
301
|
+
background: var(--button-background);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.Button--plain,
|
|
305
|
+
.Button-text {
|
|
306
|
+
--button-color: var(
|
|
307
|
+
#{UTILS__VAR_NAME('button', text-color)},
|
|
308
|
+
#{UTILS__LOCAL_VAR(theme)}
|
|
309
|
+
);
|
|
310
|
+
--button-background: transparent;
|
|
231
311
|
}
|
|
232
312
|
|
|
233
313
|
.Button--block {
|
|
@@ -241,8 +321,6 @@ $button-sizes: (
|
|
|
241
321
|
text-decoration: none;
|
|
242
322
|
text-align: center;
|
|
243
323
|
overflow: hidden;
|
|
244
|
-
color: UTILS__LOCAL_VAR(text-color);
|
|
245
|
-
background: UTILS__LOCAL_VAR(theme);
|
|
246
324
|
border: none;
|
|
247
325
|
|
|
248
326
|
@include button-size('block', 'normal');
|
|
@@ -275,7 +353,7 @@ $button-sizes: (
|
|
|
275
353
|
}
|
|
276
354
|
}
|
|
277
355
|
|
|
278
|
-
.Button--loading {
|
|
356
|
+
.Button--loading-icon {
|
|
279
357
|
position: absolute;
|
|
280
358
|
top: 50%;
|
|
281
359
|
left: 50%;
|
|
@@ -285,8 +363,8 @@ $button-sizes: (
|
|
|
285
363
|
}
|
|
286
364
|
|
|
287
365
|
&.Button--disabled {
|
|
288
|
-
color: #fff;
|
|
289
|
-
background: #ccc;
|
|
366
|
+
--button-color: #fff;
|
|
367
|
+
--button-background: #ccc;
|
|
290
368
|
}
|
|
291
369
|
}
|
|
292
370
|
|
|
@@ -309,9 +387,6 @@ $button-sizes: (
|
|
|
309
387
|
}
|
|
310
388
|
|
|
311
389
|
.Button--plain {
|
|
312
|
-
color: UTILS__LOCAL_VAR(theme);
|
|
313
|
-
background: transparent;
|
|
314
|
-
|
|
315
390
|
.Button--plain-border {
|
|
316
391
|
position: absolute;
|
|
317
392
|
top: 0;
|
|
@@ -329,9 +404,7 @@ $button-sizes: (
|
|
|
329
404
|
@extend %button-reset;
|
|
330
405
|
display: inline-block;
|
|
331
406
|
padding: 0;
|
|
332
|
-
color: UTILS__LOCAL_VAR(theme);
|
|
333
407
|
line-height: inherit;
|
|
334
|
-
background: transparent;
|
|
335
408
|
font-weight: inherit;
|
|
336
409
|
will-change: color;
|
|
337
410
|
|
|
@@ -347,11 +420,11 @@ $button-sizes: (
|
|
|
347
420
|
|
|
348
421
|
&.Button--active,
|
|
349
422
|
&.Button--not-clickable {
|
|
350
|
-
color: #999;
|
|
423
|
+
--button-color: #999;
|
|
351
424
|
}
|
|
352
425
|
|
|
353
426
|
&.Button--disabled {
|
|
354
|
-
color: #ccc;
|
|
427
|
+
--button-color: #ccc;
|
|
355
428
|
}
|
|
356
429
|
}
|
|
357
430
|
</style>
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
v-if="hasIcon"
|
|
5
5
|
:icon="usingIcon || ''"
|
|
6
6
|
tap-size="50rpx"
|
|
7
|
-
:class="[
|
|
7
|
+
:class="[
|
|
8
|
+
$style['Checkbox--icon'],
|
|
9
|
+
{ [$style['Checkbox--checked']]: isChecked },
|
|
10
|
+
]"
|
|
8
11
|
/>
|
|
9
12
|
<view :class="$style['Checkbox--text']">
|
|
10
13
|
<slot>{{ label }}</slot>
|
|
@@ -13,7 +16,8 @@
|
|
|
13
16
|
</template>
|
|
14
17
|
|
|
15
18
|
<script lang="ts" setup>
|
|
16
|
-
import { computed,
|
|
19
|
+
import { computed, inject, ref } from 'vue';
|
|
20
|
+
import type { ComputedRef, Ref } from 'vue';
|
|
17
21
|
import IconCpn from '../icon/icon.vue';
|
|
18
22
|
import useClassNames from '../../composable/component-name';
|
|
19
23
|
|
|
@@ -25,23 +29,26 @@ defineOptions({
|
|
|
25
29
|
});
|
|
26
30
|
|
|
27
31
|
const classNames = useClassNames('checkbox');
|
|
32
|
+
|
|
28
33
|
/** 表单是否只读 */
|
|
29
34
|
const isFormReadonly = inject<ComputedRef<boolean>>(
|
|
30
35
|
'ecolovo/form/readonly',
|
|
31
36
|
computed(() => false)
|
|
32
37
|
);
|
|
33
38
|
/** 勾选框组当前选中值 */
|
|
34
|
-
const groupCheckedValue = inject<
|
|
35
|
-
|
|
36
|
-
);
|
|
39
|
+
const groupCheckedValue = inject<
|
|
40
|
+
Ref<undefined | string | number | boolean | Array<unknown>>
|
|
41
|
+
>('ecolovo/checkboxGroup/checkedValue', ref(undefined));
|
|
37
42
|
/** 勾选框组的 props */
|
|
38
|
-
const groupProps = inject<null | Pick<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
43
|
+
const groupProps = inject<null | Pick<
|
|
44
|
+
_Props,
|
|
45
|
+
'radio' | 'icon' | 'checkedIcon' | 'uncheckedIcon'
|
|
46
|
+
>>('ecolovo/checkboxGroup/props', null);
|
|
42
47
|
/** 勾选框组勾选选项方法 */
|
|
43
|
-
const groupCheck =
|
|
44
|
-
|
|
48
|
+
const groupCheck = inject<
|
|
49
|
+
| null
|
|
50
|
+
| ((val: undefined | string | number | boolean | Array<unknown>) => void)
|
|
51
|
+
>('ecolovo/checkboxGroup/check', null);
|
|
45
52
|
|
|
46
53
|
type _Props = {
|
|
47
54
|
/** 不在勾选框组中时使用,用于 v-model ,只能是 boolean 类型 */
|
|
@@ -80,33 +87,57 @@ const emit = defineEmits<{
|
|
|
80
87
|
|
|
81
88
|
const innerChecked = ref(false);
|
|
82
89
|
|
|
90
|
+
/** 是否只读 */
|
|
91
|
+
const isReadonly = computed<boolean>(() =>
|
|
92
|
+
props.readonly !== undefined ? props.readonly : isFormReadonly.value
|
|
93
|
+
);
|
|
83
94
|
/** 是否在 checkbox-group 中 */
|
|
84
95
|
const isInCheckboxGroup = computed<boolean>(() => !!groupProps);
|
|
85
|
-
/** 是否只读 */
|
|
86
|
-
const isReadonly = computed<boolean>(() => (props.readonly !== undefined ? props.readonly : isFormReadonly.value));
|
|
87
96
|
/** 是否显示勾选图标 */
|
|
88
|
-
const hasIcon = computed<boolean>(() =>
|
|
97
|
+
const hasIcon = computed<boolean>(() =>
|
|
98
|
+
props.icon !== undefined ? props.icon : groupProps?.icon ?? true
|
|
99
|
+
);
|
|
89
100
|
/** 是否为单选 */
|
|
90
|
-
const isRadio = computed<boolean>(() =>
|
|
101
|
+
const isRadio = computed<boolean>(() =>
|
|
102
|
+
props.radio !== undefined ? props.radio : groupProps?.radio || false
|
|
103
|
+
);
|
|
91
104
|
/** 最终使用的选中态的图标 */
|
|
92
105
|
const usingCheckedIcon = computed<string>(
|
|
93
|
-
() =>
|
|
106
|
+
() =>
|
|
107
|
+
props.checkedIcon ||
|
|
108
|
+
groupProps?.checkedIcon ||
|
|
109
|
+
(isRadio.value ? 'radio-checked' : 'checkbox-checked')
|
|
94
110
|
);
|
|
95
111
|
/** 最终使用的未选中态的图标 */
|
|
96
112
|
const usingUncheckedIcon = computed(
|
|
97
|
-
() =>
|
|
113
|
+
() =>
|
|
114
|
+
props.uncheckedIcon ||
|
|
115
|
+
groupProps?.uncheckedIcon ||
|
|
116
|
+
(isRadio.value ? 'radio-unchecked' : 'checkbox-unchecked')
|
|
98
117
|
);
|
|
99
118
|
/** 最终使用的图标 */
|
|
100
|
-
const usingIcon = computed(() =>
|
|
119
|
+
const usingIcon = computed(() =>
|
|
120
|
+
isChecked.value ? usingCheckedIcon.value : usingUncheckedIcon.value
|
|
121
|
+
);
|
|
101
122
|
/** 是否勾选 */
|
|
102
123
|
const isChecked = computed<boolean>({
|
|
103
124
|
get() {
|
|
104
125
|
if (isInCheckboxGroup.value) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
126
|
+
if (isRadio.value) return props.value === groupCheckedValue.value;
|
|
127
|
+
if (
|
|
128
|
+
groupCheckedValue.value !== undefined &&
|
|
129
|
+
groupCheckedValue.value !== null &&
|
|
130
|
+
!Array.isArray(groupCheckedValue.value)
|
|
131
|
+
) {
|
|
132
|
+
throw Error(
|
|
133
|
+
'CheckboxGroup 的值应为数组类型,或将其设为 radio 类型'
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
return groupCheckedValue.value?.includes(props.value) || false;
|
|
108
137
|
}
|
|
109
|
-
return props.modelValue === undefined
|
|
138
|
+
return props.modelValue === undefined
|
|
139
|
+
? innerChecked.value
|
|
140
|
+
: (props.modelValue as boolean);
|
|
110
141
|
},
|
|
111
142
|
set(val) {
|
|
112
143
|
emit('update:modelValue', val);
|
|
@@ -141,7 +172,7 @@ const toggle = (checked?: boolean) => {
|
|
|
141
172
|
|
|
142
173
|
// 定义外部变量
|
|
143
174
|
%external-vars {
|
|
144
|
-
@include UTILS__DEFINE_COMPONENT_VARS(
|
|
175
|
+
@include UTILS__DEFINE_COMPONENT_VARS('checkbox', $checkbox);
|
|
145
176
|
}
|
|
146
177
|
|
|
147
178
|
.Checkbox {
|
|
@@ -39,15 +39,22 @@ const props = withDefaults(defineProps<_Props>(), {
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
const emit = defineEmits<{
|
|
42
|
-
(
|
|
42
|
+
(
|
|
43
|
+
event: 'update:modelValue',
|
|
44
|
+
value?: string | number | boolean | Array<unknown>
|
|
45
|
+
): void;
|
|
43
46
|
(event: 'change', value?: string | number | boolean | Array<unknown>): void;
|
|
44
47
|
}>();
|
|
45
48
|
|
|
46
|
-
const checkedValue = ref<
|
|
49
|
+
const checkedValue = ref<
|
|
50
|
+
undefined | string | number | boolean | Array<unknown>
|
|
51
|
+
>(undefined);
|
|
47
52
|
|
|
48
53
|
const currentValue = computed({
|
|
49
54
|
get: function () {
|
|
50
|
-
return props.modelValue === undefined
|
|
55
|
+
return props.modelValue === undefined
|
|
56
|
+
? checkedValue.value
|
|
57
|
+
: props.modelValue;
|
|
51
58
|
},
|
|
52
59
|
set: function (val) {
|
|
53
60
|
if (checkedValue.value === val) return;
|
|
@@ -95,7 +102,7 @@ provide('ecolovo/checkboxGroup/check', check);
|
|
|
95
102
|
</script>
|
|
96
103
|
|
|
97
104
|
<style lang="scss" module>
|
|
98
|
-
@use '../../styles/
|
|
105
|
+
@use '../../styles/utils' as *;
|
|
99
106
|
|
|
100
107
|
.CheckboxGroup {
|
|
101
108
|
flex: 1;
|
|
@@ -4,11 +4,19 @@
|
|
|
4
4
|
v-for="(item, index) in options"
|
|
5
5
|
:key="index"
|
|
6
6
|
:value="
|
|
7
|
-
radio
|
|
7
|
+
radio
|
|
8
|
+
? item.value === currentValue
|
|
9
|
+
: Array.isArray(currentValue) &&
|
|
10
|
+
currentValue.includes(item.value)
|
|
8
11
|
"
|
|
9
12
|
:icon="icon"
|
|
10
|
-
:checked-icon="
|
|
11
|
-
|
|
13
|
+
:checked-icon="
|
|
14
|
+
checkedIcon || (radio ? 'radio-checked' : 'checkbox-checked')
|
|
15
|
+
"
|
|
16
|
+
:unchecked-icon="
|
|
17
|
+
uncheckedIcon ||
|
|
18
|
+
(radio ? 'radio-unchecked' : 'checkbox-unchecked')
|
|
19
|
+
"
|
|
12
20
|
:class="$style['CheckboxGroup2--item']"
|
|
13
21
|
@change="check(item.value)"
|
|
14
22
|
>
|
|
@@ -29,7 +37,7 @@ defineOptions({
|
|
|
29
37
|
},
|
|
30
38
|
});
|
|
31
39
|
|
|
32
|
-
const classNames = useClassNames('
|
|
40
|
+
const classNames = useClassNames('checkbox-group2');
|
|
33
41
|
|
|
34
42
|
type OptionValue = string | number | boolean;
|
|
35
43
|
interface _Option {
|
|
@@ -70,7 +78,9 @@ const checkedValue = ref<OptionValue | OptionValue[]>();
|
|
|
70
78
|
|
|
71
79
|
const currentValue = computed<undefined | OptionValue | OptionValue[]>({
|
|
72
80
|
get() {
|
|
73
|
-
return props.modelValue === undefined
|
|
81
|
+
return props.modelValue === undefined
|
|
82
|
+
? checkedValue.value
|
|
83
|
+
: props.modelValue;
|
|
74
84
|
},
|
|
75
85
|
set(val) {
|
|
76
86
|
emit('update:modelValue', val);
|
|
@@ -117,11 +127,16 @@ const toggle = (isSelectedAll: boolean | OptionValue | OptionValue[]) => {
|
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
if (Array.isArray(isSelectedAll)) {
|
|
120
|
-
currentValue.value = isSelectedAll.filter((item) =>
|
|
130
|
+
currentValue.value = isSelectedAll.filter((item) =>
|
|
131
|
+
optionsValue.value.includes(item)
|
|
132
|
+
);
|
|
121
133
|
return;
|
|
122
134
|
}
|
|
123
135
|
|
|
124
|
-
if (
|
|
136
|
+
if (
|
|
137
|
+
Array.isArray(currentValue.value) &&
|
|
138
|
+
currentValue.value.length === props.options.length
|
|
139
|
+
) {
|
|
125
140
|
currentValue.value = [];
|
|
126
141
|
} else {
|
|
127
142
|
currentValue.value = optionsValue.value;
|
|
@@ -132,7 +147,7 @@ defineExpose({ toggle });
|
|
|
132
147
|
</script>
|
|
133
148
|
|
|
134
149
|
<style lang="scss" module>
|
|
135
|
-
@use '../../styles/
|
|
150
|
+
@use '../../styles/utils' as *;
|
|
136
151
|
|
|
137
152
|
.CheckboxGroup2 {
|
|
138
153
|
display: flex;
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
<view :class="[...classNames, $style['Checkbox2']]" @click="toggle()">
|
|
3
3
|
<icon-cpn
|
|
4
4
|
v-if="icon"
|
|
5
|
-
:icon="
|
|
5
|
+
:icon="
|
|
6
|
+
currentValue
|
|
7
|
+
? checkedIcon || 'checkbox-checked'
|
|
8
|
+
: uncheckedIcon || 'checkbox-unchecked'
|
|
9
|
+
"
|
|
6
10
|
tap-size="50rpx"
|
|
7
|
-
:class="[
|
|
11
|
+
:class="[
|
|
12
|
+
$style['Checkbox2--icon'],
|
|
13
|
+
{ [$style['Checkbox2--checked']]: currentValue },
|
|
14
|
+
]"
|
|
8
15
|
/>
|
|
9
16
|
<view :class="$style['Checkbox2--text']">
|
|
10
17
|
<slot></slot>
|
|
@@ -24,7 +31,7 @@ defineOptions({
|
|
|
24
31
|
},
|
|
25
32
|
});
|
|
26
33
|
|
|
27
|
-
const classNames = useClassNames('
|
|
34
|
+
const classNames = useClassNames('checkbox2');
|
|
28
35
|
|
|
29
36
|
type _Props = {
|
|
30
37
|
/** 选项值 */
|
|
@@ -81,7 +88,7 @@ const toggle = (checked?: boolean) => {
|
|
|
81
88
|
|
|
82
89
|
// 定义外部变量
|
|
83
90
|
%external-vars {
|
|
84
|
-
@include UTILS__DEFINE_COMPONENT_VARS(
|
|
91
|
+
@include UTILS__DEFINE_COMPONENT_VARS('checkbox', $checkbox);
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
.Checkbox2 {
|
|
@@ -10,13 +10,23 @@
|
|
|
10
10
|
@load-more="$emit('load-more')"
|
|
11
11
|
/>
|
|
12
12
|
|
|
13
|
-
<view
|
|
13
|
+
<view
|
|
14
|
+
v-if="pagingData && pagingData.hasMore"
|
|
15
|
+
:class="$style['DataList--observe-view']"
|
|
16
|
+
></view>
|
|
14
17
|
</view>
|
|
15
18
|
</template>
|
|
16
19
|
|
|
17
20
|
<script lang="ts" setup>
|
|
18
|
-
import {
|
|
19
|
-
|
|
21
|
+
import {
|
|
22
|
+
getCurrentInstance,
|
|
23
|
+
onBeforeUnmount,
|
|
24
|
+
onMounted,
|
|
25
|
+
useCssModule,
|
|
26
|
+
watch,
|
|
27
|
+
} from 'vue';
|
|
28
|
+
import type { WatchStopHandle } from 'vue';
|
|
29
|
+
import type { PagingData } from '@ecolovo/utils';
|
|
20
30
|
import useClassNames from '../../composable/component-name';
|
|
21
31
|
import LoadMoreCpn from '../load-more/load-more.vue';
|
|
22
32
|
|
|
@@ -68,7 +78,7 @@ const stopObserver = () => {
|
|
|
68
78
|
_observer?.disconnect();
|
|
69
79
|
};
|
|
70
80
|
|
|
71
|
-
let _stopHasMoreWatcher:
|
|
81
|
+
let _stopHasMoreWatcher: WatchStopHandle | null = null;
|
|
72
82
|
|
|
73
83
|
onMounted(() => {
|
|
74
84
|
_stopHasMoreWatcher = watch(
|
|
@@ -94,7 +104,17 @@ onBeforeUnmount(() => {
|
|
|
94
104
|
|
|
95
105
|
// 定义外部变量
|
|
96
106
|
%external-vars {
|
|
97
|
-
@include UTILS__DEFINE_COMPONENT_VARS(
|
|
107
|
+
@include UTILS__DEFINE_COMPONENT_VARS('data-list', $data-list);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
:host {
|
|
111
|
+
position: relative;
|
|
112
|
+
display: block;
|
|
113
|
+
width: 100%;
|
|
114
|
+
|
|
115
|
+
flex: 1;
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
98
118
|
}
|
|
99
119
|
|
|
100
120
|
.DataList {
|