diff --git a/frontend/src/components/scan/ProductCard.tsx b/frontend/src/components/scan/ProductCard.tsx index a391e74..9f794f7 100644 --- a/frontend/src/components/scan/ProductCard.tsx +++ b/frontend/src/components/scan/ProductCard.tsx @@ -1,7 +1,7 @@ /** 产品信息卡片 */ import { Package } from "lucide-react"; import type { ProductScanResponse } from "../../types/api"; -import { statusColor, statusLabel } from "../../constants/task"; +import { lifecycleBadge, statusColor, statusLabel } from "../../constants/task"; interface ProductCardProps { product: ProductScanResponse; @@ -10,6 +10,8 @@ interface ProductCardProps { export default function ProductCard({ product }: ProductCardProps) { // 优先显示宏观状态(整体流转),回退到产品状态字段 const displayStatus = product.overall_status || product.status; + // 🔧 发货测试 / 售后维修 — 仅「测试 / 维修」工序下显示 + const lifeBadge = lifecycleBadge(product.overall_status, product.lifecycle_phase); return (
@@ -18,6 +20,11 @@ export default function ProductCard({ product }: ProductCardProps) { {statusLabel(displayStatus)} + {lifeBadge && ( + + {lifeBadge.label} + + )}
diff --git a/frontend/src/pages/MatrixBoard.tsx b/frontend/src/pages/MatrixBoard.tsx index 6e6549a..0ec8454 100644 --- a/frontend/src/pages/MatrixBoard.tsx +++ b/frontend/src/pages/MatrixBoard.tsx @@ -8,6 +8,7 @@ import { Loader2 } from "lucide-react"; import dayjs, { type Dayjs } from "dayjs"; import { fetchWipMatrix, fetchWipMatrixDetail, type WipMatrixRow, type WipMatrixDetailRow } from "../services/dashboardApi"; import { fetchDeviceRecords, type DeviceRecord } from "../services/analyticsApi"; +import { lifecycleBadge } from "../constants/task"; const { RangePicker } = DatePicker; @@ -285,8 +286,21 @@ export default function MatrixBoard() { { title: "产品名称", dataIndex: "material_name", - width: 160, - render: (v) => {v || "—"}, + width: 200, + render: (v: string, record: WipMatrixDetailRow) => { + // 🔧 发货测试 / 售后维修 — 工序取当前下钻的列名(点产品名时为全部工序,不显示) + const lb = lifecycleBadge(drill?.process, record.lifecycle_phase); + return ( + + {v || "—"} + {lb && ( + + {lb.label} + + )} + + ); + }, }, { title: "身份证号", diff --git a/frontend/src/pages/ScanPage.tsx b/frontend/src/pages/ScanPage.tsx index 1f36a6c..90058f5 100644 --- a/frontend/src/pages/ScanPage.tsx +++ b/frontend/src/pages/ScanPage.tsx @@ -6,6 +6,7 @@ import { scanProduct } from "../services/productApi"; import type { ProductScanResponse } from "../types/api"; import ManualInput from "../components/scan/ManualInput"; import QueryResult from "../components/scan/QueryResult"; +import { lifecycleBadge } from "../constants/task"; // 🚀 CameraScanner → QrScanner → html5-qrcode (~200KB),仅在首次点开摄像头时加载 const CameraScanner = lazy(() => import("../components/scan/CameraScanner")); @@ -74,6 +75,11 @@ export default function ScanPage() { {product.overall_status || "未设定"} + {/* 🔧 售后回流标识:处于发货测试/售后维修环节时红底白字提示 */} + {(() => { + const lb = lifecycleBadge(product.overall_status, product.lifecycle_phase); + return lb ? {lb.label} : null; + })()}
)} @@ -126,6 +132,11 @@ export default function ScanPage() { {product.overall_status || "未设定"} + {/* 🔧 售后回流标识:处于发货测试/售后维修环节时红底白字提示 */} + {(() => { + const lb = lifecycleBadge(product.overall_status, product.lifecycle_phase); + return lb ? {lb.label} : null; + })()}
)} diff --git a/frontend/src/pages/admin/AdminProductsPage.tsx b/frontend/src/pages/admin/AdminProductsPage.tsx index 0c8e39a..1880248 100644 --- a/frontend/src/pages/admin/AdminProductsPage.tsx +++ b/frontend/src/pages/admin/AdminProductsPage.tsx @@ -13,7 +13,7 @@ import { } from "../../services/printApi"; import { useToast } from "../../components/ui/Toast"; import { useAuth } from "../../contexts/AuthContext"; -import { getStatusConfig } from "../../constants/task"; +import { getStatusConfig, lifecycleBadge } from "../../constants/task"; const QR_BASE = "/api/v1/products/qrcode"; @@ -275,12 +275,21 @@ 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; - })()} +
+ {(() => { + const cfg = getStatusConfig(p.macro_status || p.status); + return cfg.label ? ( + {cfg.label} + ) : null; + })()} + {/* 🔧 发货测试 / 售后维修 — 仅「测试 / 维修」工序下显示 */} + {(() => { + const lb = lifecycleBadge(p.overall_status, p.lifecycle_phase); + return lb ? ( + {lb.label} + ) : null; + })()} +
diff --git a/frontend/src/pages/admin/AdminTasksPage.tsx b/frontend/src/pages/admin/AdminTasksPage.tsx index 4a68dc5..19340d8 100644 --- a/frontend/src/pages/admin/AdminTasksPage.tsx +++ b/frontend/src/pages/admin/AdminTasksPage.tsx @@ -17,7 +17,7 @@ import { Modal, ReceiveConfirmModal, RejectModal, TransferModal } from "../../co import type { ProductResponse } from "../../types/admin"; import type { ProductScanResponse } from "../../types/api"; import { useToast } from "../../components/ui/Toast"; -import { getStatusConfig } from "../../constants/task"; +import { getStatusConfig, lifecycleBadge, ALL_OVERALL_OPTIONS } from "../../constants/task"; import { useAuth } from "../../contexts/AuthContext"; const STATUS_TABS = [ @@ -107,8 +107,21 @@ export default function AdminTasksPage() { { key: "overall_status", label: "当前工序", colSpan: 1, filterType: "enum", getFilterValue: (p) => p.overall_status || "—", - enumOptions: ["备货", "生产", "测试", "维修", "待仓库收货", "已入库", "已出库"].map((v) => ({ value: v, label: v })), - render: (p) => {p.overall_status || "—"}, + // 🔧 筛选用两阶段并集:售后设备的「发货测试 / 售后维修」也要能被筛出来 + enumOptions: ALL_OVERALL_OPTIONS.map((v) => ({ value: v, label: v })), + render: (p) => { + const lb = lifecycleBadge(p.overall_status, p.lifecycle_phase); + return ( + + {p.overall_status || "—"} + {lb && ( + + {lb.label} + + )} + + ); + }, }, { key: "status", label: "产品状态", colSpan: 1,