@netang/quasar 0.2.32 → 0.2.33
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/.editorconfig +12 -12
- package/_docs/docs/components/field-table.md +58 -58
- package/_docs/docs/components/field-tree.md +21 -21
- package/_docs/docs/components/table.md +24 -24
- package/_docs/docs/utils/table.md +196 -196
- package/components/column-title/index.vue +38 -38
- package/components/data/index.vue +20 -20
- package/components/dialog/img-viewer/index.vue +697 -697
- package/components/dialog/index.vue +387 -387
- package/components/dragger/index.vue +203 -203
- package/components/drawer/index.vue +303 -303
- package/components/editor-code/index.vue +328 -328
- package/components/empty/index.vue +82 -82
- package/components/field-date/index.vue +860 -860
- package/components/field-date/methods.js +100 -100
- package/components/field-table/index.vue +1483 -1483
- package/components/field-text/index.vue +166 -166
- package/components/field-tree/index.vue +755 -755
- package/components/img/index.vue +279 -279
- package/components/input-number/index.vue +560 -560
- package/components/list-menu/index.vue +149 -149
- package/components/list-menu-item/index.vue +79 -79
- package/components/mixed-table/index.vue +532 -532
- package/components/mixed-table-splitter/index.vue +377 -377
- package/components/power-page/index.vue +96 -96
- package/components/price/index.vue +188 -188
- package/components/private/components/index.js +11 -11
- package/components/private/components/move-to-tree/index.vue +154 -154
- package/components/private/edit-power-data/index.vue +846 -846
- package/components/private/table-visible-columns-button/index.vue +114 -114
- package/components/render/index.vue +123 -123
- package/components/search/index.vue +231 -231
- package/components/search-item/index.vue +210 -210
- package/components/select/index.vue +177 -177
- package/components/splitter/index.vue +422 -422
- package/components/table/index.vue +513 -513
- package/components/table-column-fixed/index.vue +110 -110
- package/components/table-pagination/index.vue +192 -192
- package/components/table-summary/index.vue +107 -107
- package/components/thumbnail/index.vue +72 -72
- package/components/toolbar/index.vue +150 -150
- package/components/tree/index.vue +1728 -1728
- package/components/tree/virtual-scroll.vue +41 -41
- package/components/uploader/index.vue +196 -196
- package/components/uploader-query/index.vue +945 -945
- package/components/value-format/index.vue +274 -274
- package/components/virtual-scroll/index.vue +136 -136
- package/configs/area3.js +1 -1
- package/docs/404.html +33 -33
- package/docs/assets/404.html-60b35caa.js +1 -1
- package/docs/assets/404.html-d1e63d77.js +1 -1
- package/docs/assets/alert.html-b2a2a72f.js +5 -5
- package/docs/assets/alert.html-ba46d137.js +1 -1
- package/docs/assets/app-9f30aa4b.js +6 -6
- package/docs/assets/area.html-01b9b58d.js +42 -42
- package/docs/assets/area.html-9a4fce6a.js +1 -1
- package/docs/assets/arr.html-145d27e7.js +1 -1
- package/docs/assets/arr.html-674e65ab.js +11 -11
- package/docs/assets/auth.html-579fa830.js +1 -1
- package/docs/assets/auth.html-8544ed95.js +8 -8
- package/docs/assets/bus.html-c71254aa.js +1 -1
- package/docs/assets/bus.html-dc7d3d19.js +6 -6
- package/docs/assets/column-title.html-c735cb5a.js +3 -3
- package/docs/assets/column-title.html-e9316762.js +1 -1
- package/docs/assets/confirm.html-ddfdc27f.js +10 -10
- package/docs/assets/confirm.html-ef3e2bef.js +1 -1
- package/docs/assets/copy.html-d20345b6.js +1 -1
- package/docs/assets/copy.html-ef8c8571.js +13 -13
- package/docs/assets/data.html-6432175d.js +30 -30
- package/docs/assets/data.html-a3b05d5b.js +1 -1
- package/docs/assets/dialog.html-1f698e5a.js +1 -1
- package/docs/assets/dialog.html-62902b83.js +68 -68
- package/docs/assets/dialog.html-baea77c9.js +1 -1
- package/docs/assets/dialog.html-bb082fc4.js +1 -1
- package/docs/assets/dict.html-1311da3d.js +23 -23
- package/docs/assets/dict.html-b96fbf0c.js +1 -1
- package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
- package/docs/assets/dictOptions.html-fb99d175.js +5 -5
- package/docs/assets/dragger.html-668d3efa.js +1 -1
- package/docs/assets/dragger.html-749d585a.js +1 -1
- package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
- package/docs/assets/editor-code.html-d196205d.js +1 -1
- package/docs/assets/empty.html-1c139131.js +1 -1
- package/docs/assets/empty.html-1e9c441d.js +1 -1
- package/docs/assets/field-date.html-069fdb13.js +1 -1
- package/docs/assets/field-date.html-ad204aa9.js +1 -1
- package/docs/assets/field-table.html-ce480f03.js +1 -1
- package/docs/assets/field-table.html-d9236160.js +1 -1
- package/docs/assets/field-text.html-7277c62f.js +1 -1
- package/docs/assets/field-text.html-ccb4cecf.js +1 -1
- package/docs/assets/field-tree.html-519bfb45.js +1 -1
- package/docs/assets/field-tree.html-fdc748d6.js +1 -1
- package/docs/assets/form.html-2b562c37.js +2 -2
- package/docs/assets/form.html-75104cd5.js +1 -1
- package/docs/assets/framework-204010b2.js +5 -5
- package/docs/assets/getData.html-990e3787.js +1 -1
- package/docs/assets/getData.html-bb72025f.js +34 -34
- package/docs/assets/getFile.html-42368004.js +1 -1
- package/docs/assets/getFile.html-99abd054.js +3 -3
- package/docs/assets/getImage.html-3429c5a1.js +1 -1
- package/docs/assets/getImage.html-4d886d83.js +3 -3
- package/docs/assets/getTime.html-7435f922.js +1 -1
- package/docs/assets/getTime.html-b37f49eb.js +20 -20
- package/docs/assets/img.html-7d1da657.js +1 -1
- package/docs/assets/img.html-fbea1105.js +1 -1
- package/docs/assets/index.html-1695dd7c.js +1 -1
- package/docs/assets/index.html-65a4aa67.js +1 -1
- package/docs/assets/index.html-7b98d5bd.js +1 -1
- package/docs/assets/index.html-c01f2648.js +1 -1
- package/docs/assets/input-number.html-0b250d2a.js +1 -1
- package/docs/assets/input-number.html-a8eb0378.js +1 -1
- package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
- package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
- package/docs/assets/list-menu.html-28b4163f.js +1 -1
- package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
- package/docs/assets/loading.html-dae9e39d.js +6 -6
- package/docs/assets/loading.html-dc74c9e6.js +1 -1
- package/docs/assets/notify.html-e6c4c514.js +1 -1
- package/docs/assets/notify.html-f2c4d914.js +8 -8
- package/docs/assets/power-page.html-32e02f82.js +1 -1
- package/docs/assets/power-page.html-485e77da.js +1 -1
- package/docs/assets/power.html-d258cc19.js +93 -93
- package/docs/assets/power.html-e490bd32.js +1 -1
- package/docs/assets/previewImage.html-6a6b4245.js +1 -1
- package/docs/assets/previewImage.html-c5b7e945.js +2 -2
- package/docs/assets/price.html-1882c548.js +19 -19
- package/docs/assets/price.html-94d3f5be.js +1 -1
- package/docs/assets/price.html-d213df0f.js +1 -1
- package/docs/assets/price.html-deaf880f.js +1 -1
- package/docs/assets/render.html-8efcbdd4.js +1 -1
- package/docs/assets/render.html-df228e38.js +1 -1
- package/docs/assets/rule.html-2cd57fc2.js +13 -13
- package/docs/assets/rule.html-61662001.js +1 -1
- package/docs/assets/ruleValid.html-04fe2552.js +1 -1
- package/docs/assets/ruleValid.html-e0a776af.js +14 -14
- package/docs/assets/search-0782d0d1.svg +1 -1
- package/docs/assets/search-item.html-3f75394c.js +1 -1
- package/docs/assets/search-item.html-4e942ecd.js +1 -1
- package/docs/assets/search.html-2807043e.js +1 -1
- package/docs/assets/search.html-c24f8806.js +1 -1
- package/docs/assets/select.html-00d0607c.js +1 -1
- package/docs/assets/select.html-de7731f5.js +1 -1
- package/docs/assets/splitter.html-56f51a70.js +1 -1
- package/docs/assets/splitter.html-f5c836d7.js +1 -1
- package/docs/assets/style-161e43ab.css +1 -1
- package/docs/assets/symbols.html-a6aea4bf.js +1 -1
- package/docs/assets/symbols.html-b1f65bad.js +21 -21
- package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
- package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
- package/docs/assets/table-pagination.html-236934d3.js +1 -1
- package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
- package/docs/assets/table-splitter.html-07eab15c.js +1 -1
- package/docs/assets/table-splitter.html-7670ee65.js +1 -1
- package/docs/assets/table-summary.html-04db434f.js +1 -1
- package/docs/assets/table-summary.html-943c65a0.js +1 -1
- package/docs/assets/table.html-36253ad7.js +1 -1
- package/docs/assets/table.html-7f9c5d1b.js +38 -38
- package/docs/assets/table.html-93d53dc8.js +1 -1
- package/docs/assets/table.html-ac99b9cb.js +1 -1
- package/docs/assets/thumbnail.html-bab1976b.js +1 -1
- package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
- package/docs/assets/timestamp.html-4e54f79b.js +13 -13
- package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
- package/docs/assets/toast.html-58ecbe21.js +1 -1
- package/docs/assets/toast.html-c9b9d36b.js +6 -6
- package/docs/assets/toolbar.html-83d9f97c.js +1 -1
- package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
- package/docs/assets/tree.html-d07cbe79.js +23 -23
- package/docs/assets/tree.html-ea04193e.js +1 -1
- package/docs/assets/uploader-query.html-05590718.js +1 -1
- package/docs/assets/uploader-query.html-3175bac5.js +1 -1
- package/docs/assets/uploader.html-36da4394.js +2 -2
- package/docs/assets/uploader.html-6b5f3079.js +1 -1
- package/docs/assets/uploader.html-b9340b57.js +1 -1
- package/docs/assets/uploader.html-bc1c22e3.js +1 -1
- package/docs/assets/value-format.html-8ae3d47d.js +1 -1
- package/docs/assets/value-format.html-afa99b3d.js +1 -1
- package/docs/components/column-title.html +35 -35
- package/docs/components/data.html +62 -62
- package/docs/components/dialog.html +33 -33
- package/docs/components/dragger.html +33 -33
- package/docs/components/editor-code.html +33 -33
- package/docs/components/empty.html +33 -33
- package/docs/components/field-date.html +33 -33
- package/docs/components/field-table.html +33 -33
- package/docs/components/field-text.html +33 -33
- package/docs/components/field-tree.html +33 -33
- package/docs/components/img.html +33 -33
- package/docs/components/input-number.html +33 -33
- package/docs/components/list-menu-item.html +33 -33
- package/docs/components/list-menu.html +33 -33
- package/docs/components/power-page.html +33 -33
- package/docs/components/price.html +33 -33
- package/docs/components/render.html +33 -33
- package/docs/components/search-item.html +33 -33
- package/docs/components/search.html +33 -33
- package/docs/components/select.html +33 -33
- package/docs/components/splitter.html +33 -33
- package/docs/components/table-column-fixed.html +33 -33
- package/docs/components/table-pagination.html +33 -33
- package/docs/components/table-splitter.html +33 -33
- package/docs/components/table-summary.html +33 -33
- package/docs/components/table.html +33 -33
- package/docs/components/thumbnail.html +33 -33
- package/docs/components/toolbar.html +33 -33
- package/docs/components/uploader-query.html +33 -33
- package/docs/components/uploader.html +33 -33
- package/docs/components/value-format.html +33 -33
- package/docs/css/index.css +3 -3
- package/docs/index.html +33 -33
- package/docs/utils/alert.html +37 -37
- package/docs/utils/area.html +74 -74
- package/docs/utils/arr.html +43 -43
- package/docs/utils/auth.html +40 -40
- package/docs/utils/bus.html +38 -38
- package/docs/utils/confirm.html +42 -42
- package/docs/utils/copy.html +45 -45
- package/docs/utils/dialog.html +100 -100
- package/docs/utils/dict.html +55 -55
- package/docs/utils/dictOptions.html +37 -37
- package/docs/utils/form.html +34 -34
- package/docs/utils/getData.html +66 -66
- package/docs/utils/getFile.html +35 -35
- package/docs/utils/getImage.html +35 -35
- package/docs/utils/getTime.html +52 -52
- package/docs/utils/index.html +33 -33
- package/docs/utils/loading.html +38 -38
- package/docs/utils/notify.html +40 -40
- package/docs/utils/power.html +125 -125
- package/docs/utils/previewImage.html +34 -34
- package/docs/utils/price.html +51 -51
- package/docs/utils/rule.html +45 -45
- package/docs/utils/ruleValid.html +46 -46
- package/docs/utils/symbols.html +53 -53
- package/docs/utils/table.html +70 -70
- package/docs/utils/timestamp.html +45 -45
- package/docs/utils/toast.html +38 -38
- package/docs/utils/tree.html +55 -55
- package/docs/utils/uploader.html +34 -34
- package/package.json +25 -25
- package/sass/common.scss +184 -184
- package/sass/index.scss +12 -12
- package/sass/line.scss +39 -39
- package/sass/quasar/btn.scss +46 -46
- package/sass/quasar/common.scss +3 -3
- package/sass/quasar/drawer.scss +6 -6
- package/sass/quasar/field.scss +259 -259
- package/sass/quasar/loading.scss +6 -6
- package/sass/quasar/table.scss +168 -168
- package/sass/quasar/toolbar.scss +22 -22
- package/sass/variables.scss +140 -140
- package/store/index.js +29 -29
- package/utils/$auth.js +128 -128
- package/utils/$form.js +72 -72
- package/utils/$power.js +1494 -1494
- package/utils/$render.js +75 -75
- package/utils/$rule.js +13 -13
- package/utils/$ruleValid.js +10 -10
- package/utils/$search.js +416 -416
- package/utils/$table.js +1351 -1348
- package/utils/$tree.js +682 -682
- package/utils/alert.js +12 -12
- package/utils/area.js +400 -400
- package/utils/arr.js +51 -51
- package/utils/bus.js +6 -6
- package/utils/config.js +66 -66
- package/utils/confirm.js +11 -11
- package/utils/copy.js +30 -30
- package/utils/dialog.js +36 -36
- package/utils/dict.js +21 -21
- package/utils/dictOptions.js +28 -28
- package/utils/getData.js +88 -88
- package/utils/getFile.js +67 -67
- package/utils/getImage.js +276 -276
- package/utils/getTime.js +113 -113
- package/utils/index.js +67 -67
- package/utils/loading.js +15 -15
- package/utils/notify.js +13 -13
- package/utils/play.js +40 -40
- package/utils/previewImage.js +14 -14
- package/utils/price.js +18 -18
- package/utils/symbols.js +18 -18
- package/utils/timestamp.js +18 -18
- package/utils/toast.js +13 -13
- package/utils/uploader.js +2114 -2114
- package/utils/useAuth.js +30 -30
- package/utils/useFileUrl.js +26 -26
- package/utils/useRouter.js +47 -47
- package/utils/useSearch.js +587 -562
|
@@ -1,560 +1,560 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<q-input
|
|
3
|
-
class="n-input-number"
|
|
4
|
-
:class="{
|
|
5
|
-
'n-input-number--center': center,
|
|
6
|
-
}"
|
|
7
|
-
:disable="disable"
|
|
8
|
-
:readonly="readonly"
|
|
9
|
-
v-model="currentValue"
|
|
10
|
-
@update:model-value="onUpdate"
|
|
11
|
-
@blur="onBlur"
|
|
12
|
-
v-bind="$attrs"
|
|
13
|
-
>
|
|
14
|
-
<!-- 内部前置插槽 -->
|
|
15
|
-
<template #prepend v-if="controls && center">
|
|
16
|
-
|
|
17
|
-
<!-- 减少按钮 -->
|
|
18
|
-
<q-btn
|
|
19
|
-
class="n-input-number__left"
|
|
20
|
-
color="default"
|
|
21
|
-
icon="remove"
|
|
22
|
-
flat
|
|
23
|
-
dense
|
|
24
|
-
:disable="currentDisableMinus"
|
|
25
|
-
@click="onChange('minus')"
|
|
26
|
-
/>
|
|
27
|
-
|
|
28
|
-
<!-- 内部前置插槽 -->
|
|
29
|
-
<slot name="prepend" />
|
|
30
|
-
|
|
31
|
-
</template>
|
|
32
|
-
|
|
33
|
-
<!-- 内部后置插槽 -->
|
|
34
|
-
<template #append v-if="controls">
|
|
35
|
-
|
|
36
|
-
<!-- 内部后置插槽 -->
|
|
37
|
-
<slot name="append" />
|
|
38
|
-
|
|
39
|
-
<!-- 减少按钮 -->
|
|
40
|
-
<q-btn
|
|
41
|
-
color="default"
|
|
42
|
-
icon="remove"
|
|
43
|
-
flat
|
|
44
|
-
dense
|
|
45
|
-
:disable="currentDisableMinus"
|
|
46
|
-
@click="onChange('minus')"
|
|
47
|
-
v-if="! center"
|
|
48
|
-
/>
|
|
49
|
-
|
|
50
|
-
<!-- 增加按钮 -->
|
|
51
|
-
<q-btn
|
|
52
|
-
class="n-input-number__right"
|
|
53
|
-
color="default"
|
|
54
|
-
icon="add"
|
|
55
|
-
flat
|
|
56
|
-
dense
|
|
57
|
-
:disable="currentDisablePlus"
|
|
58
|
-
@click="onChange('plus')"
|
|
59
|
-
/>
|
|
60
|
-
|
|
61
|
-
</template>
|
|
62
|
-
|
|
63
|
-
<!-- 插槽 -->
|
|
64
|
-
<template
|
|
65
|
-
v-for="slotName in slotNames"
|
|
66
|
-
v-slot:[slotName]
|
|
67
|
-
>
|
|
68
|
-
<slot :name="slotName" />
|
|
69
|
-
</template>
|
|
70
|
-
|
|
71
|
-
</q-input>
|
|
72
|
-
</template>
|
|
73
|
-
|
|
74
|
-
<script>
|
|
75
|
-
import { computed, ref, watch } from 'vue'
|
|
76
|
-
import BigNumber from 'bignumber.js'
|
|
77
|
-
|
|
78
|
-
import $n_filter from 'lodash/filter'
|
|
79
|
-
|
|
80
|
-
import $n_isValidObject from '@netang/utils/isValidObject'
|
|
81
|
-
import $n_sleep from '@netang/utils/sleep'
|
|
82
|
-
|
|
83
|
-
export default {
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* 标识
|
|
87
|
-
*/
|
|
88
|
-
name: 'NInputNumber',
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* 声明属性
|
|
92
|
-
*/
|
|
93
|
-
props: {
|
|
94
|
-
// 值 v-model
|
|
95
|
-
modelValue: {
|
|
96
|
-
required: true,
|
|
97
|
-
},
|
|
98
|
-
// 最小值
|
|
99
|
-
min: {
|
|
100
|
-
type: [Number, String],
|
|
101
|
-
default: 0,
|
|
102
|
-
},
|
|
103
|
-
// 最大值
|
|
104
|
-
max: {
|
|
105
|
-
type: [Number, String],
|
|
106
|
-
default: Infinity,
|
|
107
|
-
},
|
|
108
|
-
// 步长, 每次点击时改变的值(默认为 1, centToYuan开启后默认为 100)
|
|
109
|
-
step: [Number, String],
|
|
110
|
-
// 小数位数(默认为 0, centToYuan开启后默认为 2)
|
|
111
|
-
decimalLength: [Number, String],
|
|
112
|
-
// 是否禁用减少按钮
|
|
113
|
-
disableMinus: Boolean,
|
|
114
|
-
// 是否禁用增加按钮
|
|
115
|
-
disablePlus: Boolean,
|
|
116
|
-
// 是否使用控制按钮
|
|
117
|
-
controls: Boolean,
|
|
118
|
-
// 居中显示
|
|
119
|
-
center: Boolean,
|
|
120
|
-
// 不允许输入的值为空
|
|
121
|
-
noEmpty: Boolean,
|
|
122
|
-
// 是否为人民币的分转元(值为分, 显示为元)
|
|
123
|
-
// 如果为 true, 则 min / max / step 的值默认的单位为人民币的分
|
|
124
|
-
centToYuan: Boolean,
|
|
125
|
-
// 精度舍入模式(默认: 向下取整)
|
|
126
|
-
// 参考文档: https://mikemcl.github.io/bignumber.js/#constructor-properties
|
|
127
|
-
roundMode: {
|
|
128
|
-
type: Number,
|
|
129
|
-
default: BigNumber.ROUND_DOWN,
|
|
130
|
-
},
|
|
131
|
-
// 是否禁用
|
|
132
|
-
disable: Boolean,
|
|
133
|
-
// 是否只读
|
|
134
|
-
readonly: Boolean,
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* 声明事件
|
|
139
|
-
*/
|
|
140
|
-
emits: [
|
|
141
|
-
'update:modelValue',
|
|
142
|
-
'blur',
|
|
143
|
-
'minus',
|
|
144
|
-
'plus',
|
|
145
|
-
],
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* 组合式
|
|
149
|
-
*/
|
|
150
|
-
setup(props, { emit, slots }) {
|
|
151
|
-
|
|
152
|
-
// ==========【数据】============================================================================================
|
|
153
|
-
|
|
154
|
-
// 创建睡眠实例
|
|
155
|
-
const sleep = $n_sleep()
|
|
156
|
-
|
|
157
|
-
// ==========【计算属性】=========================================================================================
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* 插槽标识
|
|
161
|
-
*/
|
|
162
|
-
const slotNames = computed(function() {
|
|
163
|
-
|
|
164
|
-
if ($n_isValidObject(slots)) {
|
|
165
|
-
|
|
166
|
-
// 忽略插槽
|
|
167
|
-
const ignoreKeys = []
|
|
168
|
-
|
|
169
|
-
if (props.controls) {
|
|
170
|
-
ignoreKeys.push('append')
|
|
171
|
-
|
|
172
|
-
if (props.center) {
|
|
173
|
-
ignoreKeys.push('prepend')
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const keys = Object.keys(slots)
|
|
178
|
-
|
|
179
|
-
if (ignoreKeys.length) {
|
|
180
|
-
return $n_filter(keys, e => ignoreKeys.indexOf(e) === -1)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return keys
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return []
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* 当前最小值
|
|
191
|
-
*/
|
|
192
|
-
const currentMin = computed(function() {
|
|
193
|
-
// 格式化数字
|
|
194
|
-
return formatNumber(props.min, true, true, null)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* 当前最大值
|
|
199
|
-
*/
|
|
200
|
-
const currentMax = computed(function() {
|
|
201
|
-
|
|
202
|
-
// 如果为无限大
|
|
203
|
-
if (props.max === Infinity) {
|
|
204
|
-
// 则返回无限大
|
|
205
|
-
return Infinity
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// 格式化数字
|
|
209
|
-
return formatNumber(props.max, true, true, null)
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* 当前步长(默认为 1, centToYuan开启后默认为 100)
|
|
214
|
-
*/
|
|
215
|
-
const currentStep = computed(function() {
|
|
216
|
-
|
|
217
|
-
// 格式化数字
|
|
218
|
-
return formatNumber(props.step ?? (props.centToYuan ? 100 : 1), true, true, null)
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* 当前小数位数(默认为 0, centToYuan开启后默认为 2)
|
|
223
|
-
*/
|
|
224
|
-
const currentDecimalLength = computed(function() {
|
|
225
|
-
return props.decimalLength ?? (props.centToYuan ? 2 : 0)
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* 当前是否禁用减少按钮
|
|
230
|
-
*/
|
|
231
|
-
const currentDisableMinus = computed(function () {
|
|
232
|
-
|
|
233
|
-
// 如果禁用 || 如果只读 || 禁用减少按钮
|
|
234
|
-
if (props.disable || props.readonly || props.disableMinus) {
|
|
235
|
-
// 则禁用减少按钮
|
|
236
|
-
return true
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// 如果没有当前最小值
|
|
240
|
-
if (currentMin.value === null) {
|
|
241
|
-
// 则不禁用减少按钮
|
|
242
|
-
return false
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// 将当前值转为 BigNumber 类型
|
|
246
|
-
const val = new BigNumber(currentValue.value)
|
|
247
|
-
|
|
248
|
-
// 如果当前值不是有效数字
|
|
249
|
-
if (! val.isFinite()) {
|
|
250
|
-
// 则禁用减少按钮
|
|
251
|
-
return true
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// 当前值 <= 当前最小值
|
|
255
|
-
return val.lte(currentMin.value)
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* 当前是否禁用增加按钮
|
|
260
|
-
*/
|
|
261
|
-
const currentDisablePlus = computed(function () {
|
|
262
|
-
|
|
263
|
-
// 如果禁用 || 如果只读 || 禁用增加按钮
|
|
264
|
-
if (props.disable || props.readonly || props.disablePlus) {
|
|
265
|
-
// 则禁用增加按钮
|
|
266
|
-
return true
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// 如果没有当前最大值
|
|
270
|
-
if (currentMax.value === null) {
|
|
271
|
-
// 则不禁用增加按钮
|
|
272
|
-
return false
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// 将当前值转为 BigNumber 类型
|
|
276
|
-
const val = new BigNumber(currentValue.value)
|
|
277
|
-
|
|
278
|
-
// 如果当前值不是有效数字
|
|
279
|
-
if (! val.isFinite()) {
|
|
280
|
-
// 则禁用减少按钮
|
|
281
|
-
return true
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// 当前值 >= 当前最大值
|
|
285
|
-
return val.gte(currentMax.value)
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
// ==========【数据】============================================================================================
|
|
289
|
-
|
|
290
|
-
// 格式化为当前值
|
|
291
|
-
const currentValue = ref(formatToCurrentValue(props.modelValue, true))
|
|
292
|
-
|
|
293
|
-
// 如果当前值 !== 声明值
|
|
294
|
-
const rawModelValue = formatToModelValue(currentValue.value)
|
|
295
|
-
if (rawModelValue !== props.modelValue) {
|
|
296
|
-
|
|
297
|
-
// 触发更新值
|
|
298
|
-
emitModelValue(rawModelValue)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// ==========【监听数据】=========================================================================================
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* 监听声明值
|
|
305
|
-
*/
|
|
306
|
-
watch(() => props.modelValue, function (val) {
|
|
307
|
-
|
|
308
|
-
// 格式化为当前值
|
|
309
|
-
val = formatToCurrentValue(val, true)
|
|
310
|
-
|
|
311
|
-
// 如果当前值有变化
|
|
312
|
-
if (val !== currentValue.value) {
|
|
313
|
-
// 更新当前值
|
|
314
|
-
currentValue.value = val
|
|
315
|
-
// 触发更新值
|
|
316
|
-
emitModelValue(formatToModelValue(val))
|
|
317
|
-
}
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* 监听 当前最小值 / 当前最大值 / 当前小数位数
|
|
322
|
-
*/
|
|
323
|
-
watch([currentMin, currentMax, currentDecimalLength], onUpdate)
|
|
324
|
-
|
|
325
|
-
// ==========【方法】=============================================================================================
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* 触发更新值
|
|
329
|
-
*/
|
|
330
|
-
function emitModelValue(val) {
|
|
331
|
-
|
|
332
|
-
// 触发更新值
|
|
333
|
-
emit('update:modelValue', val)
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* 格式化数字
|
|
338
|
-
*/
|
|
339
|
-
function formatNumber(val, isCentToYuan, isToNumber, defaultValue) {
|
|
340
|
-
|
|
341
|
-
// 转为 BigNumber 类型
|
|
342
|
-
val = new BigNumber(val)
|
|
343
|
-
|
|
344
|
-
// 如果为有效数字
|
|
345
|
-
if (val.isFinite()) {
|
|
346
|
-
|
|
347
|
-
// 如果不为 0
|
|
348
|
-
if (! val.isZero()) {
|
|
349
|
-
|
|
350
|
-
// 如果为人民币的分转元
|
|
351
|
-
if (props.centToYuan && isCentToYuan) {
|
|
352
|
-
// 除 100
|
|
353
|
-
val = val.dividedBy(100)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// 如果设置了小数位数
|
|
357
|
-
if (currentDecimalLength.value) {
|
|
358
|
-
// 将值舍入 xx 位精度(如 68.345 -> 68.34)
|
|
359
|
-
val = val.dp(currentDecimalLength.value, props.roundMode)
|
|
360
|
-
|
|
361
|
-
// 否则值为整数
|
|
362
|
-
} else {
|
|
363
|
-
// 将值取整
|
|
364
|
-
val = val.integerValue(props.roundMode)
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// 转为数字
|
|
369
|
-
return isToNumber ? val.toNumber() : val
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return defaultValue
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* 格式化为更新值
|
|
377
|
-
*/
|
|
378
|
-
function formatToModelValue(value) {
|
|
379
|
-
|
|
380
|
-
// 转为 BigNumber 类型
|
|
381
|
-
let val = new BigNumber(value)
|
|
382
|
-
|
|
383
|
-
// 如果不是有效数字
|
|
384
|
-
if (! val.isFinite()) {
|
|
385
|
-
|
|
386
|
-
// 返回当前值
|
|
387
|
-
return value
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// 如果为人民币的分转元
|
|
391
|
-
if (props.centToYuan) {
|
|
392
|
-
// 乘以 100
|
|
393
|
-
val = val.times(100)
|
|
394
|
-
// 再取整(分必须是整数)
|
|
395
|
-
.integerValue(props.roundMode)
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// 将值转为数字
|
|
399
|
-
return val.toNumber()
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* 格式化值
|
|
404
|
-
*/
|
|
405
|
-
function formatToCurrentValue(value, isCentToYuan) {
|
|
406
|
-
|
|
407
|
-
// 格式化数字
|
|
408
|
-
const val = formatNumber(value, isCentToYuan, false, false)
|
|
409
|
-
|
|
410
|
-
// 如果为有效数字
|
|
411
|
-
if (val !== false) {
|
|
412
|
-
|
|
413
|
-
// 如果值 >= 最大值
|
|
414
|
-
if (currentMax.value !== null && val.gte(currentMax.value)) {
|
|
415
|
-
|
|
416
|
-
// 返回最大值
|
|
417
|
-
return currentMax.value
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// 如果值 <= 最小值
|
|
421
|
-
if (currentMin.value !== null && val.lte(currentMin.value)) {
|
|
422
|
-
|
|
423
|
-
// 返回最小值
|
|
424
|
-
return currentMin.value
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// 将值转为数字
|
|
428
|
-
return val.toNumber()
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (
|
|
432
|
-
// 如果不允许值为空
|
|
433
|
-
props.noEmpty
|
|
434
|
-
// 如果有最小值
|
|
435
|
-
&& currentMin.value !== null
|
|
436
|
-
) {
|
|
437
|
-
// 则返回最小值
|
|
438
|
-
return currentMin.value
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return ''
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* 更新值触发
|
|
446
|
-
*/
|
|
447
|
-
async function onUpdate() {
|
|
448
|
-
|
|
449
|
-
// 延迟执行
|
|
450
|
-
await sleep(500)
|
|
451
|
-
|
|
452
|
-
// 格式化当前值
|
|
453
|
-
const newVal = formatToCurrentValue(currentValue.value, false)
|
|
454
|
-
|
|
455
|
-
// 如果当前值有变化
|
|
456
|
-
if (newVal !== currentValue.value) {
|
|
457
|
-
// 更新当前值
|
|
458
|
-
currentValue.value = newVal
|
|
459
|
-
// 更新值
|
|
460
|
-
emitModelValue(formatToModelValue(newVal))
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* 失去焦点触发
|
|
466
|
-
*/
|
|
467
|
-
function onBlur() {
|
|
468
|
-
|
|
469
|
-
// 格式化当前值
|
|
470
|
-
let val = formatToCurrentValue(currentValue.value, false)
|
|
471
|
-
|
|
472
|
-
// 更新当前值
|
|
473
|
-
currentValue.value = val
|
|
474
|
-
|
|
475
|
-
// 将当前值转为声明值
|
|
476
|
-
val = formatToModelValue(val)
|
|
477
|
-
|
|
478
|
-
// 触发更新值
|
|
479
|
-
emitModelValue(val)
|
|
480
|
-
|
|
481
|
-
// 失去焦点触发
|
|
482
|
-
emit('blur', val)
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/**
|
|
486
|
-
* 改变值
|
|
487
|
-
*/
|
|
488
|
-
function onChange(type) {
|
|
489
|
-
|
|
490
|
-
// 格式化当前值
|
|
491
|
-
const val = formatToCurrentValue(
|
|
492
|
-
new BigNumber(+currentValue.value)
|
|
493
|
-
// 增加 / 减少
|
|
494
|
-
.plus(type === 'minus' ? -currentStep.value : +currentStep.value)
|
|
495
|
-
.toNumber()
|
|
496
|
-
, false
|
|
497
|
-
)
|
|
498
|
-
|
|
499
|
-
// 如果当前值有变动
|
|
500
|
-
if (val !== currentValue.value) {
|
|
501
|
-
|
|
502
|
-
// 更新当前值
|
|
503
|
-
currentValue.value = val
|
|
504
|
-
|
|
505
|
-
// 触发更新值
|
|
506
|
-
emitModelValue(formatToModelValue(val))
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// ==========【返回】=============================================================================================
|
|
511
|
-
|
|
512
|
-
return {
|
|
513
|
-
// 插槽标识
|
|
514
|
-
slotNames,
|
|
515
|
-
// 当前值
|
|
516
|
-
currentValue,
|
|
517
|
-
// 当前是否禁用减少按钮
|
|
518
|
-
currentDisableMinus,
|
|
519
|
-
// 当前是否禁用增加按钮
|
|
520
|
-
currentDisablePlus,
|
|
521
|
-
|
|
522
|
-
// 更新值触发
|
|
523
|
-
onUpdate,
|
|
524
|
-
// 失去焦点触发
|
|
525
|
-
onBlur,
|
|
526
|
-
// 改变值
|
|
527
|
-
onChange,
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
</script>
|
|
532
|
-
|
|
533
|
-
<style lang="scss">
|
|
534
|
-
.n-input-number {
|
|
535
|
-
|
|
536
|
-
// 居中显示
|
|
537
|
-
&--center {
|
|
538
|
-
&.q-field {
|
|
539
|
-
&--outlined {
|
|
540
|
-
.q-field__control {
|
|
541
|
-
.q-field__native {
|
|
542
|
-
text-align: center;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// 左边按钮
|
|
550
|
-
&__left {
|
|
551
|
-
margin-left: -8px;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// 右边按钮
|
|
555
|
-
&__right {
|
|
556
|
-
margin-right: -8px;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
</style>
|
|
560
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<q-input
|
|
3
|
+
class="n-input-number"
|
|
4
|
+
:class="{
|
|
5
|
+
'n-input-number--center': center,
|
|
6
|
+
}"
|
|
7
|
+
:disable="disable"
|
|
8
|
+
:readonly="readonly"
|
|
9
|
+
v-model="currentValue"
|
|
10
|
+
@update:model-value="onUpdate"
|
|
11
|
+
@blur="onBlur"
|
|
12
|
+
v-bind="$attrs"
|
|
13
|
+
>
|
|
14
|
+
<!-- 内部前置插槽 -->
|
|
15
|
+
<template #prepend v-if="controls && center">
|
|
16
|
+
|
|
17
|
+
<!-- 减少按钮 -->
|
|
18
|
+
<q-btn
|
|
19
|
+
class="n-input-number__left"
|
|
20
|
+
color="default"
|
|
21
|
+
icon="remove"
|
|
22
|
+
flat
|
|
23
|
+
dense
|
|
24
|
+
:disable="currentDisableMinus"
|
|
25
|
+
@click="onChange('minus')"
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
<!-- 内部前置插槽 -->
|
|
29
|
+
<slot name="prepend" />
|
|
30
|
+
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<!-- 内部后置插槽 -->
|
|
34
|
+
<template #append v-if="controls">
|
|
35
|
+
|
|
36
|
+
<!-- 内部后置插槽 -->
|
|
37
|
+
<slot name="append" />
|
|
38
|
+
|
|
39
|
+
<!-- 减少按钮 -->
|
|
40
|
+
<q-btn
|
|
41
|
+
color="default"
|
|
42
|
+
icon="remove"
|
|
43
|
+
flat
|
|
44
|
+
dense
|
|
45
|
+
:disable="currentDisableMinus"
|
|
46
|
+
@click="onChange('minus')"
|
|
47
|
+
v-if="! center"
|
|
48
|
+
/>
|
|
49
|
+
|
|
50
|
+
<!-- 增加按钮 -->
|
|
51
|
+
<q-btn
|
|
52
|
+
class="n-input-number__right"
|
|
53
|
+
color="default"
|
|
54
|
+
icon="add"
|
|
55
|
+
flat
|
|
56
|
+
dense
|
|
57
|
+
:disable="currentDisablePlus"
|
|
58
|
+
@click="onChange('plus')"
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<!-- 插槽 -->
|
|
64
|
+
<template
|
|
65
|
+
v-for="slotName in slotNames"
|
|
66
|
+
v-slot:[slotName]
|
|
67
|
+
>
|
|
68
|
+
<slot :name="slotName" />
|
|
69
|
+
</template>
|
|
70
|
+
|
|
71
|
+
</q-input>
|
|
72
|
+
</template>
|
|
73
|
+
|
|
74
|
+
<script>
|
|
75
|
+
import { computed, ref, watch } from 'vue'
|
|
76
|
+
import BigNumber from 'bignumber.js'
|
|
77
|
+
|
|
78
|
+
import $n_filter from 'lodash/filter'
|
|
79
|
+
|
|
80
|
+
import $n_isValidObject from '@netang/utils/isValidObject'
|
|
81
|
+
import $n_sleep from '@netang/utils/sleep'
|
|
82
|
+
|
|
83
|
+
export default {
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 标识
|
|
87
|
+
*/
|
|
88
|
+
name: 'NInputNumber',
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 声明属性
|
|
92
|
+
*/
|
|
93
|
+
props: {
|
|
94
|
+
// 值 v-model
|
|
95
|
+
modelValue: {
|
|
96
|
+
required: true,
|
|
97
|
+
},
|
|
98
|
+
// 最小值
|
|
99
|
+
min: {
|
|
100
|
+
type: [Number, String],
|
|
101
|
+
default: 0,
|
|
102
|
+
},
|
|
103
|
+
// 最大值
|
|
104
|
+
max: {
|
|
105
|
+
type: [Number, String],
|
|
106
|
+
default: Infinity,
|
|
107
|
+
},
|
|
108
|
+
// 步长, 每次点击时改变的值(默认为 1, centToYuan开启后默认为 100)
|
|
109
|
+
step: [Number, String],
|
|
110
|
+
// 小数位数(默认为 0, centToYuan开启后默认为 2)
|
|
111
|
+
decimalLength: [Number, String],
|
|
112
|
+
// 是否禁用减少按钮
|
|
113
|
+
disableMinus: Boolean,
|
|
114
|
+
// 是否禁用增加按钮
|
|
115
|
+
disablePlus: Boolean,
|
|
116
|
+
// 是否使用控制按钮
|
|
117
|
+
controls: Boolean,
|
|
118
|
+
// 居中显示
|
|
119
|
+
center: Boolean,
|
|
120
|
+
// 不允许输入的值为空
|
|
121
|
+
noEmpty: Boolean,
|
|
122
|
+
// 是否为人民币的分转元(值为分, 显示为元)
|
|
123
|
+
// 如果为 true, 则 min / max / step 的值默认的单位为人民币的分
|
|
124
|
+
centToYuan: Boolean,
|
|
125
|
+
// 精度舍入模式(默认: 向下取整)
|
|
126
|
+
// 参考文档: https://mikemcl.github.io/bignumber.js/#constructor-properties
|
|
127
|
+
roundMode: {
|
|
128
|
+
type: Number,
|
|
129
|
+
default: BigNumber.ROUND_DOWN,
|
|
130
|
+
},
|
|
131
|
+
// 是否禁用
|
|
132
|
+
disable: Boolean,
|
|
133
|
+
// 是否只读
|
|
134
|
+
readonly: Boolean,
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 声明事件
|
|
139
|
+
*/
|
|
140
|
+
emits: [
|
|
141
|
+
'update:modelValue',
|
|
142
|
+
'blur',
|
|
143
|
+
'minus',
|
|
144
|
+
'plus',
|
|
145
|
+
],
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 组合式
|
|
149
|
+
*/
|
|
150
|
+
setup(props, { emit, slots }) {
|
|
151
|
+
|
|
152
|
+
// ==========【数据】============================================================================================
|
|
153
|
+
|
|
154
|
+
// 创建睡眠实例
|
|
155
|
+
const sleep = $n_sleep()
|
|
156
|
+
|
|
157
|
+
// ==========【计算属性】=========================================================================================
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 插槽标识
|
|
161
|
+
*/
|
|
162
|
+
const slotNames = computed(function() {
|
|
163
|
+
|
|
164
|
+
if ($n_isValidObject(slots)) {
|
|
165
|
+
|
|
166
|
+
// 忽略插槽
|
|
167
|
+
const ignoreKeys = []
|
|
168
|
+
|
|
169
|
+
if (props.controls) {
|
|
170
|
+
ignoreKeys.push('append')
|
|
171
|
+
|
|
172
|
+
if (props.center) {
|
|
173
|
+
ignoreKeys.push('prepend')
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const keys = Object.keys(slots)
|
|
178
|
+
|
|
179
|
+
if (ignoreKeys.length) {
|
|
180
|
+
return $n_filter(keys, e => ignoreKeys.indexOf(e) === -1)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return keys
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return []
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 当前最小值
|
|
191
|
+
*/
|
|
192
|
+
const currentMin = computed(function() {
|
|
193
|
+
// 格式化数字
|
|
194
|
+
return formatNumber(props.min, true, true, null)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 当前最大值
|
|
199
|
+
*/
|
|
200
|
+
const currentMax = computed(function() {
|
|
201
|
+
|
|
202
|
+
// 如果为无限大
|
|
203
|
+
if (props.max === Infinity) {
|
|
204
|
+
// 则返回无限大
|
|
205
|
+
return Infinity
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 格式化数字
|
|
209
|
+
return formatNumber(props.max, true, true, null)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 当前步长(默认为 1, centToYuan开启后默认为 100)
|
|
214
|
+
*/
|
|
215
|
+
const currentStep = computed(function() {
|
|
216
|
+
|
|
217
|
+
// 格式化数字
|
|
218
|
+
return formatNumber(props.step ?? (props.centToYuan ? 100 : 1), true, true, null)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* 当前小数位数(默认为 0, centToYuan开启后默认为 2)
|
|
223
|
+
*/
|
|
224
|
+
const currentDecimalLength = computed(function() {
|
|
225
|
+
return props.decimalLength ?? (props.centToYuan ? 2 : 0)
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* 当前是否禁用减少按钮
|
|
230
|
+
*/
|
|
231
|
+
const currentDisableMinus = computed(function () {
|
|
232
|
+
|
|
233
|
+
// 如果禁用 || 如果只读 || 禁用减少按钮
|
|
234
|
+
if (props.disable || props.readonly || props.disableMinus) {
|
|
235
|
+
// 则禁用减少按钮
|
|
236
|
+
return true
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// 如果没有当前最小值
|
|
240
|
+
if (currentMin.value === null) {
|
|
241
|
+
// 则不禁用减少按钮
|
|
242
|
+
return false
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// 将当前值转为 BigNumber 类型
|
|
246
|
+
const val = new BigNumber(currentValue.value)
|
|
247
|
+
|
|
248
|
+
// 如果当前值不是有效数字
|
|
249
|
+
if (! val.isFinite()) {
|
|
250
|
+
// 则禁用减少按钮
|
|
251
|
+
return true
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 当前值 <= 当前最小值
|
|
255
|
+
return val.lte(currentMin.value)
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* 当前是否禁用增加按钮
|
|
260
|
+
*/
|
|
261
|
+
const currentDisablePlus = computed(function () {
|
|
262
|
+
|
|
263
|
+
// 如果禁用 || 如果只读 || 禁用增加按钮
|
|
264
|
+
if (props.disable || props.readonly || props.disablePlus) {
|
|
265
|
+
// 则禁用增加按钮
|
|
266
|
+
return true
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// 如果没有当前最大值
|
|
270
|
+
if (currentMax.value === null) {
|
|
271
|
+
// 则不禁用增加按钮
|
|
272
|
+
return false
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// 将当前值转为 BigNumber 类型
|
|
276
|
+
const val = new BigNumber(currentValue.value)
|
|
277
|
+
|
|
278
|
+
// 如果当前值不是有效数字
|
|
279
|
+
if (! val.isFinite()) {
|
|
280
|
+
// 则禁用减少按钮
|
|
281
|
+
return true
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// 当前值 >= 当前最大值
|
|
285
|
+
return val.gte(currentMax.value)
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
// ==========【数据】============================================================================================
|
|
289
|
+
|
|
290
|
+
// 格式化为当前值
|
|
291
|
+
const currentValue = ref(formatToCurrentValue(props.modelValue, true))
|
|
292
|
+
|
|
293
|
+
// 如果当前值 !== 声明值
|
|
294
|
+
const rawModelValue = formatToModelValue(currentValue.value)
|
|
295
|
+
if (rawModelValue !== props.modelValue) {
|
|
296
|
+
|
|
297
|
+
// 触发更新值
|
|
298
|
+
emitModelValue(rawModelValue)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ==========【监听数据】=========================================================================================
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* 监听声明值
|
|
305
|
+
*/
|
|
306
|
+
watch(() => props.modelValue, function (val) {
|
|
307
|
+
|
|
308
|
+
// 格式化为当前值
|
|
309
|
+
val = formatToCurrentValue(val, true)
|
|
310
|
+
|
|
311
|
+
// 如果当前值有变化
|
|
312
|
+
if (val !== currentValue.value) {
|
|
313
|
+
// 更新当前值
|
|
314
|
+
currentValue.value = val
|
|
315
|
+
// 触发更新值
|
|
316
|
+
emitModelValue(formatToModelValue(val))
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 监听 当前最小值 / 当前最大值 / 当前小数位数
|
|
322
|
+
*/
|
|
323
|
+
watch([currentMin, currentMax, currentDecimalLength], onUpdate)
|
|
324
|
+
|
|
325
|
+
// ==========【方法】=============================================================================================
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* 触发更新值
|
|
329
|
+
*/
|
|
330
|
+
function emitModelValue(val) {
|
|
331
|
+
|
|
332
|
+
// 触发更新值
|
|
333
|
+
emit('update:modelValue', val)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 格式化数字
|
|
338
|
+
*/
|
|
339
|
+
function formatNumber(val, isCentToYuan, isToNumber, defaultValue) {
|
|
340
|
+
|
|
341
|
+
// 转为 BigNumber 类型
|
|
342
|
+
val = new BigNumber(val)
|
|
343
|
+
|
|
344
|
+
// 如果为有效数字
|
|
345
|
+
if (val.isFinite()) {
|
|
346
|
+
|
|
347
|
+
// 如果不为 0
|
|
348
|
+
if (! val.isZero()) {
|
|
349
|
+
|
|
350
|
+
// 如果为人民币的分转元
|
|
351
|
+
if (props.centToYuan && isCentToYuan) {
|
|
352
|
+
// 除 100
|
|
353
|
+
val = val.dividedBy(100)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 如果设置了小数位数
|
|
357
|
+
if (currentDecimalLength.value) {
|
|
358
|
+
// 将值舍入 xx 位精度(如 68.345 -> 68.34)
|
|
359
|
+
val = val.dp(currentDecimalLength.value, props.roundMode)
|
|
360
|
+
|
|
361
|
+
// 否则值为整数
|
|
362
|
+
} else {
|
|
363
|
+
// 将值取整
|
|
364
|
+
val = val.integerValue(props.roundMode)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 转为数字
|
|
369
|
+
return isToNumber ? val.toNumber() : val
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return defaultValue
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* 格式化为更新值
|
|
377
|
+
*/
|
|
378
|
+
function formatToModelValue(value) {
|
|
379
|
+
|
|
380
|
+
// 转为 BigNumber 类型
|
|
381
|
+
let val = new BigNumber(value)
|
|
382
|
+
|
|
383
|
+
// 如果不是有效数字
|
|
384
|
+
if (! val.isFinite()) {
|
|
385
|
+
|
|
386
|
+
// 返回当前值
|
|
387
|
+
return value
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// 如果为人民币的分转元
|
|
391
|
+
if (props.centToYuan) {
|
|
392
|
+
// 乘以 100
|
|
393
|
+
val = val.times(100)
|
|
394
|
+
// 再取整(分必须是整数)
|
|
395
|
+
.integerValue(props.roundMode)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// 将值转为数字
|
|
399
|
+
return val.toNumber()
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* 格式化值
|
|
404
|
+
*/
|
|
405
|
+
function formatToCurrentValue(value, isCentToYuan) {
|
|
406
|
+
|
|
407
|
+
// 格式化数字
|
|
408
|
+
const val = formatNumber(value, isCentToYuan, false, false)
|
|
409
|
+
|
|
410
|
+
// 如果为有效数字
|
|
411
|
+
if (val !== false) {
|
|
412
|
+
|
|
413
|
+
// 如果值 >= 最大值
|
|
414
|
+
if (currentMax.value !== null && val.gte(currentMax.value)) {
|
|
415
|
+
|
|
416
|
+
// 返回最大值
|
|
417
|
+
return currentMax.value
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// 如果值 <= 最小值
|
|
421
|
+
if (currentMin.value !== null && val.lte(currentMin.value)) {
|
|
422
|
+
|
|
423
|
+
// 返回最小值
|
|
424
|
+
return currentMin.value
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// 将值转为数字
|
|
428
|
+
return val.toNumber()
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (
|
|
432
|
+
// 如果不允许值为空
|
|
433
|
+
props.noEmpty
|
|
434
|
+
// 如果有最小值
|
|
435
|
+
&& currentMin.value !== null
|
|
436
|
+
) {
|
|
437
|
+
// 则返回最小值
|
|
438
|
+
return currentMin.value
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return ''
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* 更新值触发
|
|
446
|
+
*/
|
|
447
|
+
async function onUpdate() {
|
|
448
|
+
|
|
449
|
+
// 延迟执行
|
|
450
|
+
await sleep(500)
|
|
451
|
+
|
|
452
|
+
// 格式化当前值
|
|
453
|
+
const newVal = formatToCurrentValue(currentValue.value, false)
|
|
454
|
+
|
|
455
|
+
// 如果当前值有变化
|
|
456
|
+
if (newVal !== currentValue.value) {
|
|
457
|
+
// 更新当前值
|
|
458
|
+
currentValue.value = newVal
|
|
459
|
+
// 更新值
|
|
460
|
+
emitModelValue(formatToModelValue(newVal))
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* 失去焦点触发
|
|
466
|
+
*/
|
|
467
|
+
function onBlur() {
|
|
468
|
+
|
|
469
|
+
// 格式化当前值
|
|
470
|
+
let val = formatToCurrentValue(currentValue.value, false)
|
|
471
|
+
|
|
472
|
+
// 更新当前值
|
|
473
|
+
currentValue.value = val
|
|
474
|
+
|
|
475
|
+
// 将当前值转为声明值
|
|
476
|
+
val = formatToModelValue(val)
|
|
477
|
+
|
|
478
|
+
// 触发更新值
|
|
479
|
+
emitModelValue(val)
|
|
480
|
+
|
|
481
|
+
// 失去焦点触发
|
|
482
|
+
emit('blur', val)
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* 改变值
|
|
487
|
+
*/
|
|
488
|
+
function onChange(type) {
|
|
489
|
+
|
|
490
|
+
// 格式化当前值
|
|
491
|
+
const val = formatToCurrentValue(
|
|
492
|
+
new BigNumber(+currentValue.value)
|
|
493
|
+
// 增加 / 减少
|
|
494
|
+
.plus(type === 'minus' ? -currentStep.value : +currentStep.value)
|
|
495
|
+
.toNumber()
|
|
496
|
+
, false
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
// 如果当前值有变动
|
|
500
|
+
if (val !== currentValue.value) {
|
|
501
|
+
|
|
502
|
+
// 更新当前值
|
|
503
|
+
currentValue.value = val
|
|
504
|
+
|
|
505
|
+
// 触发更新值
|
|
506
|
+
emitModelValue(formatToModelValue(val))
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ==========【返回】=============================================================================================
|
|
511
|
+
|
|
512
|
+
return {
|
|
513
|
+
// 插槽标识
|
|
514
|
+
slotNames,
|
|
515
|
+
// 当前值
|
|
516
|
+
currentValue,
|
|
517
|
+
// 当前是否禁用减少按钮
|
|
518
|
+
currentDisableMinus,
|
|
519
|
+
// 当前是否禁用增加按钮
|
|
520
|
+
currentDisablePlus,
|
|
521
|
+
|
|
522
|
+
// 更新值触发
|
|
523
|
+
onUpdate,
|
|
524
|
+
// 失去焦点触发
|
|
525
|
+
onBlur,
|
|
526
|
+
// 改变值
|
|
527
|
+
onChange,
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
</script>
|
|
532
|
+
|
|
533
|
+
<style lang="scss">
|
|
534
|
+
.n-input-number {
|
|
535
|
+
|
|
536
|
+
// 居中显示
|
|
537
|
+
&--center {
|
|
538
|
+
&.q-field {
|
|
539
|
+
&--outlined {
|
|
540
|
+
.q-field__control {
|
|
541
|
+
.q-field__native {
|
|
542
|
+
text-align: center;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// 左边按钮
|
|
550
|
+
&__left {
|
|
551
|
+
margin-left: -8px;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// 右边按钮
|
|
555
|
+
&__right {
|
|
556
|
+
margin-right: -8px;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
</style>
|
|
560
|
+
|