@ecolovo/uniapp-components 2.0.2 → 2.0.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 (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 +69 -22
  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 +4 -0
  73. package/index.js +4 -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
@@ -1,23 +1,29 @@
1
1
  <template>
2
2
  <dialog-cpn
3
+ v-if="isVisible"
3
4
  :model-value="isVisible"
4
- :cancel="false"
5
- confirm="我知道了"
6
- modal
7
- :title="title"
5
+ :modal="innerOptions.modal"
6
+ :center-title="innerOptions.centerTitle"
7
+ :title="innerOptions.title"
8
+ :show-close="innerOptions.showClose"
9
+ :cancel="innerOptions.cancel"
10
+ :confirm="innerOptions.confirm"
8
11
  :class="[...classNames, $style['MessageBox']]"
9
12
  @update:model-value="emit('update:modelValue', $event)"
10
13
  @confirm="onConfirm()"
14
+ @cancel="onCancel()"
11
15
  @closed="isVisible = false"
12
16
  >
13
- {{ content }}
17
+ {{ innerOptions.content }}
14
18
  </dialog-cpn>
15
19
  </template>
16
20
 
17
21
  <script lang="ts" setup>
22
+ import { mergeWith, omit } from 'lodash-es';
18
23
  import { ref, useCssModule, watch } from 'vue';
19
24
  import useClassNames from '../../composable/component-name';
20
25
  import DialogCpn from '../dialog/dialog.vue';
26
+ import type { MessageBoxOptions } from './message-box';
21
27
 
22
28
  defineOptions({
23
29
  options: {
@@ -29,22 +35,37 @@ defineOptions({
29
35
  const classNames = useClassNames('message-box');
30
36
  const $style = useCssModule();
31
37
 
32
- type _Props = {
33
- /** 是否可见 */
34
- modelValue?: boolean;
35
- /** 对话框标题 */
36
- title?: string;
37
- /** 内容 */
38
- content?: string;
39
- };
40
-
41
- const props = withDefaults(defineProps<_Props>(), {
38
+ const props = withDefaults(defineProps<MessageBoxOptions>(), {
42
39
  modelValue: false,
43
- title: '提示',
44
40
  content: '',
41
+ modal: true,
42
+ centerTitle: false,
43
+ title: '提示',
44
+ showClose: false,
45
+ cancel: false,
46
+ confirm: '好的',
45
47
  });
46
48
 
47
49
  const isVisible = ref(false);
50
+ const innerOptions = ref<Omit<MessageBoxOptions, 'modelValue'>>(
51
+ omit(props, ['modelValue'])
52
+ );
53
+
54
+ watch(
55
+ props,
56
+ (newProps, oldProps) => {
57
+ const { modelValue, ...otherProps } = newProps;
58
+ innerOptions.value = mergeWith(
59
+ innerOptions.value,
60
+ otherProps,
61
+ (objValue, srcValue, key) =>
62
+ srcValue === oldProps?.[key as keyof MessageBoxOptions]
63
+ ? objValue
64
+ : srcValue
65
+ );
66
+ },
67
+ { immediate: true, deep: true }
68
+ );
48
69
 
49
70
  watch(
50
71
  () => props.modelValue,
@@ -57,12 +78,19 @@ const emit = defineEmits<{
57
78
  (e: 'update:modelValue', val: boolean): void;
58
79
  }>();
59
80
 
60
- let resolvePromise: PromiseWithResolvers<void>['resolve'] | undefined;
81
+ let resolvePromise: UniApp.PromiseResolvers<void>['resolve'] | undefined;
82
+ let rejectPromise: UniApp.PromiseResolvers<void>['reject'] | undefined;
61
83
 
62
- const show = () => {
84
+ const show = (options: Omit<MessageBoxOptions, 'modelValue'>) => {
85
+ innerOptions.value = { ...innerOptions.value, ...options };
63
86
  emit('update:modelValue', (isVisible.value = true));
64
- const { promise, resolve } = Promise.withResolvers();
65
- resolvePromise = resolve;
87
+
88
+ // const { promise, resolve } = Promise.withResolvers();
89
+ const promise = new Promise<void>((resolve, reject) => {
90
+ resolvePromise = resolve;
91
+ rejectPromise = reject;
92
+ });
93
+
66
94
  return promise;
67
95
  };
68
96
 
@@ -70,9 +98,13 @@ const onConfirm = () => {
70
98
  resolvePromise?.();
71
99
  };
72
100
 
101
+ const onCancel = () => {
102
+ rejectPromise?.(undefined);
103
+ };
104
+
73
105
  defineExpose({ show });
74
106
  </script>
75
107
 
76
108
  <style lang="scss" module>
77
- @use '../../styles/index' as *;
109
+ @use '../../styles/utils' as *;
78
110
  </style>
@@ -1,45 +1,66 @@
1
1
  <template>
2
2
  <view
3
- :class="[...classNames, $style['NumberDialog'], { [$style['NumberDialog--disabled']]: disabled }]"
4
- @click.stop.prevent="doNothing"
3
+ :class="[
4
+ ...classNames,
5
+ $style['NumberDialog'],
6
+ { [$style['NumberDialog--disabled']]: disabled },
7
+ ]"
8
+ @click.stop.prevent
5
9
  >
6
10
  <view
7
11
  v-if="!isReadonly"
8
12
  :class="[
9
13
  $style['NumberDialog--step-button'],
10
14
  $style['NumberDialog--step-button-minus'],
11
- { [$style['NumberDialog--step-button-disabled']]: disabledDecrease },
15
+ {
16
+ [$style['NumberDialog--step-button-disabled']]:
17
+ disabledDecrease,
18
+ },
12
19
  ]"
13
20
  >
14
21
  <icon-cpn
15
22
  icon="step-minus"
16
23
  tap-size="60rpx"
17
- @touchstart="handleStepLongTouchStart($event, -step, disabledDecrease)"
24
+ @touchstart="
25
+ handleStepLongTouchStart($event, -step, disabledDecrease)
26
+ "
18
27
  @touchend="handleStepLongTouchEnd(-step)"
19
28
  @touchcancel="handleStepLongTouchEnd(-step)"
20
29
  />
21
30
  </view>
22
31
  <view
23
- :class="[$style['NumberDialog--input'], { [$style['NumberDialog--readonly']]: isReadonly }]"
32
+ :class="[
33
+ $style['NumberDialog--input'],
34
+ { [$style['NumberDialog--readonly']]: isReadonly },
35
+ ]"
24
36
  @click="showPad"
25
37
  >
26
- <text v-if="isReadonly || modelValue === 0 || modelValue" :class="$style['NumberDialog--value']">{{
27
- modelValue
38
+ <text
39
+ v-if="isReadonly || modelValue === 0 || modelValue"
40
+ :class="$style['NumberDialog--value']"
41
+ >{{ modelValue }}</text
42
+ >
43
+ <text v-else :class="$style['NumberDialog--placeholder']">{{
44
+ placeholder
28
45
  }}</text>
29
- <text v-else :class="$style['NumberDialog--placeholder']">{{ placeholder }}</text>
30
46
  </view>
31
47
  <view
32
48
  v-if="!isReadonly"
33
49
  :class="[
34
50
  $style['NumberDialog--step-button'],
35
51
  $style['NumberDialog--step-button-plus'],
36
- { [$style['NumberDialog--step-button-disabled']]: disabledIncrease },
52
+ {
53
+ [$style['NumberDialog--step-button-disabled']]:
54
+ disabledIncrease,
55
+ },
37
56
  ]"
38
57
  >
39
58
  <icon-cpn
40
59
  icon="step-plus"
41
60
  tap-size="60rpx"
42
- @touchstart="handleStepLongTouchStart($event, step, disabledIncrease)"
61
+ @touchstart="
62
+ handleStepLongTouchStart($event, step, disabledIncrease)
63
+ "
43
64
  @touchend="handleStepLongTouchEnd(step)"
44
65
  @touchcancel="handleStepLongTouchEnd(step)"
45
66
  />
@@ -55,12 +76,21 @@
55
76
  @cancel="closePad()"
56
77
  >
57
78
  <view :class="$style['NumberDialog--dialog-input']">
58
- <text v-if="editValue === 0 || editValue">{{ editValue }}</text>
59
- <text v-else :class="$style['NumberDialog--placeholder']">{{ placeholder }}</text>
79
+ <text v-if="editValue === 0 || editValue">{{
80
+ editValue
81
+ }}</text>
82
+ <text v-else :class="$style['NumberDialog--placeholder']">{{
83
+ placeholder
84
+ }}</text>
60
85
  </view>
61
86
  </dialog-content-cpn>
62
87
  <popover-content-cpn position="bottom">
63
- <numpad-cpn v-model="editValue" :precision="precision" :min="min" :max="max" />
88
+ <numpad-cpn
89
+ v-model="editValue"
90
+ :precision="precision"
91
+ :min="min"
92
+ :max="max"
93
+ />
64
94
  </popover-content-cpn>
65
95
  </popover-mask-cpn>
66
96
  </view>
@@ -123,7 +153,10 @@ const props = withDefaults(defineProps<_Props>(), {
123
153
 
124
154
  const emit = defineEmits<{
125
155
  (e: 'update:modelValue', val: string | number): void;
126
- (e: 'change', payload: { value: string | number; lastValue: string | number }): void;
156
+ (
157
+ e: 'change',
158
+ payload: { value: string | number; lastValue: string | number }
159
+ ): void;
127
160
  (e: 'error', msg: string): void;
128
161
  }>();
129
162
 
@@ -171,10 +204,12 @@ let _lastValue: string | number = '';
171
204
  let _touchingStep: number | null = null;
172
205
  let _touchTimer: ReturnType<typeof setTimeout> | null = null;
173
206
 
174
- const doNothing = () => {};
175
-
176
207
  /** 长按步进按钮开始处理 */
177
- const handleStepLongTouchStart = (event: TouchEvent, step: number, disabled: boolean) => {
208
+ const handleStepLongTouchStart = (
209
+ event: TouchEvent,
210
+ step: number,
211
+ disabled: boolean
212
+ ) => {
178
213
  if (disabled) return;
179
214
  if (event.touches.length > 1) return;
180
215
 
@@ -184,7 +219,9 @@ const handleStepLongTouchStart = (event: TouchEvent, step: number, disabled: boo
184
219
  let times = 0;
185
220
 
186
221
  const longTouch = () => {
187
- if (!handleOneStep(step * (times >= 30 ? 4 : times >= 12 ? 2 : 1))) return;
222
+ if (!handleOneStep(step * (times >= 30 ? 4 : times >= 12 ? 2 : 1))) {
223
+ return;
224
+ }
188
225
 
189
226
  _touchTimer = setTimeout(longTouch, interval);
190
227
  interval = Math.max(100, interval - 50);
@@ -206,7 +243,10 @@ const handleStepLongTouchEnd = (step: number) => {
206
243
 
207
244
  /** 单次步进处理 */
208
245
  const handleOneStep = (step: number) => {
209
- if ((step > 0 && disabledIncrease.value) || (step < 0 && disabledDecrease.value)) {
246
+ if (
247
+ (step > 0 && disabledIncrease.value) ||
248
+ (step < 0 && disabledDecrease.value)
249
+ ) {
210
250
  return false;
211
251
  }
212
252
  const nextValue = round(+props.modelValue + step, props.precision);
@@ -282,7 +322,7 @@ const onConfirm = () => {
282
322
 
283
323
  // 定义外部变量
284
324
  %external-vars {
285
- @include UTILS__DEFINE_COMPONENT_VARS($number-dialog, 'number-dialog');
325
+ @include UTILS__DEFINE_COMPONENT_VARS('number-dialog', $number-dialog);
286
326
  }
287
327
 
288
328
  .NumberDialog {
@@ -354,7 +394,7 @@ const onConfirm = () => {
354
394
  }
355
395
 
356
396
  .NumberDialog--dialog {
357
- #{UTILS__VAR_NAME(position, popover)}: calc(50% - 240rpx) auto auto 50%;
397
+ #{UTILS__VAR_NAME(popover, position)}: calc(50% - 240rpx) auto auto 50%;
358
398
  }
359
399
  .NumberDialog--dialog-input {
360
400
  height: 50rpx;
@@ -1,24 +1,36 @@
1
1
  <template>
2
2
  <view
3
- :class="[...classNames, $style['NumberInput'], { [$style['NumberInput--step-mode']]: mode === 'step' }]"
4
- @click.stop.prevent="doNothing"
3
+ :class="[
4
+ ...classNames,
5
+ $style['NumberInput'],
6
+ { [$style['NumberInput--step-mode']]: mode === 'step' },
7
+ ]"
8
+ @click.stop.prevent
5
9
  >
6
10
  <view
7
11
  v-if="mode === 'step' && !isReadonly"
8
12
  :class="[
9
13
  $style['NumberInput--step-button'],
10
14
  $style['NumberInput--step-button-minus'],
11
- { [$style['NumberInput--step-button-disabled']]: disabledDecrease },
15
+ {
16
+ [$style['NumberInput--step-button-disabled']]:
17
+ disabledDecrease,
18
+ },
12
19
  ]"
13
20
  >
14
21
  <icon-cpn
15
22
  icon="step-minus"
16
- @touchstart="handleStepLongTouchStart($event, -step, disabledDecrease)"
23
+ @touchstart="
24
+ handleStepLongTouchStart($event, -step, disabledDecrease)
25
+ "
17
26
  @touchend="handleStepLongTouchEnd(-step)"
18
27
  @touchcancel="handleStepLongTouchEnd(-step)"
19
28
  />
20
29
  </view>
21
- <view v-if="isReadonly" :class="[$style['NumberInput--value'], { disabled }]">
30
+ <view
31
+ v-if="isReadonly"
32
+ :class="[$style['NumberInput--value'], { disabled }]"
33
+ >
22
34
  {{ modelValue }}
23
35
  </view>
24
36
  <input
@@ -26,7 +38,10 @@
26
38
  :value="editValue"
27
39
  :type="type"
28
40
  maxlength="14"
29
- :class="[$style['NumberInput--input'], mode === 'step' ? $style['NumberInput--step-input'] : '']"
41
+ :class="[
42
+ $style['NumberInput--input'],
43
+ mode === 'step' ? $style['NumberInput--step-input'] : '',
44
+ ]"
30
45
  :disabled="disabled"
31
46
  :placeholder="placeholder"
32
47
  :placeholder-class="$style['NumberInput--input-placeholder']"
@@ -34,18 +49,25 @@
34
49
  @focus="handleFocus"
35
50
  @blur="handleInputConfirm"
36
51
  />
37
- <view v-else :class="$style['NumberInput--input-value']">{{ modelValue || 0 }}</view>
52
+ <view v-else :class="$style['NumberInput--input-value']">{{
53
+ modelValue || 0
54
+ }}</view>
38
55
  <view
39
56
  v-if="mode === 'step' && !isReadonly"
40
57
  :class="[
41
58
  $style['NumberInput--step-button'],
42
59
  $style['NumberInput--step-button-plus'],
43
- { [$style['NumberInput--step-button-disabled']]: disabledIncrease },
60
+ {
61
+ [$style['NumberInput--step-button-disabled']]:
62
+ disabledIncrease,
63
+ },
44
64
  ]"
45
65
  >
46
66
  <icon-cpn
47
67
  icon="step-plus"
48
- @touchstart="handleStepLongTouchStart($event, step, disabledIncrease)"
68
+ @touchstart="
69
+ handleStepLongTouchStart($event, step, disabledIncrease)
70
+ "
49
71
  @touchend="handleStepLongTouchEnd(step)"
50
72
  @touchcancel="handleStepLongTouchEnd(step)"
51
73
  />
@@ -131,7 +153,9 @@ const isReadonly = computed(() => props.readonly || isFormReadonly.value);
131
153
 
132
154
  /** 输入校验正则 */
133
155
  const inputTestReg = computed(() => {
134
- return props.precision > 0 ? new RegExp('^(-?)(\\d*)(\\.\\d{0,' + props.precision + '})?(-?)$') : numberReg;
156
+ return props.precision > 0
157
+ ? new RegExp('^(-?)(\\d*)(\\.\\d{0,' + props.precision + '})?(-?)$')
158
+ : numberReg;
135
159
  });
136
160
 
137
161
  /** 是否禁用减 */
@@ -163,8 +187,6 @@ let _lastEditValue = '';
163
187
  let _touchingStep: number | null = null;
164
188
  let _touchTimer: ReturnType<typeof setTimeout> | null = null;
165
189
 
166
- const doNothing = () => {};
167
-
168
190
  /** 聚焦 */
169
191
  const handleFocus = () => {
170
192
  _lastValue = props.modelValue;
@@ -172,7 +194,11 @@ const handleFocus = () => {
172
194
  };
173
195
 
174
196
  /** 长按步进按钮开始处理 */
175
- const handleStepLongTouchStart = (event: TouchEvent, step: number, disabled: boolean) => {
197
+ const handleStepLongTouchStart = (
198
+ event: TouchEvent,
199
+ step: number,
200
+ disabled: boolean
201
+ ) => {
176
202
  if (disabled) return;
177
203
  if (event.touches.length > 1) return;
178
204
 
@@ -182,7 +208,9 @@ const handleStepLongTouchStart = (event: TouchEvent, step: number, disabled: boo
182
208
  let times = 0;
183
209
 
184
210
  const longTouch = () => {
185
- if (!handleOneStep(step * (times >= 30 ? 4 : times >= 12 ? 2 : 1))) return;
211
+ if (!handleOneStep(step * (times >= 30 ? 4 : times >= 12 ? 2 : 1))) {
212
+ return;
213
+ }
186
214
 
187
215
  _touchTimer = setTimeout(longTouch, interval);
188
216
  interval = Math.max(100, interval - 50);
@@ -204,7 +232,10 @@ const handleStepLongTouchEnd = (step: number) => {
204
232
 
205
233
  /** 单次步进处理 */
206
234
  const handleOneStep = (step: number) => {
207
- if ((step > 0 && disabledIncrease.value) || (step < 0 && disabledDecrease.value)) {
235
+ if (
236
+ (step > 0 && disabledIncrease.value) ||
237
+ (step < 0 && disabledDecrease.value)
238
+ ) {
208
239
  return false;
209
240
  }
210
241
  const nextValue = round(+props.modelValue + step, props.precision);
@@ -251,7 +282,7 @@ const validateValue = (value: string, isStepButton = false) => {
251
282
  return nextValue;
252
283
  };
253
284
 
254
- const handleInput = (e: InputEvent) => {
285
+ const handleInput = (e: Event) => {
255
286
  let value = e.detail.value.trim();
256
287
 
257
288
  const match = inputTestReg.value.exec(value);
@@ -259,7 +290,11 @@ const handleInput = (e: InputEvent) => {
259
290
  // sign: 负号; integer: 整数部分数字; decimal: 小数部分数字; resign: 再次输入负号,取消负号
260
291
  const [, sign = '', integer = '', decimal = '', resign = ''] = match;
261
292
  const signVal = (!!sign && !resign) || (!sign && !!resign) ? '-' : '';
262
- const integerVal = integer ? Number(integer) || '0' : decimal ? '0' : '';
293
+ const integerVal = integer
294
+ ? Number(integer) || '0'
295
+ : decimal
296
+ ? '0'
297
+ : '';
263
298
  value = signVal + integerVal + decimal;
264
299
 
265
300
  _lastEditValue = value;
@@ -290,7 +325,7 @@ const confirmValue = (value: string, isStepButton = false) => {
290
325
 
291
326
  // 定义外部变量
292
327
  %external-vars {
293
- @include UTILS__DEFINE_COMPONENT_VARS($number-input, 'number-input');
328
+ @include UTILS__DEFINE_COMPONENT_VARS('number-input', $number-input);
294
329
  }
295
330
 
296
331
  .NumberInput {
@@ -3,7 +3,7 @@
3
3
  <button-cpn
4
4
  v-for="btn in buttons"
5
5
  :key="btn.key"
6
- :cold-down="0"
6
+ :cool-down="0"
7
7
  :class="[$style['Numpad--key'], $style[btn.className || '']]"
8
8
  @click="onClick(btn)"
9
9
  >
@@ -82,7 +82,10 @@ const emit = defineEmits<{
82
82
  }>();
83
83
 
84
84
  const editValue = computed({
85
- get: () => (props.modelValue || props.modelValue === 0 ? props.modelValue.toString() : ''),
85
+ get: () =>
86
+ props.modelValue || props.modelValue === 0
87
+ ? props.modelValue.toString()
88
+ : '',
86
89
  set: (val: string) => emit('update:modelValue', val),
87
90
  });
88
91
 
@@ -174,7 +177,7 @@ const onClear = () => {
174
177
 
175
178
  // 定义外部变量
176
179
  %external-vars {
177
- @include UTILS__DEFINE_COMPONENT_VARS($numpad, 'numpad');
180
+ @include UTILS__DEFINE_COMPONENT_VARS('numpad', $numpad);
178
181
  }
179
182
 
180
183
  .Numpad {
@@ -193,8 +196,11 @@ const onClear = () => {
193
196
  box-shadow: 2px 2px 4px 0 #00000040;
194
197
  &:not(.Numpad--confirm-key) {
195
198
  color: UTILS__GLOBAL_VAR(color, foreground);
196
- #{UTILS__VAR_NAME(theme, button)}: white;
197
- #{UTILS__VAR_NAME(active-mask, button)}: UTILS__GLOBAL_VAR(theme, primary);
199
+ #{UTILS__VAR_NAME(button, theme)}: white;
200
+ #{UTILS__VAR_NAME(button, active-mask)}: UTILS__GLOBAL_VAR(
201
+ theme,
202
+ primary
203
+ );
198
204
  }
199
205
  }
200
206
  .Numpad--zero-key {
@@ -5,7 +5,7 @@
5
5
  $page-body: () !default;
6
6
  $page-body-default: (
7
7
  // 可视区域背景
8
- background: UTILS__GLOBAL_VAR('color', 'background'),
8
+ background: var(UTILS__VAR_NAME('page', 'background')),
9
9
  padding: 20rpx,
10
10
  padding-top: null,
11
11
  padding-right: null,
@@ -3,7 +3,9 @@
3
3
  :class="[
4
4
  ...classNames,
5
5
  $style['PageBody'],
6
- useScroll ? $style['PageBody--with-scroll'] : $style['PageBody--no-scroll'],
6
+ useScroll
7
+ ? $style['PageBody--with-scroll']
8
+ : $style['PageBody--no-scroll'],
7
9
  ]"
8
10
  :style="inlineStyle"
9
11
  >
@@ -15,6 +17,7 @@
15
17
  </view>
16
18
  <scroll-view
17
19
  v-else-if="enableRefresh"
20
+ id="page-body"
18
21
  scroll-y
19
22
  refresher-enabled
20
23
  :refresher-triggered="refreshing"
@@ -31,6 +34,7 @@
31
34
  </scroll-view>
32
35
  <scroll-view
33
36
  v-else
37
+ id="page-body"
34
38
  scroll-y
35
39
  :scroll-with-animation="scrollWithAnimation"
36
40
  :scroll-top="scrollTop"
@@ -52,7 +56,10 @@
52
56
  import { debounce } from 'lodash-es';
53
57
  import { computed, getCurrentInstance, nextTick, ref, useCssModule } from 'vue';
54
58
  import useClassNames from '../../composable/component-name';
55
- import { navBarBottomOffset, safeAreaInsetBottom } from '../../utils/windowInfo';
59
+ import {
60
+ navBarBottomOffset,
61
+ safeAreaInsetBottom,
62
+ } from '../../utils/windowInfo';
56
63
 
57
64
  defineOptions({
58
65
  options: {
@@ -108,9 +115,14 @@ const emit = defineEmits<{
108
115
  (event: 'reach-bottom'): void;
109
116
  }>();
110
117
 
118
+ /** 当前页面滚动距离 */
111
119
  const scrollOffset = ref<number | string>(0);
120
+ /** 控制页面滚动到指定位置 */
112
121
  const scrollTop = ref<number | string>(0);
122
+ /** 控制页面滚动时是否有动画 */
113
123
  const scrollWithAnimation = ref(true);
124
+ /** 控制页面滚动到指定 id 的元素位置 */
125
+ // const scrollIntoViewId = ref('');
114
126
 
115
127
  const inlineStyle = computed(() => {
116
128
  return [
@@ -132,14 +144,19 @@ const $_debounceScroll = debounce(function () {
132
144
  /* #endif */
133
145
  .select('.' + $style['PageBody--scroll-body'])
134
146
  .fields({ size: true, scrollOffset: true }, (data) => {
135
- if (!Array.isArray(data) && data.scrollHeight! - data.height! - data.scrollTop! <= 50) {
147
+ if (
148
+ !Array.isArray(data) &&
149
+ data.scrollHeight! - data.height! - data.scrollTop! <= 50
150
+ ) {
136
151
  emit('reach-bottom');
137
152
  }
138
153
  })
139
154
  .exec();
140
155
  }, 100);
141
156
 
142
- /** 处理 scroll-view 滚动 */
157
+ /**
158
+ * 处理 scroll-view 滚动
159
+ */
143
160
  const $_handleScroll = (e: {
144
161
  detail: {
145
162
  scrollLeft: number;
@@ -157,15 +174,19 @@ const $_handleScroll = (e: {
157
174
  }
158
175
  };
159
176
 
160
- /** 滚动到顶部
161
- * @param {number} position 滚动到与顶部的距离
162
- * @param {boolean} animation 是否有滚动动画
177
+ /**
178
+ * 滚动到顶部
179
+ * @param position 滚动到与顶部的距离
180
+ * @param animation 是否有滚动动画
163
181
  */
164
182
  const scrollToTop = (position = 0, animation = true) => {
165
183
  if (props.useScroll) {
166
184
  scrollWithAnimation.value = animation;
167
185
  nextTick(() => {
168
- scrollTop.value = typeof scrollTop.value === 'number' ? position + 'px' : position;
186
+ scrollTop.value =
187
+ typeof scrollTop.value === 'number'
188
+ ? position + 'px'
189
+ : position;
169
190
  scrollOffset.value = position;
170
191
  setTimeout(() => {
171
192
  scrollWithAnimation.value = true;
@@ -179,8 +200,47 @@ const scrollToTop = (position = 0, animation = true) => {
179
200
  }
180
201
  };
181
202
 
203
+ /**
204
+ * 滚动到指定 id 的元素位置
205
+ * @param viewId 目标元素的 id
206
+ * @param animation 是否有滚动动画
207
+ */
208
+ const scrollIntoView = (viewId: string, animation = true) => {
209
+ viewId = viewId.startsWith('#') ? viewId : '#' + viewId;
210
+ uni.createSelectorQuery()
211
+ .select(viewId)
212
+ .boundingClientRect()
213
+ /* #ifndef MP-ALIPAY */
214
+ .in(vm)
215
+ /* #endif */
216
+ .select('#page-body')
217
+ .boundingClientRect()
218
+ .exec((data) => {
219
+ scrollToTop(data[0].top - data[1].top, animation);
220
+ });
221
+ // 下面这种方法无法滚动,可能是因为对应的 id 是在 slot 中的原因
222
+ // if (props.useScroll) {
223
+ // scrollIntoViewId.value = '';
224
+ // scrollWithAnimation.value = animation;
225
+ // nextTick(() => {
226
+ // scrollIntoViewId.value = viewId.startsWith('#')
227
+ // ? viewId.slice(1)
228
+ // : viewId;
229
+ // setTimeout(() => {
230
+ // scrollWithAnimation.value = true;
231
+ // }, SCROLL_ANIMATION_DURATION);
232
+ // });
233
+ // } else {
234
+ // uni.pageScrollTo({
235
+ // selector: viewId,
236
+ // duration: animation ? SCROLL_ANIMATION_DURATION : 0,
237
+ // });
238
+ // }
239
+ };
240
+
182
241
  defineExpose({
183
242
  scrollToTop,
243
+ scrollIntoView,
184
244
  });
185
245
  </script>
186
246
 
@@ -190,14 +250,22 @@ defineExpose({
190
250
 
191
251
  // 定义外部变量
192
252
  %external-vars {
193
- @include UTILS__DEFINE_COMPONENT_VARS($page-body, 'page-body');
253
+ @include UTILS__DEFINE_COMPONENT_VARS('page-body', $page-body);
254
+ }
255
+
256
+ :host {
257
+ display: block;
194
258
  }
195
259
 
196
260
  .PageBody {
197
261
  @extend %external-vars;
198
262
 
199
- --header-placeholder-height: calc(var(--page-header-bottom) + #{UTILS__VAR(extra-height, page-header, 0px)});
200
- --footer-placeholder-height: calc(var(--safe-area-bottom) + #{UTILS__VAR(height, page-footer, 100rpx)});
263
+ --header-placeholder-height: calc(
264
+ var(--page-header-bottom) + #{UTILS__VAR(page-header, extra-height, 0px)}
265
+ );
266
+ --footer-placeholder-height: calc(
267
+ var(--safe-area-bottom) + #{UTILS__VAR(page-footer, height, 100rpx)}
268
+ );
201
269
 
202
270
  box-sizing: border-box;
203
271
  padding-top: var(--header-placeholder-height);