feat: 添加导入Bintask Excel文件功能,更新API和场景编辑器以支持文件上传,优化HTTP服务以处理FormData

This commit is contained in:
xudan 2025-09-12 14:57:42 +08:00
parent 5cdbcebcd3
commit 6163b0baa5
3 changed files with 71 additions and 5 deletions

View File

@ -12,6 +12,8 @@ const enum API {
= '/scene/getByGroupId',
= '/scene/saveByGroupId',
Bintask = '/scene/importBinTaskExcel',
= '/scene/monitor/:id',
= '/scene/monitor/real/:id',
= '/ws/storage-location/:id',
@ -123,6 +125,38 @@ export async function monitorRealSceneById(id: SceneInfo['id']): Promise<WebSock
}
}
export async function importBinTaskExcel(id: SceneInfo['id'], file: File): Promise<boolean> {
if (!id || !file) return false;
// 验证文件类型和大小
const allowedTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
'application/vnd.ms-excel' // .xls
];
if (!allowedTypes.includes(file.type)) {
throw new Error('请选择Excel文件.xlsx或.xls格式');
}
// 验证文件大小1MB = 1024 * 1024 bytes
const maxSize = 1024 * 1024;
if (file.size > maxSize) {
throw new Error('文件大小不能超过1MB');
}
try {
const formData = new FormData();
formData.append('file', file);
formData.append('id', id);
await http.postFormData(API.Bintask, formData);
return true;
} catch (error) {
console.debug(error);
return false;
}
}
export async function monitorStorageLocationById(
id: SceneInfo['id'],
options?: {

View File

@ -3,7 +3,7 @@ import { message, Modal } from 'ant-design-vue';
import { computed, onMounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { getSceneById, pushSceneById, saveSceneById } from '../apis/scene';
import { getSceneById, importBinTaskExcel, pushSceneById, saveSceneById } from '../apis/scene';
import BatchEditToolbar from '../components/batch-edit-toolbar.vue';
import AutoCreateStorageModal from '../components/modal/auto-create-storage-modal.vue';
import { EditorService } from '../services/editor.service';
@ -80,15 +80,15 @@ const autoCreateStorageData = ref<{
actionPoints: any[];
}>({
areaName: '',
actionPoints: []
actionPoints: [],
});
onMounted(() => {
editor.value = new EditorService(container.value!);
// editor store
editorStore.setEditor(editor as ShallowRef<EditorService>);
//
editor.value?.on('autoCreateStorageDialog', (data: any) => {
autoCreateStorageData.value = data;
@ -134,6 +134,23 @@ const exportScene = () => {
URL.revokeObjectURL(url);
};
// Bintask Excel
const importBinTask = async () => {
try {
const file = await selectFile('.xlsx,.xls');
if (!file || !file.size) return;
const success = await importBinTaskExcel(props.id, file);
if (success) {
message.success('Bintask导入成功');
} else {
message.error('Bintask导入失败');
}
} catch (error: any) {
message.error(error.message || 'Bintask导入失败');
}
};
const show = ref<boolean>(true);
const current = ref<{ type: 'robot' | 'point' | 'line' | 'area'; id: string }>();
watch(
@ -187,7 +204,7 @@ const backToCards = () => {
//
const handleAutoCreateStorageConfirm = (actionPoints: any[]) => {
if (!editor.value) return;
editor.value.autoCreateStorageLocations(autoCreateStorageData.value.areaName, actionPoints);
message.success(`已为 ${actionPoints.length} 个动作点自动生成库位`);
};
@ -216,6 +233,7 @@ const handleAutoCreateStorageCancel = () => {
</a-button>
<a-button @click="toPush">{{ $t('推送') }}</a-button>
<a-button @click="importScene">{{ $t('导入') }}</a-button>
<a-button @click="importBinTask">导入Bintask</a-button>
<a-button @click="exportScene">{{ $t('导出') }}</a-button>
</a-space>
</a-flex>

View File

@ -7,6 +7,19 @@ const http: HttpInstance = axios.create({
adapter: 'fetch',
timeout: 30_000,
});
// 添加FormData上传方法
http.postFormData = async <D = void>(url: string, formData: FormData, config?: AxiosRequestConfig): Promise<D | undefined> => {
const response = await http.post<D>(url, formData, {
...config,
headers: {
'Content-Type': 'multipart/form-data',
...config?.headers,
},
});
return response;
};
export default http;
// 添加请求拦截器
@ -63,6 +76,7 @@ http.interceptors.response.use(
type HttpInstance = Omit<AxiosInstance, 'get' | 'post'> & {
get: <D = void>(url: string, config?: AxiosRequestConfig) => Promise<D | undefined>;
post: <D = void, B = unknown>(url: string, body?: B, config?: AxiosRequestConfig<B>) => Promise<D | undefined>;
postFormData: <D = void>(url: string, formData: FormData, config?: AxiosRequestConfig) => Promise<D | undefined>;
};
type CommonRes<T = void> = {