♻️ Refactoring code. 增加头像上传组件和文件上传组件

This commit is contained in:
aeizzz 2023-02-14 15:50:29 +08:00
parent 4a94568669
commit 43200a601a
4 changed files with 288 additions and 16 deletions

View File

@ -0,0 +1,114 @@
<!--图片上传组件-->
<template>
<div>
<el-upload
ref="fileUpload"
class="avatar-uploader"
:action="props.uploadFileUrl"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:headers="headers"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</div>
</template>
<script setup lang="ts" name="upload-image">
import {useMessage} from "/@/hooks/message";
import {Session} from "/@/utils/storage";
import {watch} from "vue";
const imageUrl = ref('')
const fileUpload = ref()
const emit = defineEmits(['update:value','change']);
const props = defineProps({
value: [String, Array],
// (MB)
fileSize: {
type: Number,
default: 5,
},
uploadFileUrl: {
type: String,
default: '/admin/sys-file/upload'
}
});
watch(() => props.value,(val) => {
if(val){
imageUrl.value = val
}
},{ deep: true, immediate: true })
const handleAvatarSuccess = (res, file) => {
if(res.code === 0){
imageUrl.value = res.data.url
emit("change", imageUrl.value);
emit("update:value", imageUrl.value);
}else{
fileUpload.value.handleRemove(file);
}
}
const beforeAvatarUpload = (rawFile: any) => {
if (rawFile.type !== 'image/jpeg') {
useMessage().error(`文件格式不正确, 请上传 image/jpeg 格式文件!`)
return false
}
//
if (props.fileSize) {
const isLt = rawFile.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
useMessage().error(`上传文件大小不能超过 ${props.fileSize} MB!`)
return false;
}
}
return true
}
const headers = reactive({
Authorization: ''
})
onMounted(() => {
if (Session.get('token')) {
headers.Authorization = `Bearer ${Session.get('token')}`;
}
})
</script>
<style scoped>
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar{
width: 178px;
height: 100%;
}
</style>

View File

@ -0,0 +1,171 @@
<!--文件上传组件-->
<template>
<div class="upload-file">
<el-upload
multiple
:action="props.uploadFileUrl"
:before-upload="handleBeforeUpload"
:file-list="fileList"
:limit="limit"
:on-error="handleUploadError"
:on-success="handleUploadSuccess"
:on-remove="handleRemove"
:headers="headers"
class="upload-file-uploader"
ref="fileUpload"
>
<el-button type="primary">选取文件</el-button>
<template #tip>
<div class="el-upload__tip" v-if="props.isShowTip">
请上传
<template v-if="props.fileSize"> 大小不超过 <b style="color: #f56c6c">{{ props.fileSize }}MB</b> </template>
<template v-if="props.fileType"> 格式为 <b style="color: #f56c6c">{{ props.fileType.join("/") }}</b> </template>
的文件
</div>
</template>
</el-upload>
</div>
</template>
<script setup lang="ts" name="upload-file">
import {useMessage} from "/@/hooks/message";
import {Session} from "/@/utils/storage";
const props = defineProps({
value: [String, Array],
//
limit: {
type: Number,
default: 5,
},
// (MB)
fileSize: {
type: Number,
default: 5,
},
// , ['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["doc", "xls", "ppt", "txt", "pdf","docx", "xlsx", "pptx"],
},
//
isShowTip: {
type: Boolean,
default: true
},
uploadFileUrl: {
type: String,
default: '/admin/sys-file/upload'
}
});
const emit = defineEmits(['update:modelValue','change']);
const number = ref(0);
const fileList = ref([]);
const uploadList = ref([]);
const fileUpload = ref()
const headers = reactive({
Authorization: ''
})
onMounted(() => {
if (Session.get('token')) {
headers.Authorization = `Bearer ${Session.get('token')}`;
}
})
//
const handleBeforeUpload = (file: File) => {
//
if (props.fileType.length) {
const fileName = file.name.split('.');
const fileExt = fileName[fileName.length - 1];
const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
if (!isTypeOk) {
useMessage().error(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`)
return false;
}
}
//
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
useMessage().error(`上传文件大小不能超过 ${props.fileSize} MB!`)
return false;
}
}
number.value++;
return true;
}
//
function handleUploadSuccess(res, file) {
if (res.code === 0) {
uploadList.value.push({ name: res.data.fileName, url: res.data.url });
uploadedSuccessfully();
} else {
number.value--;
useMessage().error(res.msg);
fileUpload.value.handleRemove(file);
uploadedSuccessfully();
}
}
//
const uploadedSuccessfully = () => {
if (number.value > 0 && uploadList.value.length === number.value) {
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
uploadList.value = [];
number.value = 0;
emit("change", listToString(fileList.value));
}
}
const handleRemove = (file: any) => {
fileList.value = fileList.value.filter(f => !(f === file.url))
emit("change", listToString(fileList.value));
}
//
const listToString = (list, separator = ',') => {
let strs = "";
separator = separator || ",";
for (let i in list) {
if (list[i].url) {
strs += list[i].url + separator;
}
}
return strs != '' ? strs.substr(0, strs.length - 1) : '';
}
const handleUploadError = () => {
useMessage().error("上传文件失败")
}
watch(() => props.value, val => {
if (val) {
let temp = 1;
//
const list = Array.isArray(val) ? val : props.value.split(',');
//
fileList.value = list.map(item => {
if (typeof item === "string") {
item = { name: item, url: item };
}
item.uid = item.uid || new Date().getTime() + temp++;
return item;
});
} else {
fileList.value = [];
return [];
}
},{ deep: true, immediate: true });
</script>
<style scoped>
</style>

View File

@ -48,22 +48,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
title: 'hzxc',
isKeepAlive: true,
},
children: [
{
path: '/home',
name: 'home',
component: () => import('/@/views/home/index.vue'),
meta: {
title: 'router.home',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: false,
icon: 'iconfont icon-shouye',
},
},
],
children: []
},
];

View File

@ -43,6 +43,7 @@ import {downBlobFile} from "/@/utils/other";
//
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const UploadImage = defineAsyncComponent(() => import('/@/components/Upload/Image.vue'))
const { t } = useI18n()
//
@ -78,6 +79,7 @@ const download = (row: any) => {
);
}
//
const handleDelete = (row: any) => {
if (!row) {