feat: 建立前端 TS 类型系统与 API 请求服务层

This commit is contained in:
2026-08-04 17:09:55 +08:00
parent daae052878
commit d18d9dbaac
6 changed files with 162 additions and 0 deletions

View File

@ -0,0 +1,17 @@
import api from "./api";
export interface DashboardStats {
products_total: number;
products_pending: number;
products_in_progress: number;
products_completed: number;
tasks_total: number;
tasks_pending: number;
tasks_in_progress: number;
tasks_completed: number;
}
export async function fetchDashboardStats(): Promise<DashboardStats> {
const { data } = await api.get<DashboardStats>("/dashboard/stats");
return data;
}

View File

@ -0,0 +1,12 @@
import api from "./api";
export interface OrderOption {
id: string;
order_no: string;
}
/** 获取订单列表(供下拉选择) */
export async function listOrders(): Promise<OrderOption[]> {
const { data } = await api.get<OrderOption[]>("/orders/");
return data;
}

View File

@ -0,0 +1,10 @@
import api from "./api";
import type { ProductScanResponse } from "../types/api";
/** 扫码查询 — 根据 16 位序列号查产品 + 顶层任务 */
export async function scanProduct(serialNumber: string): Promise<ProductScanResponse> {
const { data } = await api.get<ProductScanResponse>(
`/products/scan/${encodeURIComponent(serialNumber)}`
);
return data;
}

View File

@ -0,0 +1,64 @@
import api from "./api";
import type {
TaskResponse,
TaskCompleteResponse,
TaskListResponse,
} from "../types/api";
// ============================================================
// 请求体类型
// ============================================================
export interface SubtaskCreatePayload {
task_name: string;
assignee_id: string | null;
notify_parent_on_complete: boolean;
}
export interface TaskCompletePayload {
operator_id: string | null;
next_assignee_id: string | null;
next_task_name: string | null;
remark: string | null;
}
// ============================================================
// API 方法
// ============================================================
/** 获取任务详情 — 递归包含子任务树 */
export async function getTask(taskId: string): Promise<TaskResponse> {
const { data } = await api.get<TaskResponse>(`/tasks/${taskId}`);
return data;
}
/** 获取任务列表(可按产品筛选) */
export async function listTasks(productId?: string): Promise<TaskListResponse> {
const params = productId ? { product_id: productId } : {};
const { data } = await api.get<TaskListResponse>("/tasks/", { params });
return data;
}
/** 创建子任务 */
export async function createSubtask(
parentTaskId: string,
payload: SubtaskCreatePayload
): Promise<TaskResponse> {
const { data } = await api.post<TaskResponse>(
`/tasks/${parentTaskId}/subtasks`,
payload
);
return data;
}
/** 完成任务 + 转交 */
export async function completeTask(
taskId: string,
payload: TaskCompletePayload
): Promise<TaskCompleteResponse> {
const { data } = await api.post<TaskCompleteResponse>(
`/tasks/${taskId}/complete`,
payload
);
return data;
}

View File

@ -0,0 +1,12 @@
/** 管理端 API 响应类型 */
export interface ProductResponse {
id: string;
serial_number: string;
order_id: string;
order_no?: string;
material_id: string | null;
parent_product_id: string | null;
status: string;
created_at: string;
}

47
frontend/src/types/api.ts Normal file
View File

@ -0,0 +1,47 @@
/** 后端 API 响应类型 */
// ============================================================
// 任务
// ============================================================
export interface TaskSummary {
id: string;
product_id: string;
parent_task_id: string | null;
task_name: string;
assignee_id: string | null;
status: string;
notify_parent_on_complete: boolean;
created_at: string;
}
export interface TaskResponse extends TaskSummary {
child_tasks: TaskResponse[];
}
export interface TaskCompleteResponse {
completed_task: TaskResponse;
next_task: TaskResponse | null;
message: string;
}
export interface TaskListResponse {
tasks: TaskResponse[];
total: number;
}
// ============================================================
// 产品
// ============================================================
export interface ProductScanResponse {
id: string;
serial_number: string;
order_id: string;
order_no: string;
material_id: string | null;
parent_product_id: string | null;
status: string;
created_at: string;
top_level_tasks: TaskSummary[];
}