Files
track/frontend/src/services/dashboardApi.ts
duxingchen 90f5718e68 fix(驳回/返工): 抽屉与卡片数字口径一致,同时展示已驳回+返工任务
- 根因:卡片数字含返工任务(tasks_rework 实时快照),但抽屉只列已驳回 → 点开为空
- get_rejected_tasks 扩展返回两类(kind=rejected 按时间过滤 / kind=rework 实时不过滤)
- 前端抽屉按「已驳回」「返工任务」分组展示,数字与明细一一对应
2026-08-28 11:33:54 +08:00

186 lines
4.9 KiB
TypeScript

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;
tasks_rejected: number;
tasks_rework: number;
unread_notifications: number;
unread_messages: number;
}
export interface WipTask {
task_id: string;
task_name: string;
assignee: string;
product_sn: string;
external_serial: string | null;
material_name: string;
spec_model: string;
status: string;
received_at: string;
duration_hours: number;
}
export interface CompletedTask {
task_id: string;
task_name: string;
assignee: string;
product_sn: string;
external_serial: string | null;
material_name: string;
spec_model: string;
completed_at: string;
}
export interface RejectedTask {
task_id: string;
kind: "rejected" | "rework";
task_name: string;
product_sn: string;
external_serial: string | null;
material_name: string;
spec_model: string;
rejected_by: string;
rework_assignee: string;
reject_reason: string | null;
status: string | null;
rejected_at: string | null;
}
export interface PersonDevice {
product_id: string;
serial_number: string;
external_serial: string | null;
material_name: string;
spec_model: string;
task_status: string;
duration_hours: number;
received_at: string | null;
}
export interface PersonWorkload {
assignee_id: string;
assignee_name: string;
device_count: number;
devices: PersonDevice[];
}
export interface PersonHistoryRecord {
task_id: string;
task_name: string;
assignee_id: string;
assignee_name: string;
product_sn: string;
external_serial: string | null;
material_name: string;
spec_model: string;
status: string;
received_at: string | null;
completed_at: string | null;
duration_hours: number;
latest_valid_remark: string | null;
record_count: number;
}
export interface PeopleHistoryQuery {
since?: string;
until?: string;
assignee_id?: string;
spec_model?: string;
product_sn?: string;
task_name?: string;
}
export interface ProductMessageItem {
id: string;
content: string;
operator_name: string;
product_sn: string;
external_serial: string | null;
material_name: string;
created_at: string;
}
export interface ProductMessageList {
items: ProductMessageItem[];
total: number;
}
export async function fetchDashboardStats(since?: string, until?: string): Promise<DashboardStats> {
const params: Record<string, string> = {};
if (since) params.since = since;
if (until) params.until = until;
const { data } = await api.get<DashboardStats>("/dashboard/stats", { params });
return data;
}
export async function fetchWipTasks(limit = 20): Promise<WipTask[]> {
const { data } = await api.get<WipTask[]>("/dashboard/wip-tasks", { params: { limit } });
return data;
}
export async function fetchCompletedTasks(since?: string, until?: string): Promise<CompletedTask[]> {
const params: Record<string, string> = {};
if (since) params.since = since;
if (until) params.until = until;
const { data } = await api.get<CompletedTask[]>("/dashboard/completed-tasks", { params });
return data;
}
export async function fetchRejectedTasks(since?: string, until?: string): Promise<RejectedTask[]> {
const params: Record<string, string> = {};
if (since) params.since = since;
if (until) params.until = until;
const { data } = await api.get<RejectedTask[]>("/dashboard/rejected-tasks", { params });
return data;
}
export async function fetchPeopleWorkload(): Promise<PersonWorkload[]> {
const { data } = await api.get<PersonWorkload[]>("/dashboard/people-workload");
return data;
}
export async function fetchPeopleHistory(query: PeopleHistoryQuery = {}): Promise<PersonHistoryRecord[]> {
const params: Record<string, string> = {};
for (const [k, v] of Object.entries(query)) {
if (v) params[k] = v;
}
const { data } = await api.get<PersonHistoryRecord[]>("/dashboard/people-history", { params });
return data;
}
export async function downloadPeopleHistory(query: PeopleHistoryQuery = {}): Promise<void> {
const params: Record<string, string> = {};
for (const [k, v] of Object.entries(query)) {
if (v) params[k] = v;
}
const res = await api.get("/dashboard/people-history/export", {
params,
responseType: "blob",
});
const url = window.URL.createObjectURL(res.data as Blob);
const a = document.createElement("a");
a.href = url;
a.download = "people_history.csv";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}
export async function fetchDashboardMessages(
keyword = "", skip = 0, limit = 30,
): Promise<ProductMessageList> {
const { data } = await api.get<ProductMessageList>("/dashboard/messages", {
params: { keyword, skip, limit },
});
return data;
}