宏观状态
-
+
{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() {
{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[];
/** 完整递归任务树 — 供十字矩阵树状图渲染 */