- 根因:卡片数字含返工任务(tasks_rework 实时快照),但抽屉只列已驳回 → 点开为空 - get_rejected_tasks 扩展返回两类(kind=rejected 按时间过滤 / kind=rework 实时不过滤) - 前端抽屉按「已驳回」「返工任务」分组展示,数字与明细一一对应
186 lines
4.9 KiB
TypeScript
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;
|
|
}
|