feat: PC 端直接完结入口与当前工序口径(前端)

【直接完结入口】
- 共享 TransferModal 新增「🏁 直接完结」开关,与「入库」互斥;选中后下游字段
  禁用(保留输入便于反悔)、标题/预览/按钮切换为独立视觉
- 入口仅超管/主管可见(useAuth + isAdminRole),并加防御性 useEffect 清掉
  非管理员的残留选中态,避免提交出 finish_directly
- 表单重置改为「打开时重置」:TransferModal 被 memo 后常驻挂载会跨次残留状态,
  且原实现于提交时清空会让等待期主题从「直接完结」闪回普通转交

【角色判断收口】
- 新增 ADMIN_ROLES / isAdminRole(与后端 task_service.ADMIN_ROLES 对齐)
  此前该判断散落在 TaskFlowView / AdminProductsPage 各处,移动端那份还只判了
  SUPER_ADMIN 漏了 SUPERVISOR,导致主管被前端误挡

【当前工序口径】
- 「当前工序」列改用后端派生的 current_step,不再用 overall_status ——
  后者会被"最新主干任务名"覆盖,让已 COMPLETED 的历史工序(扫码出库/测试…)
  冒充当前工序。显示与筛选值一并切换以保持一致
- ProductResponse 类型补齐 current_step
This commit is contained in:
2026-09-17 17:05:51 +08:00
parent d666bbd4ed
commit ee25b8fd23
4 changed files with 62 additions and 10 deletions

View File

@ -114,15 +114,19 @@ export default function AdminTasksPage() {
render: (p) => <div className="text-xs text-gray-500 truncate">{p.spec_model || p.material_name || p.material_id || "—"}</div>,
},
{
key: "overall_status", label: "当前工序", colSpan: 1,
filterType: "enum", getFilterValue: (p) => p.overall_status || "—",
key: "current_step", label: "当前工序", colSpan: 1,
// 🔧 改用后端派生的 current_step,而不是 overall_status ——
// 后者的取值被"最新主干任务名"覆盖(含已 COMPLETED 的历史工序),
// 会让「扫码出库 / 测试 / 发货测试」等已完结工序冒充"当前工序"。
// current_step 只认活跃主干任务;无活跃任务时返回终态或空。
filterType: "enum", getFilterValue: (p) => p.current_step || "—",
// 🔧 筛选用两阶段并集:售后设备的「发货测试 / 售后维修」也要能被筛出来
enumOptions: ALL_OVERALL_OPTIONS.map((v) => ({ value: v, label: v })),
render: (p) => {
const lb = lifecycleBadge(p.overall_status, p.lifecycle_phase);
const lb = lifecycleBadge(p.current_step, p.lifecycle_phase);
return (
<span className="flex items-center gap-1.5">
<span className="text-xs font-medium text-gray-700">{p.overall_status || "—"}</span>
<span className="text-xs font-medium text-gray-700">{p.current_step || "—"}</span>
{lb && (
<span className={`shrink-0 rounded-full px-1.5 py-0.5 text-[10px] font-bold leading-none ${lb.className}`}>
{lb.label}