|
|
|
@ -64,10 +64,36 @@ |
|
|
|
</template> |
|
|
|
</van-uploader> |
|
|
|
|
|
|
|
<!-- 生产环境:自定义上传按钮,点击弹出 action-sheet --> |
|
|
|
<div v-else class="uploader-custom-btn" @click="onOpenUploadAction(item)"> |
|
|
|
<van-icon name="photograph" size="24" color="#dcdee0" /> |
|
|
|
</div> |
|
|
|
<!-- 生产环境:已上传文件预览 + 上传按钮 --> |
|
|
|
<template v-else> |
|
|
|
<template v-for="(file, fileIndex) in item.fileList" :key="fileIndex"> |
|
|
|
<div v-if="file.status === 'uploading'" class="media-item media-item--uploading"> |
|
|
|
<div class="uploading-overlay"> |
|
|
|
<van-loading color="#fff" size="24" /> |
|
|
|
<span class="uploading-text">{{ file.message || '上传中...' }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-else-if="file.status === 'failed'" class="media-item media-item--failed" @click="onRemoveFile(item, fileIndex)"> |
|
|
|
<div class="failed-overlay"> |
|
|
|
<van-icon name="cross" color="#fff" size="24" /> |
|
|
|
<span class="failed-text">{{ file.message || '上传失败' }}</span> |
|
|
|
<span class="failed-hint">点击删除重试</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div v-else-if="file.isImage" class="media-item" @click="onPreviewItem(item, fileIndex)"> |
|
|
|
<van-image :src="file.url" fit="cover" class="media-item-img" /> |
|
|
|
<van-icon name="cross" class="media-item--remove" @click.stop="onRemoveFile(item, fileIndex)" /> |
|
|
|
</div> |
|
|
|
<div v-else class="media-item media-item--video" @click="onPreviewItem(item, fileIndex)"> |
|
|
|
<video :src="file.url" muted preload="metadata" class="video-thumb"></video> |
|
|
|
<van-icon name="play-circle-o" class="play-icon" /> |
|
|
|
<van-icon name="cross" class="media-item--remove" @click.stop="onRemoveFile(item, fileIndex)" /> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<div v-if="(item.fileList?.length || 0) < 20" class="uploader-custom-btn" @click="onOpenUploadAction(item)"> |
|
|
|
<van-icon name="photograph" size="24" color="#dcdee0" /> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="objection-card" v-if="Number(item.pass) === 0"> |
|
|
|
@ -540,6 +566,34 @@ const onPreview = (url, itemValue) => { |
|
|
|
startPosition: start >= 0 ? start : 0 |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
const onPreviewItem = (item, fileIndex) => { |
|
|
|
const file = item.fileList?.[fileIndex] |
|
|
|
if (!file) return |
|
|
|
if (file.isImage) { |
|
|
|
const images = (item.fileList || []) |
|
|
|
.filter((f) => f.isImage && f.status === 'done') |
|
|
|
.map((f) => f.url) |
|
|
|
const start = images.indexOf(file.url) |
|
|
|
showImagePreview({ |
|
|
|
images, |
|
|
|
startPosition: start >= 0 ? start : 0 |
|
|
|
}) |
|
|
|
} else { |
|
|
|
previewVideoUrl.value = file.url |
|
|
|
showVideoPreview.value = true |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const onRemoveFile = (item, fileIndex) => { |
|
|
|
showConfirmDialog({ |
|
|
|
title: '确认删除', |
|
|
|
message: '确定删除该文件吗?', |
|
|
|
}).then(() => { |
|
|
|
item.fileList.splice(fileIndex, 1) |
|
|
|
showToast('已删除') |
|
|
|
}).catch(() => {}) |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style lang="less" scoped> |
|
|
|
@ -626,6 +680,72 @@ const onPreview = (url, itemValue) => { |
|
|
|
height: 100%; |
|
|
|
} |
|
|
|
|
|
|
|
.media-item-img { |
|
|
|
width: 100%; |
|
|
|
height: 100%; |
|
|
|
} |
|
|
|
|
|
|
|
.media-item--remove { |
|
|
|
position: absolute; |
|
|
|
top: 2px; |
|
|
|
right: 2px; |
|
|
|
font-size: 16px; |
|
|
|
color: #fff; |
|
|
|
background: rgba(0, 0, 0, 0.5); |
|
|
|
border-radius: 50%; |
|
|
|
width: 18px; |
|
|
|
height: 18px; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
} |
|
|
|
|
|
|
|
&--uploading { |
|
|
|
background-color: #f7f8fa; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
|
|
|
|
.uploading-overlay { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
gap: 4px; |
|
|
|
|
|
|
|
.uploading-text { |
|
|
|
font-size: 12px; |
|
|
|
color: #323233; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
&--failed { |
|
|
|
background-color: #ee0a24; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
cursor: pointer; |
|
|
|
|
|
|
|
.failed-overlay { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
align-items: center; |
|
|
|
gap: 2px; |
|
|
|
|
|
|
|
.failed-text { |
|
|
|
font-size: 12px; |
|
|
|
color: #fff; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
.failed-hint { |
|
|
|
font-size: 10px; |
|
|
|
color: rgba(255, 255, 255, 0.8); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
&--video { |
|
|
|
cursor: pointer; |
|
|
|
|
|
|
|
|