114 lines
2.6 KiB
Vue
114 lines
2.6 KiB
Vue
|
<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>
|