@ecolovo/uniapp-components 1.0.10 → 2.0.1

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 (130) hide show
  1. package/README.md +202 -66
  2. package/components/aspect/aspect.vue +24 -15
  3. package/components/badge/badge.scss +20 -0
  4. package/components/badge/badge.vue +49 -40
  5. package/components/button/button.scss +15 -0
  6. package/components/button/button.vue +121 -177
  7. package/components/checkbox/checkbox.scss +10 -0
  8. package/components/checkbox/checkbox.vue +118 -146
  9. package/components/checkbox-group/checkbox-group.vue +79 -85
  10. package/components/checkbox-group2/checkbox-group2.vue +111 -107
  11. package/components/checkbox-group2/checkbox2.vue +104 -0
  12. package/components/data-list/data-list.scss +9 -0
  13. package/components/data-list/data-list.vue +70 -79
  14. package/components/date-picker/date-picker-view.vue +125 -124
  15. package/components/date-picker/date-picker.vue +145 -146
  16. package/components/dialog/dialog-content.vue +39 -47
  17. package/components/dialog/dialog.scss +11 -0
  18. package/components/dialog/dialog.vue +125 -138
  19. package/components/dropdown/dropdown.scss +11 -0
  20. package/components/dropdown/dropdown.vue +55 -97
  21. package/components/empty/empty.scss +14 -0
  22. package/components/empty/empty.vue +42 -41
  23. package/components/flex/flex.vue +45 -54
  24. package/components/form/form.vue +29 -24
  25. package/components/form-item/form-item.scss +11 -0
  26. package/components/form-item/form-item.vue +43 -40
  27. package/components/icon/icon.vue +70 -85
  28. package/components/image/image.vue +35 -38
  29. package/components/input/input.vue +65 -79
  30. package/components/input/password-input.vue +34 -42
  31. package/components/list-page/list-page.vue +73 -99
  32. package/components/load-more/load-more.scss +12 -0
  33. package/components/load-more/load-more.vue +29 -29
  34. package/components/loading/animations/loading-animation1.vue +8 -8
  35. package/components/loading/animations/loading-animation2.vue +8 -9
  36. package/components/loading/animations/loading-animation3.vue +11 -11
  37. package/components/loading/animations/loading-animation4.vue +8 -8
  38. package/components/loading/loading.vue +19 -20
  39. package/components/message-box/message-box.vue +59 -41
  40. package/components/number-dialog/number-dialog.scss +9 -0
  41. package/components/number-dialog/number-dialog.vue +209 -204
  42. package/components/number-input/number-input.scss +9 -0
  43. package/components/number-input/number-input.vue +233 -232
  44. package/components/numpad/numpad.scss +9 -0
  45. package/components/numpad/numpad.vue +133 -150
  46. package/components/page/page-body.scss +15 -0
  47. package/components/page/page-body.vue +137 -119
  48. package/components/page/page-footer.scss +13 -0
  49. package/components/page/page-footer.vue +31 -33
  50. package/components/page/page-header.scss +17 -0
  51. package/components/page/page-header.vue +89 -94
  52. package/components/page/page.scss +9 -0
  53. package/components/page/page.vue +105 -81
  54. package/components/picker/picker-popup.vue +218 -209
  55. package/components/picker/picker.vue +99 -104
  56. package/components/popover/popover-content.vue +54 -63
  57. package/components/popover/popover-mask.vue +63 -63
  58. package/components/popover/popover.scss +28 -0
  59. package/components/popover/popover.vue +49 -47
  60. package/components/popup/popup-content.vue +49 -53
  61. package/components/popup/popup.scss +11 -0
  62. package/components/popup/popup.vue +117 -132
  63. package/components/price/price.scss +20 -0
  64. package/components/price/price.vue +31 -42
  65. package/components/search/search.scss +12 -0
  66. package/components/search/search.vue +93 -117
  67. package/components/searching/searching.vue +33 -40
  68. package/components/selector/selector.vue +43 -48
  69. package/components/switch/switch.scss +12 -0
  70. package/components/switch/switch.vue +99 -96
  71. package/components/tab/tab.scss +19 -0
  72. package/components/tab/tab.vue +151 -145
  73. package/components/textarea/textarea.vue +104 -101
  74. package/composable/component-name.d.ts +2 -0
  75. package/composable/component-name.js +8 -0
  76. package/composable/component-name.ts +10 -0
  77. package/configs/index.d.ts +25 -10
  78. package/configs/index.js +14 -23
  79. package/configs/index.ts +82 -0
  80. package/easyCom.d.ts +9 -0
  81. package/easyCom.js +1 -2
  82. package/easyCom.ts +31 -0
  83. package/index.d.ts +1 -0
  84. package/index.js +1 -0
  85. package/index.ts +1 -0
  86. package/init.d.ts +4 -7
  87. package/init.js +5 -4
  88. package/init.ts +34 -0
  89. package/package.json +14 -4
  90. package/styles/utils/css-var.scss +12 -15
  91. package/styles/utils/ellipsis.scss +0 -7
  92. package/styles/utils/z-index.scss +1 -1
  93. package/styles/var/component.scss +21 -245
  94. package/utils/date.d.ts +47 -0
  95. package/utils/date.js +23 -43
  96. package/utils/date.ts +153 -0
  97. package/utils/freezeDeep.d.ts +1 -0
  98. package/utils/freezeDeep.js +4 -14
  99. package/utils/freezeDeep.ts +9 -0
  100. package/utils/price.d.ts +24 -0
  101. package/utils/price.js +14 -8
  102. package/utils/price.ts +57 -0
  103. package/utils/round.d.ts +2 -0
  104. package/utils/round.js +2 -14
  105. package/utils/round.ts +11 -0
  106. package/utils/windowInfo.d.ts +24 -0
  107. package/utils/windowInfo.js +8 -36
  108. package/utils/windowInfo.ts +50 -0
  109. package/components/checkbox-group2/checkbox.vue +0 -109
  110. package/components/datetime-picker/datetime-picker-view.vue +0 -209
  111. package/components/datetime-picker/datetime-picker.vue +0 -235
  112. package/components/form/mixin.js +0 -13
  113. package/components/list-page/list-page.js +0 -10
  114. package/components/table/table.vue +0 -112
  115. package/components/time-picker/time-picker-view.vue +0 -127
  116. package/components/time-picker/time-picker.vue +0 -140
  117. package/components/uploader/download.js +0 -81
  118. package/components/uploader/file-uploader.vue +0 -52
  119. package/components/uploader/files.js +0 -225
  120. package/components/uploader/media-uploader.vue +0 -189
  121. package/components/uploader/mixin.js +0 -171
  122. package/components/uploader/uni.js +0 -38
  123. package/components/uploader/upload-button.vue +0 -29
  124. package/components/uploader/uploader copy.vue +0 -547
  125. package/components/uploader/uploader.vue +0 -117
  126. package/mixins/componentName.js +0 -32
  127. package/mixins/listPage.js +0 -1
  128. package/mixins/windowInfo.js +0 -1
  129. package/utils/fileSize.js +0 -39
  130. package/utils/floor.js +0 -20
