初始化版本,引入智慧食堂模块,第三方模块
This commit is contained in:
commit
d22f88efd3
677 files changed
+69341
No files matched your search
@@ -0,0 +1,165 @@
|
||||
<!-- excel 导入组件 -->
|
||||
<template>
|
||||
<el-dialog :title="prop.title" v-model="state.upload.open" :close-on-click-modal="false" draggable>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:limit="1"
|
||||
accept=".xlsx, .xls"
|
||||
:headers="headers"
|
||||
:action="baseURL + other.adaptationUrl(url)"
|
||||
:disabled="state.upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
:on-error="handleFileError"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
>
|
||||
<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 text-center">
|
||||
<span>{{ $t('excel.fileFormat') }}</span>
|
||||
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline"
|
||||
@click="downExcelTemp" v-if="tempUrl"
|
||||
>{{ $t('excel.downloadTemplate') }}
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="submitFileForm">{{ $t('common.confirmButtonText') }}</el-button>
|
||||
<el-button @click="state.upload.open = false">{{ $t('common.cancelButtonText') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!--校验失败错误数据-->
|
||||
<el-dialog :title="$t('excel.validationFailureData')" v-model="state.errorVisible">
|
||||
<el-table :data="state.errorData">
|
||||
<el-table-column property="lineNum" :label="$t('excel.lineNumbers')" width="100"></el-table-column>
|
||||
<el-table-column property="errors" :label="$t('excel.misDescription')" show-overflow-tooltip>
|
||||
<template v-slot="scope">
|
||||
<el-tag type="danger" v-for="error in scope.row.errors" :key="error">{{ error }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="upload-excel">
|
||||
import {useMessage} from '/@/hooks/message';
|
||||
import other from '/@/utils/other';
|
||||
import {Session} from '/@/utils/storage';
|
||||
|
||||
const emit = defineEmits(['sizeChange', 'refreshDataList']);
|
||||
const prop = defineProps({
|
||||
url: {
|
||||
type: String,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
tempUrl: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
const uploadRef = ref();
|
||||
|
||||
const state = reactive({
|
||||
errorVisible: false,
|
||||
errorData: [],
|
||||
dialog: {
|
||||
title: '',
|
||||
isShowDialog: false,
|
||||
},
|
||||
upload: {
|
||||
open: false,
|
||||
isUploading: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 下载模板文件
|
||||
*/
|
||||
const downExcelTemp = async () => {
|
||||
try {
|
||||
await other.downBlobFile(other.adaptationUrl(prop.tempUrl), {}, 'temp.xlsx');
|
||||
} catch (error) {
|
||||
useMessage().error('模板下载失败,请先维护模板文件');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传进度条变化事件
|
||||
*/
|
||||
const handleFileUploadProgress = () => {
|
||||
state.upload.isUploading = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传失败事件处理
|
||||
*/
|
||||
const handleFileError = () => {
|
||||
useMessage().error('上传失败,数据格式不合法!');
|
||||
state.upload.open = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传成功事件处理
|
||||
* @param {any} response - 上传成功的响应结果
|
||||
*/
|
||||
const handleFileSuccess = (response: any) => {
|
||||
state.upload.isUploading = false;
|
||||
state.upload.open = false;
|
||||
uploadRef.value.clearFiles();
|
||||
|
||||
// 校验失败
|
||||
if (response.code === 1) {
|
||||
useMessage().error('导入失败,以下数据不合法');
|
||||
state.errorVisible = true;
|
||||
state.errorData = response.data;
|
||||
uploadRef.value.clearFiles();
|
||||
// 刷新表格
|
||||
emit?.('refreshDataList');
|
||||
} else {
|
||||
useMessage().success(response.msg ? response.msg : '导入成功');
|
||||
// 刷新表格
|
||||
emit?.('refreshDataList');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 提交表单,触发上传
|
||||
*/
|
||||
const submitFileForm = () => {
|
||||
uploadRef.value.submit();
|
||||
};
|
||||
|
||||
/**
|
||||
* 显示上传文件对话框,并清除上传信息
|
||||
*/
|
||||
const show = () => {
|
||||
state.upload.isUploading = false;
|
||||
state.upload.open = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 计算请求头部信息
|
||||
*/
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
Authorization: 'Bearer ' + Session.getToken(),
|
||||
'TENANT-ID': Session.getTenant(),
|
||||
};
|
||||
});
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
show,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<div class="upload-box">
|
||||
<el-upload
|
||||
action="#"
|
||||
:id="uuid"
|
||||
:class="['upload', self_disabled ? 'disabled' : '', drag ? 'no-border' : '']"
|
||||
:multiple="false"
|
||||
:disabled="self_disabled"
|
||||
:show-file-list="false"
|
||||
:http-request="handleHttpUpload"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="uploadSuccess"
|
||||
:on-error="uploadError"
|
||||
:drag="drag"
|
||||
:accept="fileType.join(',')"
|
||||
>
|
||||
<template v-if="imageUrl">
|
||||
<!-- 如果返回的是OSS 地址则不需要增加 baseURL -->
|
||||
<img :src="imageUrl.includes('http') ? imageUrl : baseURL + imageUrl" class="upload-image" />
|
||||
<div class="upload-handle" @click.stop>
|
||||
<div class="handle-icon" @click="editImg" v-if="!self_disabled">
|
||||
<el-icon :size="props.iconSize"><Edit /></el-icon>
|
||||
<span v-if="!props.iconSize">{{ $t('common.editBtn') }}</span>
|
||||
</div>
|
||||
<div class="handle-icon" @click="imgViewVisible = true">
|
||||
<el-icon :size="props.iconSize"><ZoomIn /></el-icon>
|
||||
<span v-if="!props.iconSize">{{ $t('common.viewBtn') }}</span>
|
||||
</div>
|
||||
<div class="handle-icon" @click="deleteImg" v-if="!self_disabled">
|
||||
<el-icon :size="props.iconSize"><Delete /></el-icon>
|
||||
<span v-if="!props.iconSize">{{ $t('common.delBtn') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="upload-empty">
|
||||
<slot name="empty">
|
||||
<el-icon><Plus /></el-icon>
|
||||
<!-- <span>请上传图片</span> -->
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<div class="el-upload__tip">
|
||||
<slot name="tip"></slot>
|
||||
</div>
|
||||
<el-image-viewer
|
||||
:teleported="true"
|
||||
v-if="imgViewVisible"
|
||||
@close="imgViewVisible = false"
|
||||
:url-list="[imageUrl.includes('http') ? imageUrl : baseURL + imageUrl]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="UploadImg">
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import { ElNotification, formContextKey, formItemContextKey } from 'element-plus';
|
||||
import type { UploadProps, UploadRequestOptions } from 'element-plus';
|
||||
import { generateUUID } from '/@/utils/other';
|
||||
import request from '/@/utils/request';
|
||||
|
||||
interface UploadFileProps {
|
||||
imageUrl?: string; // 图片地址 ==> 必传
|
||||
uploadFileUrl?: string; // 上传图片的 api 方法,一般项目上传都是同一个 api 方法,在组件里直接引入即可 ==> 非必传
|
||||
drag?: boolean; // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
||||
disabled?: boolean; // 是否禁用上传组件 ==> 非必传(默认为 false)
|
||||
fileSize?: number; // 图片大小限制 ==> 非必传(默认为 5M)
|
||||
fileType?: File.ImageMimeType[]; // 图片类型限制 ==> 非必传(默认为 ["image/jpeg", "image/png", "image/gif"])
|
||||
height?: string; // 组件高度 ==> 非必传(默认为 150px)
|
||||
width?: string; // 组件宽度 ==> 非必传(默认为 150px)
|
||||
borderRadius?: string; // 组件边框圆角 ==> 非必传(默认为 8px)
|
||||
iconSize?: number;
|
||||
dir?: string; // 文件目录
|
||||
}
|
||||
|
||||
// 接受父组件参数
|
||||
const props = withDefaults(defineProps<UploadFileProps>(), {
|
||||
imageUrl: '',
|
||||
uploadFileUrl: '/admin/sys-file/upload',
|
||||
drag: true,
|
||||
disabled: false,
|
||||
fileSize: 5,
|
||||
fileType: () => ['image/jpeg', 'image/png', 'image/gif'],
|
||||
height: '150px',
|
||||
width: '150px',
|
||||
borderRadius: '8px',
|
||||
dir: ''
|
||||
});
|
||||
|
||||
// 生成组件唯一id
|
||||
const uuid = ref('id-' + generateUUID());
|
||||
|
||||
// 查看图片
|
||||
const imgViewVisible = ref(false);
|
||||
// 获取 el-form 组件上下文
|
||||
const formContext = inject(formContextKey, void 0);
|
||||
// 获取 el-form-item 组件上下文
|
||||
const formItemContext = inject(formItemContextKey, void 0);
|
||||
// 判断是否禁用上传和删除
|
||||
const self_disabled = computed(() => {
|
||||
return props.disabled || formContext?.disabled;
|
||||
});
|
||||
|
||||
/**
|
||||
* @description 图片上传
|
||||
* @param options upload 所有配置项
|
||||
* */
|
||||
interface UploadEmits {
|
||||
(e: 'update:imageUrl', value: string): void;
|
||||
}
|
||||
const emit = defineEmits<UploadEmits>();
|
||||
const handleHttpUpload = async (options: UploadRequestOptions) => {
|
||||
let formData = new FormData();
|
||||
formData.append('file', options.file);
|
||||
formData.append('dir', props.dir);
|
||||
try {
|
||||
const { data } = await request({
|
||||
url: props.uploadFileUrl,
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
data: formData,
|
||||
});
|
||||
emit('update:imageUrl', data.url);
|
||||
// 调用 el-form 内部的校验方法(可自动校验)
|
||||
formItemContext?.prop && formContext?.validateField([formItemContext.prop as string]);
|
||||
} catch (error) {
|
||||
options.onError(error as any);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 删除图片
|
||||
* */
|
||||
const deleteImg = () => {
|
||||
emit('update:imageUrl', '');
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 编辑图片
|
||||
* */
|
||||
const editImg = () => {
|
||||
const dom = document.querySelector(`#${uuid.value} .el-upload__input`);
|
||||
dom && dom.dispatchEvent(new MouseEvent('click'));
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 文件上传之前判断
|
||||
* @param rawFile 选择的文件
|
||||
* */
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize;
|
||||
const imgType = props.fileType.includes(rawFile.type as File.ImageMimeType);
|
||||
if (!imgType)
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '上传图片不符合所需的格式!',
|
||||
type: 'warning',
|
||||
});
|
||||
if (!imgSize)
|
||||
setTimeout(() => {
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: `上传图片大小不能超过 ${props.fileSize}M!`,
|
||||
type: 'warning',
|
||||
});
|
||||
}, 0);
|
||||
return imgType && imgSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 图片上传成功
|
||||
* */
|
||||
const uploadSuccess = () => {
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '图片上传成功!',
|
||||
type: 'success',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 图片上传错误
|
||||
* */
|
||||
const uploadError = () => {
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '图片上传失败,请您重新上传!',
|
||||
type: 'error',
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.is-error {
|
||||
.upload {
|
||||
:deep(.el-upload),
|
||||
:deep(.el-upload-dragger) {
|
||||
border: 1px dashed var(--el-color-danger) !important;
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.disabled) {
|
||||
.el-upload,
|
||||
.el-upload-dragger {
|
||||
cursor: not-allowed !important;
|
||||
background: var(--el-disabled-bg-color);
|
||||
border: 1px dashed var(--el-border-color-darker) !important;
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-border-color-darker) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.upload-box {
|
||||
.no-border {
|
||||
:deep(.el-upload) {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
:deep(.upload) {
|
||||
.el-upload {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: v-bind(width);
|
||||
height: v-bind(height);
|
||||
overflow: hidden;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
transition: var(--el-transition-duration-fast);
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
.upload-handle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.el-upload-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: transparent;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.el-upload-dragger.is-dragover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border: 2px dashed var(--el-color-primary) !important;
|
||||
}
|
||||
.upload-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.upload-empty {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
color: var(--el-color-info);
|
||||
.el-icon {
|
||||
font-size: 28px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
.upload-handle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background: rgb(0 0 0 / 60%);
|
||||
opacity: 0;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
.handle-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 6%;
|
||||
color: aliceblue;
|
||||
.el-icon {
|
||||
margin-bottom: 40%;
|
||||
font-size: 130%;
|
||||
line-height: 130%;
|
||||
}
|
||||
span {
|
||||
font-size: 85%;
|
||||
line-height: 85%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-upload__tip {
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,19 @@
|
||||
export default {
|
||||
excel: {
|
||||
downloadTemplate: 'downloading the template',
|
||||
fileFormat: 'only xls, xlsx format files are allowed',
|
||||
operationNotice: 'Drag the file here and',
|
||||
clickUpload: 'click upload',
|
||||
lineNumbers: 'line numbers',
|
||||
misDescription: 'misDescription',
|
||||
validationFailureData: 'validation failure data',
|
||||
pleaseUpload: 'please upload',
|
||||
size: 'size not exceeding',
|
||||
format: 'format',
|
||||
file: 'file',
|
||||
sizeErrorText: 'file size error, max ',
|
||||
typeErrorText: 'file type error, upload ',
|
||||
uploadLimit: 'Upload limit exceeded. Maximum',
|
||||
files: 'files allowed',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
export default {
|
||||
excel: {
|
||||
downloadTemplate: '下载模板',
|
||||
fileFormat: '仅允许导入xls、xlsx格式文件。',
|
||||
operationNotice: '将文件拖到此处,或',
|
||||
clickUpload: '点击上传',
|
||||
lineNumbers: '行号',
|
||||
misDescription: '错误描述',
|
||||
validationFailureData: '校验失败数据',
|
||||
pleaseUpload: '请上传',
|
||||
size: '大小不超过',
|
||||
format: '格式为',
|
||||
file: '的文件',
|
||||
sizeErrorText: '文件大小不超过',
|
||||
typeErrorText: '文件类型错误,请上传 ',
|
||||
uploadLimit: '上传文件数量超出限制,最多允许上传',
|
||||
files: '个文件',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,259 @@
|
||||
<!--文件上传组件-->
|
||||
<template>
|
||||
<div class="w-full 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"
|
||||
:on-exceed="handleExceed"
|
||||
:data="formData"
|
||||
:auto-upload="autoUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
class="upload-file-uploader"
|
||||
drag
|
||||
multiple
|
||||
>
|
||||
<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"
|
||||
:on-exceed="handleExceed"
|
||||
:data="formData"
|
||||
:on-success="handleUploadSuccess"
|
||||
class="upload-file-uploader"
|
||||
multiple
|
||||
>
|
||||
<el-button type="primary" link>{{ $t('excel.clickUpload') }}</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="upload-file">
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import other from '/@/utils/other';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
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',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
validator: (value: string) => {
|
||||
return ['default', 'simple'].includes(value);
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
dir: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
autoUpload: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const number = ref(0);
|
||||
const fileList = ref<{ name?: string; url?: string; uid?: number }[]>([]);
|
||||
const uploadList = ref<{ name: string; url: string; fileUrl: string; fileSize: number; fileName: string; fileType: string }[]>([]);
|
||||
const fileUpload = ref();
|
||||
const { t } = useI18n();
|
||||
|
||||
// 请求头处理
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
Authorization: 'Bearer ' + Session.get('token'),
|
||||
'TENANT-ID': Session.getTenant(),
|
||||
};
|
||||
});
|
||||
|
||||
// 请求参数处理
|
||||
const formData = computed(() => {
|
||||
return Object.assign(props.data, { dir: props.dir });
|
||||
});
|
||||
|
||||
// 上传前校检格式和大小
|
||||
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;
|
||||
};
|
||||
|
||||
// 上传成功回调
|
||||
function handleUploadSuccess(res: any, file: any) {
|
||||
if (res.code === 0) {
|
||||
uploadList.value.push({
|
||||
name: file.name,
|
||||
url: res.data.url,
|
||||
fileUrl: res.data.fileName,
|
||||
fileSize: file.size,
|
||||
fileName: file.name,
|
||||
fileType: file.raw.type,
|
||||
});
|
||||
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), fileList.value);
|
||||
emit('update:modelValue', listToString(fileList.value));
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = (file: { url: string }) => {
|
||||
fileList.value = fileList.value.filter((f) => f.url !== file.url);
|
||||
emit('change', listToString(fileList.value));
|
||||
emit('update:modelValue', listToString(fileList.value));
|
||||
};
|
||||
|
||||
const handlePreview = (file: any) => {
|
||||
other.downBlobFile(file.url, {}, file.name);
|
||||
};
|
||||
|
||||
// 添加 handleExceed 函数
|
||||
const handleExceed = (files: File[]) => {
|
||||
useMessage().warning(`${t('excel.uploadLimit')} ${props.limit} ${t('excel.files')}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 将对象数组转为字符串,以逗号分隔。
|
||||
* @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) : '';
|
||||
};
|
||||
|
||||
const handleUploadError = () => {
|
||||
useMessage().error('上传文件失败');
|
||||
};
|
||||
|
||||
/**
|
||||
* 监听 props 中的 modelValue 值变化,更新 fileList。
|
||||
*/
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val) {
|
||||
let temp = 1;
|
||||
// 首先将值转为数组
|
||||
const list = Array.isArray(val) ? val : (props.modelValue as string).split(',');
|
||||
// 然后将数组转为对象数组
|
||||
fileList.value = list.map((item) => {
|
||||
if (typeof item === 'string') {
|
||||
item = { name: item.split('fileName=')[1], url: item };
|
||||
}
|
||||
item.uid = item.uid || new Date().getTime() + temp++;
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
fileList.value = [];
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
const submit = () => {
|
||||
fileUpload.value.submit();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
submit,
|
||||
});
|
||||
</script>
|
||||
Reference in new issue
Block a user