Pre Merge pull request !5 from NicholasLD/fileupload-fix
This commit is contained in:
commit
eb8abd9599
@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, useAttrs, watch } from 'vue';
|
||||
import { computed, ref, useAttrs, watch } from 'vue';
|
||||
import type { UploadFileInfo, UploadProps } from 'naive-ui';
|
||||
import { fetchBatchDeleteOss } from '@/service/api/system/oss';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { fetchBatchDeleteOss, listByIds } from '@/service/api/system/oss';
|
||||
import { getToken } from '@/store/modules/auth/shared';
|
||||
import { getServiceBaseURL } from '@/utils/service';
|
||||
|
||||
@ -18,6 +19,7 @@ interface Props {
|
||||
accept?: string;
|
||||
fileSize?: number;
|
||||
uploadType?: 'file' | 'image';
|
||||
modelValue?: string | string[] | any[]; // 用于回显
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@ -26,26 +28,70 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
defaultUpload: true,
|
||||
showTip: true,
|
||||
max: 5,
|
||||
accept: '.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.pdf',
|
||||
accept: '',
|
||||
fileSize: 5,
|
||||
uploadType: 'file'
|
||||
uploadType: 'file',
|
||||
modelValue: ''
|
||||
});
|
||||
|
||||
const attrs: UploadProps = useAttrs();
|
||||
|
||||
const accept = computed(() => {
|
||||
return props.uploadType === 'file' ? '.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.pdf' : '.jpg,.jpeg,.png,.gif,.bmp,.webp';
|
||||
});
|
||||
|
||||
let fileNum = 0;
|
||||
const fileList = ref<UploadFileInfo[]>([]);
|
||||
|
||||
const needRelaodData = ref(false);
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void;
|
||||
}>();
|
||||
|
||||
defineExpose({
|
||||
needRelaodData
|
||||
});
|
||||
watch(
|
||||
() => fileList.value,
|
||||
newValue => {
|
||||
needRelaodData.value = newValue.length > 0;
|
||||
}
|
||||
() => props.modelValue,
|
||||
async (newValue: string | any[] | string[]) => {
|
||||
if (!newValue) {
|
||||
fileList.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let list: UploadFileInfo[] = [];
|
||||
|
||||
if (Array.isArray(newValue)) {
|
||||
list = newValue as UploadFileInfo[];
|
||||
} else {
|
||||
try {
|
||||
const res = await listByIds(newValue);
|
||||
list = res.data;
|
||||
} catch (error) {
|
||||
list = [];
|
||||
throw new Error(`获取文件列表失败: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
fileList.value = list.map((item: any) => {
|
||||
if (typeof item === 'string') {
|
||||
return {
|
||||
id: item,
|
||||
name: item,
|
||||
url: item,
|
||||
status: 'finished'
|
||||
} as UploadFileInfo;
|
||||
}
|
||||
|
||||
return {
|
||||
id: String(item.ossId),
|
||||
name: item.fileName,
|
||||
url: item.url,
|
||||
status: 'finished'
|
||||
} as UploadFileInfo;
|
||||
});
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
|
||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||
@ -56,7 +102,12 @@ const headers: Record<string, string> = {
|
||||
clientid: import.meta.env.VITE_APP_CLIENT_ID!
|
||||
};
|
||||
|
||||
// 拷贝一份当前的FileList
|
||||
let currentFileList: UploadFileInfo[] = [];
|
||||
|
||||
function beforeUpload(options: { file: UploadFileInfo; fileList: UploadFileInfo[] }) {
|
||||
currentFileList = cloneDeep(fileList.value);
|
||||
|
||||
fileNum += 1;
|
||||
const { file } = options;
|
||||
|
||||
@ -70,6 +121,12 @@ function beforeUpload(options: { file: UploadFileInfo; fileList: UploadFileInfo[
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (accept.value && !file.name.match(new RegExp(accept.value.replace(/\./g, '\\.').replace(/,/g, '|')))) {
|
||||
window.$message?.error(`文件格式不正确, 请上传 ${accept.value} 格式文件!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 校检文件名是否包含特殊字符
|
||||
if (file.name.includes(',')) {
|
||||
window.$message?.error('文件名不正确,不能包含英文逗号!');
|
||||
@ -92,23 +149,54 @@ function isErrorState(xhr: XMLHttpRequest) {
|
||||
return response.code !== 200;
|
||||
}
|
||||
|
||||
// 对象转成指定字符串分隔
|
||||
const listToString = (list: any[]) => {
|
||||
let strs = '';
|
||||
const separator = ',';
|
||||
for (const i in list) {
|
||||
if (undefined !== list[i].id && list[i].url?.indexOf('blob:') !== 0) {
|
||||
strs += list[i].id + separator;
|
||||
}
|
||||
}
|
||||
return strs !== '' ? strs.substring(0, strs.length - 1) : '';
|
||||
};
|
||||
|
||||
// 上传中的文件列表
|
||||
const uploadingFiles = ref<any[]>([]);
|
||||
|
||||
function handleFinish(options: { file: UploadFileInfo; event?: ProgressEvent }) {
|
||||
fileNum -= 1;
|
||||
const { file, event } = options;
|
||||
// @ts-expect-error Ignore type errors
|
||||
const responseText = event?.target?.responseText;
|
||||
const response = JSON.parse(responseText);
|
||||
const oss: Api.System.Oss = response.data;
|
||||
fileList.value.find(item => item.id === file.id)!.id = String(oss.ossId);
|
||||
file.id = String(oss.ossId);
|
||||
file.url = oss.url;
|
||||
file.name = oss.fileName;
|
||||
const { file } = options;
|
||||
|
||||
// 标记当前文件上传完成
|
||||
const target = event?.target as XMLHttpRequest;
|
||||
const responseText = target?.responseText;
|
||||
const uploadFileResp = JSON.parse(responseText).data;
|
||||
|
||||
uploadingFiles.value.push({
|
||||
id: uploadFileResp.ossId,
|
||||
name: uploadFileResp.fileName,
|
||||
url: uploadFileResp.url
|
||||
});
|
||||
|
||||
// 检查是否所有文件都上传完成
|
||||
if (fileNum === 0) {
|
||||
// 所有文件上传完成,执行批量查询
|
||||
handleAllFilesUploaded();
|
||||
window.$message?.success('上传成功');
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
async function handleAllFilesUploaded() {
|
||||
fileList.value = [...currentFileList, ...uploadingFiles.value];
|
||||
uploadingFiles.value = [];
|
||||
const fileIds = listToString(fileList.value);
|
||||
emit('update:modelValue', fileIds);
|
||||
needRelaodData.value = true;
|
||||
}
|
||||
|
||||
function handleError(options: { file: UploadFileInfo; event?: ProgressEvent }) {
|
||||
const { event } = options;
|
||||
// @ts-expect-error Ignore type errors
|
||||
@ -121,8 +209,13 @@ async function handleRemove(file: UploadFileInfo) {
|
||||
if (file.status !== 'finished') {
|
||||
return;
|
||||
}
|
||||
fileList.value = fileList.value.filter(item => item.id !== file.id);
|
||||
const fileIds = listToString(fileList.value);
|
||||
emit('update:modelValue', fileIds);
|
||||
needRelaodData.value = true;
|
||||
const { error } = await fetchBatchDeleteOss([file.id]);
|
||||
if (error) return;
|
||||
|
||||
window.$message?.success('删除成功');
|
||||
}
|
||||
</script>
|
||||
|
@ -10,6 +10,14 @@ export function fetchGetOssList(params?: Api.System.OssSearchParams) {
|
||||
});
|
||||
}
|
||||
|
||||
// 查询OSS对象基于id串
|
||||
export function listByIds(ossId: string | number) {
|
||||
return request({
|
||||
url: `/resource/oss/listByIds/${ossId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/** 批量删除文件管理 */
|
||||
export function fetchBatchDeleteOss(ossIds: CommonType.IdType[]) {
|
||||
return request<boolean>({
|
||||
|
Loading…
Reference in New Issue
Block a user