@netang/quasar 0.2.14 → 0.2.15

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