@@ -1,547 +0,0 @@
1
- <template>
2
- <view :class="[componentClassNames, isCardView ? $style['Uploader--card'] : $style['Uploader--list']]">
3
- <template v-if="isCardView">
4
- <!-- 附件列表 -->
5
- <view
6
- v-for="(item, index) in currentValue"
7
- :key="index"
8
- :class="$style['Uploader--file']"
9
- @click="previewFile(item)"
10
- >
11
- <view
12
- v-if="!computedReadonly && item.uploadStatus !== 'uploading'"
13
- :class="$style['Uploader--icon-close']"
14
- @click.stop="deleteFile(item)"
15
- >
16
- </view>
17
- <image
18
- v-if="item.fileType === FILE_TYPE_IMAGE"
19
- :class="$style['Uploader--image']"
20
- mode="aspectFill"
21
- :src="item.fileUrl"
22
- />
23
- <video
24
- v-if="item.fileType === FILE_TYPE_VIDEO"
25
- :id="'video_' + item.fileId"
26
- :muted="true"
27
- :src="item.fileUrl"
28
- :controls="false"
29
- :show-progress="false"
30
- :show-fullscreen-btn="false"
31
- :show-play-btn="false"
32
- :show-center-play-btn="false"
33
- :show-loading="false"
34
- :enable-progress-gesture="false"
35
- object-fit="fill"
36
- :class="[$style['Uploader--image'], $style['Uploader--video']]"
37
- @click.stop.prevent="previewVideo(item)"
38
- @fullscreenchange="stopPreviewVideo"
39
- ></video>
40
- <view v-if="item.uploadStatus === 'error'" :class="$style['Uploader--error']">
41
- <view>上传</view>
42
- <view>失败</view>
43
- </view>
44
- <view v-else-if="item.uploadStatus === 'uploading'" :class="$style['Uploader--uploading']">
45
- <icon-cpn icon="loading" :class="$style['Uploader--icon-loading']" />
46
- 上传中
47
- </view>
48
- </view>
49
- <view
50
- v-if="!computedReadonly && (max <= 0 || currentValue.length < max)"
51
- :class="$style['Uploader--file']"
52
- @click="beforeChoose"
53
- >
54
- <icon-cpn icon="add-photo" :class="$style['Uploader--uploader-icon']" />
55
- <view :class="$style['Uploader--uploader-text']">
56
- <slot>添加图片</slot>
57
- </view>
58
- </view>
59
- </template>
60
- <template v-else>
61
- <button-cpn
62
- v-if="!computedReadonly && (max <= 0 || currentValue.length < max)"
63
- plain
64
- :class="$style['Uploader--uploader']"
65
- @click="beforeChoose"
66
- >
67
- <icon-cpn icon="plus-circle" />
68
- 上传附件
69
- </button-cpn>
70
- <!-- 附件列表 -->
71
- <view v-for="(item, index) in currentValue" :key="index">
72
- <view :class="$style['Uploader--file']" @click="previewFile(item)">
73
- <icon-cpn icon="attachment" :class="$style['Uploader--icon-attachment']" />
74
- <view :class="$style['Uploader--file-name']">{{ item.fileName || item.name }}</view>
75
- <icon-cpn
76
- v-if="!computedReadonly && item.uploadStatus !== 'uploading'"
77
- icon="close-circle-filled"
78
- expand-tap-area
79
- :class="$style['Uploader--icon-close']"
80
- @click.native.stop="deleteFile(item)"
81
- />
82
- <view v-else-if="item.uploadStatus === 'uploading'" :class="$style['Uploader--uploading']">
83
- <icon-cpn icon="loading" />
84
- </view>
85
- </view>
86
- <view v-if="item.uploadStatus === 'error'" :class="$style['Uploader--error']">上传失败</view>
87
- </view>
88
- </template>
89
-
90
- <popup-cpn v-if="isSelectTypeVisible" ref="popup" v-model="isSelectTypeVisible" :confirm="false">
91
- <button-cpn :class="$style['Uploader--button']" @click="choose('file')">从聊天记录选择文件</button-cpn>
92
- <button-cpn :class="$style['Uploader--button']" @click="choose()">
93
- 拍摄或从相册选择{{ mediaTypeName }}
94
- </button-cpn>
95
- </popup-cpn>
96
-
97
- <dialog-cpn v-if="isShowVideoPreview" v-model="isShowVideoPreview">
98
- <template #custom>
99
- <view :class="$style['Uploader--preview-video-wrapper']">
100
- <video
101
- :src="previewVideoUrl"
102
- :autoplay="true"
103
- :muted="true"
104
- show-mute-btn
105
- :class="$style['Uploader--preview-video']"
106
- ></video>
107
- <icon-cpn
108
- icon="clear"
109
- :class="$style['Uploader--preview-video-close']"
110
- @click="isShowVideoPreview = false"
111
- ></icon-cpn>
112
- </view>
113
- </template>
114
- </dialog-cpn>
115
- </view>
116
- </template>
117
-
118
- <script>
119
- import componentName from '../../mixins/componentName';
120
- import ButtonCpn from '../button/button.vue';
121
- import DialogCpn from '../dialog/dialog.vue';
122
- import IconCpn from '../icon/icon.vue';
123
- import PopupCpn from '../popup/popup.vue';
124
- import {
125
- FILE_TYPE_IMAGE,
126
- FILE_TYPE_VIDEO,
127
- FILE_TYPE_FILE,
128
- typeStringValidator,
129
- typeStringToArr,
130
- chooseFile,
131
- isImage,
132
- isVideo,
133
- } from './files';
134
- import { openDocument } from './uni';
135
-
136
- export default {
137
- name: 'Uploader',
138
- options: {
139
- virtualHost: true,
140
- styleIsolation: 'shared',
141
- },
142
- components: { ButtonCpn, DialogCpn, IconCpn, PopupCpn },
143
- mixins: [componentName],
144
- inject: {
145
- injectReadonly: {
146
- from: 'readonly',
147
- default: false,
148
- },
149
- },
150
- props: {
151
- /** 绑定值 */
152
- value: {
153
- type: Array,
154
- default: () => [],
155
- },
156
- /** 最大上传数量 */
157
- max: {
158
- type: Number,
159
- default: 9,
160
- },
161
- /** 是否使用卡片样式,不设置的话,如果 type 不包含文件类型,也会使用卡片样式 */
162
- card: {
163
- type: Boolean,
164
- default: null,
165
- },
166
- /** 上传文件类型 */
167
- type: {
168
- type: String,
169
- validator: typeStringValidator,
170
- default: 'all',
171
- },
172
- /** 选择文件时限制文件类型,仅 type 为 file 或 all 时有效 */
173
- selectExtension: {
174
- type: String,
175
- default: '',
176
- },
177
- /** 选中文件后文件类型限制 */
178
- allowedExtension: {
179
- type: String,
180
- default: '',
181
- },
182
- /** 是否只读 */
183
- readonly: {
184
- type: Boolean,
185
- default: false,
186
- },
187
- },
188
- data() {
189
- return {
190
- FILE_TYPE_IMAGE,
191
- FILE_TYPE_VIDEO,
192
- /** 是否显示选择文件类型弹窗 */
193
- isSelectTypeVisible: false,
194
- isShowVideoPreview: false,
195
- previewVideoUrl: '',
196
- };
197
- },
198
- computed: {
199
- currentValue: {
200
- get: function () {
201
- return this.value === null ? this.innerValue : this.value;
202
- },
203
- set: function (value) {
204
- this.$emit('input', value);
205
- this.innerValue = value;
206
- this.$emit('change', value);
207
- },
208
- },
209
- computedReadonly() {
210
- return this.readonly || this.injectReadonly;
211
- },
212
- /** 上传文件类型数组 */
213
- typeList() {
214
- return typeStringToArr(this.type);
215
- },
216
- /** 是否可以选择图片类型 */
217
- isImageType() {
218
- return this.typeList.includes(FILE_TYPE_IMAGE);
219
- },
220
- /** 是否可以选择视频类型 */
221
- isVideoType() {
222
- return this.typeList.includes(FILE_TYPE_VIDEO);
223
- },
224
- /** 是否可以选择文件类型 */
225
- isFileType() {
226
- return this.typeList.includes(FILE_TYPE_FILE);
227
- },
228
- /** 是否使用卡片样式 */
229
- isCardView() {
230
- return typeof this.card === 'boolean' ? this.card : this.isFileType ? false : true;
231
- },
232
- /** 媒体文件类型 */
233
- mediaType() {
234
- return [...(this.isImageType ? [FILE_TYPE_IMAGE] : []), ...(this.isVideoType ? [FILE_TYPE_VIDEO] : [])];
235
- },
236
- /** 媒体文件类型中文文本 */
237
- mediaTypeName() {
238
- return [...(this.isImageType ? ['图片'] : []), ...(this.isVideoType ? ['视频'] : [])].join('、');
239
- },
240
- /** 选择文件时过滤的文件后缀数组 */
241
- selectExtensionList() {
242
- return this.selectExtension ? this.selectExtension.split(',') : undefined;
243
- },
244
- /** 选择文件后过滤的文件后缀数组 */
245
- allowedExtensionList() {
246
- return this.allowedExtension ? this.allowedExtension.split(',') : undefined;
247
- },
248
- /** 图片预览列表 */
249
- previewImageList() {
250
- return this.currentValue
251
- .filter((item) => item.fileType === FILE_TYPE_IMAGE)
252
- .map((item) => item.path || item.fileUrl);
253
- },
254
- },
255
- created() {
256
- // 处理初始值
257
- this.currentValue = (this.value || []).map((item) => {
258
- item = { ...item, filePreviewUrl: item.filePreviewUrl || item.fileUrl };
259
- if (!item.fileType) {
260
- item.fileType = isImage(item.fileExt || item.fileName || item.fileUrl.split('?').shift())
261
- ? FILE_TYPE_IMAGE
262
- : isVideo(item.fileExt || item.fileName || item.fileUrl.split('?').shift())
263
- ? FILE_TYPE_VIDEO
264
- : FILE_TYPE_FILE;
265
- }
266
- return item;
267
- });
268
- },
269
- methods: {
270
- /** 选择前判断文件类型 */
271
- async beforeChoose() {
272
- // 包含选择文件,且包含图片或视频,需要提示用户选择
273
- if (this.isFileType && this.mediaType.length > 0) {
274
- this.isSelectTypeVisible = true;
275
- return;
276
- }
277
-
278
- this.choose(this.isFileType ? 'file' : 'media');
279
- },
280
- /** 选择文件 */
281
- async choose(type = 'media') {
282
- this.$refs.popup?.close();
283
-
284
- if (type === 'file') {
285
- type = ['file'];
286
- } else {
287
- type = this.mediaType;
288
- }
289
-
290
- const { files, invalidFiles } = await chooseFile({
291
- max: this.max <= 0 ? 9 : this.max - this.currentValue.length,
292
- type: type,
293
- selectExtension: this.selectExtensionList,
294
- allowedExtension: this.allowedExtensionList,
295
- });
296
- if (invalidFiles.length > 0) {
297
- this.$toast('已剔除不符合格式的文件');
298
- }
299
- this.currentValue = this.currentValue.concat(files.map((item) => ({ ...item, uploadStatus: 'uploading' })));
300
- if (this.max > 0 && this.currentValue.length >= this.max) {
301
- this.$toast(`最多只能上传${this.max}个文件`);
302
- this.currentValue = this.currentValue.slice(0, this.max);
303
- }
304
- this.upload(files);
305
- },
306
- /** 上传文件 */
307
- upload(files) {
308
- files.map(async (file) => {
309
- try {
310
- const res = null;
311
- // const res = await httpUpload({ url: apis.common.uploadFile.url, file });
312
- const index = this.currentValue.findIndex((item) => item.path === file.path);
313
- if (index < 0) {
314
- return;
315
- }
316
- const currentValue = [...this.currentValue];
317
- currentValue.splice(index, 1, {
318
- fileId: res.fileId,
319
- fileName: res.fileName,
320
- filePreviewUrl: res.filePreviewUrl,
321
- fileUrl: res.fileUrl,
322
- fileType: file.type,
323
- });
324
- this.currentValue = currentValue;
325
- return this.currentValue[index];
326
- } catch {
327
- const index = this.currentValue.findIndex((item) => item.path === file.path);
328
- if (index < 0) {
329
- return;
330
- }
331
- const currentValue = [...this.currentValue];
332
- currentValue.splice(index, 1, { ...file, uploadStatus: 'error' });
333
- this.currentValue = currentValue;
334
- }
335
- });
336
- },
337
- /** 删除文件 */
338
- deleteFile(file) {
339
- const index = this.currentValue.findIndex((item) => file === item);
340
- if (index >= 0) {
341
- const currentValue = [...this.currentValue];
342
- currentValue.splice(index, 1);
343
- this.currentValue = currentValue;
344
- }
345
- },
346
- /**
347
- * @param {UploadFile} file 文件
348
- */
349
- previewFile(file) {
350
- if (file.fileType === FILE_TYPE_IMAGE) {
351
- this.previewImage(this.previewImageList.findIndex((item) => item === file.fileUrl));
352
- }
353
- if (file.fileType === FILE_TYPE_FILE) {
354
- openDocument(file.fileUrl, file.fileName).catch((err) => {
355
- this.$toast(err);
356
- });
357
- }
358
- },
359
- /** 预览图片 */
360
- previewImage(index) {
361
- uni.previewImage({
362
- current: index,
363
- urls: this.previewImageList,
364
- });
365
- },
366
- /** 预览视频 */
367
- previewVideo(file) {
368
- this.isShowVideoPreview = true;
369
- this.previewVideoUrl = file.fileUrl;
370
- },
371
- },
372
- };
373
- </script>
374
-
375
- <style lang="scss" module>
376
- @use '../../styles/index' as *;
377
-
378
- :host {
379
- display: block;
380
- }
381
- :host(.display-inline) {
382
- display: inline;
383
- }
384
-
385
- .Uploader {
386
- width: 100%;
387
- position: relative;
388
- }
389
-
390
- .Uploader--card {
391
- display: flex;
392
- flex-wrap: wrap;
393
- text-align: center;
394
- margin: 0 calc(-1 * #{get-value('size-l')}) calc(-1 * #{get-value('size-l')}) 0;
395
-
396
- .Uploader--file {
397
- position: relative;
398
- width: 160rpx;
399
- height: 160rpx;
400
- margin: 0 get-value('size-l') get-value('size-l') 0;
401
- background: get-value('color-background');
402
- border-radius: get-value('size-radius-xxs');
403
- color: get-value('color-info');
404
- font-size: get-value('size-font-s');
405
- display: flex;
406
- flex-direction: column;
407
- justify-content: center;
408
- align-items: center;
409
- z-index: 0;
410
- }
411
- .Uploader--image {
412
- width: 100%;
413
- height: 100%;
414
- border-radius: get-value('size-radius-xxs');
415
- }
416
- // .Uploader--icon-close {
417
- // position: absolute;
418
- // top: 0;
419
- // right: 0;
420
- // transform: translate(30%, -30%);
421
- // color: get-value('color-danger');
422
- // font-size: get-value('size-font-l');
423
- // z-index: 1;
424
- // }
425
- .Uploader--icon-close {
426
- position: absolute;
427
- top: 0;
428
- right: 0;
429
- z-index: 1;
430
- transform: translate(25%, -25%);
431
- width: get-value('size-xxxl');
432
- height: get-value('size-xxxl');
433
- background: red;
434
- border-radius: 50%;
435
- &:before,
436
- &:after {
437
- content: '';
438
- position: absolute;
439
- top: 50%;
440
- left: 50%;
441
- height: 70%;
442
- width: 10%;
443
- background: #fff;
444
- }
445
- &:before {
446
- transform: translate(-50%, -50%) rotate(45deg);
447
- }
448
- &:after {
449
- transform: translate(-50%, -50%) rotate(-45deg);
450
- }
451
- }
452
- .Uploader--uploader-icon {
453
- font-size: 48rpx;
454
- color: get-value('color-info-6');
455
- }
456
- .Uploader--uploading {
457
- position: absolute;
458
- top: 50%;
459
- left: 50%;
460
- transform: translate(-50%, -50%);
461
- display: flex;
462
- flex-direction: column;
463
- justify-content: center;
464
- align-items: center;
465
- }
466
- .Uploader--icon-loading {
467
- font-size: get-value('size-font-l');
468
- }
469
- .Uploader--error {
470
- position: absolute;
471
- top: 50%;
472
- left: 50%;
473
- width: 70%;
474
- height: 70%;
475
- transform: translate(-50%, -50%);
476
- border-radius: 50%;
477
- background: rgba(255, 255, 255, 0.75);
478
- display: flex;
479
- flex-direction: column;
480
- justify-content: center;
481
- align-items: center;
482
- }
483
- }
484
-
485
- .Uploader--list {
486
- .Uploader--uploader {
487
- #{UTILS__VAR_NAME(height, button)}: 88rpx;
488
- #{UTILS__VAR_NAME(border-style, button)}: dashed;
489
- }
490
- .Uploader--file {
491
- position: relative;
492
- margin-top: get-value('size-s');
493
- width: 100%;
494
- height: 88rpx;
495
- padding: 0 get-value('size-s');
496
- display: flex;
497
- justify-content: start;
498
- align-items: center;
499
- background: get-value('color-background');
500
- border-radius: get-value('size-radius-xxs');
501
- }
502
- .Uploader--file-name {
503
- flex: 1;
504
- @include UTILS__ELLIPSIS();
505
- }
506
- .Uploader--icon-attachment {
507
- font-size: get-value('size-font-l');
508
- color: get-value('color-primary');
509
- margin-right: get-value('size-xxs');
510
- }
511
- .Uploader--uploading,
512
- .Uploader--icon-close {
513
- position: relative;
514
- font-size: get-value('size-font-l');
515
- color: get-value('color-info');
516
- #{UTILS__VAR_NAME(tap-size, icon)}: 200rpx;
517
- }
518
- .Uploader--error {
519
- color: get-value('color-danger');
520
- font-size: get-value('size-font-s');
521
- margin: get-value('size-xxs') 0 get-value('size-s') get-value('size-s');
522
- }
523
- .Uploader--button {
524
- margin-bottom: get-value('size-m');
525
- }
526
- }
527
-
528
- .Uploader--preview-video-wrapper {
529
- width: 80vw;
530
- height: 75vh;
531
- display: flex;
532
- justify-content: center;
533
- align-items: center;
534
- }
535
- .Uploader--preview-video {
536
- width: 100%;
537
- height: 100%;
538
- }
539
- .Uploader--preview-video-close {
540
- position: absolute;
541
- color: get-value('color-white');
542
- bottom: -20rpx;
543
- left: 50%;
544
- transform: translate(-50%, 100%);
545
- font-size: 80rpx;
546
- }
547
- </style>
@@ -1,117 +0,0 @@
1
- <template>
2
- <view :class="componentClassNames">
3
- <view v-if="card" :class="$style['Uploader--card-list']" :style="{ '--columns': columns }">
4
- <!-- 已上传文件列表 -->
5
- <aspect-cpn v-for="img in value" :key="img" :class="$style['Uploader--card-item']" :style="styleWidth">
6
- <image-cpn
7
- :src="img"
8
- :preview-list="value"
9
- :class="$style['Uploader--card-image']"
10
- :style="styleSize"
11
- mode="aspectFill"
12
- >
13
- </image-cpn>
14
- </aspect-cpn>
15
- <!-- 上传按钮 -->
16
- <aspect-cpn :class="$style['Uploader--card-item']" :style="styleWidth">
17
- <button-cpn plain :class="$style['Uploader--card-uploader']">
18
- <view style="line-height: 1.3em">
19
- <view>上传</view>
20
- <view>图片</view>
21
- </view>
22
- </button-cpn>
23
- </aspect-cpn>
24
- </view>
25
- <view v-else :class="$style['Uploader--list-view']">
26
- <view>
27
- <button-cpn>上传</button-cpn>
28
- </view>
29
- <view>
30
- <view v-for="file in value" :key="file" :class="$style['Uploader--file-item']">{{ file }}</view>
31
- </view>
32
- </view>
33
- </view>
34
- </template>
35
-
36
- <script>
37
- import componentName from '../../mixins/componentName';
38
- import AspectCpn from '../aspect/aspect.vue';
39
- import ButtonCpn from '../button/button.vue';
40
- import ImageCpn from '../image/image.vue';
41
-
42
- export default {
43
- name: 'Uploader',
44
- options: {
45
- virtualHost: true,
46
- styleIsolation: 'shared',
47
- },
48
- components: { AspectCpn, ButtonCpn, ImageCpn },
49
- mixins: [componentName],
50
- props: {
51
- /** 文件列表 */
52
- value: {
53
- type: Array,
54
- default: () => [],
55
- },
56
- /** 是否使用卡片样式,不设置的话,如果 type 不包含文件类型,也会使用卡片样式 */
57
- card: {
58
- type: Boolean,
59
- default: false,
60
- },
61
- /** 显示宽度 */
62
- columns: {
63
- type: [String, Number],
64
- default: 4,
65
- },
66
- /** 显示宽度 */
67
- width: {
68
- type: [String, Number],
69
- default: '',
70
- },
71
- },
72
- computed: {
73
- styleWidth() {
74
- if (!this.width) return '';
75
- const width = typeof this.width === 'number' ? `${this.width}rpx` : this.width;
76
- return `width: ${width};`;
77
- },
78
- },
79
- methods: {},
80
- };
81
- </script>
82
-
83
- <style lang="scss" module>
84
- .Uploader {
85
- width: 100%;
86
- }
87
-
88
- .Uploader--card-uploader {
89
- height: 100%;
90
- border-color: #ccc;
91
- border-radius: 16rpx;
92
- }
93
- .Uploader--card-list {
94
- display: flex;
95
- flex-wrap: wrap;
96
- gap: 12rpx;
97
- }
98
- .Uploader--card-item {
99
- width: calc(100% / var(--columns) - 12rpx * (var(--columns) - 1) / var(--columns));
100
- }
101
- .Uploader--card-image {
102
- border-radius: 16rpx;
103
- }
104
- .Uploader--list-view {
105
- width: 100%;
106
- }
107
- .Uploader--file-item {
108
- &:first-child {
109
- margin-top: 20rpx;
110
- }
111
- padding: 15rpx 0;
112
- font-size: 28rpx;
113
- white-space: nowrap;
114
- overflow: hidden;
115
- text-overflow: ellipsis;
116
- }
117
- </style>
@@ -1,32 +0,0 @@
1
- import { kebabCase, pascalCase } from 'case-anything';
2
- import { componentPrefix } from '../configs';
3
-
4
- export default {
5
- /* #ifdef MP */
6
- data() {
7
- return {
8
- // 添加 $style 属性,否则在 wxml 中无法使用
9
- $style: {},
10
- };
11
- },
12
- /* #endif */
13
- computed: {
14
- /** 组件公共前缀,大驼峰模式 */
15
- componentPrefix() {
16
- return pascalCase(componentPrefix);
17
- },
18
- /** 添加前缀后的组件名-大驼峰模式 */
19
- componentClass() {
20
- return this.componentPrefix + this.$options.name;
21
- },
22
- /** 添加前缀后的组件名-短横线模式 */
23
- componentKebabClass() {
24
- return kebabCase(this.componentClass);
25
- },
26
- /** 合并后的组件类名 */
27
- componentClassNames() {
28
- const baseClass = this.$style?.[this.$options.name];
29
- return [...(baseClass ? [baseClass] : []), this.componentClass, this.componentKebabClass];
30
- },
31
- },
32
- };
@@ -1 +0,0 @@
1
- export { pulldownRefreshMixin } from '../components/list-page/list-page';
@@ -1 +0,0 @@
1
- export { windowInfoMixin as default } from '../utils/windowInfo';