上传
readme.md
## ∨--- 上传组件改款 ---∨
### HTML
<v-file ref="uploadFileRef" v-model="form.relevantFilesDate" />
### JS
//引用
import { filePropertyInit, subtractFileProperty } from '/@/utils/other';
//定义
const uploadFileRef = ref();
form:{
relevantFiles: [], //数据库字段 text类型
relevantFilesDate: [] //控件绑定字段
}
//回显
Object.assign(form, res.data);
form.relevantFilesDate= filePropertyInit(form.relevantFiles)
//保存
form.relevantFiles = subtractFileProperty(form.relevantFilesDate)
### JAVA
#### entity
/**
* 附件相关
*/
@Schema(description="附件相关")
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String relevantFiles;
## ∧--- 上传组件改款 ---∧
控件文件
<template>
<div class="upload-file">
<el-upload
ref="fileUpload"
v-if="props.type === 'default'"
:action="baseURL + other.adaptationUrl(props.uploadFileUrl)"
:before-upload="handleBeforeUpload"
:file-list="fileList"
:headers="headers"
:limit="limit"
:on-error="handleUploadError"
:on-remove="handleRemove"
:on-preview="handlePreview"
:data="data"
:auto-upload="autoUpload"
:on-success="handleUploadSuccess"
class="upload-file-uploader"
drag
multiple
:disabled="disabled"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
{{ $t('excel.operationNotice') }}
<em>{{ $t('excel.clickUpload') }}</em>
</div>
<template #tip>
<div class="el-upload__tip" v-if="props.isShowTip">
{{ $t('excel.pleaseUpload') }}
<template v-if="props.fileSize">
{{ $t('excel.size') }} <b style="color: #f56c6c">{{ props.fileSize }}MB</b></template
>
<template v-if="props.fileType">
{{ $t('excel.format') }} <b style="color: #f56c6c">{{ props.fileType.join('/') }}</b>
</template>
{{ $t('excel.file') }}
</div>
</template>
</el-upload>
<el-upload
ref="fileUpload"
v-if="props.type === 'simple'"
:action="baseURL + other.adaptationUrl(props.uploadFileUrl)"
:before-upload="handleBeforeUpload"
:file-list="fileList"
:headers="headers"
:limit="limit"
:auto-upload="autoUpload"
:on-error="handleUploadError"
:on-remove="handleRemove"
:data="data"
:on-success="handleUploadSuccess"
class="upload-file-uploader"
multiple
:disabled="disabled"
>
<el-button type="primary" link>{{ $t('excel.clickUpload') }}</el-button>
</el-upload>
<!--<el-button type="primary" @click='btnFileSee'>查看</el-button>-->
</div>
</template>
<script setup lang="ts" name="sysIndex">
import { useMessage } from '/@/hooks/message';
import { Session } from '/@/utils/storage';
import other from '/@/utils/other';
import { useI18n } from 'vue-i18n';
import { delObj, deleteAttachment } from '/@/api/admin/file';
import { validateNull } from '/@/utils/validate';
const props = defineProps({
modelValue: [String, Array],
// 数量限制
limit: {
type: Number,
default: 5,
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 5,
},
fileType: {
type: Array,
default: () => ['png', 'jpg', 'jpeg', 'doc', 'xls', 'ppt', 'txt', 'pdf', 'docx', 'xlsx', 'pptx'],
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true,
},
uploadFileUrl: {
type: String,
default: '/admin/sys-file/upload',
// default: '/admin/sys-file/uploadfile',
},
type: {
type: String,
default: 'default',
validator: (value: string) => {
return ['default', 'simple'].includes(value);
},
},
data: {
type: Object,
},
autoUpload: {
type: Boolean,
default: true,
},
disabled: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue', 'change', 'success']);
const number = ref(0);
const fileList = ref([]) as any;
const fileUpload = ref();
const { t } = useI18n();
const headers = computed(() => {
return {
Authorization: 'Bearer ' + Session.get('token'),
'TENANT-ID': Session.getTenant(),
};
});
// 上传前校检格式和大小
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(`${t('excel.typeErrorText')} ${props.fileType.join('/')}!`);
return false;
}
}
// 校检文件大小
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
useMessage().error(`${t('excel.sizeErrorText')} ${props.fileSize} MB!`);
return false;
}
}
number.value++;
return true;
};
// 错误
const handleUploadError = () => {
useMessage().error('上传文件失败');
};
// 查看
const handlePreview = (file: any) => {
other.downBlobFile(file.url, {}, file.name);
};
// 删除
const handleRemove = (file: any) => {
//这里是假删除,因为要兼顾编辑状态,如若真删除,则需要写删除逻辑(前台+后台)
//file.fileId ? delObj(file.fileId) : deleteAttachment(file.relationid);
let iDelete = -1;
for(let i=0;i<fileList.value.length;i++){
if(fileList.value[i].id === file.id){
//if(fileList.value[i].id === file.response.data.id){
iDelete = i;
break;
}
}
if(iDelete != -1) fileList.value.splice(iDelete, 1);
emit('update:modelValue', fileList.value);
// emit('change', listToString(fileList.value));
};
// 上传成功回调
function handleUploadSuccess(res: any, file: any) {
if (res.code === 0){
fileList.value.push( res.data)
emit('update:modelValue', fileList.value);
}
// useMessage().error(res.msg);
}
const submit = () => {
fileUpload.value.submit();
};
/**
* 将对象数组转为字符串,以逗号分隔。
* @param list 待转换的对象数组。
* @param separator 分隔符,默认为逗号。
* @returns {string} 返回转换后的字符串。
*/
const listToString = (list: { url: string }[], separator = ','): string => {
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) : '';
};
/**
* 监听 props 中的 modelValue 值变化,更新 fileList。
*/
watch(
() => props.modelValue,
(val) => {
if (val) {
// console.log(val)
if(validateNull(val)){
fileList.value = [];
}else {
fileList.value = JSON.parse(JSON.stringify(val))
}
} else {
fileList.value = [];
return [];
}
},
{ deep: true, immediate: true }
);
const btnFileSee = ()=>{
console.log(fileList)
}
defineExpose({
submit
});
</script>
<style scoped>
</style>
other.ts
/**
* 判断是否为空
* @param val 数据
*/
export const validateNull = (val: any) => {
if (typeof val === 'boolean') {
return false;
}
if (typeof val === 'number') {
return false;
}
if (val instanceof Array) {
if (val.length === 0) return true;
} else if (val instanceof Object) {
if (JSON.stringify(val) === '{}') return true;
} else {
if (val === 'null' || val == null || val === 'undefined' || val === undefined || val === '') return true;
return false;
}
return false;
};
downBlobFile: (url: any, query: any, fileName: string) => {
return downBlobFile(url, query, fileName);
},
/**
*
* @param url 目标下载接口
* @param query 查询参数
* @param fileName 文件名称
* @returns {*}
*/
export function downBlobFile(url: any, query: any, fileName: string) {
return request({
url: url,
method: 'get',
responseType: 'blob',
params: query,
}).then((response) => {
handleBlobFile(response, fileName);
});
}
/**
* @description 去掉数组属性
* @param val ["uid","status"]
*/
export const subtractProperty = (val: any,list: any) =>{
// (val,list)
if(!Array.isArray(list)) return list
// let val = ["uid","status"]
for(let item of list){
for(let property1 of val){
delete item[property1]
}
}
return list
}
/**
* @description 去掉数组属性(上传附件专属)
*/
export const subtractFileProperty = (columnFile: any) =>{
let lResult = null
if(validateNull(columnFile)){
if(columnFile.length == 0) lResult = JSON.stringify([])
}else {
lResult = JSON.stringify(subtractProperty(["uid","status"],columnFile))
}
if(lResult == null) lResult = JSON.stringify([])
return lResult
}
/**
* @description 初始化赋值(上传附件专属)
*/
export const filePropertyInit = (columnFile: any) =>{
let lResult = []
if(!validateNull(columnFile)) lResult = JSON.parse(columnFile)
return lResult
}
// 统一批量导出
export default other;
择善人而交,择善书而读,择善言而听,择善行而从。