@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.
Files changed (91) hide show
  1. package/components/aspect/aspect.vue +4 -2
  2. package/components/badge/badge.scss +3 -1
  3. package/components/badge/badge.vue +15 -11
  4. package/components/button/button.vue +100 -27
  5. package/components/checkbox/checkbox.scss +1 -1
  6. package/components/checkbox/checkbox.vue +54 -23
  7. package/components/checkbox-group/checkbox-group.vue +11 -4
  8. package/components/checkbox-group2/checkbox-group2.vue +23 -8
  9. package/components/checkbox-group2/checkbox2.vue +11 -4
  10. package/components/data-list/data-list.vue +25 -5
  11. package/components/date-picker/date-picker-view.vue +45 -16
  12. package/components/date-picker/date-picker.vue +58 -18
  13. package/components/dialog/dialog-content.vue +39 -12
  14. package/components/dialog/dialog.vue +30 -19
  15. package/components/dropdown/dropdown.vue +29 -6
  16. package/components/empty/empty.vue +10 -3
  17. package/components/flex/flex.vue +16 -6
  18. package/components/form-item/form-item.vue +13 -4
  19. package/components/icon/icon.scss +9 -0
  20. package/components/icon/icon.vue +46 -8
  21. package/components/image/image.vue +13 -8
  22. package/components/index.d.ts +50 -0
  23. package/components/index.js +50 -0
  24. package/components/index.ts +50 -0
  25. package/components/input/input.vue +13 -3
  26. package/components/input/password-input.vue +2 -2
  27. package/components/list-page/list-page.vue +24 -6
  28. package/components/load-more/load-more.vue +7 -2
  29. package/components/loading/animations/loading-animation3.vue +10 -5
  30. package/components/loading/animations/loading-animation4.vue +65 -8
  31. package/components/loading/loading.vue +7 -6
  32. package/components/message-box/message-box.d.ts +18 -0
  33. package/components/message-box/message-box.js +1 -0
  34. package/components/message-box/message-box.ts +18 -0
  35. package/components/message-box/message-box.vue +53 -21
  36. package/components/number-dialog/number-dialog.vue +61 -21
  37. package/components/number-input/number-input.vue +53 -18
  38. package/components/numpad/numpad.vue +11 -5
  39. package/components/page/page-body.scss +1 -1
  40. package/components/page/page-body.vue +79 -11
  41. package/components/page/page-footer.vue +11 -5
  42. package/components/page/page-header.vue +49 -24
  43. package/components/page/page.scss +2 -1
  44. package/components/page/page.vue +74 -29
  45. package/components/picker/picker-popup.vue +96 -68
  46. package/components/picker/picker.vue +11 -5
  47. package/components/popover/popover-content.vue +59 -19
  48. package/components/popover/popover-mask.vue +18 -11
  49. package/components/popover/popover.vue +13 -3
  50. package/components/popup/popup-content.vue +35 -11
  51. package/components/popup/popup.vue +36 -17
  52. package/components/price/price.scss +1 -0
  53. package/components/price/price.vue +18 -7
  54. package/components/search/search.vue +24 -10
  55. package/components/searching/searching.scss +14 -0
  56. package/components/searching/searching.vue +17 -10
  57. package/components/selector/selector.vue +10 -3
  58. package/components/switch/switch.vue +31 -10
  59. package/components/tab/tab.vue +41 -8
  60. package/components/textarea/textarea.vue +55 -13
  61. package/composable/component-name.js +2 -1
  62. package/composable/component-name.ts +2 -1
  63. package/composable/message-box.d.ts +35 -0
  64. package/composable/message-box.js +56 -0
  65. package/composable/message-box.ts +98 -0
  66. package/configs/index.d.ts +8 -1
  67. package/configs/index.js +14 -3
  68. package/configs/index.ts +8 -1
  69. package/easyCom.js +10 -5
  70. package/easyCom.ts +10 -5
  71. package/globals.d.ts +36 -0
  72. package/index.d.ts +5 -0
  73. package/index.js +5 -0
  74. package/index.ts +5 -0
  75. package/package.json +14 -6
  76. package/styles/global.scss +123 -2
  77. package/styles/reset.scss +5 -0
  78. package/styles/utils/css-var.scss +11 -11
  79. package/styles/utils/index.scss +0 -1
  80. package/styles/var/component.scss +23 -20
  81. package/styles/var/theme.scss +3 -3
  82. package/utils/date.d.ts +7 -2
  83. package/utils/date.js +31 -10
  84. package/utils/date.ts +20 -6
  85. package/utils/price.d.ts +4 -1
  86. package/utils/price.js +12 -7
  87. package/utils/price.ts +8 -3
  88. package/utils/round.js +4 -1
  89. package/utils/round.ts +4 -1
  90. package/utils/windowInfo.d.ts +0 -1
  91. 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(() => `padding-top: ${100 * Number(props.ratio)}%;`);
