feat: 优化文件上传功能柜

This commit is contained in:
lbw 2023-02-15 14:45:06 +08:00
parent 822ba36246
commit 0fd375fe26
8 changed files with 93 additions and 114 deletions

View File

@ -1,3 +1,4 @@
<!-- excel 导入组件 -->
<template> <template>
<el-dialog :title="prop.title" v-model="state.upload.open" width="60%"> <el-dialog :title="prop.title" v-model="state.upload.open" width="60%">
<el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="headers" :action="url" <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="headers" :action="url"

View File

@ -2,30 +2,27 @@
<template> <template>
<div> <div>
<el-upload <el-upload ref="fileUpload" class="avatar-uploader" :action="props.uploadFileUrl" :show-file-list="false"
ref="fileUpload" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :headers="headers" :limit="props.limit">
class="avatar-uploader" <slot>
:action="props.uploadFileUrl" 123<img v-if="imageUrl" :src="imageUrl" class="avatar" />
:show-file-list="false" <el-icon v-else class="avatar-uploader-icon">
:on-success="handleAvatarSuccess" <Plus />
:before-upload="beforeAvatarUpload" </el-icon>
:headers="headers" </slot>
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload> </el-upload>
</div> </div>
</template> </template>
<script setup lang="ts" name="upload-image"> <script setup lang="ts" name="upload-image">
import {useMessage} from "/@/hooks/message"; import { useMessage } from "/@/hooks/message";
import {Session} from "/@/utils/storage"; import { Local, Session } from "/@/utils/storage";
import {watch} from "vue"; import { watch } from "vue";
const imageUrl = ref('') const imageUrl = ref('')
const fileUpload = ref() const fileUpload = ref()
const emit = defineEmits(['update:value','change']); const emit = defineEmits(['update:value', 'change']);
const props = defineProps({ const props = defineProps({
value: [String, Array], value: [String, Array],
@ -34,32 +31,36 @@ const props = defineProps({
type: Number, type: Number,
default: 5, default: 5,
}, },
limit: {
type: Number,
default: 1,
},
uploadFileUrl: { uploadFileUrl: {
type: String, type: String,
default: '/admin/sys-file/upload' default: '/admin/sys-file/upload'
} }
}); });
watch(() => props.value,(val) => { watch(() => props.value, (val) => {
if(val){ if (val) {
imageUrl.value = val imageUrl.value = val
} }
},{ deep: true, immediate: true }) }, { deep: true, immediate: true })
const handleAvatarSuccess = (res, file) => { const handleAvatarSuccess = (res, file) => {
if(res.code === 0){ if (res.code === 0) {
imageUrl.value = res.data.url imageUrl.value = res.data.url
emit("change", imageUrl.value); emit("change", imageUrl.value);
emit("update:value", imageUrl.value); emit("update:value", imageUrl.value);
}else{ } else {
fileUpload.value.handleRemove(file); fileUpload.value.handleRemove(file);
} }
} }
const beforeAvatarUpload = (rawFile: any) => { const beforeAvatarUpload = (rawFile: any) => {
if (rawFile.type !== 'image/jpeg') { if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png') {
useMessage().error(`文件格式不正确, 请上传 image/jpeg 格式文件!`) useMessage().error(`文件格式不正确, 请上传 jpeg/png格式文件!`)
return false return false
} }
// //
@ -73,14 +74,12 @@ const beforeAvatarUpload = (rawFile: any) => {
return true return true
} }
const headers = reactive({ const headers = computed(() => {
Authorization: '' const tenantId = Local.get("tenantId") ? Local.get("tenantId") : 1
}) return {
'Authorization': "Bearer " + Session.get("token"),
onMounted(() => { 'TENANT-ID': tenantId
if (Session.get('token')) { };
headers.Authorization = `Bearer ${Session.get('token')}`;
}
}) })
</script> </script>
@ -107,7 +106,7 @@ onMounted(() => {
text-align: center; text-align: center;
} }
.avatar{ .avatar {
width: 178px; width: 178px;
height: 100%; height: 100%;
} }

View File

