@netang/quasar 0.0.20

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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/components/column-title/index.vue +32 -0
  4. package/components/dialog/components/index.js +6 -0
  5. package/components/dialog/components/move-to-tree/index.vue +150 -0
  6. package/components/dialog/index.vue +330 -0
  7. package/components/dialog-table/index.vue +92 -0
  8. package/components/dragger/index.vue +202 -0
  9. package/components/drawer/index.vue +262 -0
  10. package/components/field-date/index.vue +844 -0
  11. package/components/field-date/methods.js +100 -0
  12. package/components/field-table/index.vue +468 -0
  13. package/components/field-text/index.vue +167 -0
  14. package/components/field-tree/index.vue +435 -0
  15. package/components/input-number/index.vue +324 -0
  16. package/components/input-number/number.js +67 -0
  17. package/components/input-price-cent/index.vue +213 -0
  18. package/components/input-price-yuan/index.vue +179 -0
  19. package/components/layout/index.vue +119 -0
  20. package/components/list-menu/index.vue +137 -0
  21. package/components/list-menu-item/index.vue +79 -0
  22. package/components/power-data/index.vue +667 -0
  23. package/components/search/index.vue +176 -0
  24. package/components/search-item/index.vue +219 -0
  25. package/components/select/index.vue +71 -0
  26. package/components/select-filter/index.vue +75 -0
  27. package/components/table/index.vue +347 -0
  28. package/components/table-column-fixed/index.vue +68 -0
  29. package/components/table-pagination/index.vue +83 -0
  30. package/components/table-summary/index.vue +91 -0
  31. package/components/thumbnail/index.vue +87 -0
  32. package/components/toolbar/container.vue +31 -0
  33. package/components/toolbar/index.vue +405 -0
  34. package/components/uploader/index.vue +157 -0
  35. package/components/uploader-query/index.vue +731 -0
  36. package/package.json +21 -0
  37. package/sass/common.scss +165 -0
  38. package/sass/index.scss +14 -0
  39. package/sass/line.scss +39 -0
  40. package/sass/quasar/btn.scss +46 -0
  41. package/sass/quasar/common.scss +3 -0
  42. package/sass/quasar/dialog.scss +7 -0
  43. package/sass/quasar/drawer.scss +6 -0
  44. package/sass/quasar/field.scss +210 -0
  45. package/sass/quasar/loading.scss +6 -0
  46. package/sass/quasar/menu.scss +8 -0
  47. package/sass/quasar/table.scss +112 -0
  48. package/sass/quasar/toolbar.scss +22 -0
  49. package/store/index.js +32 -0
  50. package/utils/$area.js +387 -0
  51. package/utils/$auth.js +135 -0
  52. package/utils/$dialog.js +43 -0
  53. package/utils/$role.js +807 -0
  54. package/utils/$rule.js +17 -0
  55. package/utils/$search.js +336 -0
  56. package/utils/$table.js +802 -0
  57. package/utils/$tree.js +620 -0
  58. package/utils/$uploader.js +1029 -0
  59. package/utils/alert.js +10 -0
  60. package/utils/bus.js +6 -0
  61. package/utils/config.js +22 -0
  62. package/utils/confrim.js +11 -0
  63. package/utils/dict.js +44 -0
  64. package/utils/getData.js +61 -0
  65. package/utils/getFile.js +30 -0
  66. package/utils/getImage.js +136 -0
  67. package/utils/getTime.js +94 -0
  68. package/utils/http.js +251 -0
  69. package/utils/loading.js +13 -0
  70. package/utils/notify.js +13 -0
  71. package/utils/previewImage.js +8 -0
  72. package/utils/symbols.js +3 -0
  73. package/utils/timestamp.js +18 -0
  74. package/utils/toast.js +13 -0
  75. package/utils/uploader/aliyun.js +6 -0
  76. package/utils/uploader/local.js +8 -0
  77. package/utils/uploader/qiniu.js +311 -0
  78. package/utils/useAuth.js +26 -0
  79. package/utils/useRouter.js +36 -0
  80. package/utils/useUploader.js +58 -0
