xydata-tools 1.0.45 → 1.0.47
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.
- package/dist/components/uni-app/file-picker/file-picker.vue +9 -2
- package/dist/components/uni-app/file-picker/styles.scss +2 -2
- package/dist/components/uni-app/media-picker/media-picker.vue +64 -23
- package/dist/components/uni-app/media-picker/shmily-drag-media.vue +97 -60
- package/dist/components/uni-app/media-picker/styles.scss +460 -459
- package/package.json +9 -26
|
@@ -178,8 +178,6 @@ export default {
|
|
|
178
178
|
case 'jpeg':
|
|
179
179
|
case 'jpg':
|
|
180
180
|
case 'gif':
|
|
181
|
-
case 'webp':
|
|
182
|
-
case 'svg':
|
|
183
181
|
return require('../../../assets/file-icon/image.png')
|
|
184
182
|
case 'mp4':
|
|
185
183
|
case 'mov':
|
|
@@ -515,6 +513,15 @@ export default {
|
|
|
515
513
|
const ext = this.getFileExtension(file.name)
|
|
516
514
|
const supportedTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
|
|
517
515
|
const isDocument = supportedTypes.includes(ext)
|
|
516
|
+
|
|
517
|
+
const imageTypes = ['png', 'jpeg', 'jpg', 'gif']
|
|
518
|
+
console.log(ext)
|
|
519
|
+
if (imageTypes.includes(ext)) {
|
|
520
|
+
uni.previewImage({
|
|
521
|
+
urls: [file.url]
|
|
522
|
+
})
|
|
523
|
+
return
|
|
524
|
+
}
|
|
518
525
|
|
|
519
526
|
// 显示加载提示
|
|
520
527
|
uni.showLoading({
|
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
<view v-if="enableImage && showFileList" class="media-section">
|
|
9
9
|
<shmily-drag-media v-if="imageFileList.length > 0" v-model="imageUrls" :number="imageLimit"
|
|
10
10
|
:cols="cols" :imageWidth="itemWidth" :padding="10" :borderRadius="itemBorderRadius"
|
|
11
|
-
:
|
|
12
|
-
@update:modelValue="handleImageDragChange">
|
|
11
|
+
:draggable="draggable" moveType="image" @update:modelValue="handleImageDragChange">
|
|
13
12
|
</shmily-drag-media>
|
|
14
13
|
</view>
|
|
15
14
|
|
|
@@ -18,8 +17,8 @@
|
|
|
18
17
|
:style="{ marginTop: enableImage && videoFileList.length > 0 ? '20rpx' : '0' }">
|
|
19
18
|
<shmily-drag-media v-if="videoFileList.length > 0" v-model="videoUrls" :number="videoLimit"
|
|
20
19
|
:cols="cols" :imageWidth="itemWidth" :padding="10" :borderRadius="itemBorderRadius"
|
|
21
|
-
:
|
|
22
|
-
@
|
|
20
|
+
:draggable="draggable" moveType="video" @update:modelValue="handleVideoDragChange"
|
|
21
|
+
@videoClick="handleVideoItemClick">
|
|
23
22
|
</shmily-drag-media>
|
|
24
23
|
</view>
|
|
25
24
|
|
|
@@ -29,8 +28,8 @@
|
|
|
29
28
|
<view v-if="enableImage" class="upload-button-wrapper">
|
|
30
29
|
<slot name="image-upload-button" :select="selectAndUploadImage" :limit="imageLimit"
|
|
31
30
|
:count="imageFileList.length">
|
|
32
|
-
<view class="upload-btn-vertical"
|
|
33
|
-
@click="selectAndUploadImage">
|
|
31
|
+
<view class="upload-btn-vertical" :style="{ borderRadius: itemBorderRadius + 'rpx' }"
|
|
32
|
+
v-if="imageFileList.length < imageLimit" @click="selectAndUploadImage">
|
|
34
33
|
<image :src="imageUploadIcon" class="upload-icon"></image>
|
|
35
34
|
<view class="upload-text">{{ imageButtonTitle }}</view>
|
|
36
35
|
</view>
|
|
@@ -41,8 +40,8 @@
|
|
|
41
40
|
<view v-if="enableVideo" class="upload-button-wrapper">
|
|
42
41
|
<slot name="video-upload-button" :select="selectAndUploadVideo" :limit="videoLimit"
|
|
43
42
|
:count="videoFileList.length">
|
|
44
|
-
<view class="upload-btn-vertical"
|
|
45
|
-
@click="selectAndUploadVideo">
|
|
43
|
+
<view class="upload-btn-vertical" :style="{ borderRadius: itemBorderRadius + 'rpx' }"
|
|
44
|
+
v-if="videoFileList.length < videoLimit" @click="selectAndUploadVideo">
|
|
46
45
|
<image :src="videoUploadIcon" class="upload-icon"></image>
|
|
47
46
|
<view class="upload-text">{{ videoButtonTitle }}</view>
|
|
48
47
|
</view>
|
|
@@ -57,15 +56,15 @@
|
|
|
57
56
|
<shmily-drag-media v-if="enableImage && !enableVideo && showFileList" v-model="imageUrls"
|
|
58
57
|
:number="imageLimit" :cols="cols" :imageWidth="itemWidth" :padding="10"
|
|
59
58
|
:borderRadius="itemBorderRadius" :align="align" :draggable="draggable" :enableAddButton="true"
|
|
60
|
-
moveType="image" @update:modelValue="handleImageDragChange"
|
|
61
|
-
<template #add-button>
|
|
59
|
+
moveType="image" @update:modelValue="handleImageDragChange">
|
|
60
|
+
<template #add-button="{ childWidth }">
|
|
62
61
|
<slot name="image-upload-button" :select="selectAndUploadImage" :limit="imageLimit"
|
|
63
62
|
:count="imageFileList.length">
|
|
64
|
-
<view class="drag-upload-btn">
|
|
63
|
+
<view class="drag-upload-btn" @click="selectAndUploadImage">
|
|
65
64
|
<image :src="imageUploadIcon" class="upload-icon"
|
|
66
|
-
:style="
|
|
67
|
-
<view class="upload-text" :style="{
|
|
68
|
-
|
|
65
|
+
:style="getUploadIconStyle(childWidth)"></image>
|
|
66
|
+
<view class="upload-text" :style="getUploadTextStyle(childWidth)">{{ imageButtonTitle }}
|
|
67
|
+
</view>
|
|
69
68
|
</view>
|
|
70
69
|
</slot>
|
|
71
70
|
</template>
|
|
@@ -75,16 +74,15 @@
|
|
|
75
74
|
<shmily-drag-media v-else-if="enableVideo && !enableImage && showFileList" v-model="videoUrls"
|
|
76
75
|
:number="videoLimit" :cols="cols" :imageWidth="itemWidth" :padding="10"
|
|
77
76
|
:borderRadius="itemBorderRadius" :align="align" :draggable="draggable" :enableAddButton="true"
|
|
78
|
-
moveType="video" @update:modelValue="handleVideoDragChange" @
|
|
79
|
-
|
|
80
|
-
<template #add-button>
|
|
77
|
+
moveType="video" @update:modelValue="handleVideoDragChange" @videoClick="handleVideoItemClick">
|
|
78
|
+
<template #add-button="{ childWidth }">
|
|
81
79
|
<slot name="video-upload-button" :select="selectAndUploadVideo" :limit="videoLimit"
|
|
82
80
|
:count="videoFileList.length">
|
|
83
|
-
<view class="drag-upload-btn">
|
|
81
|
+
<view class="drag-upload-btn" @click="selectAndUploadVideo">
|
|
84
82
|
<image :src="videoUploadIcon" class="upload-icon"
|
|
85
|
-
:style="
|
|
86
|
-
<view class="upload-text" :style="{
|
|
87
|
-
|
|
83
|
+
:style="getUploadIconStyle(childWidth)"></image>
|
|
84
|
+
<view class="upload-text" :style="getUploadTextStyle(childWidth)">{{ videoButtonTitle }}
|
|
85
|
+
</view>
|
|
88
86
|
</view>
|
|
89
87
|
</slot>
|
|
90
88
|
</template>
|
|
@@ -198,7 +196,7 @@ export default {
|
|
|
198
196
|
/** 上传类型: 'image' - 仅图片, 'video' - 仅视频, 'both' - 图片+视频(必填) */
|
|
199
197
|
uploadType: {
|
|
200
198
|
type: String,
|
|
201
|
-
|
|
199
|
+
default: 'image',
|
|
202
200
|
validator: (value) => ['image', 'video', 'both'].includes(value)
|
|
203
201
|
},
|
|
204
202
|
/** 上传地址 */
|
|
@@ -335,6 +333,7 @@ export default {
|
|
|
335
333
|
popupAnimated: false,
|
|
336
334
|
mediaLoadingStatus: {},
|
|
337
335
|
fullscreenVideoSrc: '', // 专门用于全屏播放的视频源
|
|
336
|
+
windowWidth: uni.getSystemInfoSync ? uni.getSystemInfoSync().windowWidth : 375,
|
|
338
337
|
}
|
|
339
338
|
},
|
|
340
339
|
computed: {
|
|
@@ -457,7 +456,7 @@ export default {
|
|
|
457
456
|
},
|
|
458
457
|
|
|
459
458
|
// ==================== 弹窗模式网格样式 ====================
|
|
460
|
-
popupGridStyle() {
|
|
459
|
+
popupGridStyle() {
|
|
461
460
|
return {
|
|
462
461
|
gridTemplateColumns: `repeat(${this.cols}, 1fr)`,
|
|
463
462
|
gap: '10rpx'
|
|
@@ -493,6 +492,48 @@ export default {
|
|
|
493
492
|
hasEventListener(eventName) {
|
|
494
493
|
return !!(this.$listeners && this.$listeners[eventName])
|
|
495
494
|
},
|
|
495
|
+
parseChildWidth(childWidth) {
|
|
496
|
+
if (typeof childWidth === 'number') {
|
|
497
|
+
return childWidth
|
|
498
|
+
}
|
|
499
|
+
if (typeof childWidth === 'string') {
|
|
500
|
+
const parsed = parseFloat(childWidth)
|
|
501
|
+
return Number.isFinite(parsed) ? parsed : null
|
|
502
|
+
}
|
|
503
|
+
return null
|
|
504
|
+
},
|
|
505
|
+
pxToRpx(px) {
|
|
506
|
+
if (!px || !this.windowWidth) {
|
|
507
|
+
return 0
|
|
508
|
+
}
|
|
509
|
+
return px / this.windowWidth * 750
|
|
510
|
+
},
|
|
511
|
+
computeUploadIconSize(childWidth) {
|
|
512
|
+
const parsedPx = this.parseChildWidth(childWidth)
|
|
513
|
+
if (!parsedPx) {
|
|
514
|
+
return this.uploadIconSize
|
|
515
|
+
}
|
|
516
|
+
const widthRpx = this.pxToRpx(parsedPx)
|
|
517
|
+
const size = Math.floor(widthRpx * 0.3)
|
|
518
|
+
return Math.max(20, size)
|
|
519
|
+
},
|
|
520
|
+
computeUploadTextSize(childWidth) {
|
|
521
|
+
const iconSize = this.computeUploadIconSize(childWidth)
|
|
522
|
+
const size = Math.floor(iconSize * 0.4)
|
|
523
|
+
return Math.max(20, size)
|
|
524
|
+
},
|
|
525
|
+
getUploadIconStyle(childWidth) {
|
|
526
|
+
const size = this.computeUploadIconSize(childWidth)
|
|
527
|
+
return {
|
|
528
|
+
width: size + 'rpx',
|
|
529
|
+
height: size + 'rpx'
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
getUploadTextStyle(childWidth) {
|
|
533
|
+
return {
|
|
534
|
+
fontSize: this.computeUploadTextSize(childWidth) + 'rpx'
|
|
535
|
+
}
|
|
536
|
+
},
|
|
496
537
|
|
|
497
538
|
// ==================== 图片相关方法 ====================
|
|
498
539
|
/**
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
<template v-if="viewWidth">
|
|
4
4
|
<movable-area class="area" :style="{ height: areaHeight }" @mouseenter="mouseenter"
|
|
5
5
|
@mouseleave="mouseleave">
|
|
6
|
-
<movable-view
|
|
6
|
+
<movable-view v-for="(item, index) in imageList" :key="item.id" class="view" direction="all" :y="item.y"
|
|
7
7
|
:x="item.x" :damping="40" :disabled="!draggable" @change="onChange($event, item)"
|
|
8
8
|
@touchstart="touchstart(item)" @mousedown="touchstart(item)" @touchend="touchend($event, item)"
|
|
9
|
-
@mouseup="touchend($event, item)" :style="{
|
|
9
|
+
@click="handleClick(item)" @mouseup="touchend($event, item)" :style="{
|
|
10
10
|
width: viewWidth + 'px',
|
|
11
11
|
height: viewWidth + 'px',
|
|
12
12
|
'z-index': item.zIndex,
|
|
@@ -18,9 +18,14 @@
|
|
|
18
18
|
borderRadius: borderRadius + 'rpx',
|
|
19
19
|
transform: 'scale(' + item.scale + ')'
|
|
20
20
|
}">
|
|
21
|
-
<image v-if="moveType === 'image'" class="pre-image" :src="item.src" mode="aspectFill"
|
|
21
|
+
<image v-if="moveType === 'image'" class="pre-image" :src="item.src" mode="aspectFill"
|
|
22
|
+
@load="handleMediaLoad(item)" @error="handleMediaError(item)"></image>
|
|
22
23
|
<video v-else-if="moveType === 'video'" :id="'readonlyVideo' + index" class="myVideo"
|
|
23
|
-
:src="item.src" :controls="false" :show-center-play-btn="true" object-fit="cover"
|
|
24
|
+
:src="item.src" :controls="false" :show-center-play-btn="true" object-fit="cover"
|
|
25
|
+
@loadedmetadata="handleMediaLoad(item)" @error="handleMediaError(item)"></video>
|
|
26
|
+
<view class="media-loading-overlay" v-if="item.loading">
|
|
27
|
+
<view class="loading-spinner"></view>
|
|
28
|
+
</view>
|
|
24
29
|
<view class="del-con" @click="delImages(item, index)" @touchstart.stop="delImageMp(item, index)"
|
|
25
30
|
@touchend.stop="nothing()" @mousedown.stop="nothing()" @mouseup.stop="nothing()">
|
|
26
31
|
<view class="del-wrap">
|
|
@@ -33,16 +38,10 @@
|
|
|
33
38
|
</movable-view>
|
|
34
39
|
<!-- 添加按钮或自定义插槽 -->
|
|
35
40
|
<view class="add" v-if="imageList.length < number && showAddButton"
|
|
36
|
-
:style="{ top: add.y, left: add.x, width: viewWidth + 'px', height: viewWidth + 'px' }"
|
|
37
|
-
@click="addImages">
|
|
41
|
+
:style="{ top: add.y, left: add.x, width: viewWidth + 'px', height: viewWidth + 'px' }">
|
|
38
42
|
<view class="add-wrap"
|
|
39
43
|
:style="{ width: childWidth, height: childWidth, borderRadius: borderRadius + 'rpx' }">
|
|
40
|
-
<slot name="add-button" :childWidth="childWidth" :borderRadius="borderRadius">
|
|
41
|
-
<!-- 默认添加按钮 -->
|
|
42
|
-
<image style="width: 54rpx;height: 54rpx;"
|
|
43
|
-
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADYAAAA2CAYAAACMRWrdAAABIUlEQVRoQ+2a2w2DMAxFeQzWrsMUbadAsEw3S1CqVgppKwLX8BEOP4iHTXx8uUgWdVXoVhdaV0VhSmf7vr/H8V3XzY6V3P9iD+nYOI5P7/01LMI596AwoZV0TIBXIUWFXhKLFBWYSFGhhxQN6SFFQ5i4ogITKSr0cEVDekjRECauqMBEigq9U7piOk2yAti27SUe5ljlTfPEQ6KZecTvwl4P3ytvOv06R2HDMNzes7+6aRrvnHvtf50L13Lp50rx88zcvNlS3JpwKQ67XyK04nq2nFbk/LqVjin0TvmBNgQ2S4UUDcliHgpMpKjQwxUN6SFFQ5i4ogITKSr0cEVDekjRECauqMAsVoph+hVPtYr5+03p9tbYQ96xrYtT4ootbAJGVxxVTapVswAAAABJRU5ErkJggg==">
|
|
44
|
-
</image>
|
|
45
|
-
</slot>
|
|
44
|
+
<slot name="add-button" :childWidth="childWidth" :borderRadius="borderRadius"></slot>
|
|
46
45
|
</view>
|
|
47
46
|
</view>
|
|
48
47
|
</movable-area>
|
|
@@ -129,18 +128,18 @@ export default {
|
|
|
129
128
|
type: Boolean,
|
|
130
129
|
default: false
|
|
131
130
|
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
// 对齐方式:'left' 从左往右排列,'right' 从右往左排列
|
|
132
|
+
align: {
|
|
133
|
+
type: String,
|
|
134
|
+
default: 'left',
|
|
135
|
+
validator: (value) => ['left', 'right'].includes(value)
|
|
136
|
+
},
|
|
137
|
+
// 是否可以拖拽排序
|
|
138
|
+
draggable: {
|
|
139
|
+
type: Boolean,
|
|
140
|
+
default: true
|
|
141
|
+
},
|
|
142
|
+
},
|
|
144
143
|
data() {
|
|
145
144
|
return {
|
|
146
145
|
imageList: [],
|
|
@@ -274,7 +273,7 @@ export default {
|
|
|
274
273
|
*/
|
|
275
274
|
calculatePosition(index, total) {
|
|
276
275
|
const absY = Math.floor(index / this.colsValue)
|
|
277
|
-
|
|
276
|
+
|
|
278
277
|
if (this.align === 'right') {
|
|
279
278
|
// 靠右对齐:计算当前行的元素数量(包括按钮),然后从右往左排列
|
|
280
279
|
const currentRowItemCount = Math.min(total - absY * this.colsValue, this.colsValue)
|
|
@@ -306,7 +305,7 @@ export default {
|
|
|
306
305
|
const theoreticalWidth = this.viewWidth * this.colsValue
|
|
307
306
|
this.rightAlignOffset = Math.max(0, this.containerWidth - theoreticalWidth)
|
|
308
307
|
},
|
|
309
|
-
|
|
308
|
+
|
|
310
309
|
/**
|
|
311
310
|
* 获取总数(如果显示添加按钮,则包括按钮)
|
|
312
311
|
*/
|
|
@@ -317,7 +316,7 @@ export default {
|
|
|
317
316
|
}
|
|
318
317
|
return this.imageList.length
|
|
319
318
|
},
|
|
320
|
-
|
|
319
|
+
|
|
321
320
|
getSrc(item) {
|
|
322
321
|
if (this.keyName !== null) {
|
|
323
322
|
return item[this.keyName]
|
|
@@ -356,6 +355,8 @@ export default {
|
|
|
356
355
|
this.$nextTick(() => {
|
|
357
356
|
obj.x = this.getAlignedX(obj.absX)
|
|
358
357
|
obj.y = obj.absY * this.viewWidth
|
|
358
|
+
obj.oldX = obj.x
|
|
359
|
+
obj.oldY = obj.y
|
|
359
360
|
})
|
|
360
361
|
}, 0)
|
|
361
362
|
}
|
|
@@ -370,6 +371,8 @@ export default {
|
|
|
370
371
|
this.$nextTick(() => {
|
|
371
372
|
item.x = this.getAlignedX(item.absX)
|
|
372
373
|
item.y = item.absY * this.viewWidth
|
|
374
|
+
item.oldX = item.x
|
|
375
|
+
item.oldY = item.y
|
|
373
376
|
})
|
|
374
377
|
}, 0)
|
|
375
378
|
}
|
|
@@ -390,6 +393,8 @@ export default {
|
|
|
390
393
|
this.$nextTick(() => {
|
|
391
394
|
obj.x = this.getAlignedX(obj.absX)
|
|
392
395
|
obj.y = obj.absY * this.viewWidth
|
|
396
|
+
obj.oldX = obj.x
|
|
397
|
+
obj.oldY = obj.y
|
|
393
398
|
})
|
|
394
399
|
}, 0)
|
|
395
400
|
},
|
|
@@ -398,7 +403,7 @@ export default {
|
|
|
398
403
|
if (!this.draggable) {
|
|
399
404
|
return
|
|
400
405
|
}
|
|
401
|
-
|
|
406
|
+
|
|
402
407
|
this.imageList.forEach(v => {
|
|
403
408
|
v.zIndex = v.index + 9
|
|
404
409
|
})
|
|
@@ -412,6 +417,16 @@ export default {
|
|
|
412
417
|
this.timer = null
|
|
413
418
|
}, 200)
|
|
414
419
|
},
|
|
420
|
+
handleClick(item) {
|
|
421
|
+
// 设为disable后无法触发touch事件
|
|
422
|
+
if (!this.draggable) {
|
|
423
|
+
if (this.moveType === 'video') {
|
|
424
|
+
this.playVideo(item)
|
|
425
|
+
} else {
|
|
426
|
+
this.previewImage(item)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
},
|
|
415
430
|
touchend(event, item) {
|
|
416
431
|
const eventType = event.type // 'touchend' 或 'mouseup'
|
|
417
432
|
|
|
@@ -420,7 +435,7 @@ export default {
|
|
|
420
435
|
this.lastTouchEndTime = Date.now()
|
|
421
436
|
} else if (eventType === 'mouseup') {
|
|
422
437
|
// 如果 100ms 内已经处理过 touchend,则忽略此 mouseup(避免重复)
|
|
423
|
-
if (this.lastTouchEndTime && Date.now() - this.lastTouchEndTime < 100) {
|
|
438
|
+
if (this.lastTouchEndTime && Date.now() - this.lastTouchEndTime < 100) {
|
|
424
439
|
if (this.timer) {
|
|
425
440
|
clearTimeout(this.timer)
|
|
426
441
|
this.timer = null
|
|
@@ -454,6 +469,8 @@ export default {
|
|
|
454
469
|
this.$nextTick(() => {
|
|
455
470
|
item.x = this.getAlignedX(item.absX)
|
|
456
471
|
item.y = item.absY * this.viewWidth
|
|
472
|
+
item.oldX = item.x
|
|
473
|
+
item.oldY = item.y
|
|
457
474
|
this.tempItem = null
|
|
458
475
|
this.changeStatus = true
|
|
459
476
|
})
|
|
@@ -512,6 +529,8 @@ export default {
|
|
|
512
529
|
this.$nextTick(() => {
|
|
513
530
|
v.x = this.getAlignedX(v.absX)
|
|
514
531
|
v.y = v.absY * this.viewWidth
|
|
532
|
+
v.oldX = v.x
|
|
533
|
+
v.oldY = v.y
|
|
515
534
|
this.tempItem = null
|
|
516
535
|
})
|
|
517
536
|
}
|
|
@@ -520,30 +539,6 @@ export default {
|
|
|
520
539
|
}
|
|
521
540
|
//#endif
|
|
522
541
|
},
|
|
523
|
-
addImages() {
|
|
524
|
-
// 如果显示添加按钮,触发自定义事件让父组件处理
|
|
525
|
-
if (this.showAddButton) {
|
|
526
|
-
this.$emit('add-click')
|
|
527
|
-
return
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (typeof this.addImage === 'function') {
|
|
531
|
-
this.addImage.bind(this.$parent)()
|
|
532
|
-
} else {
|
|
533
|
-
let checkNumber = this.number - this.imageList.length
|
|
534
|
-
uni.chooseImage({
|
|
535
|
-
count: checkNumber,
|
|
536
|
-
sourceType: ['album', 'camera'],
|
|
537
|
-
success: res => {
|
|
538
|
-
let count = checkNumber <= res.tempFilePaths.length ? checkNumber : res.tempFilePaths.length
|
|
539
|
-
for (let i = 0; i < count; i++) {
|
|
540
|
-
this.addProperties(res.tempFilePaths[i])
|
|
541
|
-
}
|
|
542
|
-
this.sortList()
|
|
543
|
-
}
|
|
544
|
-
})
|
|
545
|
-
}
|
|
546
|
-
},
|
|
547
542
|
delImages(item, index) {
|
|
548
543
|
if (typeof this.delImage === 'function') {
|
|
549
544
|
this.delImage.bind(this.$parent)(() => {
|
|
@@ -621,7 +616,7 @@ export default {
|
|
|
621
616
|
},
|
|
622
617
|
addProperties(item) {
|
|
623
618
|
const newIndex = this.imageList.length
|
|
624
|
-
|
|
619
|
+
|
|
625
620
|
// 先添加图片到列表
|
|
626
621
|
this.imageList.push({
|
|
627
622
|
src: item,
|
|
@@ -638,9 +633,10 @@ export default {
|
|
|
638
633
|
id: this.guid(16),
|
|
639
634
|
disable: false,
|
|
640
635
|
offset: 0,
|
|
641
|
-
moveEnd: false
|
|
636
|
+
moveEnd: false,
|
|
637
|
+
loading: true
|
|
642
638
|
})
|
|
643
|
-
|
|
639
|
+
|
|
644
640
|
// 如果是右对齐且显示按钮,添加新图片后需要重新计算所有图片位置
|
|
645
641
|
if (this.align === 'right' && this.showAddButton) {
|
|
646
642
|
this.recalculateAllPositions()
|
|
@@ -656,10 +652,10 @@ export default {
|
|
|
656
652
|
obj.oldX = obj.x
|
|
657
653
|
obj.oldY = obj.y
|
|
658
654
|
}
|
|
659
|
-
|
|
655
|
+
|
|
660
656
|
this.updateAddButtonPosition()
|
|
661
657
|
},
|
|
662
|
-
|
|
658
|
+
|
|
663
659
|
/**
|
|
664
660
|
* 重新计算所有图片的位置(用于右对齐时添加/删除图片)
|
|
665
661
|
*/
|
|
@@ -669,7 +665,7 @@ export default {
|
|
|
669
665
|
const pos = this.calculatePosition(i, totalWithButton)
|
|
670
666
|
const newX = this.getAlignedX(pos.absX)
|
|
671
667
|
const newY = pos.absY * this.viewWidth
|
|
672
|
-
|
|
668
|
+
|
|
673
669
|
// 如果位置有变化,进行动画过渡
|
|
674
670
|
if (obj.absX !== pos.absX || obj.absY !== pos.absY) {
|
|
675
671
|
obj.x = obj.oldX
|
|
@@ -711,7 +707,7 @@ export default {
|
|
|
711
707
|
return
|
|
712
708
|
}
|
|
713
709
|
const length = this.imageList.length
|
|
714
|
-
|
|
710
|
+
|
|
715
711
|
if (this.align === 'right' && this.showAddButton) {
|
|
716
712
|
// 右对齐且显示按钮:按钮的位置就是"虚拟的第 length 个元素"的位置
|
|
717
713
|
// 总数包括按钮本身
|
|
@@ -726,6 +722,14 @@ export default {
|
|
|
726
722
|
this.add.x = this.getAlignedX(absX) + 'px'
|
|
727
723
|
this.add.y = absY * this.viewWidth + 'px'
|
|
728
724
|
}
|
|
725
|
+
},
|
|
726
|
+
handleMediaLoad(item) {
|
|
727
|
+
if (!item) return
|
|
728
|
+
item.loading = false
|
|
729
|
+
},
|
|
730
|
+
handleMediaError(item) {
|
|
731
|
+
if (!item) return
|
|
732
|
+
item.loading = false
|
|
729
733
|
}
|
|
730
734
|
}
|
|
731
735
|
}
|
|
@@ -774,6 +778,29 @@ export default {
|
|
|
774
778
|
}
|
|
775
779
|
}
|
|
776
780
|
|
|
781
|
+
.media-loading-overlay {
|
|
782
|
+
position: absolute;
|
|
783
|
+
top: 0;
|
|
784
|
+
left: 0;
|
|
785
|
+
right: 0;
|
|
786
|
+
bottom: 0;
|
|
787
|
+
display: flex;
|
|
788
|
+
align-items: center;
|
|
789
|
+
justify-content: center;
|
|
790
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
791
|
+
border-radius: inherit;
|
|
792
|
+
z-index: 5;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.loading-spinner {
|
|
796
|
+
width: 40rpx;
|
|
797
|
+
height: 40rpx;
|
|
798
|
+
border: 4rpx solid rgba(0, 0, 0, 0.1);
|
|
799
|
+
border-top-color: #007aff;
|
|
800
|
+
border-radius: 50%;
|
|
801
|
+
animation: spinner-rotate 0.8s linear infinite;
|
|
802
|
+
}
|
|
803
|
+
|
|
777
804
|
.del-con {
|
|
778
805
|
position: absolute;
|
|
779
806
|
top: 0rpx;
|
|
@@ -813,4 +840,14 @@ export default {
|
|
|
813
840
|
}
|
|
814
841
|
}
|
|
815
842
|
}
|
|
843
|
+
|
|
844
|
+
@keyframes spinner-rotate {
|
|
845
|
+
0% {
|
|
846
|
+
transform: rotate(0deg);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
100% {
|
|
850
|
+
transform: rotate(360deg);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
816
853
|
</style>
|