Pre Merge pull request !5 from NicholasLD/fileupload-fix

This commit is contained in:
NicholasLD 2025-06-10 12:34:27 +00:00 committed by Gitee
commit eb8abd9599
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
2 changed files with 118 additions and 17 deletions

View File

@ -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>

View File

@ -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>({