37
+ const inlineStyle = computed(
38
+ () => `padding-top: ${100 * Number(props.ratio)}%;`
39
+ );
38
40
  </script>
39
41
 
40
42
  <style lang="css" module>
@@ -15,6 +15,8 @@ $badge-default: (
15
15
  // 边框样式
16
16
  border: none,
17
17
  // 徽章高度
18
- height: calc(#{UTILS__LOCAL_VAR(font-size)} + 12rpx)
18
+ height: calc(#{UTILS__LOCAL_VAR(font-size)} + 12rpx),
19
+ // 徽章内边距-x
20
+ padding-x: 0.25em
19
21
  );
20
22
  $badge: map.merge($badge-default, $badge);
@@ -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
- return numberValue && numberValue > 0 ? (numberValue > props.max ? `${props.max}+` : numberValue) : '';
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($badge, 'badge');
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
- --padding-x: calc(#{$__font-size} / 2);
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 var(--padding-x);
84
- box-sizing: content-box;
88
+ padding: 0 $__padding-x;
85
89
  text-align: center;
86
- min-width: calc(#{$__height} - 2 * var(--padding-x));
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 v-if="!disabled && !text && plain" :class="$style['Button--plain-border']"></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 v-if="!disabled && !text" :class="$style['Button--active-mask']"></view>
61
+ <view
62
+ v-if="!disabled && !text"
63
+ :class="$style['Button--active-mask']"
64
+ ></view>
50
65
  <!-- 加载态样式:仅在非文本按钮处于加载态(不能处于禁用态)时显示 -->
51
- <view v-if="!disabled && !text && isLoading" :class="$style['Button--loading']">
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?: 'contact' | 'getPhoneNumber' | 'getUserInfo' | 'chooseAvatar' | 'agreePrivacyAuthorization';
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?: Omit<PromiseWithResolvers<unknown>, 'promise'>): void;
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
- /** 按钮 loading */
127
- const inlineCssVar = computed(() => `--theme-from-prop: var(--button-theme-${props.type});`);
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 ? $style['Button--text-large'] : props.small ? $style['Button--text-small'] : '';
171
+ return props.large
172
+ ? $style['Button--text-large']
173
+ : props.small
174
+ ? $style['Button--text-small']
175
+ : '';
132
176
  }
133
- return props.large ? $style['Button--block-large'] : props.small ? $style['Button--block-small'] : '';
177
+ return props.large
178
+ ? $style['Button--block-large']
179
+ : props.small
180
+ ? $style['Button--block-small']
181
+ : '';
134
182
  });
135
- /** 按钮 loading */
183
+ /** 按钮是否处于 loading 状态 */
136
184
  const isLoading = computed(() => props.loading || isAsyncLoading.value);
