From 6cb7731cbb076e7aee69cd5909a047830284bfc0 Mon Sep 17 00:00:00 2001 From: duxingchen Date: Tue, 1 Sep 2026 13:53:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Track=20=E7=BD=91=E9=A1=B5=E7=AB=AF?= =?UTF-8?q?=E5=B7=B2=E5=AE=8C=E6=88=90/=E5=B7=B2=E5=85=A5=E5=BA=93/?= =?UTF-8?q?=E5=B7=B2=E5=87=BA=E5=BA=93=E7=8A=B6=E6=80=81=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=E4=B8=8E=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ProductCard/ScanPage 徽标改用整体状态,补全宏观状态中文映射 - 产品管理/任务全景/我的任务/看板/WIP分析 状态筛选与徽标区分 - 转入在库显示在库实际操作人;新增已出库/OUTBOUND 状态色 --- .../src/components/TaskTree/TaskFlowView.tsx | 11 +-- frontend/src/components/scan/ProductCard.tsx | 6 +- frontend/src/constants/task.ts | 70 ++++++++++++++++++- frontend/src/pages/MyTasksPage.tsx | 1 + frontend/src/pages/ScanPage.tsx | 4 +- frontend/src/pages/admin/AdminDashboard.tsx | 2 +- .../src/pages/admin/AdminProductsPage.tsx | 12 +++- frontend/src/pages/admin/AdminTasksPage.tsx | 25 +++++-- .../src/pages/admin/AnalyticsDashboard.tsx | 6 ++ frontend/src/types/api.ts | 1 + 10 files changed, 122 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/TaskTree/TaskFlowView.tsx b/frontend/src/components/TaskTree/TaskFlowView.tsx index 6ef10aa..08007b0 100644 --- a/frontend/src/components/TaskTree/TaskFlowView.tsx +++ b/frontend/src/components/TaskTree/TaskFlowView.tsx @@ -115,7 +115,10 @@ const SlimCard = memo(function SlimCard({

{task.task_name}

{cfg.label} - {assigneeName || task.assignee_id || "—"} + {/* 在库任务不单独显示负责人,由下方"转入在库"统一展示实际操作人 */} + {!isWarehouse && ( + {assigneeName || task.assignee_id || "—"} + )}
{/* 单行时间 */}

@@ -124,9 +127,9 @@ const SlimCard = memo(function SlimCard({

{legacy &&

源自: {assigneeName || (findParent(task)?.assignee_id) || "历史任务"}

} {isNestedSpawn &&

协助: {findParent(task)?.assignee_id || "—"}

} - {/* 📥 在库任务:显示谁转入在库 */} - {isWarehouse && task.created_by && ( -

📥 转入在库: {assigneeNames?.[task.created_by] || task.created_by}

+ {/* 📥 在库任务:显示实际执行"转入在库"的操作人(任务负责人) */} + {isWarehouse && task.assignee_id && ( +

📥 转入在库: {assigneeName || task.assignee_id}

)} {/* 操作按钮 */} {active && isOwner && ( diff --git a/frontend/src/components/scan/ProductCard.tsx b/frontend/src/components/scan/ProductCard.tsx index 6f80d05..a391e74 100644 --- a/frontend/src/components/scan/ProductCard.tsx +++ b/frontend/src/components/scan/ProductCard.tsx @@ -8,13 +8,15 @@ interface ProductCardProps { } export default function ProductCard({ product }: ProductCardProps) { + // 优先显示宏观状态(整体流转),回退到产品状态字段 + const displayStatus = product.overall_status || product.status; return (

产品信息

- - {statusLabel(product.status)} + + {statusLabel(displayStatus)}
diff --git a/frontend/src/constants/task.ts b/frontend/src/constants/task.ts index 849d9c1..ce28da1 100644 --- a/frontend/src/constants/task.ts +++ b/frontend/src/constants/task.ts @@ -42,7 +42,75 @@ export const STATUS_CONFIG: Record = { bg: "bg-gray-50", text: "text-gray-600", ring: "ring-gray-300", - label: "已完成", + label: "已入库", + }, + // 产品已发货出库(MOM 出库联动) + OUTBOUND: { + bg: "bg-indigo-50", + text: "text-indigo-600", + ring: "ring-indigo-300", + label: "已出库", + }, + // 🔧 "待收货"虚拟节点(MOM 尚未扫码实收)— 警告级橙色,区别于绿色的"已完成" + IN_PROGRESS: { + bg: "bg-orange-50", + text: "text-orange-700", + ring: "ring-orange-400", + label: "待收货", + }, + // ---- 产品宏观状态(overall_status)中文映射 ---- + // 车间完工已转交仓库、待 MOM 实收 + 待仓库收货: { + bg: "bg-orange-50", + text: "text-orange-700", + ring: "ring-orange-400", + label: "待仓库收货", + }, + // MOM 已扫码实收,入库闭环 + 已入库: { + bg: "bg-gray-100", + text: "text-gray-600", + ring: "ring-gray-400", + label: "已入库", + }, + // 旧命名"在库"等价于"已入库"(后端 _resolve_macro_status 口径一致) + 在库: { + bg: "bg-gray-100", + text: "text-gray-600", + ring: "ring-gray-400", + label: "已入库", + }, + // MOM 已发货出库 + 已出库: { + bg: "bg-indigo-50", + text: "text-indigo-600", + ring: "ring-indigo-300", + label: "已出库", + }, + // 其余流转中状态(扫码详情 ProductCard 徽标会用到) + 备货: { + bg: "bg-blue-50", + text: "text-blue-700", + ring: "ring-blue-400", + label: "备货", + }, + 生产: { + bg: "bg-blue-50", + text: "text-blue-700", + ring: "ring-blue-400", + label: "生产", + }, + 测试: { + bg: "bg-blue-50", + text: "text-blue-700", + ring: "ring-blue-400", + label: "测试", + }, + 维修: { + bg: "bg-blue-50", + text: "text-blue-700", + ring: "ring-blue-400", + label: "维修", }, }; diff --git a/frontend/src/pages/MyTasksPage.tsx b/frontend/src/pages/MyTasksPage.tsx index 17f945e..59affbb 100644 --- a/frontend/src/pages/MyTasksPage.tsx +++ b/frontend/src/pages/MyTasksPage.tsx @@ -15,6 +15,7 @@ const TABS = [ { key: "PENDING", label: "待接收" }, { key: "WIP", label: "进行中" }, { key: "COMPLETED", label: "已完成" }, + { key: "ARCHIVED", label: "已入库" }, ] as const; type TabKey = (typeof TABS)[number]["key"]; diff --git a/frontend/src/pages/ScanPage.tsx b/frontend/src/pages/ScanPage.tsx index 2a79641..1f36a6c 100644 --- a/frontend/src/pages/ScanPage.tsx +++ b/frontend/src/pages/ScanPage.tsx @@ -71,7 +71,7 @@ export default function ScanPage() {
宏观状态 - + {product.overall_status || "未设定"}
@@ -123,7 +123,7 @@ export default function ScanPage() {
宏观状态 - + {product.overall_status || "未设定"}
diff --git a/frontend/src/pages/admin/AdminDashboard.tsx b/frontend/src/pages/admin/AdminDashboard.tsx index c25d43b..6829e27 100644 --- a/frontend/src/pages/admin/AdminDashboard.tsx +++ b/frontend/src/pages/admin/AdminDashboard.tsx @@ -492,7 +492,7 @@ export default function AdminDashboard() {

{stats.products_total} 个

实时快照(不受时间筛选影响)

+ total={stats.products_total} labels={["待流转", "流转中", "已完结"]} />
{/* 任务状态 */} diff --git a/frontend/src/pages/admin/AdminProductsPage.tsx b/frontend/src/pages/admin/AdminProductsPage.tsx index 6fcf5b8..784a823 100644 --- a/frontend/src/pages/admin/AdminProductsPage.tsx +++ b/frontend/src/pages/admin/AdminProductsPage.tsx @@ -13,6 +13,7 @@ import { getLabelPreview, executePrint, } from "../../services/printApi"; import { useToast } from "../../components/ui/Toast"; +import { getStatusConfig } from "../../constants/task"; const QR_BASE = "/api/v1/products/qrcode"; @@ -20,6 +21,8 @@ const STATUS_TABS = [ { key: "PENDING", label: "待接收" }, { key: "WIP", label: "进行中" }, { key: "COMPLETED", label: "已完成" }, + { key: "ARCHIVED", label: "已入库" }, + { key: "OUTBOUND", label: "已出库" }, ]; interface ProductGroup { groupKey: string; products: ProductResponse[]; allInWarehouse: boolean; } @@ -89,7 +92,8 @@ export default function AdminProductsPage() { } return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([groupKey, prods]) => ({ groupKey, products: prods, - allInWarehouse: prods.every(p => p.current_location_id === "virtual_warehouse"), + // 已入库 = MOM 已扫码实收 (macro_status==ARCHIVED),而非仅"在仓库位置" + allInWarehouse: prods.every(p => (p.macro_status || p.status).toUpperCase() === "ARCHIVED"), })); }, [products, statusFilters, groupBy]); @@ -233,6 +237,12 @@ export default function AdminProductsPage() {
{`QR-${p.serial_number}`}

{p.serial_number}

+ {(() => { + const cfg = getStatusConfig(p.macro_status || p.status); + return cfg.label ? ( + {cfg.label} + ) : null; + })()}
diff --git a/frontend/src/pages/admin/AdminTasksPage.tsx b/frontend/src/pages/admin/AdminTasksPage.tsx index 935193d..67f5e4d 100644 --- a/frontend/src/pages/admin/AdminTasksPage.tsx +++ b/frontend/src/pages/admin/AdminTasksPage.tsx @@ -24,6 +24,8 @@ const STATUS_TABS = [ { key: "PENDING", label: "待接收" }, { key: "WIP", label: "进行中" }, { key: "COMPLETED", label: "已完成" }, + { key: "ARCHIVED", label: "已入库" }, + { key: "OUTBOUND", label: "已出库" }, ]; type SortOrder = "asc" | "desc"; @@ -44,6 +46,7 @@ interface OrderGroup { orderNo: string; products: ProductResponse[]; allInWarehouse: boolean; + allCompleted: boolean; } /** 滞留时长格式化:小时 → 天/小时/分钟 */ @@ -102,18 +105,20 @@ export default function AdminTasksPage() { render: (p) =>
{p.spec_model || p.material_name || p.material_id || "—"}
, }, { - key: "overall_status", label: "宏观状态", colSpan: 1, + key: "overall_status", label: "当前工序", colSpan: 1, filterType: "enum", getFilterValue: (p) => p.overall_status || "—", - enumOptions: ["备货", "生产", "测试", "维修", "在库"].map((v) => ({ value: v, label: v })), + enumOptions: ["备货", "生产", "测试", "维修", "在库", "待仓库收货", "已入库", "已出库"].map((v) => ({ value: v, label: v })), render: (p) => {p.overall_status || "—"}, }, { - key: "status", label: "任务状态", colSpan: 1, + key: "status", label: "产品状态", colSpan: 1, filterType: "enum", getFilterValue: (p) => (p.macro_status || p.status).toUpperCase(), enumOptions: [ { value: "PENDING", label: "待接收" }, { value: "WIP", label: "进行中" }, { value: "COMPLETED", label: "已完成" }, + { value: "ARCHIVED", label: "已入库" }, + { value: "OUTBOUND", label: "已出库" }, ], render: (p) => { const statusCfg = getStatusConfig(p.macro_status || p.status); @@ -292,8 +297,12 @@ export default function AdminTasksPage() { return { orderNo, products: sorted, + // 已入库 = MOM 已扫码实收 (macro_status==ARCHIVED),而非仅"在仓库位置" allInWarehouse: prods.every( - (p) => p.current_location_id === "virtual_warehouse" + (p) => (p.macro_status || p.status).toUpperCase() === "ARCHIVED" + ), + allCompleted: prods.every( + (p) => (p.macro_status || p.status).toUpperCase() === "COMPLETED" ), }; }); @@ -683,7 +692,13 @@ export default function AdminTasksPage() { 已全部入库 )} - {!group.allInWarehouse && ( + {group.allCompleted && !group.allInWarehouse && group.products.length > 0 && ( + + + 已完工待入库 + + )} + {!group.allInWarehouse && !group.allCompleted && ( 流转中 )} diff --git a/frontend/src/pages/admin/AnalyticsDashboard.tsx b/frontend/src/pages/admin/AnalyticsDashboard.tsx index 05c4c89..e34fbb3 100644 --- a/frontend/src/pages/admin/AnalyticsDashboard.tsx +++ b/frontend/src/pages/admin/AnalyticsDashboard.tsx @@ -24,6 +24,8 @@ const STATUS_LABEL: Record = { WIP: "进行中", PENDING: "待接收", COMPLETED: "已完成", + ARCHIVED: "已入库", + OUTBOUND: "已出库", "—": "未涉及", }; @@ -31,6 +33,8 @@ const STATUS_BADGE: Record = { WIP: "bg-blue-100 text-blue-700", PENDING: "bg-amber-100 text-amber-700", COMPLETED: "bg-green-100 text-green-700", + ARCHIVED: "bg-gray-100 text-gray-600", + OUTBOUND: "bg-indigo-100 text-indigo-700", "—": "bg-gray-100 text-gray-500", }; @@ -38,6 +42,8 @@ const STATUS_DOT: Record = { WIP: "blue", PENDING: "orange", COMPLETED: "green", + ARCHIVED: "gray", + OUTBOUND: "indigo", "—": "gray", }; diff --git a/frontend/src/types/api.ts b/frontend/src/types/api.ts index 6e9a7a3..3af6c34 100644 --- a/frontend/src/types/api.ts +++ b/frontend/src/types/api.ts @@ -96,6 +96,7 @@ export interface ProductScanResponse { parent_product_id: string | null; current_location_id: string | null; status: string; + overall_status: string | null; created_at: string; top_level_tasks: TaskSummary[]; /** 完整递归任务树 — 供十字矩阵树状图渲染 */