fix: WorkflowPage UserDropdown selectedIds.map 报错 — 防御非数组值

- UserDropdown 组件加 Array.isArray(selectedIds) 防御
- 加载 workflow steps 时 approver_ids 加 try/catch 和类型判断
- 兼容后端返回 string/JSON/array/null 各种格式
This commit is contained in:
logan committed 2026-05-26 15:59:31 +08:00
1 parent 5411cd6db9
commit 9372053574
1 file changed
+9 -8
+9 -8
View File
@@ -97,7 +97,8 @@ interface UserDropdownProps {
function UserDropdown({ users, selectedIds, label, onToggle, onToggleAll, onClear, getUserName }: UserDropdownProps) { function UserDropdown({ users, selectedIds, label, onToggle, onToggleAll, onClear, getUserName }: UserDropdownProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const allSelected = selectedIds.length === users.length && users.length > 0; const ids = Array.isArray(selectedIds) ? selectedIds : [];
const allSelected = ids.length === users.length && users.length > 0;
return ( return (
<div className="relative"> <div className="relative">
@@ -112,20 +113,20 @@ function UserDropdown({ users, selectedIds, label, onToggle, onToggleAll, onClea
}`} }`}
> >
<span className="truncate"> <span className="truncate">
{selectedIds.length === 0 {ids.length === 0
? `${label} * 请选择` ? `${label} * 请选择`
: selectedIds.length === 1 : ids.length === 1
? getUserName(selectedIds[0]) ? getUserName(ids[0])
: `${label} (${selectedIds.length}人)` : `${label} (${ids.length}人)`
} }
</span> </span>
<ChevronDown className={`w-4 h-4 text-[var(--dg-text-muted)] transition-transform ${open ? 'rotate-180' : ''}`} /> <ChevronDown className={`w-4 h-4 text-[var(--dg-text-muted)] transition-transform ${open ? 'rotate-180' : ''}`} />
</button> </button>
{/* Selected tags */} {/* Selected tags */}
{selectedIds.length > 1 && ( {ids.length > 1 && (
<div className="flex flex-wrap gap-1 mt-1.5"> <div className="flex flex-wrap gap-1 mt-1.5">
{selectedIds.map((uid) => ( {ids.map((uid) => (
<span <span
key={uid} key={uid}
className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] bg-blue-500/15 text-blue-400" className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] bg-blue-500/15 text-blue-400"
@@ -218,7 +219,7 @@ function WorkflowEditorModal({ workflow, users, onClose, onSaved }: EditorProps)
step_type: (s.step_type === 'serial' || s.step_type === 'parallel' || s.step_type === 'any_one') step_type: (s.step_type === 'serial' || s.step_type === 'parallel' || s.step_type === 'any_one')
? 'audit' as const ? 'audit' as const
: s.step_type as 'submit' | 'audit' | 'execute', : s.step_type as 'submit' | 'audit' | 'execute',
approver_ids: s.approver_ids ? JSON.parse(s.approver_ids) : [], approver_ids: Array.isArray(s.approver_ids) ? s.approver_ids : (s.approver_ids ? ((): number[] => { try { const p = JSON.parse(s.approver_ids as string); return Array.isArray(p) ? p : []; } catch { return []; } })() : []),
})) }))
); );
} else { } else {