<template>
<div :class="uploadDisabled ? 'upload' : ''">
<el-upload action="#"
accept=".jpg,.jpeg,.png,.bmp"
list-type="picture-card"
:auto-upload="false"
v-model:file-list="fileList"
:limit="maxlimit"
:before-upload="beforeAvatarUpload"
:on-change="handleChange"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove">
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="viewImages">
<img w-full :src="dialogImageUrl" alt="Preview Image"
style="width: 950px;height: 460px;"/>
</el-dialog>
</div>
</template>
<script lang="ts">
import {
defineComponent,
ref,
watch,
watchEffect,
} from 'vue';
import axios from 'axios';
import type { AxiosResponse } from 'axios';
import {
UploadUserFile,
ElLoading,
UploadProps,
UploadFile,
ElMessage,
} from 'element-plus';
interface Files {
name: string,
url: string,
}
interface UploadRawFile extends File {
uid: number;
}
interface UploadFils {
name: string;
percentage?: number;
size?: number;
response?: unknown;
uid: number;
url?: string;
raw?: UploadRawFile;
}
export default defineComponent({
props: {
updateFile: {
type: Array,
default: () => [],
},
maxlimit: {
type: Number,
default: 1,
},
uploadTypes: {
type: String,
default: 'preview',
},
BaseUrl: {
type: String,
default: import.meta.env.VITE_UPLOAD_URL,
},
echoAddress: {
type: String,
default: '',
},
Width: {
type: String,
default: '148px',
},
Hieght: {
type: String,
default: '148px',
},
},
setup(props, context) {
const fileList = ref<UploadUserFile[]>([]);
const viewImages = ref(false);
const dialogImageUrl = ref<string |undefined >('');
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
fileList.value = uploadFiles;
context.emit('removeAfterFile', uploadFiles);
};
const handlePictureCardPreview = (file: UploadFile) => {
dialogImageUrl.value = file.url;
viewImages.value = true;
};
const Width = ref('');
const Hieght = ref('');
watch(() => props, (newVal) => {
fileList.value = newVal.updateFile as Files[];
Width.value = newVal.Width;
Hieght.value = newVal.Hieght;
}, {
immediate: true,
deep: true,
});
const uploadDisabled = ref(false);
watchEffect(() => {
fileList.value = fileList.value.filter((item) => (!item.raw ? item : ''));
if (fileList.value.length >= props.maxlimit) {
uploadDisabled.value = true;
} else {
uploadDisabled.value = false;
}
});
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
if (rawFile.type !== 'image/png' && rawFile.type !== 'image/jpg' && rawFile.type !== 'image/jpeg') {
ElMessage.error('图片仅支持jpg、jpeg、png格式!');
return false;
} if (rawFile.size / 1024 / 1024 > 3) {
ElMessage.error('图片大小不能超过3M!');
return false;
}
return true;
};
const handleChange: UploadProps['onChange'] = async (uploadFile: UploadFils) => {
const files = new FormData();
if (uploadFile && uploadFile.raw) {
files.append(props.uploadTypes, uploadFile.raw);
}
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
});
axios({
method: 'post',
url: `${props.BaseUrl}?type=${props.uploadTypes}`,
data: files,
}).then((res: AxiosResponse) => {
if (props.echoAddress === 'false') {
context.emit('images', res.data.data);
loading.close();
return;
}
fileList.value.push({
name: res.data.data.path,
url: res.data.data.url_path,
});
context.emit('images', res.data.data);
loading.close();
});
};
return {
fileList,
viewImages,
dialogImageUrl,
uploadDisabled,
beforeAvatarUpload,
handleRemove,
handlePictureCardPreview,
handleChange,
};
},
});
</script>
<style lang="scss" scoped>
.preview_box{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(215, 215, 215);
}
:deep(.el-dialog){
width: 1000px;
height: 500px;
}
:deep(.el-dialog__body){
padding: 0px 20px;
}
.upload :deep(.el-upload--picture-card) {
display: none !important;
}
:deep(.el-upload--picture-card){
width: v-bind(Width) !important;
height: v-bind(Hieght) !important;
}
:deep(.el-upload-list__item){
width: v-bind(Width) !important;
height: v-bind(Hieght) !important;
}
</style>