feat: add project work order UI

This commit is contained in:
Frudrax Cheng
2026-06-04 10:26:05 +08:00
parent eafe55bef9
commit d8d305c051
13 changed files with 1653 additions and 9 deletions
+126
View File
@@ -10,6 +10,13 @@ import type {
CreateAftersalesRequest,
UpdateAftersalesRequest,
CustomerConfirmRequest,
ProjectOrder,
ProjectOrderPublicView,
ProjectOrderListFilter,
ProjectOrderListResponse,
CreateProjectOrderRequest,
UpdateProjectOrderRequest,
ProjectEngineerCompleteRequest,
CreateUserRequest,
UpdateUserRequest,
UserListFilter,
@@ -460,6 +467,125 @@ export const aftersalesApi = {
},
};
export const projectOrdersApi = {
create: async (data: CreateProjectOrderRequest) => {
const response = await apiClient.post('/project-orders', data);
if (response.data.order) {
return response.data.order as ProjectOrder;
}
throw new Error(response.data.error || '创建项目工单失败');
},
list: async (filter?: ProjectOrderListFilter) => {
const params = new URLSearchParams();
if (filter?.page && filter.page > 1) params.append('page', String(filter.page));
if (filter?.limit && filter.limit !== 20) params.append('limit', String(filter.limit));
if (filter?.search) params.append('search', filter.search);
if (filter?.workOrderStatus) params.append('workOrderStatus', filter.workOrderStatus);
if (filter?.projectType) params.append('serviceType', filter.projectType);
if (filter?.technicianId) params.append('technicianId', String(filter.technicianId));
if (filter?.mine) params.append('mine', 'true');
const url = params.toString() ? `/project-orders?${params.toString()}` : '/project-orders';
const response = await apiClient.get(url);
if (response.data) {
return response.data as ProjectOrderListResponse;
}
throw new Error('获取项目工单列表失败');
},
get: async (serialNumber: string) => {
const response = await apiClient.get(`/project-orders/${encodeURIComponent(serialNumber)}`);
if (response.data.order) {
return response.data.order as ProjectOrder;
}
throw new Error(response.data.error || '查询项目工单失败');
},
update: async (serialNumber: string, data: UpdateProjectOrderRequest) => {
const response = await apiClient.patch(`/project-orders/${encodeURIComponent(serialNumber)}`, data);
if (response.data.order) {
return response.data.order as ProjectOrder;
}
throw new Error(response.data.error || '更新项目工单失败');
},
submit: async (serialNumber: string, completionNote: string) => {
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/submit`, {
completionNote,
});
if (response.data.order) {
return response.data.order as ProjectOrder;
}
throw new Error(response.data.error || '提交完成资料失败');
},
generateQrCode: async (serialNumber: string, baseUrl?: string) => {
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/qrcode`, {
baseUrl,
});
if (response.data.qrCodeData) {
return response.data as { qrCodeData: string; queryUrl: string };
}
throw new Error(response.data.error || '生成二维码失败');
},
reassign: async (serialNumber: string, technicianId: number) => {
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/reassign`, {
technicianId,
});
if (response.data.order) {
return response.data.order as ProjectOrder;
}
throw new Error(response.data.error || '重新分配失败');
},
forceClose: async (serialNumber: string) => {
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/force-close`);
if (response.data.order) {
return response.data.order as ProjectOrder;
}
throw new Error(response.data.error || '确认完成失败');
},
delete: async (serialNumber: string) => {
const response = await apiClient.delete(`/project-orders/${encodeURIComponent(serialNumber)}`);
if (response.data.message) {
return true;
}
throw new Error(response.data.error || '删除项目工单失败');
},
publicQuery: async (serialNumber: string) => {
const response = await apiClient.get(`/project-orders/${encodeURIComponent(serialNumber)}/query`);
if (response.data.order) {
return response.data.order as ProjectOrderPublicView;
}
throw new Error(response.data.error || '查询项目工单失败');
},
complete: async (serialNumber: string, data: ProjectEngineerCompleteRequest) => {
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/complete`, data);
if (response.data.order) {
return response.data.order as ProjectOrderPublicView;
}
throw new Error(response.data.error || '提交完成失败');
},
uploadSiteImages: async (serialNumber: string, files: File[]) => {
const formData = new FormData();
files.forEach((file) => formData.append('files', file));
const response = await apiClient.post(
`/project-orders/${encodeURIComponent(serialNumber)}/site-images`,
formData,
);
if (response.data.siteImages) {
return response.data.siteImages as string[];
}
throw new Error(response.data.error || '上传现场图片失败');
},
};
export const usersApi = {
assignable: async () => {
const response = await apiClient.get('/users/assignable');