<template>
|
<el-upload
|
ref="upload"
|
class="my-3" action="#"
|
v-model:file-list="list"
|
:accept="acceptType"
|
:list-type="listType"
|
:http-request="uploadRequest"
|
:multiple="true"
|
:limit="limitFileCount"
|
:on-preview="handlePreview"
|
:on-remove="handleRemove"
|
:before-remove="beforeRemove"
|
:on-exceed="handleExceed"
|
:disabled="disabled"
|
:class="{ hideUpload: hideUpload }"
|
>
|
<template #default>
|
<template v-if="listType=='picture-card'">
|
<el-icon v-if="!disabled"><Plus /></el-icon>
|
<el-text v-if="disabled">暂未上传</el-text>
|
</template>
|
<template v-else>
|
<el-row>
|
<el-button type="primary">
|
<el-row align="middle">
|
<Icon icon="material-symbols:upload-rounded" width="20" height="20" style="color: #fff" />
|
<el-text class="text-white ml-1">{{ againUploadFlag ? '重新上传' : '立即上传' }}</el-text>
|
</el-row>
|
</el-button>
|
<el-text style="color: #666666" class="ml-4">
|
{{ tip }}
|
</el-text>
|
</el-row>
|
</template>
|
</template>
|
<template #file="{ file, index }">
|
<template v-if="listType=='picture-card'">
|
<el-image
|
ref="previewImg"
|
:src="file.url"
|
:initial-index="initialPreviewImgIndex"
|
:preview-src-list="filterPreviewImgList"
|
>
|
</el-image>
|
<span class="el-upload-list__item-actions">
|
<span @click="previewImage(index)">
|
<el-icon><zoom-in /></el-icon>
|
</span>
|
<!-- <span @click="replaceUpload(index)">
|
<el-icon><upload /></el-icon>
|
</span> -->
|
<span @click="deleteFileItem(index)">
|
<el-icon><delete /></el-icon>
|
</span>
|
</span>
|
</template>
|
<template v-else>
|
<div class="file-box">
|
<Icon
|
@click="deleteFileItem(index)"
|
class="cursor-p mr-3"
|
icon="eva:close-fill"
|
width="18"
|
height="18"
|
style="color: #666666"
|
/>
|
<Icon class="mr-1" icon="uis:paperclip" width="18" height="18" style="color:#007AFF" />
|
<span>{{ file.name }}</span>
|
</div>
|
</template>
|
</template>
|
</el-upload>
|
<el-dialog v-model="imgPreviewDialogFlag">
|
<img w-full :src="previewUrl" alt="Preview Image" />
|
</el-dialog>
|
</template>
|
|
<script>
|
const pdf = 'application/pdf'
|
const xls = 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
const doc = 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
const image = 'image/*'
|
const jpg = 'image/jpeg'
|
const png = 'image/png'
|
import { genFileId } from 'element-plus'
|
export default {
|
data() {
|
return {
|
list: [],
|
imgPreviewDialogFlag: false,
|
previewUrl: '',
|
initialPreviewImgIndex: 0
|
}
|
},
|
props: {
|
listType: {
|
type: String,
|
default: 'text'
|
},
|
accept: {
|
type: Array,
|
default: () => {
|
return ['pdf', 'xls', 'doc', 'image', 'jpg', 'png']
|
}
|
},
|
limitFileCount: {
|
type: Number,
|
default: 1
|
},
|
modelValue: {
|
type: Array,
|
default: () => {
|
return []
|
}
|
},
|
disabled: {
|
type: Boolean,
|
default: false
|
}
|
},
|
watch: {
|
modelValue: {
|
handler: function() {
|
this.list = this.modelValue
|
},
|
deep: true
|
},
|
list: {
|
handler: function(val) {
|
this.$emit('update:modelValue', val)
|
},
|
deep: true
|
}
|
},
|
computed: {
|
acceptType() {
|
let obj = { pdf, xls, doc, image, jpg, png }
|
return this.accept.map(ele => obj[ele]).join(',')
|
},
|
tip() {
|
let obj = {
|
pdf: 'PDF',
|
xls: 'EXCEL',
|
doc: 'WORD',
|
image: '图片',
|
jpg: 'JPEG/JPG',
|
png: 'PNG'
|
}
|
let tip = this.accept.map(ele => obj[ele]).join('、')
|
return `支持${tip}类型文件`
|
},
|
againUploadFlag() {
|
return this.limitFileCount == 1 && this.list.length == 1
|
},
|
filterPreviewImgList() {
|
let list = this.list.map(ele => ele.url )
|
return list
|
},
|
hideUpload() {
|
return this.list.length >= this.limitFileCount
|
}
|
},
|
methods: {
|
uploadRequest(UploadRequestOptions) {
|
const data = {
|
file: UploadRequestOptions.file,
|
directory: ''
|
}
|
this.$axios.post('/infra/file/upload', data, {
|
headers: { 'Content-Type': "multipart/form-data" }
|
}).then(res => {
|
let index = this.list.findIndex(ele => ele.uid == data.file.uid)
|
if (res.data.code == 0) {
|
let index = this.list.findIndex(ele => ele.uid == data.file.uid)
|
if (index != -1) {
|
this.list[index].uploadStatus = 'success'
|
this.list[index].url = res.data.data
|
}
|
this.$message.success('上传成功')
|
} else {
|
if (index != -1) {
|
this.list[index].uploadStatus = 'fail'
|
}
|
this.$message.error(res.data.msg || '上传失败')
|
}
|
})
|
},
|
deleteFileItem(index) {
|
this.list.splice(index, 1)
|
},
|
previewImage(index) {
|
this.initialPreviewImgIndex = index
|
this.$refs.previewImg?.showPreview()
|
},
|
replaceUpload() {
|
|
},
|
handleRemove() {},
|
beforeRemove() {},
|
handlePreview() {},
|
handleExceed(file) {
|
if (this.againUploadFlag) {
|
this.$refs.upload?.clearFiles()
|
let newFile = file[0]
|
newFile.uid = genFileId()
|
this.$refs.upload?.handleStart(newFile)
|
this.$refs.upload?.submit()
|
} else {
|
this.$message.error(`最多支持上传 ${this.limitFileCount} 个文件`)
|
}
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.hideUpload :deep(.el-upload--picture-card) {
|
display: none !important;
|
}
|
.file-box {
|
display: flex;
|
color: #007AFF;
|
align-content: center;
|
background-color: #ECF5FF;
|
padding: 8px;
|
font-size: 15px;
|
line-height: 16px;
|
}
|
.el-upload-list__item-actions {
|
position: absolute;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色蒙版 */
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
opacity: 0; /* 默认透明 */
|
transition: opacity .3s; /* 添加过渡动画效果 */
|
}
|
|
/* 鼠标悬停时显示蒙版 */
|
.el-upload-list__item:hover .el-upload-list__item-actions {
|
opacity: 1;
|
}
|
</style>
|