137
- /** 按钮是否可点击 */
138
- const isNotClickable = computed(() => props.disabled || props.forbidClick || isLoading.value || isCoolingDown.value);
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 = async () => {
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($button, 'button');
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>
@@ -5,6 +5,6 @@
5
5
  $checkbox: () !default;
6
6
  $checkbox-default: (
7
7
  checked-color: UTILS__GLOBAL_VAR(theme, primary),
8
- unchecked-color: UTILS__GLOBAL_VAR(color, foreground),
8
+ unchecked-color: inherit,
9
9
  );
10
10
  $checkbox: map.merge($checkbox-default, $checkbox);
@@ -4,7 +4,10 @@
4
4
  v-if="hasIcon"
5
5
  :icon="usingIcon || ''"
6
6
  tap-size="50rpx"
7
- :class="[$style['Checkbox--icon'], { [$style['Checkbox--checked']]: isChecked }]"
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, ComputedRef, inject, Ref, ref } from 'vue';
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<Ref<undefined | string | number | boolean | Array<unknown>>>(
35
- 'ecolovo/checkboxGroup/checkedValue'
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<_Props, 'radio' | 'icon' | 'checkedIcon' | 'uncheckedIcon'>>(
39
- 'ecolovo/checkboxGroup/props',
40
- null
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
- inject<(val: undefined | string | number | boolean | Array<unknown>) => void>('ecolovo/checkboxGroup/check');
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>(() => (props.icon !== undefined ? props.icon : groupProps?.icon ?? true));
97
+ const hasIcon = computed<boolean>(() =>
98
+ props.icon !== undefined ? props.icon : groupProps?.icon ?? true
99
+ );
89
100
  /** 是否为单选 */
90
- const isRadio = computed<boolean>(() => (props.radio !== undefined ? props.radio : groupProps?.radio || false));
101
+ const isRadio = computed<boolean>(() =>
102
+ props.radio !== undefined ? props.radio : groupProps?.radio || false
103
+ );
91
104
  /** 最终使用的选中态的图标 */
92
105
  const usingCheckedIcon = computed<string>(
93
- () => props.checkedIcon || groupProps?.checkedIcon || (isRadio.value ? 'radio-checked' : 'checkbox-checked')
106
+ () =>
107
+ props.checkedIcon ||
108
+ groupProps?.checkedIcon ||
109
+ (isRadio.value ? 'radio-checked' : 'checkbox-checked')
94
110
  );
95
111
  /** 最终使用的未选中态的图标 */
96
112
  const usingUncheckedIcon = computed(
97
- () => props.uncheckedIcon || groupProps?.uncheckedIcon || (isRadio.value ? 'radio-unchecked' : 'checkbox-unchecked')
113
+ () =>
114
+ props.uncheckedIcon ||
115
+ groupProps?.uncheckedIcon ||
116
+ (isRadio.value ? 'radio-unchecked' : 'checkbox-unchecked')
98
117
  );
99
118
  /** 最终使用的图标 */
100
- const usingIcon = computed(() => (isChecked.value ? usingCheckedIcon.value : usingUncheckedIcon.value));
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
- return isRadio.value
106
- ? props.value === groupCheckedValue!.value
107
- : (groupCheckedValue as Ref<unknown[]>).value?.includes(props.value) || false;
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 ? innerChecked.value : (props.modelValue as boolean);
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($checkbox, 'checkbox');
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
- (event: 'update:modelValue', value?: string | number | boolean | Array<unknown>): void;
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<undefined | string | number | boolean | Array<unknown>>(undefined);
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 ? checkedValue.value : props.modelValue;
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/index' as *;
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 ? item.value === currentValue : Array.isArray(currentValue) && currentValue.includes(item.value)
7
+ radio
8
+ ? item.value === currentValue
9
+ : Array.isArray(currentValue) &&
10
+ currentValue.includes(item.value)
8
11
  "
9
12
  :icon="icon"
10
- :checked-icon="checkedIcon || (radio ? 'radio-checked' : 'checkbox-checked')"
11
- :unchecked-icon="uncheckedIcon || (radio ? 'radio-unchecked' : 'checkbox-unchecked')"
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('aspect');
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 ? checkedValue.value : props.modelValue;
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) => optionsValue.value.includes(item));
130
+ currentValue.value = isSelectedAll.filter((item) =>
131
+ optionsValue.value.includes(item)
132
+ );
121
133
  return;
122
134
  }
123
135
 
124
- if (Array.isArray(currentValue.value) && currentValue.value.length === props.options.length) {
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/index' as *;
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="currentValue ? checkedIcon || 'checkbox-checked' : uncheckedIcon || 'checkbox-unchecked'"
5
+ :icon="
6
+ currentValue
7
+ ? checkedIcon || 'checkbox-checked'
8
+ : uncheckedIcon || 'checkbox-unchecked'
9
+ "
6
10
  tap-size="50rpx"
7
- :class="[$style['Checkbox2--icon'], { [$style['Checkbox2--checked']]: currentValue }]"
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('aspect');
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($checkbox, 'checkbox');
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 v-if="pagingData && pagingData.hasMore" :class="$style['DataList--observe-view']"></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 { getCurrentInstance, onBeforeUnmount, onMounted, useCssModule, watch, WatchHandle } from 'vue';
19
- import { PagingData } from '@ecolovo/utils/uniapp/paging';
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: WatchHandle | null = null;
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($data-list, 'data-list');
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 {