@@ -0,0 +1,167 @@
1
+ <template>
2
+ <q-field
3
+ class="n-field-fieldset"
4
+ :label="label"
5
+ :stack-label="stackLabel"
6
+ :outlined="outlined"
7
+ :dense="dense"
8
+ :readonly="readonly"
9
+ v-bind="$attrs"
10
+ >
11
+ <template v-slot:control>
12
+
13
+ <!-- 如果有默认插槽 -->
14
+ <template v-if="$slots.default">
15
+
16
+ <!-- 如果开启复制 -->
17
+ <div
18
+ class="full-width"
19
+ :class="valueClass"
20
+ :style="valueStyle"
21
+ @click="onCopy"
22
+ v-if="! noCopy"
23
+ >
24
+ <slot
25
+ :value="value"
26
+ />
27
+ </div>
28
+
29
+ <!-- 否则仅展示 -->
30
+ <div
31
+ class="full-width"
32
+ :class="valueClass"
33
+ :style="valueStyle"
34
+ v-else
35
+ >
36
+ <slot
37
+ :value="value"
38
+ />
39
+ </div>
40
+ </template>
41
+
42
+ <!-- 否则如果开启复制 -->
43
+ <div
44
+ class="full-width"
45
+ :class="valueClass"
46
+ :style="valueStyle"
47
+ @click="onCopy"
48
+ v-else-if="! noCopy"
49
+ >{{value}}</div>
50
+
51
+ <!-- 否则仅展示 -->
52
+ <div
53
+ class="full-width"
54
+ :class="valueClass"
55
+ :style="valueStyle"
56
+ v-else
57
+ >{{value}}</div>
58
+
59
+ </template>
60
+
61
+ <template
62
+ v-for="slotName in slotNames"
63
+ v-slot:[slotName]
64
+ >
65
+ <slot
66
+ :name="slotName"
67
+ :value="value"
68
+ />
69
+ </template>
70
+ </q-field>
71
+ </template>
72
+
73
+ <script>
74
+ import { computed } from 'vue'
75
+
76
+ export default {
77
+
78
+ /**
79
+ * 标识
80
+ */
81
+ name: 'NFieldText',
82
+
83
+ /**
84
+ * 声明属性
85
+ */
86
+ props: {
87
+ // 标签
88
+ label: [Array, String, Number],
89
+ // 值
90
+ value: [String, Number],
91
+ // 复制文字
92
+ copyText: [String, Number],
93
+ // 标签始终显示在字段上方
94
+ stackLabel: {
95
+ type: Boolean,
96
+ default: true,
97
+ },
98
+ // 线条
99
+ outlined: {
100
+ type: Boolean,
101
+ default: true,
102
+ },
103
+ // 紧凑模式
104
+ dense: {
105
+ type: Boolean,
106
+ default: true,
107
+ },
108
+ // 只读模式
109
+ readonly: {
110
+ type: Boolean,
111
+ default: true,
112
+ },
113
+ // 禁止复制
114
+ noCopy: Boolean,
115
+ // 值类名
116
+ valueClass: String,
117
+ // 值样式
118
+ valueStyle: [String, Object, Array],
119
+ },
120
+
121
+ /**
122
+ * 组合式
123
+ */
124
+ setup(props, { slots }) {
125
+
126
+ // ==========【计算属性】==========================================================================================
127
+
128
+ /**
129
+ * 插槽标识数组
130
+ */
131
+ const slotNames = computed(function() {
132
+ const lists = []
133
+
134
+ utils.forIn(slots, function(val, key) {
135
+ if (key !== 'default') {
136
+ lists.push(key)
137
+ }
138
+ })
139
+
140
+ return lists
141
+ })
142
+
143
+ // ==========【方法】=============================================================================================
144
+
145
+ /**
146
+ * 复制
147
+ */
148
+ function onCopy() {
149
+ const val = props.copyText || props.value
150
+ if (val) {
151
+ utils.copy(val, `复制【${props.label}】成功`)
152
+ }
153
+ }
154
+
155
+ // ==========【返回】=============================================================================================
156
+
157
+ return {
158
+ // 字段组件传参
159
+ // fieldProps,
160
+ // 插槽标识数组
161
+ slotNames,
162
+ // 复制
163
+ onCopy,
164
+ }
165
+ },
166
+ }
167
+ </script>
@@ -0,0 +1,435 @@
1
+ <template>
2
+ <q-field
3
+ :class="fieldFocused ? 'q-field--float q-field--focused q-field--highlighted' : ''"
4
+ :model-value="modelValue"
5
+ @clear="onClear"
6
+ v-bind="$attrs"
7
+ >
8
+ <template v-slot:control>
9
+
10
+ <!-- 如果有值 -->
11
+ <template v-if="treeTickedNodes.length">
12
+
13
+ <!-- 如果显示单个值 -->
14
+ <div v-if="! multiple">{{treeTickedNodes[0].label}}</div>
15
+
16
+ <!-- 显示折叠的值数量 -->
17
+ <div v-else-if="collapseTags">
18
+ <q-chip dense>+{{treeTickedNodes.length}}</q-chip>
19
+ </div>
20
+
21
+ <!-- 否则显示多个值 -->
22
+ <q-chip
23
+ v-for="(item, itemIndex) in treeTickedNodes"
24
+ :key="`item-${item.id}`"
25
+ @remove="onRemoveItem(itemIndex)"
26
+ removable
27
+ dense
28
+ v-else
29
+ >{{item.label}}</q-chip>
30
+ </template>
31
+
32
+ <!-- 否则显示占位符 -->
33
+ <div class="n-placeholder" v-else-if="placeholder">{{placeholder}}</div>
34
+ </template>
35
+
36
+ <template v-slot:before v-if="$slots.before">
37
+ <slot name="before" />
38
+ </template>
39
+ <template v-slot:prepend v-if="$slots.prepend">
40
+ <slot name="prepend" />
41
+ </template>
42
+ <template v-slot:append v-if="$slots.append">
43
+ <slot name="append" />
44
+ </template>
45
+ <template v-slot:after v-if="$slots.after">
46
+ <slot name="after" />
47
+ </template>
48
+
49
+ <!-- 弹出层代理 -->
50
+ <q-popup-proxy
51
+ ref="popupRef"
52
+ @before-show="onPopupBeforeShow"
53
+ @before-hide="onPopupBeforeHide"
54
+ v-if="! readonly"
55
+ >
56
+ <q-card>
57
+ <!-- 树 -->
58
+ <q-tree
59
+ class="q-pa-sm q-pr-md"
60
+ style="min-width:260px;"
61
+ ref="treeRef"
62
+ :nodes="nodes"
63
+ :node-key="nodeKey"
64
+ :label-key="labelKey"
65
+ v-model:expanded="treeExpanded"
66
+ :tick-strategy="currentTickStrategy"
67
+ :ticked="treeTicked"
68
+ @update:ticked="onUpdateTicked"
69
+ :accordion="accordion"
70
+ >
71
+ <template v-slot:default-header="{ node }">
72
+ <div
73
+ class="cursor-pointer full-width"
74
+ :class="{
75
+ 'text-primary': utils.indexOf(treeTicked, node.id) > -1,
76
+ }"
77
+ @click="onNode($event, node)"
78
+ >{{node.label}}</div>
79
+ </template>
80
+ </q-tree>
81
+ </q-card>
82
+ </q-popup-proxy>
83
+ </q-field>
84
+ </template>
85
+
86
+ <script>
87
+ import { ref, computed, watch } from 'vue'
88
+
89
+ export default {
90
+
91
+ /**
92
+ * 标识
93
+ */
94
+ name: 'NFieldTree',
95
+
96
+ /**
97
+ * 声明属性
98
+ */
99
+ props: {
100
+ // 是否只读
101
+ readonly: Boolean,
102
+ // 值
103
+ modelValue: [Array, String, Number],
104
+ // 树展开节点
105
+ expanded: Array, // v-model:expanded
106
+ // 占位符
107
+ placeholder: String,
108
+ // 节点数组
109
+ nodes: Array,
110
+ // 唯一的节点 id
111
+ nodeKey: {
112
+ type: String,
113
+ default: 'id',
114
+ },
115
+ // label 字段
116
+ labelKey: {
117
+ type: String,
118
+ default: 'label',
119
+ },
120
+ // 是否可选任意一级(true:可选任意一级, false: 仅能选叶子节点)
121
+ strict: Boolean,
122
+ // 是否多选
123
+ multiple: Boolean,
124
+ // 手风琴模式
125
+ accordion: Boolean,
126
+ // 输入框中是否显示选中值的完整路径
127
+ showAllLevels: {
128
+ type: Boolean,
129
+ default: true,
130
+ },
131
+ // 多选模式下是否折叠 Tag
132
+ collapseTags: Boolean,
133
+ },
134
+
135
+ /**
136
+ * 声明事件
137
+ */
138
+ emits: [
139
+ 'update:modelValue',
140
+ ],
141
+
142
+ /**
143
+ * 组合式
144
+ */
145
+ setup(props, { emit }) {
146
+
147
+ // ==========【数据】============================================================================================
148
+
149
+ // 字段组件获取焦点
150
+ const fieldFocused = ref(false)
151
+ // 弹出层节点
152
+ const popupRef = ref(null)
153
+ // 树节点
154
+ const treeRef = ref(null)
155
+ // 树选择数据
156
+ const treeTicked = ref(formatModelValue())
157
+ // tree all
158
+ let treeAll = getTreeAll()
159
+ // 树展开数据
160
+ const treeExpanded = ref(getExpanded())
161
+
162
+ // ==========【计算属性】=========================================================================================
163
+
164
+ /**
165
+ * 当前节点选择策略
166
+ */
167
+ const currentTickStrategy = computed(function () {
168
+ return props.multiple ? (
169
+ props.strict ? 'strict' : 'leaf'
170
+ ) : 'none'
171
+ })
172
+
173
+ /**
174
+ * 树选择节点数据
175
+ */
176
+ const treeTickedNodes = computed(function () {
177
+
178
+ const lists = []
179
+
180
+ utils.forEach(treeTicked.value, function (treeKey) {
181
+
182
+ // 获取树选择的节点
183
+ if (_.has(treeAll, treeKey)) {
184
+ lists.push({
185
+ id: treeKey,
186
+ label: treeAll[treeKey][props.showAllLevels ? 'path' : 'label'],
187
+ })
188
+ }
189
+ })
190
+
191
+ return lists
192
+ })
193
+
194
+ // ==========【监听数据】=========================================================================================
195
+
196
+ /**
197
+ * 监听节点数组
198
+ */
199
+ watch(()=>props.nodes, function () {
200
+ // 更新 tree all
201
+ treeAll = getTreeAll()
202
+ })
203
+
204
+ /**
205
+ * 监听声明值
206
+ */
207
+ watch(()=>props.modelValue, function() {
208
+ treeTicked.value = formatModelValue()
209
+ })
210
+
211
+ // ==========【方法】=============================================================================================
212
+
213
+ /**
214
+ * 获取 tree all
215
+ */
216
+ function getTreeAll() {
217
+
218
+ const all = {}
219
+
220
+ // 获取子节点
221
+ function getChildren(data, pid, pPath) {
222
+ for (const item of data) {
223
+
224
+ const label = item[props.labelKey]
225
+
226
+ const path = pPath ? (pPath + ' / ' + label) : label
227
+
228
+ all[item[props.nodeKey]] = {
229
+ id: item[props.nodeKey],
230
+ pid,
231
+ label,
232
+ children: item.children,
233
+ path,
234
+ }
235
+
236
+ // 如果是父节点
237
+ if (utils.isValidArray(item.children)) {
238
+ getChildren(item.children, item.id, path)
239
+ }
240
+ }
241
+ }
242
+
243
+ if (utils.isValidArray(props.nodes)) {
244
+ getChildren(props.nodes, 0, '')
245
+ }
246
+
247
+ return all
248
+ }
249
+
250
+ /**
251
+ * 获取展开节点数组
252
+ */
253
+ function getExpanded() {
254
+
255
+ let expanded = []
256
+
257
+ if (
258
+ // 如果是单选
259
+ ! props.multiple
260
+ // 如果有值
261
+ && utils.isRequired(props.modelValue)
262
+ // 存在节点
263
+ && _.has(treeAll, props.modelValue)
264
+ ) {
265
+ // 获取父节点
266
+ function getParent({ id, pid, children }) {
267
+
268
+ // 如果是父级节点
269
+ if (utils.isValidArray(children)) {
270
+ // 设为展开
271
+ expanded.push(id)
272
+ }
273
+
274
+ // 如果有父节点, 则继续向上寻找
275
+ if (pid && _.has(treeAll, pid)) {
276
+ getParent(treeAll[pid])
277
+ }
278
+ }
279
+
280
+ getParent(treeAll[props.modelValue])
281
+ }
282
+
283
+ if (props.expanded) {
284
+ expanded = _.uniq(_.concat(expanded, props.expanded))
285
+ }
286
+
287
+ return expanded
288
+ }
289
+
290
+ /**
291
+ * 格式化传值
292
+ */
293
+ function formatModelValue() {
294
+ if (props.multiple) {
295
+ if (utils.isValidArray(props.modelValue)) {
296
+ return props.modelValue
297
+ }
298
+ return []
299
+ }
300
+
301
+ if (utils.isRequired(props.modelValue)) {
302
+ return [props.modelValue]
303
+ }
304
+
305
+ return []
306
+ }
307
+
308
+ /**
309
+ * 更新选择树数据回调
310
+ */
311
+ function onUpdateTicked(val) {
312
+ emit('update:modelValue', val)
313
+ }
314
+
315
+ /**
316
+ * 点击节点
317
+ */
318
+ function onNode(e, { id, label, children }) {
319
+
320
+ // 如果是多选
321
+ if (props.multiple) {
322
+
323
+ // 如果是父节点
324
+ if (utils.isValidArray(children)) {
325
+ // 则无任何操作
326
+ return
327
+ }
328
+
329
+ const newTicked = [...treeTicked.value]
330
+
331
+ // 如果在数据中
332
+ const index = utils.indexOf(newTicked, id)
333
+ if (index > -1) {
334
+ newTicked.splice(index, 1)
335
+ } else {
336
+ newTicked.push(id)
337
+ }
338
+
339
+ // 设置树选择数据
340
+ emit('update:modelValue', newTicked)
341
+
342
+ } else {
343
+
344
+ if (
345
+ // 如果是父节点
346
+ utils.isValidArray(children)
347
+ // 如果仅可选择叶子节点
348
+ && ! props.strict
349
+ ) {
350
+ // 则无任何操作
351
+ return
352
+ }
353
+
354
+ // 设置树选择数据
355
+ emit('update:modelValue', id)
356
+
357
+ // 则停止冒泡
358
+ e.preventDefault()
359
+ e.stopPropagation()
360
+
361
+ // 则关闭弹出层
362
+ popupRef.value.hide()
363
+ }
364
+ }
365
+
366
+ /**
367
+ * 移除单个
368
+ */
369
+ function onRemoveItem(index) {
370
+ const newValue = [...treeTicked.value]
371
+ newValue.splice(index, 1)
372
+ emit('update:modelValue', newValue)
373
+ }
374
+
375
+ /**
376
+ * 弹出层显示前回调
377
+ */
378
+ function onPopupBeforeShow() {
379
+
380
+ // 字段组件获取焦点
381
+ fieldFocused.value = true
382
+ }
383
+
384
+ /**
385
+ * 弹出层隐藏前回调
386
+ */
387
+ function onPopupBeforeHide() {
388
+
389
+ // 字段组件失去焦点
390
+ fieldFocused.value = false
391
+ }
392
+
393
+ /**
394
+ * 清空
395
+ */
396
+ function onClear() {
397
+ emit('update:modelValue', props.multiple ? [] : null)
398
+ popupRef.value.hide()
399
+ }
400
+
401
+ // ==========【返回】=============================================================================================
402
+
403
+ return {
404
+ // 字段组件获取焦点
405
+ fieldFocused,
406
+ // 弹出层节点
407
+ popupRef,
408
+ // 树节点
409
+ treeRef,
410
+ // 树选择数据
411
+ treeTicked,
412
+ // 树选择节点数据
413
+ treeTickedNodes,
414
+ // 树展开数据
415
+ treeExpanded,
416
+ // 当前节点选择策略
417
+ currentTickStrategy,
418
+
419
+ // 更新选择树数据回调
420
+ onUpdateTicked,
421
+ // 点击节点
422
+ onNode,
423
+ // 清空
424
+ onClear,
425
+ // 移除单个
426
+ onRemoveItem,
427
+
428
+ // 弹出层显示前回调
429
+ onPopupBeforeShow,
430
+ // 弹出层隐藏前回调
431
+ onPopupBeforeHide,
432
+ }
433
+ },
434
+ }
435
+ </script>