@netang/quasar 0.2.31 → 0.2.32

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 (289) hide show
  1. package/.editorconfig +12 -12
  2. package/_docs/docs/components/field-table.md +58 -58
  3. package/_docs/docs/components/field-tree.md +21 -21
  4. package/_docs/docs/components/table.md +24 -24
  5. package/_docs/docs/utils/table.md +196 -196
  6. package/components/column-title/index.vue +38 -38
  7. package/components/data/index.vue +20 -20
  8. package/components/dialog/img-viewer/index.vue +697 -697
  9. package/components/dialog/index.vue +387 -387
  10. package/components/dragger/index.vue +203 -203
  11. package/components/drawer/index.vue +303 -303
  12. package/components/editor-code/index.vue +328 -328
  13. package/components/empty/index.vue +82 -82
  14. package/components/field-date/index.vue +860 -860
  15. package/components/field-date/methods.js +100 -100
  16. package/components/field-table/index.vue +1483 -1483
  17. package/components/field-text/index.vue +166 -166
  18. package/components/field-tree/index.vue +755 -755
  19. package/components/img/index.vue +279 -279
  20. package/components/input-number/index.vue +560 -560
  21. package/components/list-menu/index.vue +149 -149
  22. package/components/list-menu-item/index.vue +79 -79
  23. package/components/mixed-table/index.vue +532 -532
  24. package/components/mixed-table-splitter/index.vue +377 -377
  25. package/components/power-page/index.vue +96 -96
  26. package/components/price/index.vue +188 -188
  27. package/components/private/components/index.js +11 -11
  28. package/components/private/components/move-to-tree/index.vue +154 -154
  29. package/components/private/edit-power-data/index.vue +846 -846
  30. package/components/private/table-visible-columns-button/index.vue +114 -114
  31. package/components/render/index.vue +123 -123
  32. package/components/search/index.vue +231 -231
  33. package/components/search-item/index.vue +210 -210
  34. package/components/select/index.vue +177 -177
  35. package/components/splitter/index.vue +422 -422
  36. package/components/table/index.vue +513 -513
  37. package/components/table-column-fixed/index.vue +110 -110
  38. package/components/table-pagination/index.vue +192 -192
  39. package/components/table-summary/index.vue +107 -107
  40. package/components/thumbnail/index.vue +72 -72
  41. package/components/toolbar/index.vue +150 -150
  42. package/components/tree/index.vue +1728 -1728
  43. package/components/tree/virtual-scroll.vue +41 -41
  44. package/components/uploader/index.vue +196 -196
  45. package/components/uploader-query/index.vue +945 -945
  46. package/components/value-format/index.vue +274 -274
  47. package/components/virtual-scroll/index.vue +136 -136
  48. package/configs/area3.js +1 -1
  49. package/docs/404.html +33 -33
  50. package/docs/assets/404.html-60b35caa.js +1 -1
  51. package/docs/assets/404.html-d1e63d77.js +1 -1
  52. package/docs/assets/alert.html-b2a2a72f.js +5 -5
  53. package/docs/assets/alert.html-ba46d137.js +1 -1
  54. package/docs/assets/app-9f30aa4b.js +6 -6
  55. package/docs/assets/area.html-01b9b58d.js +42 -42
  56. package/docs/assets/area.html-9a4fce6a.js +1 -1
  57. package/docs/assets/arr.html-145d27e7.js +1 -1
  58. package/docs/assets/arr.html-674e65ab.js +11 -11
  59. package/docs/assets/auth.html-579fa830.js +1 -1
  60. package/docs/assets/auth.html-8544ed95.js +8 -8
  61. package/docs/assets/bus.html-c71254aa.js +1 -1
  62. package/docs/assets/bus.html-dc7d3d19.js +6 -6
  63. package/docs/assets/column-title.html-c735cb5a.js +3 -3
  64. package/docs/assets/column-title.html-e9316762.js +1 -1
  65. package/docs/assets/confirm.html-ddfdc27f.js +10 -10
  66. package/docs/assets/confirm.html-ef3e2bef.js +1 -1
  67. package/docs/assets/copy.html-d20345b6.js +1 -1
  68. package/docs/assets/copy.html-ef8c8571.js +13 -13
  69. package/docs/assets/data.html-6432175d.js +30 -30
  70. package/docs/assets/data.html-a3b05d5b.js +1 -1
  71. package/docs/assets/dialog.html-1f698e5a.js +1 -1
  72. package/docs/assets/dialog.html-62902b83.js +68 -68
  73. package/docs/assets/dialog.html-baea77c9.js +1 -1
  74. package/docs/assets/dialog.html-bb082fc4.js +1 -1
  75. package/docs/assets/dict.html-1311da3d.js +23 -23
  76. package/docs/assets/dict.html-b96fbf0c.js +1 -1
  77. package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
  78. package/docs/assets/dictOptions.html-fb99d175.js +5 -5
  79. package/docs/assets/dragger.html-668d3efa.js +1 -1
  80. package/docs/assets/dragger.html-749d585a.js +1 -1
  81. package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
  82. package/docs/assets/editor-code.html-d196205d.js +1 -1
  83. package/docs/assets/empty.html-1c139131.js +1 -1
  84. package/docs/assets/empty.html-1e9c441d.js +1 -1
  85. package/docs/assets/field-date.html-069fdb13.js +1 -1
  86. package/docs/assets/field-date.html-ad204aa9.js +1 -1
  87. package/docs/assets/field-table.html-ce480f03.js +1 -1
  88. package/docs/assets/field-table.html-d9236160.js +1 -1
  89. package/docs/assets/field-text.html-7277c62f.js +1 -1
  90. package/docs/assets/field-text.html-ccb4cecf.js +1 -1
  91. package/docs/assets/field-tree.html-519bfb45.js +1 -1
  92. package/docs/assets/field-tree.html-fdc748d6.js +1 -1
  93. package/docs/assets/form.html-2b562c37.js +2 -2
  94. package/docs/assets/form.html-75104cd5.js +1 -1
  95. package/docs/assets/framework-204010b2.js +5 -5
  96. package/docs/assets/getData.html-990e3787.js +1 -1
  97. package/docs/assets/getData.html-bb72025f.js +34 -34
  98. package/docs/assets/getFile.html-42368004.js +1 -1
  99. package/docs/assets/getFile.html-99abd054.js +3 -3
  100. package/docs/assets/getImage.html-3429c5a1.js +1 -1
  101. package/docs/assets/getImage.html-4d886d83.js +3 -3
  102. package/docs/assets/getTime.html-7435f922.js +1 -1
  103. package/docs/assets/getTime.html-b37f49eb.js +20 -20
  104. package/docs/assets/img.html-7d1da657.js +1 -1
  105. package/docs/assets/img.html-fbea1105.js +1 -1
  106. package/docs/assets/index.html-1695dd7c.js +1 -1
  107. package/docs/assets/index.html-65a4aa67.js +1 -1
  108. package/docs/assets/index.html-7b98d5bd.js +1 -1
  109. package/docs/assets/index.html-c01f2648.js +1 -1
  110. package/docs/assets/input-number.html-0b250d2a.js +1 -1
  111. package/docs/assets/input-number.html-a8eb0378.js +1 -1
  112. package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
  113. package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
  114. package/docs/assets/list-menu.html-28b4163f.js +1 -1
  115. package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
  116. package/docs/assets/loading.html-dae9e39d.js +6 -6
  117. package/docs/assets/loading.html-dc74c9e6.js +1 -1
  118. package/docs/assets/notify.html-e6c4c514.js +1 -1
  119. package/docs/assets/notify.html-f2c4d914.js +8 -8
  120. package/docs/assets/power-page.html-32e02f82.js +1 -1
  121. package/docs/assets/power-page.html-485e77da.js +1 -1
  122. package/docs/assets/power.html-d258cc19.js +93 -93
  123. package/docs/assets/power.html-e490bd32.js +1 -1
  124. package/docs/assets/previewImage.html-6a6b4245.js +1 -1
  125. package/docs/assets/previewImage.html-c5b7e945.js +2 -2
  126. package/docs/assets/price.html-1882c548.js +19 -19
  127. package/docs/assets/price.html-94d3f5be.js +1 -1
  128. package/docs/assets/price.html-d213df0f.js +1 -1
  129. package/docs/assets/price.html-deaf880f.js +1 -1
  130. package/docs/assets/render.html-8efcbdd4.js +1 -1
  131. package/docs/assets/render.html-df228e38.js +1 -1
  132. package/docs/assets/rule.html-2cd57fc2.js +13 -13
  133. package/docs/assets/rule.html-61662001.js +1 -1
  134. package/docs/assets/ruleValid.html-04fe2552.js +1 -1
  135. package/docs/assets/ruleValid.html-e0a776af.js +14 -14
  136. package/docs/assets/search-0782d0d1.svg +1 -1
  137. package/docs/assets/search-item.html-3f75394c.js +1 -1
  138. package/docs/assets/search-item.html-4e942ecd.js +1 -1
  139. package/docs/assets/search.html-2807043e.js +1 -1
  140. package/docs/assets/search.html-c24f8806.js +1 -1
  141. package/docs/assets/select.html-00d0607c.js +1 -1
  142. package/docs/assets/select.html-de7731f5.js +1 -1
  143. package/docs/assets/splitter.html-56f51a70.js +1 -1
  144. package/docs/assets/splitter.html-f5c836d7.js +1 -1
  145. package/docs/assets/style-161e43ab.css +1 -1
  146. package/docs/assets/symbols.html-a6aea4bf.js +1 -1
  147. package/docs/assets/symbols.html-b1f65bad.js +21 -21
  148. package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
  149. package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
  150. package/docs/assets/table-pagination.html-236934d3.js +1 -1
  151. package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
  152. package/docs/assets/table-splitter.html-07eab15c.js +1 -1
  153. package/docs/assets/table-splitter.html-7670ee65.js +1 -1
  154. package/docs/assets/table-summary.html-04db434f.js +1 -1
  155. package/docs/assets/table-summary.html-943c65a0.js +1 -1
  156. package/docs/assets/table.html-36253ad7.js +1 -1
  157. package/docs/assets/table.html-7f9c5d1b.js +38 -38
  158. package/docs/assets/table.html-93d53dc8.js +1 -1
  159. package/docs/assets/table.html-ac99b9cb.js +1 -1
  160. package/docs/assets/thumbnail.html-bab1976b.js +1 -1
  161. package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
  162. package/docs/assets/timestamp.html-4e54f79b.js +13 -13
  163. package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
  164. package/docs/assets/toast.html-58ecbe21.js +1 -1
  165. package/docs/assets/toast.html-c9b9d36b.js +6 -6
  166. package/docs/assets/toolbar.html-83d9f97c.js +1 -1
  167. package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
  168. package/docs/assets/tree.html-d07cbe79.js +23 -23
  169. package/docs/assets/tree.html-ea04193e.js +1 -1
  170. package/docs/assets/uploader-query.html-05590718.js +1 -1
  171. package/docs/assets/uploader-query.html-3175bac5.js +1 -1
  172. package/docs/assets/uploader.html-36da4394.js +2 -2
  173. package/docs/assets/uploader.html-6b5f3079.js +1 -1
  174. package/docs/assets/uploader.html-b9340b57.js +1 -1
  175. package/docs/assets/uploader.html-bc1c22e3.js +1 -1
  176. package/docs/assets/value-format.html-8ae3d47d.js +1 -1
  177. package/docs/assets/value-format.html-afa99b3d.js +1 -1
  178. package/docs/components/column-title.html +35 -35
  179. package/docs/components/data.html +62 -62
  180. package/docs/components/dialog.html +33 -33
  181. package/docs/components/dragger.html +33 -33
  182. package/docs/components/editor-code.html +33 -33
  183. package/docs/components/empty.html +33 -33
  184. package/docs/components/field-date.html +33 -33
  185. package/docs/components/field-table.html +33 -33
  186. package/docs/components/field-text.html +33 -33
  187. package/docs/components/field-tree.html +33 -33
  188. package/docs/components/img.html +33 -33
  189. package/docs/components/input-number.html +33 -33
  190. package/docs/components/list-menu-item.html +33 -33
  191. package/docs/components/list-menu.html +33 -33
  192. package/docs/components/power-page.html +33 -33
  193. package/docs/components/price.html +33 -33
  194. package/docs/components/render.html +33 -33
  195. package/docs/components/search-item.html +33 -33
  196. package/docs/components/search.html +33 -33
  197. package/docs/components/select.html +33 -33
  198. package/docs/components/splitter.html +33 -33
  199. package/docs/components/table-column-fixed.html +33 -33
  200. package/docs/components/table-pagination.html +33 -33
  201. package/docs/components/table-splitter.html +33 -33
  202. package/docs/components/table-summary.html +33 -33
  203. package/docs/components/table.html +33 -33
  204. package/docs/components/thumbnail.html +33 -33
  205. package/docs/components/toolbar.html +33 -33
  206. package/docs/components/uploader-query.html +33 -33
  207. package/docs/components/uploader.html +33 -33
  208. package/docs/components/value-format.html +33 -33
  209. package/docs/css/index.css +3 -3
  210. package/docs/index.html +33 -33
  211. package/docs/utils/alert.html +37 -37
  212. package/docs/utils/area.html +74 -74
  213. package/docs/utils/arr.html +43 -43
  214. package/docs/utils/auth.html +40 -40
  215. package/docs/utils/bus.html +38 -38
  216. package/docs/utils/confirm.html +42 -42
  217. package/docs/utils/copy.html +45 -45
  218. package/docs/utils/dialog.html +100 -100
  219. package/docs/utils/dict.html +55 -55
  220. package/docs/utils/dictOptions.html +37 -37
  221. package/docs/utils/form.html +34 -34
  222. package/docs/utils/getData.html +66 -66
  223. package/docs/utils/getFile.html +35 -35
  224. package/docs/utils/getImage.html +35 -35
  225. package/docs/utils/getTime.html +52 -52
  226. package/docs/utils/index.html +33 -33
  227. package/docs/utils/loading.html +38 -38
  228. package/docs/utils/notify.html +40 -40
  229. package/docs/utils/power.html +125 -125
  230. package/docs/utils/previewImage.html +34 -34
  231. package/docs/utils/price.html +51 -51
  232. package/docs/utils/rule.html +45 -45
  233. package/docs/utils/ruleValid.html +46 -46
  234. package/docs/utils/symbols.html +53 -53
  235. package/docs/utils/table.html +70 -70
  236. package/docs/utils/timestamp.html +45 -45
  237. package/docs/utils/toast.html +38 -38
  238. package/docs/utils/tree.html +55 -55
  239. package/docs/utils/uploader.html +34 -34
  240. package/package.json +25 -25
  241. package/sass/common.scss +184 -184
  242. package/sass/index.scss +12 -12
  243. package/sass/line.scss +39 -39
  244. package/sass/quasar/btn.scss +46 -46
  245. package/sass/quasar/common.scss +3 -3
  246. package/sass/quasar/drawer.scss +6 -6
  247. package/sass/quasar/field.scss +259 -259
  248. package/sass/quasar/loading.scss +6 -6
  249. package/sass/quasar/table.scss +168 -168
  250. package/sass/quasar/toolbar.scss +22 -22
  251. package/sass/variables.scss +140 -140
  252. package/store/index.js +29 -29
  253. package/utils/$auth.js +128 -128
  254. package/utils/$form.js +72 -72
  255. package/utils/$power.js +1494 -1492
  256. package/utils/$render.js +75 -75
  257. package/utils/$rule.js +13 -13
  258. package/utils/$ruleValid.js +10 -10
  259. package/utils/$search.js +416 -416
  260. package/utils/$table.js +1348 -1348
  261. package/utils/$tree.js +682 -682
  262. package/utils/alert.js +12 -12
  263. package/utils/area.js +400 -400
  264. package/utils/arr.js +51 -51
  265. package/utils/bus.js +6 -6
  266. package/utils/config.js +66 -66
  267. package/utils/confirm.js +11 -11
  268. package/utils/copy.js +30 -30
  269. package/utils/dialog.js +36 -36
  270. package/utils/dict.js +21 -21
  271. package/utils/dictOptions.js +28 -28
  272. package/utils/getData.js +88 -88
  273. package/utils/getFile.js +67 -67
  274. package/utils/getImage.js +276 -276
  275. package/utils/getTime.js +113 -113
  276. package/utils/index.js +67 -67
  277. package/utils/loading.js +15 -15
  278. package/utils/notify.js +13 -13
  279. package/utils/play.js +40 -40
  280. package/utils/previewImage.js +14 -14
  281. package/utils/price.js +18 -18
  282. package/utils/symbols.js +18 -18
  283. package/utils/timestamp.js +18 -18
  284. package/utils/toast.js +13 -13
  285. package/utils/uploader.js +2114 -2114
  286. package/utils/useAuth.js +30 -30
  287. package/utils/useFileUrl.js +26 -26
  288. package/utils/useRouter.js +47 -47
  289. package/utils/useSearch.js +562 -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
+