feat: 前端补充生命周期类型定义与工序词表
This commit is contained in:
@ -4,7 +4,7 @@
|
||||
* 供 TaskTreeViewer / TaskListCard / ProductCard 等组件共用,
|
||||
* 避免在多处重复维护相同的映射逻辑。
|
||||
*/
|
||||
import { TASK_STATUS } from "../types/api";
|
||||
import { TASK_STATUS, type LifecyclePhase } from "../types/api";
|
||||
|
||||
export interface StatusStyle {
|
||||
bg: string;
|
||||
@ -112,6 +112,19 @@ export const STATUS_CONFIG: Record<string, StatusStyle> = {
|
||||
ring: "ring-blue-400",
|
||||
label: "维修",
|
||||
},
|
||||
// ---- 售后回流阶段专属工序(红系,与生产阶段一眼区分)----
|
||||
发货测试: {
|
||||
bg: "bg-red-50",
|
||||
text: "text-red-700",
|
||||
ring: "ring-red-400",
|
||||
label: "发货测试",
|
||||
},
|
||||
售后维修: {
|
||||
bg: "bg-red-50",
|
||||
text: "text-red-700",
|
||||
ring: "ring-red-400",
|
||||
label: "售后维修",
|
||||
},
|
||||
};
|
||||
|
||||
const FALLBACK: StatusStyle = {
|
||||
@ -137,3 +150,100 @@ export function statusColor(status: string): string {
|
||||
export function statusLabel(status: string): string {
|
||||
return getStatusConfig(status).label;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 🔧 生命周期阶段(lifecycle_phase)与工序选项隔离
|
||||
//
|
||||
// 生产制造(PRODUCTION)与售后回流(AFTER_SALES)各有一套合法工序名。
|
||||
// ⚠️ 本段与后端 app/core/lifecycle.py 是同一份口径,改动请两边同步。
|
||||
//
|
||||
// 售后阶段使用**独立工序名**(发货测试 / 售后维修),不复用生产阶段的
|
||||
// 「测试 / 维修」—— 这样看板、下钻、导出无需 JOIN lifecycle_phase 即可区分。
|
||||
// ============================================================
|
||||
|
||||
export const LIFECYCLE_PHASE = {
|
||||
PRODUCTION: "PRODUCTION",
|
||||
AFTER_SALES: "AFTER_SALES",
|
||||
} as const satisfies Record<string, LifecyclePhase>;
|
||||
|
||||
/** 售后专属工序名 — 选中即代表设备进入售后生命周期 */
|
||||
export const STEP_SHIP_TEST = "发货测试";
|
||||
export const STEP_AFTER_SALES_REPAIR = "售后维修";
|
||||
|
||||
const AFTER_SALES_ONLY_STEPS = [STEP_SHIP_TEST, STEP_AFTER_SALES_REPAIR];
|
||||
|
||||
// ── 生产制造阶段合法工序(原有词表,一字未改)──
|
||||
export const PRODUCTION_TASK_OPTIONS = ["备货", "生产", "测试", "维修", "在库"];
|
||||
export const PRODUCTION_OVERALL_OPTIONS = [
|
||||
"备货", "生产", "测试", "维修", "在库", "已入库", "已出库",
|
||||
];
|
||||
|
||||
// ── 售后回流阶段合法工序:只保留「发货测试 / 售后维修 / 入库出库」──
|
||||
export const AFTER_SALES_TASK_OPTIONS = [STEP_SHIP_TEST, STEP_AFTER_SALES_REPAIR, "在库"];
|
||||
export const AFTER_SALES_OVERALL_OPTIONS = [
|
||||
STEP_SHIP_TEST, STEP_AFTER_SALES_REPAIR, "在库", "已入库", "已出库",
|
||||
];
|
||||
|
||||
/**
|
||||
* 按生命周期阶段取「可选工序」——选项隔离的 UI 侧实现。
|
||||
*
|
||||
* hasHistory = false(无任何历史任务的首次激活 / 老设备)时返回**并集**,
|
||||
* 让操作员自行声明这是生产设备还是售后回流设备:一旦选中售后专属工序,
|
||||
* 后端即把设备判为 AFTER_SALES,之后下拉就只剩售后选项。
|
||||
*
|
||||
* 注意:这只是体验层的第一道防线,真正的拦截在后端
|
||||
* task_service._enforce_step_isolation(防伪造传参)。
|
||||
*/
|
||||
export function taskOptionsFor(
|
||||
phase: string | null | undefined,
|
||||
hasHistory = true,
|
||||
): string[] {
|
||||
if (phase === LIFECYCLE_PHASE.AFTER_SALES) return AFTER_SALES_TASK_OPTIONS;
|
||||
if (!hasHistory) return [...PRODUCTION_TASK_OPTIONS, ...AFTER_SALES_ONLY_STEPS];
|
||||
return PRODUCTION_TASK_OPTIONS;
|
||||
}
|
||||
|
||||
/** 按生命周期阶段取「可选宏观状态」— 同上,含已入库/已出库等终态 */
|
||||
export function overallOptionsFor(
|
||||
phase: string | null | undefined,
|
||||
hasHistory = true,
|
||||
): string[] {
|
||||
if (phase === LIFECYCLE_PHASE.AFTER_SALES) return AFTER_SALES_OVERALL_OPTIONS;
|
||||
if (!hasHistory) return [...PRODUCTION_OVERALL_OPTIONS, ...AFTER_SALES_ONLY_STEPS];
|
||||
return PRODUCTION_OVERALL_OPTIONS;
|
||||
}
|
||||
|
||||
/** 列表筛选枚举 — 两阶段并集(用于筛选,不是录入项) */
|
||||
export const ALL_OVERALL_OPTIONS = [
|
||||
...PRODUCTION_OVERALL_OPTIONS, ...AFTER_SALES_ONLY_STEPS,
|
||||
];
|
||||
|
||||
/** 售后服务相关环节 — 只有落到这些工序才打红色标签 */
|
||||
const AFTER_SALES_TAG_STEPS = new Set<string>(AFTER_SALES_ONLY_STEPS);
|
||||
|
||||
export interface LifecycleBadge {
|
||||
label: string;
|
||||
className: string;
|
||||
phase: LifecyclePhase;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生命周期标签 — 只在设备确实处于**售后回流环节**时返回:
|
||||
* 生命周期为 AFTER_SALES 且当前工序是「发货测试」或「售后维修」
|
||||
* → 红底白字,文案即工序名。
|
||||
*
|
||||
* 生产制造阶段一律返回 null(不打标),避免和售后设备混淆。
|
||||
*/
|
||||
export function lifecycleBadge(
|
||||
overallStatus: string | null | undefined,
|
||||
phase: string | null | undefined,
|
||||
): LifecycleBadge | null {
|
||||
if (phase !== LIFECYCLE_PHASE.AFTER_SALES) return null;
|
||||
const step = (overallStatus || "").trim();
|
||||
if (!AFTER_SALES_TAG_STEPS.has(step)) return null;
|
||||
return {
|
||||
label: step,
|
||||
className: "bg-red-600 text-white ring-1 ring-red-600",
|
||||
phase: LIFECYCLE_PHASE.AFTER_SALES,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import api from "./api";
|
||||
import type { LifecyclePhase } from "../types/api";
|
||||
|
||||
export interface DashboardStats {
|
||||
products_total: number;
|
||||
@ -86,6 +87,8 @@ export interface WipMatrixDetailRow {
|
||||
material_name: string;
|
||||
spec_model: string;
|
||||
task_status: string;
|
||||
/** 🔧 生命周期阶段:PRODUCTION(生产制造/发货测试) | AFTER_SALES(出库后返厂售后维修) */
|
||||
lifecycle_phase?: LifecyclePhase;
|
||||
assignee_id: string;
|
||||
assignee: string;
|
||||
duration_hours: number;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/** 管理端 API 响应类型 */
|
||||
import type { LifecyclePhase } from "./api";
|
||||
|
||||
export interface ProductResponse {
|
||||
id: string;
|
||||
@ -17,6 +18,8 @@ export interface ProductResponse {
|
||||
macro_status: string | null;
|
||||
overall_status: string | null;
|
||||
status: string;
|
||||
/** 🔧 生命周期阶段:PRODUCTION(生产制造/发货测试) | AFTER_SALES(出库后返厂售后维修) */
|
||||
lifecycle_phase?: LifecyclePhase;
|
||||
created_at: string;
|
||||
latest_record_time: string | null;
|
||||
latest_record_content: string | null;
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
/** 后端 API 响应类型 */
|
||||
|
||||
// ============================================================
|
||||
// 生命周期阶段 — 区分「生产阶段的测试(发货测试)」与「出库后返厂(售后维修)」
|
||||
// ============================================================
|
||||
|
||||
export type LifecyclePhase = "PRODUCTION" | "AFTER_SALES";
|
||||
|
||||
// ============================================================
|
||||
// 任务状态常量
|
||||
// ============================================================
|
||||
@ -97,6 +103,8 @@ export interface ProductScanResponse {
|
||||
current_location_id: string | null;
|
||||
status: string;
|
||||
overall_status: string | null;
|
||||
/** 🔧 生命周期阶段:PRODUCTION(生产制造/发货测试) | AFTER_SALES(出库后返厂售后维修) */
|
||||
lifecycle_phase?: LifecyclePhase;
|
||||
created_at: string;
|
||||
top_level_tasks: TaskSummary[];
|
||||
/** 完整递归任务树 — 供十字矩阵树状图渲染 */
|
||||
|
||||
Reference in New Issue
Block a user