* 更新任务状态(含状态流转校验) * 更新后通过 EventBus 发射 task:updated 事件,通知前端实时更新
(id: string, status: TaskStatus)
| 470 | taskId: row.taskId, |
| 471 | status: row.workspaceStatus, |
| 472 | workspaceKind: row.workspaceKind, |
| 473 | branchName: row.branchName, |
| 474 | agentType: row.agentType, |
| 475 | hasActiveSession: Boolean(row.hasActiveSession), |
| 476 | })); |
| 477 | |
| 478 | const workspacesByTaskId = new Map<string, typeof workspaces>(); |
| 479 | for (const workspace of workspaces) { |
| 480 | const group = workspacesByTaskId.get(workspace.taskId) ?? []; |
| 481 | group.push(workspace); |
| 482 | workspacesByTaskId.set(workspace.taskId, group); |
| 483 | } |
| 484 | |
| 485 | const preferredWorkspaceByTaskId = new Map<string, (typeof workspaces)[number]>(); |
| 486 | for (const task of tasks) { |
| 487 | const candidates = workspacesByTaskId.get(task.id) ?? []; |
| 488 | const preferred = candidates.find((workspace) => workspace.status === WorkspaceStatus.ACTIVE) |
| 489 | ?? candidates[0]; |
| 490 | if (preferred) { |
| 491 | preferredWorkspaceByTaskId.set(task.id, preferred); |
| 492 | } |
| 493 | } |
| 494 | |
| 495 | const statusOrder: Record<string, number> = { |
| 496 | [TaskStatus.IN_PROGRESS]: 0, |
| 497 | [TaskStatus.IN_REVIEW]: 1, |
| 498 | [TaskStatus.TODO]: 2, |
| 499 | [TaskStatus.DONE]: 3, |
| 500 | [TaskStatus.CANCELLED]: 4, |
| 501 | }; |
| 502 | tasks.sort((a, b) => { |
| 503 | const statusDelta = (statusOrder[a.status] ?? 99) - (statusOrder[b.status] ?? 99); |
| 504 | if (statusDelta !== 0) return statusDelta; |
| 505 | return a.position - b.position; |
| 506 | }); |
| 507 | |
| 508 | const data: TaskBoardItem[] = tasks.map((task) => { |
| 509 | const titlePreview = buildTextPreview(task.title, TASK_TITLE_MAX_LENGTH); |
| 510 | const preferredWorkspace = preferredWorkspaceByTaskId.get(task.id); |
| 511 | const hasRunningSession = (workspacesByTaskId.get(task.id) ?? []) |
| 512 | .some((workspace) => workspace.hasActiveSession); |
| 513 | |
| 514 | return { |
| 515 | id: task.id, |
| 516 | projectId: task.projectId, |
| 517 | title: titlePreview, |
| 518 | status: task.status as TaskStatus, |
| 519 | ...(preferredWorkspace ? { |
| 520 | preferredWorkspace: { |
| 521 | ...(preferredWorkspace.workspaceKind === WorkspaceKind.MAIN_DIRECTORY |
| 522 | ? { workspaceKind: WorkspaceKind.MAIN_DIRECTORY } |
no test coverage detected