@ -1,20 +1,14 @@
<!--文件上传组件--> <!--文件上传组件-->
<template> <template>
<div class="upload-file"> <div class="upload-file">
<el-upload <el-upload multiple :action="props.uploadFileUrl" :before-upload="handleBeforeUpload" :file-list="fileList"
multiple :limit="limit" :on-error="handleUploadError" :on-success="handleUploadSuccess" :on-remove="handleRemove"
:action="props.uploadFileUrl" :headers="headers" class="upload-file-uploader" ref="fileUpload" :auto-upload="false" drag>
:before-upload="handleBeforeUpload" <i class="el-icon-upload"></i>
:file-list="fileList" <div class="el-upload__text">
:limit="limit" 将文件拖到此处
:on-error="handleUploadError" <em>点击上传</em>
:on-success="handleUploadSuccess" </div>
:on-remove="handleRemove"
:headers="headers"
class="upload-file-uploader"
ref="fileUpload"
>
<el-button type="primary">选取文件</el-button>
<template #tip> <template #tip>
<div class="el-upload__tip" v-if="props.isShowTip"> <div class="el-upload__tip" v-if="props.isShowTip">
请上传 请上传
@ -28,8 +22,8 @@
</template> </template>
<script setup lang="ts" name="upload-file"> <script setup lang="ts" name="upload-file">
import {useMessage} from "/@/hooks/message"; import { useMessage } from "/@/hooks/message";
import {Session} from "/@/utils/storage"; import { Local, Session } from "/@/utils/storage";
const props = defineProps({ const props = defineProps({
value: [String, Array], value: [String, Array],
@ -46,7 +40,7 @@ const props = defineProps({
// , ['png', 'jpg', 'jpeg'] // , ['png', 'jpg', 'jpeg']
fileType: { fileType: {
type: Array, type: Array,
default: () => ["doc", "xls", "ppt", "txt", "pdf","docx", "xlsx", "pptx"], default: () => ['png', 'jpg', 'jpeg', "doc", "xls", "ppt", "txt", "pdf", "docx", "xlsx", "pptx"],
}, },
// //
isShowTip: { isShowTip: {
@ -59,25 +53,24 @@ const props = defineProps({
} }
}); });
const emit = defineEmits(['update:modelValue','change']); const emit = defineEmits(['update:modelValue', 'change']);
const number = ref(0); const number = ref(0)
const fileList = ref([]); const fileList = ref([]) as any
const uploadList = ref([]); const uploadList = ref([]) as any
const fileUpload = ref() const fileUpload = ref()
const headers = reactive({
Authorization: ''
})
onMounted(() => { const headers = computed(() => {
if (Session.get('token')) { const tenantId = Local.get("tenantId") ? Local.get("tenantId") : 1
headers.Authorization = `Bearer ${Session.get('token')}`; return {
} 'Authorization': "Bearer " + Session.get("token"),
'TENANT-ID': tenantId
};
}) })
// //
const handleBeforeUpload = (file: File) => { const handleBeforeUpload = (file: File) => {
// //
if (props.fileType.length) { if (props.fileType.length) {
const fileName = file.name.split('.'); const fileName = file.name.split('.');
@ -101,7 +94,7 @@ const handleBeforeUpload = (file: File) => {
} }
// //
function handleUploadSuccess(res, file) { function handleUploadSuccess(res: any, file: any) {
if (res.code === 0) { if (res.code === 0) {
uploadList.value.push({ name: res.data.fileName, url: res.data.url }); uploadList.value.push({ name: res.data.fileName, url: res.data.url });
uploadedSuccessfully(); uploadedSuccessfully();
@ -114,7 +107,7 @@ function handleUploadSuccess(res, file) {
} }
// //
const uploadedSuccessfully = () => { const uploadedSuccessfully = () => {
if (number.value > 0 && uploadList.value.length === number.value) { if (number.value > 0 && uploadList.value.length === number.value) {
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value); fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
uploadList.value = []; uploadList.value = [];
@ -129,7 +122,7 @@ const handleRemove = (file: any) => {
} }
// //
const listToString = (list, separator = ',') => { const listToString = (list, separator = ',') => {
let strs = ""; let strs = "";
separator = separator || ","; separator = separator || ",";
for (let i in list) { for (let i in list) {
@ -161,7 +154,7 @@ watch(() => props.value, val => {
fileList.value = []; fileList.value = [];
return []; return [];
} }
},{ deep: true, immediate: true }); }, { deep: true, immediate: true });
</script> </script>

View File

@ -55,7 +55,7 @@
<el-table-column label="操作" width="200"> <el-table-column label="操作" width="200">
<template #default="scope"> <template #default="scope">
<el-button text type="primary" @click="onOpenEditDic('edit', scope.row)">修改</el-button> <el-button text type="primary" @click="onOpenEditDic('edit', scope.row)">修改</el-button>
<el-button text type="primary" v-if="scope.row.systemFlag !== '1'" <el-button text type="primary" :disabled="scope.row.systemFlag !== '1'"
@click="handleDelete([scope.row.id])">删除</el-button> @click="handleDelete([scope.row.id])">删除</el-button>
<el-button text type="primary" @click="showDictITem(scope.row)">字典项</el-button> <el-button text type="primary" @click="showDictITem(scope.row)">字典项</el-button>
</template> </template>

View File

@ -1,17 +1,6 @@
<template> <template>
<el-dialog title="上传文件" v-model="visible" :close-on-click-modal="false" draggable> <el-dialog title="上传文件" v-model="visible" :close-on-click-modal="false" draggable>
<el-upload class="upload-demo" drag action="/admin/sys-file/upload" :headers="headers" multiple @success="success"> <upload @change="success" />
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
拖拽到这个位置或者<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">
上传同步至文件服务器
</div>
</template>
</el-upload>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button> <el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
@ -21,23 +10,12 @@
</template> </template>
<script setup lang="ts" name="SysFileDialog"> <script setup lang="ts" name="SysFileDialog">
// / const Upload = defineAsyncComponent(() => import('/@/components/Upload/index.vue'))
import { Local } from "/@/utils/storage";
import { Session } from "/@/utils/storage";
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);
// //
const visible = ref(false) const visible = ref(false)
//
const headers = computed(() => {
const tenantId = Local.get("tenantId") ? Local.get("tenantId") : 1
return {
'Authorization': "Bearer " + Session.get("token"),
'TENANT-ID': tenantId
};
})
// //
const openDialog = () => { const openDialog = () => {

View File

@ -64,7 +64,6 @@ import { downBlobFile } from "/@/utils/other";
// //
const FormDialog = defineAsyncComponent(() => import('./form.vue')); const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const UploadImage = defineAsyncComponent(() => import('/@/components/Upload/Image.vue'))
const { t } = useI18n() const { t } = useI18n()
// //
@ -96,8 +95,7 @@ const resetQuery = () => {
// //
const download = (row: any) => { const download = (row: any) => {
downBlobFile("/admin/sys-file/" + row.bucketName + "/" + row.fileName, null, row.fileName downBlobFile("/admin/sys-file/" + row.bucketName + "/" + row.fileName, null, row.fileName);
);
} }
// //

View File

@ -58,7 +58,7 @@
$t('common.editBtn') $t('common.editBtn')
}} }}
</el-button> </el-button>
<el-button text v-if="scope.row.systemFlag !== '1'" type="primary" <el-button text :disabled="scope.row.systemFlag === '1'" type="primary"
@click="handleDelete([scope.row.publicId])">{{ @click="handleDelete([scope.row.publicId])">{{
$t('common.delBtn') $t('common.delBtn')
}} }}
@ -118,7 +118,7 @@ const resetQuery = () => {
getDataList() getDataList()
} }
// //
const handleSelectable = (row: any) => { const handleSelectable = (row: any) => {
// //
return row.systemFlag !== '1' return row.systemFlag !== '1'

View File

@ -6,10 +6,12 @@
<el-card shadow="hover" header="个人信息"> <el-card shadow="hover" header="个人信息">
<div class="personal-user"> <div class="personal-user">
<div class="personal-user-left"> <div class="personal-user-left">
<el-upload class="h100 personal-user-left-upload" action="/admin/sys-file/upload" <image-upload class="h100 personal-user-left-upload" @change="handleAvatarSuccess">
:headers="headers" :on-success="handleAvatarSuccess" :limit="1"> <img v-if="formData.avatar" :src="formData.avatar" class="avatar" />
<img :src="formData.avatar" /> <el-icon v-else class="avatar-uploader-icon">
</el-upload> <Plus />
</el-icon>
</image-upload>
</div> </div>
<div class="personal-user-right"> <div class="personal-user-right">
<el-row> <el-row>
@ -50,7 +52,7 @@
<el-col :span="24"> <el-col :span="24">
<el-card shadow="hover" class="mt15 personal-edit" header="更新信息"> <el-card shadow="hover" class="mt15 personal-edit" header="更新信息">
<div class="personal-edit-title">基本信息</div> <div class="personal-edit-title">基本信息</div>
<el-form :model="formData" :rules="ruleForm" label-width="100px" class="mt35 mb35" <el-form :model="formData" :rules="ruleForm" label-width="100px" class="mt35 mb35"
ref="formdataRef"> ref="formdataRef">
<el-row :gutter="35"> <el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20"> <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
@ -148,10 +150,12 @@ import { formatAxis } from '/@/utils/formatTime';
import { useUserInfo } from '/@/stores/userInfo'; import { useUserInfo } from '/@/stores/userInfo';
import { editInfo } from '/@/api/admin/user' import { editInfo } from '/@/api/admin/user'
import { useMessage } from "/@/hooks/message"; import { useMessage } from "/@/hooks/message";
import { Session } from "/@/utils/storage";
import { rule } from "/@/utils/validate"; import { rule } from "/@/utils/validate";
import other from '/@/utils/other'; import other from '/@/utils/other';
const ImageUpload = defineAsyncComponent(() => import('/@/components/Upload/Image.vue'))
// //
const formData = reactive({ const formData = reactive({
username: '', username: '',
@ -181,26 +185,19 @@ const ruleForm = reactive({
}] }]
}) })
const handleAvatarSuccess = (res: any) => {
formData.avatar = res.data.url;
}
const headers = computed(() => {
const tenantId = Session.get("tenantId")
return {
'Authorization': "Bearer " + Session.get("token"),
'TENANT-ID': tenantId ? tenantId : '1'
};
})
onMounted(() => { onMounted(() => {
const data = useUserInfo().userInfos const data = useUserInfo().userInfos
Object.assign(formData, data.user) Object.assign(formData, data.user)
formData.password = '' formData.password = ''
}) })
//
const handleAvatarSuccess = (url: any) => {
formData.avatar = url;
}
//
const handleSaveUser = () => { const handleSaveUser = () => {
formdataRef.value.validate((valid: boolean) => { formdataRef.value.validate((valid: boolean) => {
if (!valid) { if (!valid) {
@ -439,4 +436,17 @@ const handleClick = (thirdpart: string) => {
} }
} }
} }
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 100%;
}
</style> </style>