@netang/quasar 0.0.102 → 0.0.103

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 (162) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +11 -11
  3. package/_docs/docs/.vuepress/client.js +8 -8
  4. package/_docs/docs/.vuepress/config.js +40 -40
  5. package/_docs/docs/.vuepress/configs/index.js +2 -2
  6. package/_docs/docs/.vuepress/configs/navbar/index.js +1 -1
  7. package/_docs/docs/.vuepress/configs/navbar/zh.js +16 -16
  8. package/_docs/docs/.vuepress/configs/sidebar/index.js +1 -1
  9. package/_docs/docs/.vuepress/configs/sidebar/zh.js +75 -75
  10. package/_docs/docs/.vuepress/public/css/index.css +3 -3
  11. package/_docs/docs/.vuepress/styles/index.scss +3 -3
  12. package/_docs/docs/components/column-title.md +25 -25
  13. package/_docs/docs/components/data.md +66 -66
  14. package/_docs/docs/components/dialog.md +59 -59
  15. package/_docs/docs/components/dragger.md +26 -26
  16. package/_docs/docs/components/editor-code.md +16 -16
  17. package/_docs/docs/components/empty.md +13 -13
  18. package/_docs/docs/components/field-date.md +16 -16
  19. package/_docs/docs/components/field-text.md +57 -57
  20. package/_docs/docs/components/field-tree.md +14 -14
  21. package/_docs/docs/components/img.md +25 -25
  22. package/_docs/docs/components/input-number.md +21 -21
  23. package/_docs/docs/components/list-menu-item.md +21 -21
  24. package/_docs/docs/components/list-menu.md +21 -21
  25. package/_docs/docs/components/power-page.md +21 -21
  26. package/_docs/docs/components/price.md +21 -21
  27. package/_docs/docs/components/render.md +12 -12
  28. package/_docs/docs/components/search-item.md +10 -10
  29. package/_docs/docs/components/search.md +12 -12
  30. package/_docs/docs/components/select.md +11 -11
  31. package/_docs/docs/components/splitter.md +15 -15
  32. package/_docs/docs/components/table-column-fixed.md +20 -20
  33. package/_docs/docs/components/table-pagination.md +20 -20
  34. package/_docs/docs/components/table-splitter.md +20 -20
  35. package/_docs/docs/components/table-summary.md +20 -20
  36. package/_docs/docs/components/table.md +25 -25
  37. package/_docs/docs/components/thumbnail.md +18 -18
  38. package/_docs/docs/components/toolbar.md +9 -9
  39. package/_docs/docs/components/uploader-query.md +19 -19
  40. package/_docs/docs/components/uploader.md +16 -16
  41. package/_docs/docs/components/value-format.md +26 -26
  42. package/_docs/docs/index.md +1 -1
  43. package/_docs/docs/utils/alert.md +26 -26
  44. package/_docs/docs/utils/area.md +112 -112
  45. package/_docs/docs/utils/arr.md +80 -80
  46. package/_docs/docs/utils/auth.md +101 -101
  47. package/_docs/docs/utils/bus.md +18 -18
  48. package/_docs/docs/utils/confirm.md +31 -31
  49. package/_docs/docs/utils/copy.md +22 -22
  50. package/_docs/docs/utils/dialog.md +98 -98
  51. package/_docs/docs/utils/dict.md +50 -50
  52. package/_docs/docs/utils/dictOptions.md +27 -27
  53. package/_docs/docs/utils/form.md +33 -33
  54. package/_docs/docs/utils/getData.md +60 -60
  55. package/_docs/docs/utils/getFile.md +21 -21
  56. package/_docs/docs/utils/getImage.md +33 -33
  57. package/_docs/docs/utils/getTime.md +51 -51
  58. package/_docs/docs/utils/index.md +1 -1
  59. package/_docs/docs/utils/loading.md +18 -18
  60. package/_docs/docs/utils/notify.md +29 -29
  61. package/_docs/docs/utils/power.md +353 -353
  62. package/_docs/docs/utils/previewImage.md +11 -11
  63. package/_docs/docs/utils/price.md +45 -45
  64. package/_docs/docs/utils/rule.md +30 -30
  65. package/_docs/docs/utils/ruleValid.md +31 -31
  66. package/_docs/docs/utils/symbols.md +30 -30
  67. package/_docs/docs/utils/table.md +194 -194
  68. package/_docs/docs/utils/timestamp.md +27 -27
  69. package/_docs/docs/utils/toast.md +27 -27
  70. package/_docs/docs/utils/tree.md +174 -174
  71. package/_docs/docs/utils/uploader.md +29 -29
  72. package/_docs/package.json +11 -11
  73. package/components/column-title/index.vue +37 -37
  74. package/components/data/index.vue +20 -20
  75. package/components/dialog/index.vue +372 -372
  76. package/components/dragger/index.vue +203 -203
  77. package/components/drawer/index.vue +303 -303
  78. package/components/editor-code/index.vue +289 -289
  79. package/components/empty/index.vue +71 -71
  80. package/components/field-date/index.vue +850 -850
  81. package/components/field-date/methods.js +100 -100
  82. package/components/field-table/index.vue +1222 -1222
  83. package/components/field-text/index.vue +165 -165
  84. package/components/field-tree/index.vue +103 -81
  85. package/components/img/index.vue +202 -202
  86. package/components/input-number/index.vue +546 -546
  87. package/components/list-menu/index.vue +149 -149
  88. package/components/list-menu-item/index.vue +79 -79
  89. package/components/power-page/index.vue +92 -92
  90. package/components/price/index.vue +188 -188
  91. package/components/private/components/index.js +11 -11
  92. package/components/private/components/move-to-tree/index.vue +154 -154
  93. package/components/private/edit-power-data/index.vue +816 -816
  94. package/components/private/table-visible-columns-button/index.vue +109 -109
  95. package/components/render/index.vue +150 -150
  96. package/components/search/index.vue +222 -222
  97. package/components/search-item/index.vue +210 -210
  98. package/components/splitter/index.vue +415 -415
  99. package/components/table/index.vue +456 -456
  100. package/components/table-column-fixed/index.vue +112 -112
  101. package/components/table-pagination/index.vue +192 -192
  102. package/components/table-splitter/index.vue +360 -360
  103. package/components/table-summary/index.vue +110 -110
  104. package/components/thumbnail/index.vue +72 -72
  105. package/components/toolbar/container.vue +31 -31
  106. package/components/toolbar/index.vue +136 -136
  107. package/components/uploader/index.vue +158 -158
  108. package/components/uploader-query/index.vue +758 -758
  109. package/components/value-format/index.vue +274 -274
  110. package/configs/area3.js +1 -1
  111. package/docs/css/index.css +3 -3
  112. package/package.json +1 -1
  113. package/sass/common.scss +174 -174
  114. package/sass/index.scss +14 -14
  115. package/sass/line.scss +39 -39
  116. package/sass/quasar/btn.scss +46 -46
  117. package/sass/quasar/common.scss +3 -3
  118. package/sass/quasar/dialog.scss +7 -7
  119. package/sass/quasar/drawer.scss +6 -6
  120. package/sass/quasar/field.scss +243 -243
  121. package/sass/quasar/loading.scss +6 -6
  122. package/sass/quasar/menu.scss +8 -8
  123. package/sass/quasar/table.scss +150 -150
  124. package/sass/quasar/toolbar.scss +22 -22
  125. package/store/index.js +29 -29
  126. package/utils/$auth.js +127 -127
  127. package/utils/$form.js +56 -56
  128. package/utils/$power.js +1215 -1215
  129. package/utils/$rule.js +13 -13
  130. package/utils/$ruleValid.js +10 -10
  131. package/utils/$table.js +999 -999
  132. package/utils/$tree.js +713 -713
  133. package/utils/alert.js +12 -12
  134. package/utils/area.js +400 -400
  135. package/utils/arr.js +51 -51
  136. package/utils/bus.js +6 -6
  137. package/utils/config.js +52 -52
  138. package/utils/confirm.js +11 -11
  139. package/utils/copy.js +30 -30
  140. package/utils/dialog.js +36 -36
  141. package/utils/dict.js +21 -21
  142. package/utils/dictOptions.js +28 -28
  143. package/utils/getData.js +73 -73
  144. package/utils/getFile.js +40 -40
  145. package/utils/getImage.js +153 -153
  146. package/utils/getTime.js +106 -106
  147. package/utils/index.js +61 -61
  148. package/utils/loading.js +15 -15
  149. package/utils/notify.js +13 -13
  150. package/utils/previewImage.js +10 -10
  151. package/utils/price.js +18 -18
  152. package/utils/symbols.js +18 -18
  153. package/utils/timestamp.js +18 -18
  154. package/utils/toast.js +13 -13
  155. package/utils/uploader/aliyun.js +6 -6
  156. package/utils/uploader/local.js +8 -8
  157. package/utils/uploader/qiniu.js +321 -321
  158. package/utils/uploader.js +1059 -1059
  159. package/utils/useAuth.js +30 -30
  160. package/utils/useRouter.js +47 -47
  161. package/utils/useSearch.js +0 -6
  162. package/utils/useUploader.js +53 -53
