114 lines
2.6 KiB
Vue
Raw Normal View History

2025-06-12 17:06:06 +08:00
<template>
<div class="file-uploader">
<el-upload
class="file-uploader__upload"
:http-request="customUploadRequest"
:on-success="handleUploadSuccess"
:on-remove="handleRemove"
:file-list="fileList"
list-type="picture-card"
:limit="limit"
:show-file-list="true"
:auto-upload="true"
:disabled="readonly"
:accept="accept"
>
<el-icon v-if="fileList.length < limit"><Plus /></el-icon>
</el-upload>
<el-image-viewer v-if="previewShow" :url-list="previewList" :initial-index="previewIndex" @close="previewShow = false" />
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { CommonUpload } from '@/apis/index';
const props = defineProps({
modelValue: {
type: Array,
default: () => [],
},
ossUrl: {
type: String,
default: 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/',
},
limit: {
type: Number,
default: 5,
},
accept: {
type: String,
default: 'image/*',
},
readonly: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['update:modelValue']);
// 构造 el-upload 所需 file-list
const fileList = computed(() => {
return props.modelValue.map((path, idx) => ({
name: `image_${idx}`,
url: props.ossUrl + path,
uid: `${idx}`,
}));
});
// 预览
const previewShow = ref(false);
const previewList = computed(() => fileList.value.map((item) => item.url));
const previewIndex = ref(0);
// 上传请求内部实现
const customUploadRequest = async ({ file, onSuccess, onError }) => {
const formData = new FormData();
formData.append('file', file);
try {
const res = await CommonUpload(formData);
// 假设后端返回 { code:200, data: { url: 'relative/path.jpg' } }
onSuccess(res, file);
} catch (err) {
onError(err);
}
};
// 上传成功回调,推入 modelValue
function handleUploadSuccess(res) {
const relative = res.data?.url;
if (relative) {
const newArr = [...props.modelValue, relative];
emit('update:modelValue', newArr);
}
}
// 删除图片
function handleRemove(file) {
const fullUrl = file.url;
const relative = fullUrl.replace(props.ossUrl, '');
const newArr = props.modelValue.filter((path) => path !== relative);
emit('update:modelValue', newArr);
}
// 点击预览
function handlePreview(file) {
const idx = fileList.value.findIndex((item) => item.uid === file.uid);
if (idx !== -1) {
previewIndex.value = idx;
previewShow.value = true;
}
}
</script>
<style scoped>
.file-uploader {
display: flex;
flex-wrap: wrap;
}
.file-uploader__upload {
margin-right: 16px;
}
</style>