/** * WIP 分布矩阵 — 在制品透视表(规格型号 × 人员/工序,单元格=设备数量) * Y 轴 = 规格型号,X 轴 = 人员 或 工序,单元格 = 该交叉点的在制品设备数 */ import { useEffect, useMemo, useState } from "react"; import { Radio, Table, DatePicker, Button } from "antd"; import type { Dayjs } from "dayjs"; import { fetchWipMatrix, type WipMatrixRow } from "../services/dashboardApi"; const { RangePicker } = DatePicker; export default function MatrixBoard() { const [dimension, setDimension] = useState<"assignee" | "task_name">("assignee"); const [range, setRange] = useState<[Dayjs, Dayjs] | null>(null); const [data, setData] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { setLoading(true); fetchWipMatrix( dimension, range ? range[0].startOf("day").toISOString() : undefined, range ? range[1].endOf("day").toISOString() : undefined, ) .then(setData) .catch(() => setData([])) .finally(() => setLoading(false)); }, [dimension, range]); // 🔧 核心:扁平数组 → 动态交叉表(规格型号为行、dimension_key 为列) const { columns, dataSource } = useMemo(() => { const keys = Array.from(new Set(data.map((d) => d.dimension_key))); const rowsMap = new Map(); for (const item of data) { if (!rowsMap.has(item.spec_model)) { rowsMap.set(item.spec_model, { spec_model: item.spec_model, _assignees: {}, row_total: 0 }); } const row = rowsMap.get(item.spec_model); row[item.dimension_key] = (row[item.dimension_key] || 0) + item.count; row.row_total += item.count; // 记录每个交叉点的主负责人(中文名,去重) row._assignees[item.dimension_key] = item.assignees || []; } const ds = Array.from(rowsMap.values()); const cols: any[] = [ { title: "规格型号", dataIndex: "spec_model", fixed: "left", width: 190, render: (v: string) => {v} }, ...keys.map((key) => ({ title: key, dataIndex: key, align: "center" as const, width: 120, render: (val: number, record: any) => { const assignees = record._assignees?.[key] || []; return (
{val || 0}
{assignees.length > 0 && (
{assignees.join("、")}
)}
); }, })), { title: "合计", dataIndex: "row_total", fixed: "right" as const, align: "center" as const, width: 90, render: (v: number) => {v} }, ]; return { columns: cols, dataSource: ds }; }, [data]); return (

📊 WIP 分布矩阵

生产分布透视表:规格型号 × {dimension === "assignee" ? "人员" : "工序"} · 含在库/完成

setRange(dates as [Dayjs, Dayjs] | null)} style={{ width: 240 }} placeholder={["开始日期", "结束日期"]} /> {range && } setDimension(e.target.value)} optionType="button" buttonStyle="solid"> 按人员分布 按工序分布
); }