@10yun/cv-mobile-ui 0.5.62 → 0.5.63

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 (67) hide show
  1. package/package.json +1 -1
  2. package/plugins/uni-extend.js +10 -10
  3. package/ui-fireui/components/u-action-sheet/u-action-sheet.vue +46 -16
  4. package/ui-fireui/components/u-alert/u-alert.vue +11 -5
  5. package/ui-fireui/components/u-badge/u-badge.vue +52 -69
  6. package/ui-fireui/components/u-bottom-navigation/u-bottom-navigation.vue +28 -20
  7. package/ui-fireui/components/u-bottom-popup/u-bottom-popup.vue +40 -11
  8. package/ui-fireui/components/u-bubble-popup/u-bubble-popup.vue +3 -6
  9. package/ui-fireui/components/u-button/u-button.vue +262 -259
  10. package/ui-fireui/components/u-calendar/u-calendar.vue +227 -44
  11. package/ui-fireui/components/u-calendar/u-calendar2.js +562 -0
  12. package/ui-fireui/components/u-card/u-card.vue +50 -32
  13. package/ui-fireui/components/u-cascade-selection/u-cascade-selection.vue +197 -74
  14. package/ui-fireui/components/u-circular-progress/u-circular-progress.vue +324 -0
  15. package/ui-fireui/components/u-clipboard2/tui-clipboard.js +53 -0
  16. package/ui-fireui/components/u-collapse/u-collapse.vue +8 -8
  17. package/ui-fireui/components/u-config/index.js +129 -0
  18. package/ui-fireui/components/u-count-down/u-count-down.vue +124 -19
  19. package/ui-fireui/components/u-datetime/u-datetime.vue +416 -176
  20. package/ui-fireui/components/u-divider/u-divider.vue +3 -3
  21. package/ui-fireui/components/u-drawer/u-drawer.vue +55 -12
  22. package/ui-fireui/components/u-dropdown-list/u-dropdown-list.vue +103 -0
  23. package/ui-fireui/components/u-fab/u-fab.vue +344 -0
  24. package/ui-fireui/components/u-footer/u-footer.vue +148 -0
  25. package/ui-fireui/components/u-grid/u-grid.vue +2 -8
  26. package/ui-fireui/components/u-grid-item/u-grid-item.vue +22 -5
  27. package/ui-fireui/components/u-icon/u-icon-new.js +190 -0
  28. package/ui-fireui/components/u-icon/u-icon-new.vue +100 -0
  29. package/ui-fireui/components/u-image-cropper/u-image-cropper.vue +1144 -0
  30. package/ui-fireui/components/u-image-group/u-image-group.vue +164 -0
  31. package/ui-fireui/components/u-keyboard/u-keyboard.vue +3 -2
  32. package/ui-fireui/components/u-keyboard-input/u-keyboard-input.vue +1 -1
  33. package/ui-fireui/components/u-list-cell/u-list-cell.vue +82 -72
  34. package/ui-fireui/components/u-list-view/u-list-view.vue +33 -8
  35. package/ui-fireui/components/u-loading/u-loading.vue +107 -27
  36. package/ui-fireui/components/u-loadmore/u-loadmore.vue +21 -3
  37. package/ui-fireui/components/u-modal/u-modal.vue +140 -176
  38. package/ui-fireui/components/u-navigation-bar/u-navigation-bar.vue +121 -28
  39. package/ui-fireui/components/u-no-data/u-no-data.vue +58 -20
  40. package/ui-fireui/components/u-nomore/u-nomore.vue +5 -4
  41. package/ui-fireui/components/u-numberbox/u-numberbox.vue +88 -45
  42. package/ui-fireui/components/u-picture-cropper/u-picture-cropper.vue +94 -36
  43. package/ui-fireui/components/u-picture-cropper/u-picture-cropper.wxs +27 -17
  44. package/ui-fireui/components/u-rate/u-rate.vue +197 -0
  45. package/ui-fireui/components/u-round-progress/u-round-progress.vue +62 -42
  46. package/ui-fireui/components/u-scroll-top/u-scroll-top.vue +4 -3
  47. package/ui-fireui/components/u-section/u-section.vue +149 -0
  48. package/ui-fireui/components/u-skeleton/u-skeleton.vue +37 -6
  49. package/ui-fireui/components/u-steps/u-steps.vue +110 -27
  50. package/ui-fireui/components/u-sticky/u-sticky.vue +35 -21
  51. package/ui-fireui/components/u-sticky-wxs/u-sticky-wxs.vue +7 -4
  52. package/ui-fireui/components/u-sticky-wxs/u-sticky.wxs +39 -36
  53. package/ui-fireui/components/u-swipe-action/u-swipe-action.vue +76 -19
  54. package/ui-fireui/components/u-tabbar/u-tabbar.vue +71 -38
  55. package/ui-fireui/components/u-tabs/u-tabs.vue +133 -51
  56. package/ui-fireui/components/u-tag/u-tag.vue +109 -226
  57. package/ui-fireui/components/u-time-axis/u-time-axis.vue +1 -1
  58. package/ui-fireui/components/u-timeaxis-item/u-timeaxis-item.vue +1 -1
  59. package/ui-fireui/components/u-tips/u-tips.vue +35 -15
  60. package/ui-fireui/components/u-toast/u-toast.vue +9 -5
  61. package/ui-fireui/components/u-top-dropdown/u-top-dropdown.vue +8 -6
  62. package/ui-fireui/components/u-upload/u-upload-old.vue +462 -0
  63. package/ui-fireui/components/u-upload/u-upload.vue +648 -446
  64. package/ui-fireui/components/u-white-space/u-white-space.vue +68 -0
  65. package/ui-fireui/components/u-wing-blank/u-wing-blank.vue +100 -0
  66. package/uview-plus/libs/ctocode/index.js +1 -0
  67. package/uview-plus/libs/ctocode/richText.js +0 -1
