完善文件上传
This commit is contained in:
parent
b16a495cf1
commit
9a9420f423
@ -54,5 +54,6 @@
|
||||
"exportFailed": "Data export failed",
|
||||
"getDataFailed": "Failed to get data",
|
||||
"PhoneNumberFormatError": "PhoneNumber Format Error",
|
||||
"IoTPlatform": "IoTPlatform"
|
||||
"IoTPlatform": "IoTPlatform",
|
||||
"note": "note"
|
||||
}
|
||||
|
||||
@ -55,5 +55,6 @@
|
||||
"getDataFailed": "获取数据失败",
|
||||
"IsEnabled": "是否启用",
|
||||
"PhoneNumberFormatError": "手机号码格式错误",
|
||||
"IoTPlatform": "物联网平台"
|
||||
"IoTPlatform": "物联网平台",
|
||||
"note": "备注"
|
||||
}
|
||||
|
||||
@ -1,12 +1,26 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { createIconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { addFormSchema } from './schema';
|
||||
import { postFilesUpload } from '#/api-client/index';
|
||||
|
||||
const emit = defineEmits(['reload']);
|
||||
|
||||
// 创建上传图标
|
||||
const UploadIcon = createIconifyIcon('mdi:upload');
|
||||
const FolderIcon = createIconifyIcon('mdi:folder');
|
||||
|
||||
// 文件列表状态
|
||||
const fileList = ref<any[]>([]);
|
||||
const uploading = ref(false);
|
||||
const fileInput = ref<HTMLInputElement>();
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
// 所有表单项共用,可单独在表单内覆盖
|
||||
commonConfig: {
|
||||
@ -22,18 +36,277 @@ const [Form, formApi] = useVbenForm({
|
||||
schema: addFormSchema,
|
||||
wrapperClass: 'grid-cols-1',
|
||||
});
|
||||
|
||||
// 处理文件变化
|
||||
const handleFileChange = (info: any) => {
|
||||
console.log('File change:', info);
|
||||
console.log('File list before:', fileList.value);
|
||||
fileList.value = info.fileList;
|
||||
console.log('File list after:', fileList.value);
|
||||
};
|
||||
|
||||
// 文件上传前的验证
|
||||
const beforeUpload = (file: File) => {
|
||||
// 这里可以添加文件大小、类型等验证
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
if (!isLt10M) {
|
||||
message.error('文件大小不能超过10MB!');
|
||||
return false;
|
||||
}
|
||||
return true; // 允许文件选择,但不自动上传
|
||||
};
|
||||
|
||||
// 移除文件
|
||||
const handleRemove = (file: any) => {
|
||||
const index = fileList.value.indexOf(file);
|
||||
const newFileList = fileList.value.slice();
|
||||
newFileList.splice(index, 1);
|
||||
fileList.value = newFileList;
|
||||
};
|
||||
|
||||
// 触发文件选择
|
||||
const triggerFileInput = () => {
|
||||
fileInput.value?.click();
|
||||
};
|
||||
|
||||
// 处理文件输入变化
|
||||
const handleFileInputChange = (event: Event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.files) {
|
||||
const newFiles = Array.from(target.files).map(file => ({
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
type: file.type,
|
||||
originFileObj: file
|
||||
}));
|
||||
|
||||
// 验证文件大小(10MB限制)
|
||||
const validFiles = newFiles.filter(file => {
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
if (!isLt10M) {
|
||||
message.error(`文件 ${file.name} 大小超过10MB限制`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
fileList.value = [...fileList.value, ...validFiles];
|
||||
}
|
||||
};
|
||||
|
||||
// 处理拖拽
|
||||
const handleDrop = (e: DragEvent) => {
|
||||
console.log('Drop event:', e);
|
||||
e.preventDefault();
|
||||
|
||||
if (e.dataTransfer?.files) {
|
||||
const newFiles = Array.from(e.dataTransfer.files).map(file => ({
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
type: file.type,
|
||||
originFileObj: file
|
||||
}));
|
||||
|
||||
// 验证文件大小(10MB限制)
|
||||
const validFiles = newFiles.filter(file => {
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
if (!isLt10M) {
|
||||
message.error(`文件 ${file.name} 大小超过10MB限制`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
fileList.value = [...fileList.value, ...validFiles];
|
||||
}
|
||||
};
|
||||
|
||||
// 移除文件
|
||||
const removeFile = (index: number) => {
|
||||
fileList.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// 格式化文件大小
|
||||
const formatFileSize = (bytes: number) => {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
};
|
||||
|
||||
// 手动上传文件
|
||||
const handleUpload = async () => {
|
||||
if (fileList.value.length === 0) {
|
||||
message.warning('请选择要上传的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
uploading.value = true;
|
||||
try {
|
||||
// 获取表单数据
|
||||
const formValues = await formApi.getValues();
|
||||
console.log('Form values:', formValues);
|
||||
console.log('File list:', fileList.value);
|
||||
|
||||
// 创建一个FormData对象,包含所有文件
|
||||
const uploadFormData = new FormData();
|
||||
|
||||
// 添加所有文件到FormData
|
||||
fileList.value.forEach((fileInfo, index) => {
|
||||
if (fileInfo.originFileObj) {
|
||||
console.log(`Adding file ${index}:`, fileInfo.name, fileInfo.originFileObj);
|
||||
uploadFormData.append('files', fileInfo.originFileObj);
|
||||
}
|
||||
});
|
||||
|
||||
// 添加表单其他数据(如果有的话)
|
||||
if (formValues) {
|
||||
Object.keys(formValues).forEach(key => {
|
||||
if (formValues[key] !== undefined && formValues[key] !== null) {
|
||||
console.log(`Adding form field ${key}:`, formValues[key]);
|
||||
uploadFormData.append(key, formValues[key]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 打印FormData内容(调试用)
|
||||
for (let [key, value] of uploadFormData.entries()) {
|
||||
console.log(`FormData entry: ${key} =`, value);
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
const result = await postFilesUpload({
|
||||
body: uploadFormData as any,
|
||||
});
|
||||
|
||||
console.log('Upload result:', result);
|
||||
|
||||
// 检查上传结果
|
||||
if (result.status === 204 || result.status === 200) {
|
||||
message.success(`文件上传成功!共上传 ${fileList.value.length} 个文件`);
|
||||
emit('reload');
|
||||
modalApi.close();
|
||||
} else {
|
||||
message.error('文件上传失败,请重试');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Upload error:', error);
|
||||
message.error('文件上传失败');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
onCancel() {
|
||||
fileList.value = [];
|
||||
modalApi.close();
|
||||
},
|
||||
async onConfirm() {
|
||||
emit('reload');
|
||||
modalApi.close();
|
||||
await handleUpload();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Modal :title="$t('common.upload')">
|
||||
<Modal :title="$t('common.upload')" :confirm-loading="uploading">
|
||||
<Form />
|
||||
<div class="mt-4">
|
||||
<div class="upload-area" @click="triggerFileInput" @drop="handleDrop" @dragover.prevent>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
multiple
|
||||
accept="*/*"
|
||||
style="display: none"
|
||||
@change="handleFileInputChange"
|
||||
/>
|
||||
<div class="ant-upload-drag-container">
|
||||
<p class="ant-upload-drag-icon">
|
||||
<FolderIcon />
|
||||
</p>
|
||||
<p class="ant-upload-text">点击或拖拽文件到此区域上传</p>
|
||||
<p class="ant-upload-hint">
|
||||
支持单个或批量上传,严禁上传公司数据或其他敏感文件
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 显示已选择的文件列表 -->
|
||||
<div v-if="fileList.length > 0" class="mt-4">
|
||||
<h4>已选择的文件:</h4>
|
||||
<div v-for="(file, index) in fileList" :key="index" class="file-item">
|
||||
<div class="file-info">
|
||||
<span class="file-name">{{ file.name }}</span>
|
||||
<span class="file-size">{{ formatFileSize(file.size) }}</span>
|
||||
</div>
|
||||
<button type="button" class="ant-btn ant-btn-link ant-btn-sm" @click="removeFile(index)">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.ant-upload-drag-container {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border: 2px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
background: #fafafa;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
|
||||
.ant-upload-drag-container:hover {
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
.ant-upload-drag-icon {
|
||||
font-size: 48px;
|
||||
color: #999;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.ant-upload-text {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ant-upload-hint {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 8px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -10,6 +10,9 @@ import { postFilesDelete } from '#/api-client/index';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
|
||||
|
||||
export const querySchema = computed(() => [
|
||||
{
|
||||
component: 'RangePicker',
|
||||
@ -66,33 +69,13 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
||||
]);
|
||||
|
||||
export const addFormSchema = computed(() => [
|
||||
// 文件上传现在在AddModal中处理
|
||||
{
|
||||
component: 'Upload',
|
||||
fieldName: 'files',
|
||||
label: $t('abp.file.file'),
|
||||
componentProps: () => {
|
||||
return {
|
||||
listType: 'picture-card',
|
||||
autoUpload: true,
|
||||
multiple: true,
|
||||
name: 'files',
|
||||
action: `${import.meta.env.VITE_APP_API_ADDRESS}/Files/Upload?access_token=${
|
||||
userStore.userInfo?.token
|
||||
}`,
|
||||
onPreview: () => {},
|
||||
onRemove: async (file: any) => {
|
||||
await postFilesDelete({
|
||||
body: {
|
||||
id: file.response[0].id,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
renderComponentContent: () => {
|
||||
return {
|
||||
default: () => 'Upload',
|
||||
};
|
||||
component: 'Input',
|
||||
fieldName: 'note',
|
||||
label: $t('common.note'),
|
||||
componentProps: {
|
||||
placeholder: '请输入备注信息',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user