@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.
- 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 +69 -22
- 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 +4 -0
- package/index.js +4 -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
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<dialog-cpn
|
|
3
|
+
v-if="isVisible"
|
|
3
4
|
:model-value="isVisible"
|
|
4
|
-
:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
65
|
-
|
|
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/
|
|
109
|
+
@use '../../styles/utils' as *;
|
|
78
110
|
</style>
|
|
@@ -1,45 +1,66 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view
|
|
3
|
-
:class="[
|
|
4
|
-
|
|
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
|
-
{
|
|
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="
|
|
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="[
|
|
32
|
+
:class="[
|
|
33
|
+
$style['NumberDialog--input'],
|
|
34
|
+
{ [$style['NumberDialog--readonly']]: isReadonly },
|
|
35
|
+
]"
|
|
24
36
|
@click="showPad"
|
|
25
37
|
>
|
|
26
|
-
<text
|
|
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
|
-
{
|
|
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="
|
|
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">{{
|
|
59
|
-
|
|
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
|
|
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
|
-
(
|
|
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 = (
|
|
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)))
|
|
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 (
|
|
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(
|
|
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(
|
|
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="[
|
|
4
|
-
|
|
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
|
-
{
|
|
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="
|
|
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
|
|
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="[
|
|
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']">{{
|
|
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
|
-
{
|
|
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="
|
|
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
|
|
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 = (
|
|
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)))
|
|
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 (
|
|
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:
|
|
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
|
|
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(
|
|
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
|
-
:
|
|
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: () =>
|
|
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(
|
|
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(
|
|
197
|
-
#{UTILS__VAR_NAME(active-mask
|
|
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 {
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
:class="[
|
|
4
4
|
...classNames,
|
|
5
5
|
$style['PageBody'],
|
|
6
|
-
useScroll
|
|
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 {
|
|
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 (
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
162
|
-
* @param
|
|
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 =
|
|
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(
|
|
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(
|
|
200
|
-
|
|
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);
|