diff --git a/src/frontend/src/store.ts b/src/frontend/src/store.ts index 6b59078..8c963e3 100644 --- a/src/frontend/src/store.ts +++ b/src/frontend/src/store.ts @@ -412,26 +412,44 @@ export const useStore = create((set, get) => ({ // v2.6: 加载项目任务列表(含聚合统计) loadV2Tasks: async () => { const pid = get().selectedProjectId; - if (!pid) { set({ v2tasks: [] }); return; } set({ v2tasksLoading: true }); try { - const res = await fetch(`/api/projects/${pid}/tasks`); - if (!res.ok) { set({ v2tasks: [], v2tasksLoading: false }); return; } - const data = await res.json(); - const tasks = data.tasks || []; - // 批量获取每个任务的聚合字段 - // TODO: 后端应提供 list?expand=summary 接口,避免 N+1 - const enriched = await Promise.all(tasks.map(async (t: any) => { - try { - const r = await fetch(`/api/projects/${pid}/tasks/${t.id}`); - if (r.ok) { - const detail = await r.json(); - return { ...t, ...detail }; - } - } catch { /* skip */ } - return t; - })); - set({ v2tasks: enriched }); + if (!pid) { + // 全部任务模式:聚合所有项目 + const projRes = await fetch('/api/projects'); + if (!projRes.ok) { set({ v2tasks: [], v2tasksLoading: false }); return; } + const projData = await projRes.json(); + const allPids = Object.keys(projData.projects || {}); + const allTasks: any[] = []; + for (const p of allPids) { + try { + const r = await fetch(`/api/projects/${p}/tasks`); + if (r.ok) { + const d = await r.json(); + for (const t of (d.tasks || [])) { + allTasks.push({ ...t, _projectId: p, _projectName: (projData.projects[p] as any)?.name || p }); + } + } + } catch { /* skip */ } + } + set({ v2tasks: allTasks }); + } else { + const res = await fetch(`/api/projects/${pid}/tasks`); + if (!res.ok) { set({ v2tasks: [], v2tasksLoading: false }); return; } + const data = await res.json(); + const tasks = data.tasks || []; + const enriched = await Promise.all(tasks.map(async (t: any) => { + try { + const r = await fetch(`/api/projects/${pid}/tasks/${t.id}`); + if (r.ok) { + const detail = await r.json(); + return { ...t, ...detail }; + } + } catch { /* skip */ } + return t; + })); + set({ v2tasks: enriched }); + } } catch { /* silently fail */ } finally { set({ v2tasksLoading: false }); } },