@@ -1,758 +1,758 @@
1
- <template>
2
- <div class="n-uploader-query">
3
-
4
- <!-- 上传按钮 -->
5
- <slot
6
- name="button"
7
- :disable="disable || readonly"
8
- :size="currentSize"
9
- v-if="$slots.button"
10
- />
11
- <div
12
- class="n-uploader-query__button--button"
13
- v-else-if="! noButton && currentButtonType === 'button'"
14
- >
15
- <q-btn
16
- class="n-button-icon"
17
- :label="buttonText || '上传'"
18
- @click="uploader.chooseUpload"
19
- color="primary"
20
- outline
21
- :disable="disable || readonly"
22
- unelevated
23
- v-bind="buttonProps"
24
- />
25
- </div>
26
-
27
- <!-- 拖拽器 -->
28
- <n-dragger
29
- class="n-uploader-query__query row q-gutter-sm"
30
- v-model="query"
31
- :drag="currentDrag"
32
- @update:model-value="uploader.updateValue"
33
- v-slot="{ mousedown, fromIndex, dragStart, dragEnter, dragEnd }"
34
- >
35
- <!-- 上传图片队列 -->
36
- <template v-if="type === 'image'">
37
-
38
- <!-- 左边方块按钮 -->
39
- <template v-if="! disable && ! readonly && ! rightSquareButton">
40
- <slot
41
- name="square-button"
42
- :size="currentSize"
43
- :show="showSquareButton"
44
- v-if="$slots['square-button']"
45
- />
46
- <div
47
- class="n-uploader-query__button--square cursor-pointer"
48
- :style="{
49
- width: toPx(currentSize),
50
- height: toPx(currentSize),
51
- }"
52
- @click="uploader.chooseUpload"
53
- v-show="showSquareButton"
54
- v-else-if="! noButton && currentButtonType === 'square'"
55
- >
56
- <q-icon
57
- name="add"
58
- :size="toPx(currentSize / 2)"
59
- />
60
- <div class="n-uploader-query__button--square__text" v-if="buttonText">{{buttonText}}</div>
61
- </div>
62
- </template>
63
-
64
- <!-- 单个图片 -->
65
- <div
66
- v-for="(fileItem, fileItemIndex) in query"
67
- :key="`query-item-${fileItem.id}`"
68
- class="n-uploader-query__item n-uploader-query__item--image"
69
- :class="{
70
- ghost: fileItemIndex === fromIndex,
71
- }"
72
- :draggable="currentDrag"
73
- @mousedown.self="mousedown($event, fileItemIndex)"
74
- @mouseup="dragEnd"
75
- @dragstart="dragStart($event, fileItemIndex)"
76
- @dragenter="dragEnter($event, fileItemIndex)"
77
- @dragend="dragEnd"
78
- >
79
- <n-img
80
- :src="getImage(fileItem)"
81
- :spinner-size="toPx(currentSize / 2)"
82
- :width="toPx(currentSize)"
83
- :height="toPx(currentSize)"
84
- fit="fill"
85
- >
86
- <!-- 内容 -->
87
- <div
88
- class="n-uploader-query__item__inner absolute-full flex flex-center no-padding transparent"
89
- :class="{
90
- 'transparent': fileItem.status < UPLOAD_STATUS.success,
91
- }"
92
- v-if="fileItem.status !== UPLOAD_STATUS.success"
93
- >
94
- <!-- 如果上传失败 -->
95
- <div
96
- class="n-uploader-query__item__inner__msg n-uploader-query__item__inner__msg--error"
97
- v-if="fileItem.status === UPLOAD_STATUS.fail"
98
- >{{fileItem.msg}}</div>
99
-
100
- <!-- 上传中前 -->
101
- <q-circular-progress
102
- indeterminate
103
- rounded
104
- :size="toPx(currentSize / 1.5)"
105
- :thickness="0.14"
106
- color="white"
107
- v-if="fileItem.status < UPLOAD_STATUS.uploading"
108
- />
109
-
110
- <!-- 上传中 -->
111
- <q-circular-progress
112
- :value="fileItem.progress"
113
- :size="toPx(currentSize / 1.5)"
114
- :thickness="0.14"
115
- color="white"
116
- track-color="grey-5"
117
- show-value
118
- v-else-if="fileItem.status === UPLOAD_STATUS.uploading"
119
- >
120
- <q-icon
121
- class="cursor-pointer"
122
- name="pause"
123
- :size="toPx(currentSize / 3)"
124
- @click="uploader.deleteFileItem(fileItem)"
125
- />
126
- </q-circular-progress>
127
- </div>
128
-
129
- <!-- 操作 -->
130
- <div
131
- class="n-uploader-query__item__settings transparent no-padding"
132
- v-if="fileItem.status !== UPLOAD_STATUS.uploading"
133
- >
134
- <!-- 预览 -->
135
- <q-icon
136
- class="n-uploader-query__item__settings__icon cursor-pointer"
137
- name="search"
138
- size="xs"
139
- title="预览"
140
- @click="uploader.previewImage(fileItem)"
141
- v-if="! noPreview && getImage(fileItem)"
142
- />
143
-
144
- <!-- 删除 -->
145
- <q-icon
146
- class="n-uploader-query__item__settings__icon cursor-pointer"
147
- name="close"
148
- size="xs"
149
- title="删除"
150
- @click="uploader.deleteFileItem(fileItem)"
151
- v-if="! noDelete && ! disable && ! readonly"
152
- />
153
- </div>
154
- </n-img>
155
- </div>
156
-
157
- <!-- 右边方块按钮 -->
158
- <template v-if="! disable && ! readonly && rightSquareButton">
159
- <slot
160
- name="square-button"
161
- :size="currentSize"
162
- :show="showSquareButton"
163
- v-if="$slots['square-button']"
164
- />
165
- <div
166
- class="n-uploader-query__button--square cursor-pointer"
167
- :style="{
168
- width: toPx(currentSize),
169
- height: toPx(currentSize),
170
- }"
171
- @click="uploader.chooseUpload"
172
- v-show="showSquareButton"
173
- v-else-if="! noButton && currentButtonType === 'square'"
174
- >
175
- <q-icon
176
- name="add"
177
- :size="toPx(currentSize / 2)"
178
- />
179
- <div class="n-uploader-query__button--square__text" v-if="buttonText">{{buttonText}}</div>
180
- </div>
181
- </template>
182
- </template>
183
-
184
- <!-- 上传文件队列 -->
185
- <template v-else>
186
-
187
- <!-- 单个文件 -->
188
- <div
189
- v-for="(fileItem, fileItemIndex) in query"
190
- :key="`query-item-${fileItem.id}`"
191
- class="n-uploader-query__item n-uploader-query__item--file"
192
- :class="{
193
- ghost: fileItemIndex === fromIndex,
194
- }"
195
- :style="{
196
- height: toPx(currentSize),
197
- }"
198
- :draggable="currentDrag"
199
- @mousedown.self="mousedown($event, fileItemIndex)"
200
- @mouseup="dragEnd"
201
- @dragstart="dragStart($event, fileItemIndex)"
202
- @dragenter="dragEnter($event, fileItemIndex)"
203
- @dragend="dragEnd"
204
- >
205
- <!-- 图标 -->
206
- <div
207
- class="n-uploader-query__item__icon"
208
- :style="{
209
- width: toPx(currentSize),
210
- height: toPx(currentSize),
211
- }"
212
- >
213
- <!-- 上传中前 -->
214
- <q-circular-progress
215
- class="n-uploader-query__item__icon__icon"
216
- indeterminate
217
- rounded
218
- :size="toPx(currentSize / 1.8)"
219
- :thickness="0.18"
220
- v-if="fileItem.status < UPLOAD_STATUS.uploading"
221
- />
222
-
223
- <!-- 上传中 -->
224
- <q-circular-progress
225
- class="n-uploader-query__item__icon__icon"
226
- :value="fileItem.progress"
227
- :size="toPx(currentSize / 1.8)"
228
- :thickness="0.18"
229
- show-value
230
- v-else-if="fileItem.status === UPLOAD_STATUS.uploading"
231
- >
232
- <q-icon
233
- class="cursor-pointer"
234
- name="pause"
235
- :size="toPx(currentSize / 3)"
236
- @click="uploader.deleteFileItem(fileItem)"
237
- />
238
- </q-circular-progress>
239
-
240
- <!-- 文件图标 -->
241
- <q-icon
242
- class="n-uploader-query__item__icon__icon"
243
- name="description"
244
- :size="toPx(currentSize / 1.5)"
245
- v-else-if="type === 'file'"
246
- />
247
-
248
- <!-- 播放图标 -->
249
- <q-icon
250
- class="n-uploader-query__item__icon__icon cursor-pointer"
251
- name="play_circle"
252
- title="播放"
253
- :size="toPx(currentSize / 1.5)"
254
- @click="uploader.play(fileItem)"
255
- v-else
256
- />
257
- </div>
258
-
259
- <!-- 信息 -->
260
- <div class="n-uploader-query__item__info">
261
- <!-- 标题 -->
262
- <div class="n-uploader-query__item__info__title ellipsis">{{getFileName(fileItem)}}</div>
263
- <!-- 错误提示 -->
264
- <div class="n-uploader-query__item__info__msg--error" v-if="fileItem.status === UPLOAD_STATUS.fail">{{fileItem.msg}}</div>
265
- </div>
266
-
267
- <!-- 操作 -->
268
- <div class="n-uploader-query__item__settings">
269
-
270
- <template v-if="fileItem.status === UPLOAD_STATUS.success">
271
-
272
- <!-- 复制地址 -->
273
- <q-icon
274
- class="n-uploader-query__item__settings__icon cursor-pointer"
275
- name="content_copy"
276
- color="white"
277
- size="xs"
278
- title="复制地址"
279
- @click="uploader.copyUrl(fileItem)"
280
- />
281
-
282
- <!-- 修改 -->
283
- <q-icon
284
- class="n-uploader-query__item__settings__icon cursor-pointer"
285
- name="edit"
286
- color="white"
287
- size="xs"
288
- title="修改"
289
- @click="uploader.previewImage(fileItem)"
290
- v-if="! noEdit && ! disable && ! readonly"
291
- >
292
- <q-popup-edit
293
- :model-value="fileItem.title"
294
- buttons
295
- label-set="保存"
296
- @save="uploader.editFileTitle($event, fileItem)"
297
- v-slot="scope"
298
- >
299
- <q-input
300
- v-model="scope.value"
301
- dense
302
- autofocus
303
- counter
304
- :maxlength="50"
305
- @keyup.enter="scope.set"
306
- >
307
- <template v-slot:append>
308
- <span class="text-subtitle2 text-weight-bold">.{{fileItem.ext}}</span>
309
- </template>
310
- </q-input>
311
- </q-popup-edit>
312
- </q-icon>
313
- </template>
314
-
315
- <!-- 删除 -->
316
- <q-icon
317
- class="n-uploader-query__item__settings__icon cursor-pointer"
318
- name="close"
319
- color="white"
320
- size="xs"
321
- title="删除"
322
- @click="uploader.deleteFileItem(fileItem)"
323
- v-if="! noDelete && ! disable && ! readonly"
324
- />
325
- </div>
326
- </div>
327
- </template>
328
- </n-dragger>
329
- </div>
330
- </template>
331
-
332
- <script>
333
- import { onMounted, computed, inject } from 'vue'
334
- import { useQuasar } from 'quasar'
335
-
336
- import $n_has from 'lodash/has'
337
- import $n_get from 'lodash/get'
338
-
339
- import $n_px from '@netang/utils/px'
340
- import $n_isValidArray from '@netang/utils/isValidArray'
341
- import $n_isValidString from '@netang/utils/isValidString'
342
-
343
- import $n_getImage from '../../utils/getImage'
344
-
345
- import NDragger from '../dragger'
346
-
347
- import { NUploaderKey } from '../../utils/symbols'
348
-
349
- import {
350
- // 上传状态
351
- UPLOAD_STATUS,
352
- } from '../../utils/useUploader'
353
-
354
- export default {
355
-
356
- /**
357
- * 标识
358
- */
359
- name: 'NUploaderQuery',
360
-
361
- /**
362
- * 组件
363
- */
364
- components: {
365
- NDragger,
366
- },
367
-
368
- /**
369
- * 声明属性
370
- */
371
- props: {
372
- // 按钮类型, 可选值 square button
373
- buttonType: {
374
- type: String,
375
- validator: v => [ 'square', 'button' ].includes(v),
376
- },
377
- // 按钮文字
378
- buttonText: String,
379
- // 按钮声明属性
380
- buttonProps: Object,
381
- // 图片/按钮/文件 尺寸
382
- size: Number,
383
- // 是否开启拖拽
384
- drag: {
385
- type: Boolean,
386
- default: true,
387
- },
388
- // 是否禁用
389
- disable: Boolean,
390
- // 是否只读
391
- readonly: Boolean,
392
- // 是否隐藏按钮
393
- noButton: Boolean,
394
- // 是否隐藏预览按钮
395
- noPreview: Boolean,
396
- // 是否隐藏修改按钮
397
- noEdit: Boolean,
398
- // 是否隐藏删除按钮
399
- noDelete: Boolean,
400
- // 自动显示方块按钮
401
- autoShowSquareButton: Boolean,
402
- // 方块按钮在右边显示
403
- rightSquareButton: Boolean,
404
- },
405
-
406
- /**
407
- * 声明事件
408
- */
409
- emits: [
410
- 'update:modelValue',
411
- ],
412
-
413
- /**
414
- * 组合式
415
- */
416
- setup(props) {
417
-
418
- // ==========【数据】============================================================================================
419
-
420
- // quasar 对象
421
- const $q = useQuasar()
422
-
423
- // 获取上传器注入数据
424
- const {
425
- // 声明属性
426
- props: uploaderProps,
427
- // 上传器
428
- uploader,
429
- // 文件队列
430
- query,
431
- } = inject(NUploaderKey)
432
-
433
- // ==========【计算属性】=========================================================================================
434
-
435
- /**
436
- * 当前是否开启拖拽
437
- */
438
- const currentDrag = computed(function() {
439
- return props.drag
440
- && $n_isValidArray(query.value)
441
- && query.value.length > 1
442
- && ! props.readonly
443
- && ! props.disable
444
- })
445
-
446
- /**
447
- * 当前按钮类型
448
- */
449
- const currentButtonType = computed(function () {
450
- if (props.buttonType) {
451
- return props.buttonType
452
- }
453
- return uploaderProps.type === 'image' ? 'square' : 'button'
454
- })
455
-
456
- /**
457
- * 当前尺寸
458
- */
459
- const currentSize = computed(function () {
460
- if (props.size) {
461
- return props.size
462
- }
463
- return uploaderProps.type === 'image' ? 70 : 50
464
- })
465
-
466
- /**
467
- * 是否显示方块按钮
468
- */
469
- const showSquareButton = computed(function () {
470
- // 自动显示方块按钮 && 有上传文件限制数量
471
- return props.autoShowSquareButton && uploaderProps.count > 0 ?
472
- // 如果 上传文件列表数量 < 上传文件限制数量
473
- query.value.length < uploaderProps.count
474
- // 始终显示
475
- : true
476
- })
477
-
478
- // ==========【方法】=============================================================================================
479
-
480
- /**
481
- * 获取图片地址
482
- */
483
- function getImage(fileItem) {
484
- return $n_has(fileItem, '__img') ?
485
- fileItem.__img
486
- : (
487
- $n_isValidString(fileItem.hash) ?
488
- $n_getImage(fileItem.hash, { w: $q.platform.is.mobile ? currentSize.value * 2 : currentSize.value })
489
- : ''
490
- )
491
- }
492
-
493
- /**
494
- * 获取文件名称
495
- */
496
- function getFileName(fileItem) {
497
- return fileItem.title + ($n_get(fileItem, 'ext') ? '.' + fileItem.ext : '')
498
- }
499
-
500
- // ==========【生命周期】=========================================================================================
501
-
502
- /**
503
- * 实例被挂载后调用
504
- */
505
- onMounted( async function() {
506
-
507
- })
508
-
509
- // ==========【返回】=============================================================================================
510
-
511
- return {
512
- // 上传状态
513
- UPLOAD_STATUS,
514
- // 上传文件类型, 可选值 file image video audio
515
- type: uploaderProps.type,
516
- // 上传文件数量(0:不限)
517
- count: uploaderProps.count,
518
- // 上传文件队列
519
- query,
520
-
521
- // 当前是否开启拖拽
522
- currentDrag,
523
- // 当前按钮类型
524
- currentButtonType,
525
- // 当前尺寸
526
- currentSize,
527
- // 是否显示方块按钮
528
- showSquareButton,
529
-
530
- // 上传器
531
- uploader,
532
-
533
- // 获取图片地址
534
- getImage,
535
- // 获取文件名称
536
- getFileName,
537
-
538
- toPx: $n_px,
539
- }
540
- },
541
- }
542
- </script>
543
-
544
- <style lang="scss">
545
- @import "@/assets/sass/variables.scss";
546
-
547
- // 上传器队列
548
- .n-uploader-query {
549
-
550
- // 上传按钮
551
- &__button {
552
-
553
- // 方块
554
- &--square {
555
- display: inline-flex;
556
- vertical-align: middle;
557
- overflow: hidden;
558
- border: 1px dashed rgba(var(--n-reverse-color-rgb), 0.2);
559
- flex-direction: column;
560
- justify-content: center;
561
- align-items: center;
562
- color: rgba(var(--n-reverse-color-rgb), 0.4);
563
- border-radius: 4px;
564
-
565
- &:hover {
566
- border-color: $primary;
567
- }
568
-
569
- // 文字
570
- &__text {
571
- font-size: 12px;
572
- }
573
- }
574
-
575
- // 按钮
576
- &--button {
577
- + .n-uploader-query__query {
578
- margin-top: 0;
579
- }
580
- }
581
- }
582
-
583
- // 上传单个文件
584
- &__item {
585
- position: relative;
586
-
587
- // 开启拖拽
588
- &[draggable="true"] {
589
- cursor: move;
590
- }
591
-
592
- // 当前拖拽占位元素
593
- &.ghost {
594
- &:after {
595
- content: "";
596
- position: absolute;
597
- top: 0;
598
- left: 0;
599
- right: 0;
600
- bottom: 0;
601
- border: 2px dashed mix(#ffffff, $primary, 40%);
602
- border-radius: 4px;
603
- background-color: rgba(255, 255, 255, 0.75);
604
- }
605
-
606
- .n-uploader-query__item__inner,
607
- .n-uploader-query__item__settings {
608
- display: none;
609
- }
610
- }
611
-
612
- &:hover {
613
- .n-uploader-query__item__settings {
614
- visibility: visible;
615
- }
616
- }
617
-
618
- // 单个图片
619
- &--image {
620
- border-radius: 4px;
621
- background-color: rgba(0,0,0,0.1);
622
- overflow: hidden;
623
- }
624
-
625
- // 单个文件
626
- &--file {
627
- position: relative;
628
- width: 300px;
629
- display: flex;
630
- flex-direction: row;
631
- align-items: center;
632
- border-radius: 4px;
633
- color: rgba(var(--n-reverse-color-rgb), 0.8);
634
- background-color: rgba(var(--n-reverse-color-rgb), 0.05);
635
-
636
- // 图标
637
- .n-uploader-query__item__icon {
638
- position: relative;
639
- display: flex;
640
- align-items: center;
641
- justify-content: center;
642
- z-index: 1;
643
-
644
- &__icon {
645
- color: rgba(var(--n-reverse-color-rgb), 0.2);
646
- }
647
- }
648
-
649
- // 信息
650
- .n-uploader-query__item__info {
651
- display: flex;
652
- flex-direction: column;
653
- line-height: 18px;
654
-
655
- &__title {
656
- max-width: 150px;
657
- }
658
-
659
- &__msg--error {
660
- color: $negative;
661
- }
662
- }
663
- }
664
-
665
- //操作
666
- &__settings {
667
- position: absolute;
668
- top: 5px;
669
- right: 5px;
670
- visibility: hidden;
671
-
672
- &__icon {
673
- background-color: rgba(0,0,0,0.5);
674
- border-radius: 50%;
675
- padding: 5px;
676
-
677
- + .n-uploader-query__item__settings__icon {
678
- margin-left: 4px;
679
- }
680
-
681
- &:hover {
682
- background-color: rgba(0,0,0,0.8);
683
- }
684
- }
685
- }
686
-
687
- // 内容
688
- &__inner {
689
-
690
- &__msg {
691
- margin: 3px;
692
- padding: 2px 3px;
693
- line-height: 18px;
694
- font-size: 12px;
695
- background-color: rgba(0,0,0,0.6);
696
- border-radius: 6px;
697
-
698
- &--error {
699
- background-color: $warning;
700
- }
701
- }
702
- }
703
- }
704
- }
705
-
706
- @media (max-width: $breakpoint-xs-max){
707
- // 上传器队列
708
- .n-uploader-query {
709
- // 上传单个文件
710
- &__item {
711
- // 单个文件
712
- &--file {
713
- width: 100%;
714
- }
715
- }
716
-
717
- // 信息
718
- .n-uploader-query__item__info {
719
- &__title {
720
- max-width: 200px;
721
- }
722
- }
723
- }
724
- }
725
-
726
- /**
727
- * 手机版
728
- */
729
- body.mobile {
730
- // 上传器队列
731
- .n-uploader-query {
732
- // 上传单个文件
733
- &__item {
734
- &__settings {
735
- visibility: visible;
736
- }
737
- }
738
- }
739
- }
740
-
741
- /**
742
- * 暗黑
743
- */
744
- .body--dark {
745
- .n-uploader-query__item--file {
746
- .n-uploader-query__item__settings {
747
- // 图标
748
- &__icon {
749
- background-color: rgba(255,255,255, 0.1);
750
-
751
- &:hover {
752
- background-color: rgba(255,255,255, 0.2);
753
- }
754
- }
755
- }
756
- }
757
- }
758
- </style>
1
+ <template>
2
+ <div class="n-uploader-query">
3
+
4
+ <!-- 上传按钮 -->
5
+ <slot
6
+ name="button"
7
+ :disable="disable || readonly"
8
+ :size="currentSize"
9
+ v-if="$slots.button"
10
+ />
11
+ <div
12
+ class="n-uploader-query__button--button"
13
+ v-else-if="! noButton && currentButtonType === 'button'"
14
+ >
15
+ <q-btn
16
+ class="n-button-icon"
17
+ :label="buttonText || '上传'"
18
+ @click="uploader.chooseUpload"
19
+ color="primary"
20
+ outline
21
+ :disable="disable || readonly"
22
+ unelevated
23
+ v-bind="buttonProps"
24
+ />
25
+ </div>
26
+
27
+ <!-- 拖拽器 -->
28
+ <n-dragger
29
+ class="n-uploader-query__query row q-gutter-sm"
30
+ v-model="query"
31
+ :drag="currentDrag"
32
+ @update:model-value="uploader.updateValue"
33
+ v-slot="{ mousedown, fromIndex, dragStart, dragEnter, dragEnd }"
34
+ >
35
+ <!-- 上传图片队列 -->
36
+ <template v-if="type === 'image'">
37
+
38
+ <!-- 左边方块按钮 -->
39
+ <template v-if="! disable && ! readonly && ! rightSquareButton">
40
+ <slot
41
+ name="square-button"
42
+ :size="currentSize"
43
+ :show="showSquareButton"
44
+ v-if="$slots['square-button']"
45
+ />
46
+ <div
47
+ class="n-uploader-query__button--square cursor-pointer"
48
+ :style="{
49
+ width: toPx(currentSize),
50
+ height: toPx(currentSize),
51
+ }"
52
+ @click="uploader.chooseUpload"
53
+ v-show="showSquareButton"
54
+ v-else-if="! noButton && currentButtonType === 'square'"
55
+ >
56
+ <q-icon
57
+ name="add"
58
+ :size="toPx(currentSize / 2)"
59
+ />
60
+ <div class="n-uploader-query__button--square__text" v-if="buttonText">{{buttonText}}</div>
61
+ </div>
62
+ </template>
63
+
64
+ <!-- 单个图片 -->
65
+ <div
66
+ v-for="(fileItem, fileItemIndex) in query"
67
+ :key="`query-item-${fileItem.id}`"
68
+ class="n-uploader-query__item n-uploader-query__item--image"
69
+ :class="{
70
+ ghost: fileItemIndex === fromIndex,
71
+ }"
72
+ :draggable="currentDrag"
73
+ @mousedown.self="mousedown($event, fileItemIndex)"
74
+ @mouseup="dragEnd"
75
+ @dragstart="dragStart($event, fileItemIndex)"
76
+ @dragenter="dragEnter($event, fileItemIndex)"
77
+ @dragend="dragEnd"
78
+ >
79
+ <n-img
80
+ :src="getImage(fileItem)"
81
+ :spinner-size="toPx(currentSize / 2)"
82
+ :width="toPx(currentSize)"
83
+ :height="toPx(currentSize)"
84
+ fit="fill"
85
+ >
86
+ <!-- 内容 -->
87
+ <div
88
+ class="n-uploader-query__item__inner absolute-full flex flex-center no-padding transparent"
89
+ :class="{
90
+ 'transparent': fileItem.status < UPLOAD_STATUS.success,
91
+ }"
92
+ v-if="fileItem.status !== UPLOAD_STATUS.success"
93
+ >
94
+ <!-- 如果上传失败 -->
95
+ <div
96
+ class="n-uploader-query__item__inner__msg n-uploader-query__item__inner__msg--error"
97
+ v-if="fileItem.status === UPLOAD_STATUS.fail"
98
+ >{{fileItem.msg}}</div>
99
+
100
+ <!-- 上传中前 -->
101
+ <q-circular-progress
102
+ indeterminate
103
+ rounded
104
+ :size="toPx(currentSize / 1.5)"
105
+ :thickness="0.14"
106
+ color="white"
107
+ v-if="fileItem.status < UPLOAD_STATUS.uploading"
108
+ />
109
+
110
+ <!-- 上传中 -->
111
+ <q-circular-progress
112
+ :value="fileItem.progress"
113
+ :size="toPx(currentSize / 1.5)"
114
+ :thickness="0.14"
115
+ color="white"
116
+ track-color="grey-5"
117
+ show-value
118
+ v-else-if="fileItem.status === UPLOAD_STATUS.uploading"
119
+ >
120
+ <q-icon
121
+ class="cursor-pointer"
122
+ name="pause"
123
+ :size="toPx(currentSize / 3)"
124
+ @click="uploader.deleteFileItem(fileItem)"
125
+ />
126
+ </q-circular-progress>
127
+ </div>
128
+
129
+ <!-- 操作 -->
130
+ <div
131
+ class="n-uploader-query__item__settings transparent no-padding"
132
+ v-if="fileItem.status !== UPLOAD_STATUS.uploading"
133
+ >
134
+ <!-- 预览 -->
135
+ <q-icon
136
+ class="n-uploader-query__item__settings__icon cursor-pointer"
137
+ name="search"
138
+ size="xs"
139
+ title="预览"
140
+ @click="uploader.previewImage(fileItem)"
141
+ v-if="! noPreview && getImage(fileItem)"
142
+ />
143
+
144
+ <!-- 删除 -->
145
+ <q-icon
146
+ class="n-uploader-query__item__settings__icon cursor-pointer"
147
+ name="close"
148
+ size="xs"
149
+ title="删除"
150
+ @click="uploader.deleteFileItem(fileItem)"
151
+ v-if="! noDelete && ! disable && ! readonly"
152
+ />
153
+ </div>
154
+ </n-img>
155
+ </div>
156
+
157
+ <!-- 右边方块按钮 -->
158
+ <template v-if="! disable && ! readonly && rightSquareButton">
159
+ <slot
160
+ name="square-button"
161
+ :size="currentSize"
162
+ :show="showSquareButton"
163
+ v-if="$slots['square-button']"
164
+ />
165
+ <div
166
+ class="n-uploader-query__button--square cursor-pointer"
167
+ :style="{
168
+ width: toPx(currentSize),
169
+ height: toPx(currentSize),
170
+ }"
171
+ @click="uploader.chooseUpload"
172
+ v-show="showSquareButton"
173
+ v-else-if="! noButton && currentButtonType === 'square'"
174
+ >
175
+ <q-icon
176
+ name="add"
177
+ :size="toPx(currentSize / 2)"
178
+ />
179
+ <div class="n-uploader-query__button--square__text" v-if="buttonText">{{buttonText}}</div>
180
+ </div>
181
+ </template>
182
+ </template>
183
+
184
+ <!-- 上传文件队列 -->
185
+ <template v-else>
186
+
187
+ <!-- 单个文件 -->
188
+ <div
189
+ v-for="(fileItem, fileItemIndex) in query"
190
+ :key="`query-item-${fileItem.id}`"
191
+ class="n-uploader-query__item n-uploader-query__item--file"
192
+ :class="{
193
+ ghost: fileItemIndex === fromIndex,
194
+ }"
195
+ :style="{
196
+ height: toPx(currentSize),
197
+ }"
198
+ :draggable="currentDrag"
199
+ @mousedown.self="mousedown($event, fileItemIndex)"
200
+ @mouseup="dragEnd"
201
+ @dragstart="dragStart($event, fileItemIndex)"
202
+ @dragenter="dragEnter($event, fileItemIndex)"
203
+ @dragend="dragEnd"
204
+ >
205
+ <!-- 图标 -->
206
+ <div
207
+ class="n-uploader-query__item__icon"
208
+ :style="{
209
+ width: toPx(currentSize),
210
+ height: toPx(currentSize),
211
+ }"
212
+ >
213
+ <!-- 上传中前 -->
214
+ <q-circular-progress
215
+ class="n-uploader-query__item__icon__icon"
216
+ indeterminate
217
+ rounded
218
+ :size="toPx(currentSize / 1.8)"
219
+ :thickness="0.18"
220
+ v-if="fileItem.status < UPLOAD_STATUS.uploading"
221
+ />
222
+
223
+ <!-- 上传中 -->
224
+ <q-circular-progress
225
+ class="n-uploader-query__item__icon__icon"
226
+ :value="fileItem.progress"
227
+ :size="toPx(currentSize / 1.8)"
228
+ :thickness="0.18"
229
+ show-value
230
+ v-else-if="fileItem.status === UPLOAD_STATUS.uploading"
231
+ >
232
+ <q-icon
233
+ class="cursor-pointer"
234
+ name="pause"
235
+ :size="toPx(currentSize / 3)"
236
+ @click="uploader.deleteFileItem(fileItem)"
237
+ />
238
+ </q-circular-progress>
239
+
240
+ <!-- 文件图标 -->
241
+ <q-icon
242
+ class="n-uploader-query__item__icon__icon"
243
+ name="description"
244
+ :size="toPx(currentSize / 1.5)"
245
+ v-else-if="type === 'file'"
246
+ />
247
+
248
+ <!-- 播放图标 -->
249
+ <q-icon
250
+ class="n-uploader-query__item__icon__icon cursor-pointer"
251
+ name="play_circle"
252
+ title="播放"
253
+ :size="toPx(currentSize / 1.5)"
254
+ @click="uploader.play(fileItem)"
255
+ v-else
256
+ />
257
+ </div>
258
+
259
+ <!-- 信息 -->
260
+ <div class="n-uploader-query__item__info">
261
+ <!-- 标题 -->
262
+ <div class="n-uploader-query__item__info__title ellipsis">{{getFileName(fileItem)}}</div>
263
+ <!-- 错误提示 -->
264
+ <div class="n-uploader-query__item__info__msg--error" v-if="fileItem.status === UPLOAD_STATUS.fail">{{fileItem.msg}}</div>
265
+ </div>
266
+
267
+ <!-- 操作 -->
268
+ <div class="n-uploader-query__item__settings">
269
+
270
+ <template v-if="fileItem.status === UPLOAD_STATUS.success">
271
+
272
+ <!-- 复制地址 -->
273
+ <q-icon
274
+ class="n-uploader-query__item__settings__icon cursor-pointer"
275
+ name="content_copy"
276
+ color="white"
277
+ size="xs"
278
+ title="复制地址"
279
+ @click="uploader.copyUrl(fileItem)"
280
+ />
281
+
282
+ <!-- 修改 -->
283
+ <q-icon
284
+ class="n-uploader-query__item__settings__icon cursor-pointer"
285
+ name="edit"
286
+ color="white"
287
+ size="xs"
288
+ title="修改"
289
+ @click="uploader.previewImage(fileItem)"
290
+ v-if="! noEdit && ! disable && ! readonly"
291
+ >
292
+ <q-popup-edit
293
+ :model-value="fileItem.title"
294
+ buttons
295
+ label-set="保存"
296
+ @save="uploader.editFileTitle($event, fileItem)"
297
+ v-slot="scope"
298
+ >
299
+ <q-input
300
+ v-model="scope.value"
301
+ dense
302
+ autofocus
303
+ counter
304
+ :maxlength="50"
305
+ @keyup.enter="scope.set"
306
+ >
307
+ <template v-slot:append>
308
+ <span class="text-subtitle2 text-weight-bold">.{{fileItem.ext}}</span>
309
+ </template>
310
+ </q-input>
311
+ </q-popup-edit>
312
+ </q-icon>
313
+ </template>
314
+
315
+ <!-- 删除 -->
316
+ <q-icon
317
+ class="n-uploader-query__item__settings__icon cursor-pointer"
318
+ name="close"
319
+ color="white"
320
+ size="xs"
321
+ title="删除"
322
+ @click="uploader.deleteFileItem(fileItem)"
323
+ v-if="! noDelete && ! disable && ! readonly"
324
+ />
325
+ </div>
326
+ </div>
327
+ </template>
328
+ </n-dragger>
329
+ </div>
330
+ </template>
331
+
332
+ <script>
333
+ import { onMounted, computed, inject } from 'vue'
334
+ import { useQuasar } from 'quasar'
335
+
336
+ import $n_has from 'lodash/has'
337
+ import $n_get from 'lodash/get'
338
+
339
+ import $n_px from '@netang/utils/px'
340
+ import $n_isValidArray from '@netang/utils/isValidArray'
341
+ import $n_isValidString from '@netang/utils/isValidString'
342
+
343
+ import $n_getImage from '../../utils/getImage'
344
+
345
+ import NDragger from '../dragger'
346
+
347
+ import { NUploaderKey } from '../../utils/symbols'
348
+
349
+ import {
350
+ // 上传状态
351
+ UPLOAD_STATUS,
352
+ } from '../../utils/useUploader'
353
+
354
+ export default {
355
+
356
+ /**
357
+ * 标识
358
+ */
359
+ name: 'NUploaderQuery',
360
+
361
+ /**
362
+ * 组件
363
+ */
364
+ components: {
365
+ NDragger,
366
+ },
367
+
368
+ /**
369
+ * 声明属性
370
+ */
371
+ props: {
372
+ // 按钮类型, 可选值 square button
373
+ buttonType: {
374
+ type: String,
375
+ validator: v => [ 'square', 'button' ].includes(v),
376
+ },
377
+ // 按钮文字
378
+ buttonText: String,
379
+ // 按钮声明属性
380
+ buttonProps: Object,
381
+ // 图片/按钮/文件 尺寸
382
+ size: Number,
383
+ // 是否开启拖拽
384
+ drag: {
385
+ type: Boolean,
386
+ default: true,
387
+ },
388
+ // 是否禁用
389
+ disable: Boolean,
390
+ // 是否只读
391
+ readonly: Boolean,
392
+ // 是否隐藏按钮
393
+ noButton: Boolean,
394
+ // 是否隐藏预览按钮
395
+ noPreview: Boolean,
396
+ // 是否隐藏修改按钮
397
+ noEdit: Boolean,
398
+ // 是否隐藏删除按钮
399
+ noDelete: Boolean,
400
+ // 自动显示方块按钮
401
+ autoShowSquareButton: Boolean,
402
+ // 方块按钮在右边显示
403
+ rightSquareButton: Boolean,
404
+ },
405
+
406
+ /**
407
+ * 声明事件
408
+ */
409
+ emits: [
410
+ 'update:modelValue',
411
+ ],
412
+
413
+ /**
414
+ * 组合式
415
+ */
416
+ setup(props) {
417
+
418
+ // ==========【数据】============================================================================================
419
+
420
+ // quasar 对象
421
+ const $q = useQuasar()
422
+
423
+ // 获取上传器注入数据
424
+ const {
425
+ // 声明属性
426
+ props: uploaderProps,
427
+ // 上传器
428
+ uploader,
429
+ // 文件队列
430
+ query,
431
+ } = inject(NUploaderKey)
432
+
433
+ // ==========【计算属性】=========================================================================================
434
+
435
+ /**
436
+ * 当前是否开启拖拽
437
+ */
438
+ const currentDrag = computed(function() {
439
+ return props.drag
440
+ && $n_isValidArray(query.value)
441
+ && query.value.length > 1
442
+ && ! props.readonly
443
+ && ! props.disable
444
+ })
445
+
446
+ /**
447
+ * 当前按钮类型
448
+ */
449
+ const currentButtonType = computed(function () {
450
+ if (props.buttonType) {
451
+ return props.buttonType
452
+ }
453
+ return uploaderProps.type === 'image' ? 'square' : 'button'
454
+ })
455
+
456
+ /**
457
+ * 当前尺寸
458
+ */
459
+ const currentSize = computed(function () {
460
+ if (props.size) {
461
+ return props.size
462
+ }
463
+ return uploaderProps.type === 'image' ? 70 : 50
464
+ })
465
+
466
+ /**
467
+ * 是否显示方块按钮
468
+ */
469
+ const showSquareButton = computed(function () {
470
+ // 自动显示方块按钮 && 有上传文件限制数量
471
+ return props.autoShowSquareButton && uploaderProps.count > 0 ?
472
+ // 如果 上传文件列表数量 < 上传文件限制数量
473
+ query.value.length < uploaderProps.count
474
+ // 始终显示
475
+ : true
476
+ })
477
+
478
+ // ==========【方法】=============================================================================================
479
+
480
+ /**
481
+ * 获取图片地址
482
+ */
483
+ function getImage(fileItem) {
484
+ return $n_has(fileItem, '__img') ?
485
+ fileItem.__img
486
+ : (
487
+ $n_isValidString(fileItem.hash) ?
488
+ $n_getImage(fileItem.hash, { w: $q.platform.is.mobile ? currentSize.value * 2 : currentSize.value })
489
+ : ''
490
+ )
491
+ }
492
+
493
+ /**
494
+ * 获取文件名称
495
+ */
496
+ function getFileName(fileItem) {
497
+ return fileItem.title + ($n_get(fileItem, 'ext') ? '.' + fileItem.ext : '')
498
+ }
499
+
500
+ // ==========【生命周期】=========================================================================================
501
+
502
+ /**
503
+ * 实例被挂载后调用
504
+ */
505
+ onMounted( async function() {
506
+
507
+ })
508
+
509
+ // ==========【返回】=============================================================================================
510
+
511
+ return {
512
+ // 上传状态
513
+ UPLOAD_STATUS,
514
+ // 上传文件类型, 可选值 file image video audio
515
+ type: uploaderProps.type,
516
+ // 上传文件数量(0:不限)
517
+ count: uploaderProps.count,
518
+ // 上传文件队列
519
+ query,
520
+
521
+ // 当前是否开启拖拽
522
+ currentDrag,
523
+ // 当前按钮类型
524
+ currentButtonType,
525
+ // 当前尺寸
526
+ currentSize,
527
+ // 是否显示方块按钮
528
+ showSquareButton,
529
+
530
+ // 上传器
531
+ uploader,
532
+
533
+ // 获取图片地址
534
+ getImage,
535
+ // 获取文件名称
536
+ getFileName,
537
+
538
+ toPx: $n_px,
539
+ }
540
+ },
541
+ }
542
+ </script>
543
+
544
+ <style lang="scss">
545
+ @import "@/assets/sass/variables.scss";
546
+
547
+ // 上传器队列
548
+ .n-uploader-query {
549
+
550
+ // 上传按钮
551
+ &__button {
552
+
553
+ // 方块
554
+ &--square {
555
+ display: inline-flex;
556
+ vertical-align: middle;
557
+ overflow: hidden;
558
+ border: 1px dashed rgba(var(--n-reverse-color-rgb), 0.2);
559
+ flex-direction: column;
560
+ justify-content: center;
561
+ align-items: center;
562
+ color: rgba(var(--n-reverse-color-rgb), 0.4);
563
+ border-radius: 4px;
564
+
565
+ &:hover {
566
+ border-color: $primary;
567
+ }
568
+
569
+ // 文字
570
+ &__text {
571
+ font-size: 12px;
572
+ }
573
+ }
574
+
575
+ // 按钮
576
+ &--button {
577
+ + .n-uploader-query__query {
578
+ margin-top: 0;
579
+ }
580
+ }
581
+ }
582
+
583
+ // 上传单个文件
584
+ &__item {
585
+ position: relative;
586
+
587
+ // 开启拖拽
588
+ &[draggable="true"] {
589
+ cursor: move;
590
+ }
591
+
592
+ // 当前拖拽占位元素
593
+ &.ghost {
594
+ &:after {
595
+ content: "";
596
+ position: absolute;
597
+ top: 0;
598
+ left: 0;
599
+ right: 0;
600
+ bottom: 0;
601
+ border: 2px dashed mix(#ffffff, $primary, 40%);
602
+ border-radius: 4px;
603
+ background-color: rgba(255, 255, 255, 0.75);
604
+ }
605
+
606
+ .n-uploader-query__item__inner,
607
+ .n-uploader-query__item__settings {
608
+ display: none;
609
+ }
610
+ }
611
+
612
+ &:hover {
613
+ .n-uploader-query__item__settings {
614
+ visibility: visible;
615
+ }
616
+ }
617
+
618
+ // 单个图片
619
+ &--image {
620
+ border-radius: 4px;
621
+ background-color: rgba(0,0,0,0.1);
622
+ overflow: hidden;
623
+ }
624
+
625
+ // 单个文件
626
+ &--file {
627
+ position: relative;
628
+ width: 300px;
629
+ display: flex;
630
+ flex-direction: row;
631
+ align-items: center;
632
+ border-radius: 4px;
633
+ color: rgba(var(--n-reverse-color-rgb), 0.8);
634
+ background-color: rgba(var(--n-reverse-color-rgb), 0.05);
635
+
636
+ // 图标
637
+ .n-uploader-query__item__icon {
638
+ position: relative;
639
+ display: flex;
640
+ align-items: center;
641
+ justify-content: center;
642
+ z-index: 1;
643
+
644
+ &__icon {
645
+ color: rgba(var(--n-reverse-color-rgb), 0.2);
646
+ }
647
+ }
648
+
649
+ // 信息
650
+ .n-uploader-query__item__info {
651
+ display: flex;
652
+ flex-direction: column;
653
+ line-height: 18px;
654
+
655
+ &__title {
656
+ max-width: 150px;
657
+ }
658
+
659
+ &__msg--error {
660
+ color: $negative;
661
+ }
662
+ }
663
+ }
664
+
665
+ //操作
666
+ &__settings {
667
+ position: absolute;
668
+ top: 5px;
669
+ right: 5px;
670
+ visibility: hidden;
671
+
672
+ &__icon {
673
+ background-color: rgba(0,0,0,0.5);
674
+ border-radius: 50%;
675
+ padding: 5px;
676
+
677
+ + .n-uploader-query__item__settings__icon {
678
+ margin-left: 4px;
679
+ }
680
+
681
+ &:hover {
682
+ background-color: rgba(0,0,0,0.8);
683
+ }
684
+ }
685
+ }
686
+
687
+ // 内容
688
+ &__inner {
689
+
690
+ &__msg {
691
+ margin: 3px;
692
+ padding: 2px 3px;
693
+ line-height: 18px;
694
+ font-size: 12px;
695
+ background-color: rgba(0,0,0,0.6);
696
+ border-radius: 6px;
697
+
698
+ &--error {
699
+ background-color: $warning;
700
+ }
701
+ }
702
+ }
703
+ }
704
+ }
705
+
706
+ @media (max-width: $breakpoint-xs-max){
707
+ // 上传器队列
708
+ .n-uploader-query {
709
+ // 上传单个文件
710
+ &__item {
711
+ // 单个文件
712
+ &--file {
713
+ width: 100%;
714
+ }
715
+ }
716
+
717
+ // 信息
718
+ .n-uploader-query__item__info {
719
+ &__title {
720
+ max-width: 200px;
721
+ }
722
+ }
723
+ }
724
+ }
725
+
726
+ /**
727
+ * 手机版
728
+ */
729
+ body.mobile {
730
+ // 上传器队列
731
+ .n-uploader-query {
732
+ // 上传单个文件
733
+ &__item {
734
+ &__settings {
735
+ visibility: visible;
736
+ }
737
+ }
738
+ }
739
+ }
740
+
741
+ /**
742
+ * 暗黑
743
+ */
744
+ .body--dark {
745
+ .n-uploader-query__item--file {
746
+ .n-uploader-query__item__settings {
747
+ // 图标
748
+ &__icon {
749
+ background-color: rgba(255,255,255, 0.1);
750
+
751
+ &:hover {
752
+ background-color: rgba(255,255,255, 0.2);
753
+ }
754
+ }
755
+ }
756
+ }
757
+ }
758
+ </style>