import { looksLikeCode, reasonText } from "@umt/contracts"; // 原因串 → 一句人话(DEAI-2)。映射表在 @umt/contracts 的 reasons.ts,服务端与前端共用; // 原码交给 显示,不直接给人看。 /** `{ code, message }`(整理记录 / 文件结果)或裸原因串 → 一句话;不认识的码返回 fallback */ export function reasonLine( r: { code?: string | null; message?: string | null } | string | null | undefined, fallback = "处理失败", ): string | null { if (!r) return null; const code = typeof r === "string" ? r : (r.code ?? null); const message = typeof r === "string" ? null : (r.message ?? null); // 服务端给的中文说明(冲突明细等)优先 if (message && !looksLikeCode(message) && message !== code) return message; const t = reasonText(code) ?? reasonText(message); if (t) return t.action ? `${t.text}。${t.action}` : t.text; if (code && !looksLikeCode(code)) return code; return fallback; } /** 原码(给技术信息用):只有是内部码时才返回 */ export function reasonCode(r: { code?: string | null; message?: string | null } | string | null | undefined) { if (!r) return null; if (typeof r === "string") return looksLikeCode(r) ? r : null; const c = r.code ?? null; const m = r.message ?? null; return [c, m && looksLikeCode(m) && m !== c ? m : null].filter(Boolean).join(" · ") || null; } /** 原因串里的内部码替换成人话(如计划 statusReason、任务 waitReason) */ export function humanizeReason(v: string | null | undefined): string | null { if (!v) return null; return looksLikeCode(v) ? reasonLine(v, v) : v; }