@@ -1,446 +1,648 @@
1
- <template>
2
- <view class="up-container">
3
- <view class="up-upload-box">
4
- <view class="up-image-item" v-for="(item, index) in imageList" :key="index">
5
- <image :src="item" class="up-item-img" @tap.stop="previewImage(index)" mode="aspectFill"></image>
6
- <view v-if="!forbidDel" class="up-img-del" @tap.stop="delImage(index)">
7
- <image class="del-img" src="/static/images/share/icon_del.png" mode="widthFix"></image>
8
- </view>
9
- <view v-if="statusArr[index] != 1" class="up-upload-mask">
10
- <view class="up-upload-loading" v-if="statusArr[index] == 2"></view>
11
- <text class="up-tips">{{ statusArr[index] == 2 ? '上传中...' : '上传失败' }}</text>
12
- <view
13
- class="up-mask-btn"
14
- v-if="statusArr[index] == 3"
15
- @tap.stop="reUpLoad(index)"
16
- hover-class="up-btn-hover"
17
- :hover-stay-time="150"
18
- >
19
- 重新上传
20
- </view>
21
- </view>
22
- </view>
23
- <view v-if="isShowAdd" class="up-upload-add" @tap="chooseImage">
24
- <uni-icons type="camera" size="30" color="#00AFC7" />
25
- <view class="" style="font-size: 24rpx; margin-top: 20rpx">添加</view>
26
- <!-- <image class="add-img" src="/static/images/share/ad.png" mode="widthFix"></image> -->
27
- <!-- <view class="up-upload-icon up-icon-plus"></view> -->
28
- </view>
29
- </view>
30
- </view>
31
- </template>
32
- <script>
33
- export default {
34
- name: 'fuiUpload',
35
- props: {
36
- //初始化图片路径
37
- value: {
38
- type: Array,
39
- default() {
40
- return [];
41
- }
42
- },
43
- //禁用删除
44
- forbidDel: {
45
- type: Boolean,
46
- default: false
47
- },
48
- //禁用添加
49
- forbidAdd: {
50
- type: Boolean,
51
- default: false
52
- },
53
- //服务器地址
54
- serverUrl: {
55
- type: String,
56
- default: ''
57
- },
58
- //限制数
59
- limit: {
60
- type: Number,
61
- default: 9
62
- },
63
- //original 原图,compressed 压缩图,默认二者都有
64
- sizeType: {
65
- type: Array,
66
- default() {
67
- return ['original', 'compressed'];
68
- }
69
- },
70
- //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项
71
- sourceType: {
72
- type: Array,
73
- default() {
74
- return ['album', 'camera'];
75
- }
76
- },
77
- //可上传图片类型,默认为空,不限制 Array<String> ['jpg','png','gif']
78
- imageFormat: {
79
- type: Array,
80
- default() {
81
- return [];
82
- }
83
- },
84
- //单张图片大小限制 MB
85
- size: {
86
- type: Number,
87
- default: 4
88
- },
89
- //项目名,默认为 file
90
- fileKeyName: {
91
- type: String,
92
- default: 'file'
93
- },
94
- //HTTP 请求 Header, header 中不能设置 Referer。
95
- header: {
96
- type: Object,
97
- default() {
98
- return {};
99
- }
100
- },
101
- //HTTP 请求中其他额外的 form data
102
- formData: {
103
- type: Object,
104
- default() {
105
- return {};
106
- }
107
- }
108
- },
109
- data() {
110
- return {
111
- //图片地址
112
- imageList: [],
113
- //上传状态:1-上传成功 2-上传中 3-上传失败
114
- statusArr: []
115
- };
116
- },
117
- created() {
118
- this.initImages();
119
- },
120
- watch: {
121
- value(val) {
122
- console.log('监听', val);
123
- if (val) {
124
- this.initImages();
125
- }
126
- }
127
- },
128
- computed: {
129
- isShowAdd() {
130
- let isShow = true;
131
- if (this.forbidAdd || (this.limit && this.imageList.length >= this.limit)) {
132
- isShow = false;
133
- }
134
- return isShow;
135
- }
136
- },
137
- methods: {
138
- initImages() {
139
- this.imageList = [...this.value];
140
- for (let item of this.imageList) {
141
- this.statusArr.push('1');
142
- }
143
- },
144
- // 重新上传
145
- reUpLoad(index) {
146
- this.statusArr[index] = '2';
147
- this.change();
148
- this.uploadImage(index, this.imageList[index])
149
- .then(() => {
150
- this.change();
151
- })
152
- .catch(() => {
153
- this.change();
154
- });
155
- },
156
- change() {
157
- let status = ~this.statusArr.indexOf('2') ? 2 : 1;
158
- if (status != 2 && ~this.statusArr.indexOf('3')) {
159
- // 上传失败
160
- status = 3;
161
- }
162
- this.$emit('complete', {
163
- status: status,
164
- imgArr: this.imageList
165
- });
166
- },
167
- chooseImage() {
168
- uni.chooseImage({
169
- count: this.limit - this.imageList.length,
170
- sizeType: this.sizeType,
171
- sourceType: this.sourceType,
172
- success: (e) => {
173
- let imageArr = [];
174
- for (let i = 0; i < e.tempFiles.length; i++) {
175
- let len = this.imageList.length;
176
- if (len >= this.limit) {
177
- this.showToast(`最多可上传${this.limit}张图片`);
178
- break;
179
- }
180
- //过滤图片类型
181
- let path = e.tempFiles[i].path;
182
-
183
- if (this.imageFormat.length > 0) {
184
- let format = '';
185
- // #ifdef H5
186
- let type = e.tempFiles[i].type;
187
- format = type.split('/')[1];
188
- // #endif
189
-
190
- // #ifndef H5
191
- format = path.split('.')[path.split('.').length - 1];
192
- // #endif
193
-
194
- if (this.imageFormat.indexOf(format) == -1) {
195
- let text = `只能上传 ${this.imageFormat.join(',')} 格式图片!`;
196
- this.showToast(text);
197
- continue;
198
- }
199
- }
200
-
201
- //过滤超出大小限制图片
202
- let size = e.tempFiles[i].size;
203
-
204
- if (this.size * 1024 * 1024 < size) {
205
- let err = `单张图片大小不能超过:${this.size}MB`;
206
- this.showToast(err);
207
- continue;
208
- }
209
- imageArr.push(path);
210
- this.imageList.push(path);
211
- this.statusArr.push('2');
212
- }
213
- // this.change();
214
-
215
- let start = this.imageList.length - imageArr.length;
216
- for (let j = 0; j < imageArr.length; j++) {
217
- let index = start + j;
218
- //服务器地址
219
- if (this.serverUrl) {
220
- this.uploadImage(index, imageArr[j])
221
- .then(() => {
222
- this.change();
223
- })
224
- .catch(() => {
225
- this.change();
226
- });
227
- } else {
228
- //无服务器地址则直接返回成功
229
- this.statusArr[index] = '1';
230
- this.change();
231
- }
232
- }
233
- }
234
- });
235
- },
236
- // return httpObj.flagPost('API_FILE_FILE_UPLOAD', data)
237
- uploadImage(index, url) {
238
- return new Promise((resolve, reject) => {
239
- uni.uploadFile({
240
- url: this.serverUrl,
241
- name: this.fileKeyName,
242
- header: this.header,
243
- formData: this.formData,
244
- filePath: url,
245
- success: (res) => {
246
- console.log('上传后处理数据', res);
247
- if (res.statusCode == 200) {
248
- //返回结果 此处需要按接口实际返回进行修改
249
- let d = JSON.parse(res.data.replace(/\ufeff/g, '') || '{}');
250
- //判断code,以实际接口规范判断
251
- if (d.code % 100 === 0) {
252
- // 上传成功 d.url 为上传后图片地址,以实际接口返回为准
253
- d.url && (this.imageList[index] = d.url);
254
- this.statusArr[index] = d.url ? '1' : '3';
255
- } else {
256
- // 上传失败
257
- this.statusArr[index] = '3';
258
- }
259
- resolve(index);
260
- } else {
261
- this.statusArr[index] = '3';
262
-
263
- reject(index);
264
- }
265
- },
266
- fail: (res) => {
267
- this.statusArr[index] = '3';
268
- reject(index);
269
- }
270
- });
271
- });
272
- },
273
- delImage(index) {
274
- this.imageList.splice(index, 1);
275
- this.statusArr.splice(index, 1);
276
- this.$emit('remove', {
277
- index: index
278
- });
279
- this.change();
280
- },
281
- previewImage(index) {
282
- if (!this.imageList.length) return;
283
- uni.previewImage({
284
- current: this.imageList[index],
285
- loop: true,
286
- urls: this.imageList
287
- });
288
- }
289
- }
290
- };
291
- </script>
292
-
293
- <style scoped>
294
- @font-face {
295
- font-family: 'fuiUpload';
296
- src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAATcAA0AAAAAByQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAEwAAAABoAAAAciR52BUdERUYAAASgAAAAHgAAAB4AKQALT1MvMgAAAaAAAABCAAAAVjxvR/tjbWFwAAAB+AAAAEUAAAFK5ibpuGdhc3AAAASYAAAACAAAAAj//wADZ2x5ZgAAAkwAAADXAAABAAmNjcZoZWFkAAABMAAAAC8AAAA2FpiS+WhoZWEAAAFgAAAAHQAAACQH3QOFaG10eAAAAeQAAAARAAAAEgwAACBsb2NhAAACQAAAAAwAAAAMAEoAgG1heHAAAAGAAAAAHwAAACABEgA2bmFtZQAAAyQAAAFJAAACiCnmEVVwb3N0AAAEcAAAACgAAAA6OMUs4HjaY2BkYGAAYo3boY/i+W2+MnCzMIDAzb3qdQj6fwPzf+YGIJeDgQkkCgA/KAtvAHjaY2BkYGBu+N/AEMPCAALM/xkYGVABCwBZ4wNrAAAAeNpjYGRgYGBl0GJgZgABJiDmAkIGhv9gPgMADTABSQB42mNgZGFgnMDAysDA1Ml0hoGBoR9CM75mMGLkAIoysDIzYAUBaa4pDA7PGJ9xMjf8b2CIYW5gaAAKM4LkANt9C+UAAHjaY2GAABYIVmBgAAAA+gAtAAAAeNpjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYnjE+4/z/n4EBQksxSf6GqgcCRjYGOIeRCUgwMaACRoZhDwCiLwmoAAAAAAAAAAAAAAAASgCAeNpdjkFKw0AARf/vkIR0BkPayWRKQZtYY90ohJju2kOIbtz0KD1HVm50UfEmWXoAr9ADOHFARHHzeY//Fx8Ci+FJfIgdJFa4AhgiMshbrCuIsLxhFJZVs+Vl1bT1GddtbXTC3OhohN4dg4BJ3zMJAnccyfm468ZzHXddrH9ZKbHzdf9n/vkY/xv9sPQXgGEvBrHHwst5kTbXLE+YpYVPkxepPmW94W16UbdNJd6f3SAzo5W7m1jaKd+8ZZIvk5nlKw9SK6Wle7BLS3f/bTzQLmfAF2T1NsQAeNp9kD1OAzEQhZ/zByQSQiCoXVEA2vyUKRMp9Ailo0g23pBo1155nUg5AS0VB6DlGByAGyDRcgpelkmTImvt6PObmeexAZzjGwr/3yXuhBWO8ShcwREy4Sr1F+Ea+V24jhY+hRvUf4SbuFUD4RYu1BsdVO2Eu5vSbcsKZxgIV3CKJ+Eq9ZVwjfwqXMcVPoQb1L+EmxjjV7iFa2WpDOFhMEFgnEFjig3jAjEcLJIyBtahOfRmEsxMTzd6ETubOBso71dilwMeaDnngCntPbdmvkon/mDLgdSYbh4FS7YpjS4idCgbXyyc1d2oc7D9nu22tNi/a4E1x+xRDWzU/D3bM9JIbAyvkJI18jK3pBJTj2hrrPG7ZynW814IiU68y/SIx5o0dTr3bmniwOLn8owcfbS5kj33qBw+Y1kIeb/dTsQgil2GP5PYcRkAAAB42mNgYoAALjDJyIAOWMGiTIxMjMxsKak5qSWpbFmZiRmJ+QAmgAUIAAAAAf//AAIAAQAAAAwAAAAWAAAAAgABAAMABAABAAQAAAACAAAAAHjaY2BgYGQAgqtL1DlA9M296nUwGgA+8QYgAAA=)
297
- format('woff');
298
- font-weight: normal;
299
- font-style: normal;
300
- }
301
-
302
- .up-upload-icon {
303
- font-family: 'fuiUpload' !important;
304
- font-style: normal;
305
- -webkit-font-smoothing: antialiased;
306
- -moz-osx-font-smoothing: grayscale;
307
- padding: 10rpx;
308
- }
309
-
310
- .up-icon-delete:before {
311
- content: '\e601';
312
- }
313
-
314
- .up-icon-plus:before {
315
- content: '\e609';
316
- }
317
-
318
- .up-upload-box {
319
- width: 100%;
320
- display: flex;
321
- flex-wrap: wrap;
322
- }
323
-
324
- .up-upload-add {
325
- /* width: 240rpx;
326
- height: 240rpx; */
327
- width: 178rpx;
328
- height: 178rpx;
329
- font-size: 68rpx;
330
- font-weight: 100;
331
- color: #888;
332
- /* background-color: #fff; */
333
- display: flex;
334
- flex-direction: column;
335
- align-items: center;
336
- justify-content: center;
337
- padding: 0;
338
- border-radius: 18rpx;
339
- }
340
- .add-img {
341
- width: 60rpx;
342
- height: 140rpx;
343
- }
344
- .del-img {
345
- width: 36rpx;
346
- height: 36rpx;
347
- }
348
- .up-image-item {
349
- width: 178rpx;
350
- height: 178rpx;
351
- position: relative;
352
- /* margin-right: 20rpx; */
353
- margin-right: 10rpx;
354
- margin-bottom: 20rpx;
355
- border-radius: 18rpx;
356
- }
357
-
358
- .up-image-item:nth-of-type(3n) {
359
- margin-right: 0;
360
- }
361
-
362
- .up-item-img {
363
- width: 178rpx;
364
- height: 178rpx;
365
- display: block;
366
- border-radius: 18rpx;
367
- }
368
-
369
- .up-img-del {
370
- width: 36rpx;
371
- height: 36rpx;
372
- position: absolute;
373
- right: -12rpx;
374
- top: -12rpx;
375
- /* background-color: #333333; */
376
- border-radius: 50%;
377
- color: white;
378
- font-size: 34rpx;
379
- z-index: 999;
380
- }
381
-
382
- /* .up-img-del::before {
383
- content: '';
384
- width: 16rpx;
385
- height: 1px;
386
- position: absolute;
387
- left: 10rpx;
388
- top: 18rpx;
389
- background-color: #fff;
390
- } */
391
-
392
- .up-upload-mask {
393
- width: 100%;
394
- height: 100%;
395
- position: absolute;
396
- left: 0;
397
- top: 0;
398
- display: flex;
399
- flex-direction: column;
400
- align-items: center;
401
- justify-content: space-around;
402
- padding: 40rpx 0;
403
- box-sizing: border-box;
404
- background-color: rgba(0, 0, 0, 0.6);
405
- }
406
-
407
- .up-upload-loading {
408
- width: 28rpx;
409
- height: 28rpx;
410
- border-radius: 50%;
411
- border: 2px solid;
412
- border-color: #b2b2b2 #b2b2b2 #b2b2b2 #fff;
413
- animation: up-rotate 0.7s linear infinite;
414
- }
415
-
416
- @keyframes up-rotate {
417
- 0% {
418
- transform: rotate(0);
419
- }
420
-
421
- 100% {
422
- transform: rotate(360deg);
423
- }
424
- }
425
-
426
- .up-tips {
427
- font-size: 26rpx;
428
- color: #fff;
429
- }
430
-
431
- .up-mask-btn {
432
- padding: 4rpx 16rpx;
433
- border-radius: 40rpx;
434
- text-align: center;
435
- font-size: 24rpx;
436
- color: #fff;
437
- border: 1rpx solid #fff;
438
- display: flex;
439
- align-items: center;
440
- justify-content: center;
441
- }
442
-
443
- .up-btn-hover {
444
- opacity: 0.8;
445
- }
446
- </style>
1
+ <template>
2
+ <view class="up-upload__container">
3
+ <view class="up-upload-box">
4
+ <view
5
+ class="up-image-item"
6
+ :style="{ width: width + 'rpx', height: height + 'rpx', borderRadius: radius + 'rpx' }"
7
+ v-for="(item, index) in imageList"
8
+ :key="index"
9
+ >
10
+ <image
11
+ :src="item"
12
+ class="up-item-img"
13
+ :style="{ width: width + 'rpx', height: height + 'rpx', borderRadius: radius + 'rpx' }"
14
+ @tap.stop="previewImage(index)"
15
+ mode="aspectFill"
16
+ ></image>
17
+ <view v-if="!forbidDel" class="up-img-del" :style="{ background: getDelColor }" @tap.stop="delImage(index)"></view>
18
+ <view v-if="statusArr[index] != 1" class="up-upload-mask">
19
+ <view class="up-upload-loading" v-if="statusArr[index] == 2"></view>
20
+ <text class="up-tips">{{ statusArr[index] == 2 ? '上传中...' : '上传失败' }}</text>
21
+ <view
22
+ class="up-mask-btn"
23
+ v-if="statusArr[index] == 3"
24
+ @tap.stop="reUpLoad(index)"
25
+ hover-class="up-btn-hover"
26
+ :hover-stay-time="150"
27
+ >
28
+ 重新上传
29
+ </view>
30
+ </view>
31
+ </view>
32
+ <view
33
+ v-if="isShowAdd"
34
+ class="up-upload-add"
35
+ :class="[borderColor !== 'transparent' ? 'up-upload__border' : 'up-upload__unborder']"
36
+ :style="{
37
+ width: width + 'rpx',
38
+ height: height + 'rpx',
39
+ background: background,
40
+ borderRadius: radius + 'rpx',
41
+ borderColor: borderColor,
42
+ borderStyle: borderSytle
43
+ }"
44
+ @tap="chooseImage"
45
+ >
46
+ <slot>
47
+ <view class="up-upload-icon up-icon-plus" :style="{ color: addColor, fontSize: addSize + 'rpx' }"></view>
48
+ </slot>
49
+ </view>
50
+ </view>
51
+ </view>
52
+ </template>
53
+
54
+ <script>
55
+ export default {
56
+ name: 'tuiUpload',
57
+ emits: ['remove', 'complete', 'reupload'],
58
+ props: {
59
+ //展示图片宽度
60
+ width: {
61
+ type: [Number, String],
62
+ default: 218
63
+ },
64
+ //展示图片高度
65
+ height: {
66
+ type: [Number, String],
67
+ default: 218
68
+ },
69
+ //初始化图片路径
70
+ value: {
71
+ type: Array,
72
+ default() {
73
+ return [];
74
+ }
75
+ },
76
+ //2.3.0+
77
+ radius: {
78
+ type: [Number, String],
79
+ default: 0
80
+ },
81
+ //2.3.0+
82
+ background: {
83
+ type: String,
84
+ default: '#F7F7F7'
85
+ },
86
+ //2.3.0+
87
+ borderColor: {
88
+ type: String,
89
+ default: 'transparent'
90
+ },
91
+ //2.3.0+
92
+ //solid、dashed、dotted
93
+ borderSytle: {
94
+ type: String,
95
+ default: 'dashed'
96
+ },
97
+ //2.3.0+
98
+ delColor: {
99
+ type: String,
100
+ default: ''
101
+ },
102
+ //删除图片前是否弹框确认
103
+ delConfirm: {
104
+ type: Boolean,
105
+ default: false
106
+ },
107
+ //禁用删除
108
+ forbidDel: {
109
+ type: Boolean,
110
+ default: false
111
+ },
112
+ //V2.9.6+ 删除图片是否触发 @complete 事件
113
+ delTrigger: {
114
+ type: Boolean,
115
+ default: true
116
+ },
117
+ //2.3.0+
118
+ addColor: {
119
+ type: String,
120
+ default: '#888'
121
+ },
122
+ //2.3.0+
123
+ addSize: {
124
+ type: [Number, String],
125
+ default: 68
126
+ },
127
+ //禁用添加
128
+ forbidAdd: {
129
+ type: Boolean,
130
+ default: false
131
+ },
132
+ //服务器接口地址。当接口地址为空时,直接返回本地图片地址
133
+ serverUrl: {
134
+ type: String,
135
+ default: ''
136
+ },
137
+ //限制数
138
+ limit: {
139
+ type: Number,
140
+ default: 9
141
+ },
142
+ //original 原图,compressed 压缩图,默认二者都有
143
+ sizeType: {
144
+ type: Array,
145
+ default() {
146
+ return ['original', 'compressed'];
147
+ }
148
+ },
149
+ //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项
150
+ sourceType: {
151
+ type: Array,
152
+ default() {
153
+ return ['album', 'camera'];
154
+ }
155
+ },
156
+ //可上传图片类型,默认为空,不限制 Array<String> ['jpg','png','gif']
157
+ imageFormat: {
158
+ type: Array,
159
+ default() {
160
+ return [];
161
+ }
162
+ },
163
+ //单张图片大小限制 MB
164
+ size: {
165
+ type: Number,
166
+ default: 4
167
+ },
168
+ //文件对应的key,默认为 file
169
+ fileKeyName: {
170
+ type: String,
171
+ default: 'file'
172
+ },
173
+ //HTTP 请求 Header, header 中不能设置 Referer。
174
+ header: {
175
+ type: Object,
176
+ default() {
177
+ return {};
178
+ }
179
+ },
180
+ //HTTP 请求中其他额外的 form data
181
+ formData: {
182
+ type: Object,
183
+ default() {
184
+ return {};
185
+ }
186
+ },
187
+ //自定义参数
188
+ params: {
189
+ type: [Number, String],
190
+ default: 0
191
+ }
192
+ },
193
+ data() {
194
+ return {
195
+ //图片地址
196
+ imageList: [],
197
+ tempFiles: [],
198
+ //上传状态:1-上传成功 2-上传中 3-上传失败
199
+ statusArr: [],
200
+ //传入回调函数上传
201
+ callUpload: false
202
+ };
203
+ },
204
+ created() {
205
+ this.initImages();
206
+ },
207
+ watch: {
208
+ value(val) {
209
+ if (val) {
210
+ this.initImages();
211
+ }
212
+ }
213
+ },
214
+ computed: {
215
+ isShowAdd() {
216
+ let isShow = true;
217
+ if (this.forbidAdd || (this.limit && this.imageList.length >= this.limit)) {
218
+ isShow = false;
219
+ }
220
+ return isShow;
221
+ },
222
+ getDelColor() {
223
+ return this.delColor || (uni && uni.$tui && uni.$tui.color.danger) || '#EB0909';
224
+ }
225
+ },
226
+ methods: {
227
+ initImages() {
228
+ this.statusArr = [];
229
+ this.imageList = [...this.value];
230
+ let tempFiles = [];
231
+ for (let item of this.imageList) {
232
+ this.statusArr.push('1');
233
+ tempFiles.push({
234
+ path: item
235
+ });
236
+ }
237
+ this.tempFiles = tempFiles;
238
+ },
239
+ // 重新上传
240
+ reUpLoad(index) {
241
+ this.$set(this.statusArr, index, '2');
242
+ this.$emit('reupload', {
243
+ index
244
+ });
245
+ if (!this.callUpload) {
246
+ this.uploadImage(index, this.imageList[index])
247
+ .then(() => {
248
+ this.change();
249
+ })
250
+ .catch(() => {
251
+ this.change();
252
+ });
253
+ }
254
+ },
255
+ /**
256
+ * @param manual 是否手动上传
257
+ **/
258
+ change(manual = false) {
259
+ let status = ~this.statusArr.indexOf('2') ? 2 : 1;
260
+ if (status != 2 && ~this.statusArr.indexOf('3')) {
261
+ // 上传失败
262
+ status = 3;
263
+ }
264
+ this.$emit('complete', {
265
+ status: status,
266
+ imgArr: this.imageList,
267
+ params: this.params,
268
+ manual: manual
269
+ });
270
+ },
271
+ toast(text) {
272
+ text &&
273
+ uni.showToast({
274
+ title: text,
275
+ icon: 'none'
276
+ });
277
+ },
278
+ chooseImage: function () {
279
+ let _this = this;
280
+ uni.chooseImage({
281
+ count: _this.limit - _this.imageList.length,
282
+ sizeType: _this.sizeType,
283
+ sourceType: _this.sourceType,
284
+ success: function (e) {
285
+ let imageArr = [];
286
+ for (let i = 0; i < e.tempFiles.length; i++) {
287
+ let len = _this.imageList.length;
288
+ if (len >= _this.limit) {
289
+ _this.toast(`最多可上传${_this.limit}张图片`);
290
+ break;
291
+ }
292
+ //过滤图片类型
293
+ let path = e.tempFiles[i].path;
294
+
295
+ if (_this.imageFormat.length > 0) {
296
+ let format = '';
297
+ // #ifdef H5
298
+ let type = e.tempFiles[i].type;
299
+ format = type.split('/')[1];
300
+ // #endif
301
+
302
+ // #ifndef H5
303
+ format = path.split('.')[path.split('.').length - 1];
304
+ // #endif
305
+
306
+ if (_this.imageFormat.indexOf(format) == -1) {
307
+ let text = `只能上传 ${_this.imageFormat.join(',')} 格式图片!`;
308
+ _this.toast(text);
309
+ continue;
310
+ }
311
+ }
312
+
313
+ //过滤超出大小限制图片
314
+ let size = e.tempFiles[i].size;
315
+
316
+ if (_this.size * 1024 * 1024 < size) {
317
+ let err = `单张图片大小不能超过:${_this.size}MB`;
318
+ _this.toast(err);
319
+ continue;
320
+ }
321
+ imageArr.push(path);
322
+ _this.imageList.push(path);
323
+ _this.tempFiles.push(e.tempFiles[i]);
324
+ _this.statusArr.push('2');
325
+ }
326
+ _this.change();
327
+
328
+ let start = _this.imageList.length - imageArr.length;
329
+ for (let j = 0; j < imageArr.length; j++) {
330
+ let index = start + j;
331
+ //服务器地址
332
+ if (_this.serverUrl) {
333
+ _this
334
+ .uploadImage(index, imageArr[j])
335
+ .then(() => {
336
+ _this.change();
337
+ })
338
+ .catch(() => {
339
+ _this.change();
340
+ });
341
+ } else {
342
+ //无服务器地址则直接返回成功
343
+ _this.$set(_this.statusArr, index, '1');
344
+ _this.change();
345
+ }
346
+ }
347
+ }
348
+ });
349
+ },
350
+ uploadImage: function (index, url, serverUrl) {
351
+ let _this = this;
352
+ return new Promise((resolve, reject) => {
353
+ uni.uploadFile({
354
+ url: this.serverUrl || serverUrl,
355
+ name: this.fileKeyName,
356
+ header: this.header,
357
+ formData: this.formData,
358
+ filePath: url,
359
+ success: function (res) {
360
+ if (res.statusCode == 200) {
361
+ //返回结果 此处需要按接口实际返回进行修改
362
+ let d = JSON.parse(res.data.replace(/\ufeff/g, '') || '{}');
363
+ //判断code,以实际接口规范判断
364
+ if (d.code % 100 === 0) {
365
+ // 上传成功 d.url 为上传后图片地址,以实际接口返回为准
366
+ d.url && (_this.imageList[index] = d.url);
367
+ _this.$set(_this.statusArr, index, d.url ? '1' : '3');
368
+ } else {
369
+ // 上传失败
370
+ _this.$set(_this.statusArr, index, '3');
371
+ }
372
+ resolve(index);
373
+ } else {
374
+ _this.$set(_this.statusArr, index, '3');
375
+ reject(index);
376
+ }
377
+ },
378
+ fail: function (res) {
379
+ _this.$set(_this.statusArr, index, '3');
380
+ reject(index);
381
+ }
382
+ });
383
+ });
384
+ },
385
+ delImage: function (index) {
386
+ let that = this;
387
+ if (this.delConfirm) {
388
+ uni.showModal({
389
+ title: '提示',
390
+ content: '确认删除该图片吗?',
391
+ showCancel: true,
392
+ cancelColor: '#555',
393
+ confirmColor: '#eb0909',
394
+ confirmText: '确定',
395
+ success(res) {
396
+ if (res.confirm) {
397
+ that.imageList.splice(index, 1);
398
+ that.tempFiles.splice(index, 1);
399
+ that.statusArr.splice(index, 1);
400
+ that.$emit('remove', {
401
+ index: index,
402
+ params: that.params
403
+ });
404
+ that.delTrigger && that.change();
405
+ }
406
+ }
407
+ });
408
+ } else {
409
+ that.imageList.splice(index, 1);
410
+ that.tempFiles.splice(index, 1);
411
+ that.statusArr.splice(index, 1);
412
+ that.$emit('remove', {
413
+ index: index,
414
+ params: that.params
415
+ });
416
+ that.delTrigger && that.change();
417
+ }
418
+ },
419
+ previewImage: function (index) {
420
+ if (!this.imageList.length) return;
421
+ uni.previewImage({
422
+ current: this.imageList[index],
423
+ loop: true,
424
+ urls: this.imageList
425
+ });
426
+ },
427
+ /**
428
+ * 当属性serverUrl传空时,父级调用该方法一次性上传所有图片
429
+ * @param serverUrl 服务器接口地址
430
+ **/
431
+ uploadAllImage(serverUrl) {
432
+ if (!serverUrl) {
433
+ this.toast('服务器接口地址不能为空!');
434
+ return;
435
+ }
436
+ let imageArr = [...this.imageList];
437
+ const len = imageArr.length;
438
+ for (let i = 0; i < len; i++) {
439
+ //如果是服务器地址图片则无需再次上传
440
+ if (imageArr[i].startsWith('https')) {
441
+ continue;
442
+ } else {
443
+ this.$set(this.statusArr, i, '2');
444
+ this.uploadImage(i, imageArr[i], serverUrl)
445
+ .then(() => {
446
+ if (i === len - 1) {
447
+ this.change(true);
448
+ }
449
+ })
450
+ .catch(() => {
451
+ if (i === len - 1) {
452
+ this.change(true);
453
+ }
454
+ });
455
+ }
456
+ }
457
+ },
458
+ upload(callback, index) {
459
+ // 传入一个返回Promise的文件上传的函数
460
+ //上传状态:1-上传成功 2-上传中 3-上传失败
461
+ this.callUpload = true;
462
+ if (index === undefined || index === null) {
463
+ let urls = [...this.imageList];
464
+ const len = urls.length;
465
+ for (let i = 0; i < len; i++) {
466
+ if (urls[i].startsWith('https')) {
467
+ continue;
468
+ } else {
469
+ this.$set(this.statusArr, i, '2');
470
+ if (typeof callback === 'function') {
471
+ callback(this.tempFiles[i])
472
+ .then((res) => {
473
+ this.$set(this.statusArr, i, '1');
474
+ this.imageList[i] = res;
475
+ this.change(true);
476
+ })
477
+ .catch((err) => {
478
+ this.$set(this.statusArr, i, '3');
479
+ });
480
+ }
481
+ }
482
+ }
483
+ } else {
484
+ //如果传入index,则是重新上传时调用
485
+ this.$set(this.statusArr, index, '2');
486
+ if (typeof callback === 'function') {
487
+ callback(this.tempFiles[index])
488
+ .then((res) => {
489
+ this.$set(this.statusArr, index, '1');
490
+ this.imageList[index] = res;
491
+ this.change(true);
492
+ })
493
+ .catch((err) => {
494
+ this.$set(this.statusArr, index, '3');
495
+ });
496
+ }
497
+ }
498
+ }
499
+ }
500
+ };
501
+ </script>
502
+
503
+ <style scoped>
504
+ @font-face {
505
+ font-family: 'tuiUpload';
506
+ src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAATcAA0AAAAAByQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAEwAAAABoAAAAciR52BUdERUYAAASgAAAAHgAAAB4AKQALT1MvMgAAAaAAAABCAAAAVjxvR/tjbWFwAAAB+AAAAEUAAAFK5ibpuGdhc3AAAASYAAAACAAAAAj//wADZ2x5ZgAAAkwAAADXAAABAAmNjcZoZWFkAAABMAAAAC8AAAA2FpiS+WhoZWEAAAFgAAAAHQAAACQH3QOFaG10eAAAAeQAAAARAAAAEgwAACBsb2NhAAACQAAAAAwAAAAMAEoAgG1heHAAAAGAAAAAHwAAACABEgA2bmFtZQAAAyQAAAFJAAACiCnmEVVwb3N0AAAEcAAAACgAAAA6OMUs4HjaY2BkYGAAYo3boY/i+W2+MnCzMIDAzb3qdQj6fwPzf+YGIJeDgQkkCgA/KAtvAHjaY2BkYGBu+N/AEMPCAALM/xkYGVABCwBZ4wNrAAAAeNpjYGRgYGBl0GJgZgABJiDmAkIGhv9gPgMADTABSQB42mNgZGFgnMDAysDA1Ml0hoGBoR9CM75mMGLkAIoysDIzYAUBaa4pDA7PGJ9xMjf8b2CIYW5gaAAKM4LkANt9C+UAAHjaY2GAABYIVmBgAAAA+gAtAAAAeNpjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYnjE+4/z/n4EBQksxSf6GqgcCRjYGOIeRCUgwMaACRoZhDwCiLwmoAAAAAAAAAAAAAAAASgCAeNpdjkFKw0AARf/vkIR0BkPayWRKQZtYY90ohJju2kOIbtz0KD1HVm50UfEmWXoAr9ADOHFARHHzeY//Fx8Ci+FJfIgdJFa4AhgiMshbrCuIsLxhFJZVs+Vl1bT1GddtbXTC3OhohN4dg4BJ3zMJAnccyfm468ZzHXddrH9ZKbHzdf9n/vkY/xv9sPQXgGEvBrHHwst5kTbXLE+YpYVPkxepPmW94W16UbdNJd6f3SAzo5W7m1jaKd+8ZZIvk5nlKw9SK6Wle7BLS3f/bTzQLmfAF2T1NsQAeNp9kD1OAzEQhZ/zByQSQiCoXVEA2vyUKRMp9Ailo0g23pBo1155nUg5AS0VB6DlGByAGyDRcgpelkmTImvt6PObmeexAZzjGwr/3yXuhBWO8ShcwREy4Sr1F+Ea+V24jhY+hRvUf4SbuFUD4RYu1BsdVO2Eu5vSbcsKZxgIV3CKJ+Eq9ZVwjfwqXMcVPoQb1L+EmxjjV7iFa2WpDOFhMEFgnEFjig3jAjEcLJIyBtahOfRmEsxMTzd6ETubOBso71dilwMeaDnngCntPbdmvkon/mDLgdSYbh4FS7YpjS4idCgbXyyc1d2oc7D9nu22tNi/a4E1x+xRDWzU/D3bM9JIbAyvkJI18jK3pBJTj2hrrPG7ZynW814IiU68y/SIx5o0dTr3bmniwOLn8owcfbS5kj33qBw+Y1kIeb/dTsQgil2GP5PYcRkAAAB42mNgYoAALjDJyIAOWMGiTIxMjMxsKak5qSWpbFmZiRmJ+QAmgAUIAAAAAf//AAIAAQAAAAwAAAAWAAAAAgABAAMABAABAAQAAAACAAAAAHjaY2BgYGQAgqtL1DlA9M296nUwGgA+8QYgAAA=)
507
+ format('woff');
508
+ font-weight: normal;
509
+ font-style: normal;
510
+ }
511
+
512
+ .up-upload-icon {
513
+ font-family: 'tuiUpload' !important;
514
+ font-style: normal;
515
+ -webkit-font-smoothing: antialiased;
516
+ -moz-osx-font-smoothing: grayscale;
517
+ padding: 10rpx;
518
+ }
519
+
520
+ .up-icon-delete:before {
521
+ content: '\e601';
522
+ }
523
+
524
+ .up-icon-plus:before {
525
+ content: '\e609';
526
+ }
527
+
528
+ .up-upload-box {
529
+ width: 100%;
530
+ display: flex;
531
+ flex-wrap: wrap;
532
+ }
533
+
534
+ .up-upload-add {
535
+ font-weight: 100;
536
+ display: flex;
537
+ align-items: center;
538
+ justify-content: center;
539
+ padding: 0;
540
+ overflow: hidden;
541
+ box-sizing: border-box;
542
+ /* #ifdef H5 */
543
+ cursor: pointer;
544
+ /* #endif */
545
+ }
546
+
547
+ .up-upload__unborder {
548
+ border-width: 0;
549
+ }
550
+
551
+ .up-upload__border {
552
+ border-width: 1px;
553
+ }
554
+
555
+ .up-image-item {
556
+ position: relative;
557
+ margin-right: 20rpx;
558
+ margin-bottom: 20rpx;
559
+ flex-shrink: 0;
560
+ }
561
+
562
+ .up-item-img {
563
+ display: block;
564
+ }
565
+
566
+ .up-img-del {
567
+ width: 36rpx;
568
+ height: 36rpx;
569
+ position: absolute;
570
+ right: -12rpx;
571
+ top: -12rpx;
572
+ border-radius: 50%;
573
+ color: white;
574
+ font-size: 34rpx;
575
+ z-index: 5;
576
+ /* #ifdef H5 */
577
+ cursor: pointer;
578
+ /* #endif */
579
+ }
580
+
581
+ .up-img-del::before {
582
+ content: '';
583
+ width: 16rpx;
584
+ height: 1px;
585
+ position: absolute;
586
+ left: 10rpx;
587
+ top: 18rpx;
588
+ background-color: #fff;
589
+ }
590
+
591
+ .up-upload-mask {
592
+ width: 100%;
593
+ height: 100%;
594
+ position: absolute;
595
+ left: 0;
596
+ top: 0;
597
+ display: flex;
598
+ flex-direction: column;
599
+ align-items: center;
600
+ justify-content: center;
601
+ padding: 40rpx 0;
602
+ box-sizing: border-box;
603
+ background-color: rgba(0, 0, 0, 0.6);
604
+ z-index: 3;
605
+ }
606
+
607
+ .up-upload-loading {
608
+ width: 28rpx;
609
+ height: 28rpx;
610
+ border-radius: 50%;
611
+ border: 2px solid;
612
+ border-color: #b2b2b2 #b2b2b2 #b2b2b2 #fff;
613
+ animation: up-rotate 0.7s linear infinite;
614
+ }
615
+
616
+ @keyframes up-rotate {
617
+ 0% {
618
+ transform: rotate(0);
619
+ }
620
+
621
+ 100% {
622
+ transform: rotate(360deg);
623
+ }
624
+ }
625
+
626
+ .up-tips {
627
+ font-size: 26rpx;
628
+ color: #fff;
629
+ }
630
+
631
+ .up-mask-btn {
632
+ padding: 4rpx 16rpx;
633
+ border-radius: 40rpx;
634
+ text-align: center;
635
+ font-size: 24rpx;
636
+ color: #fff;
637
+ border: 1px solid #fff;
638
+ display: flex;
639
+ align-items: center;
640
+ justify-content: center;
641
+ flex-shrink: 0;
642
+ margin-top: 26rpx;
643
+ }
644
+
645
+ .up-btn-hover {
646
+ opacity: 0.8;
647
+ }
648
+ </style>