Files
ftb-project-management/apps/web/hooks/useWorkspaceWorkItems.ts
2e595c7e72
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
refactor(data): 收口关系表运行时数据源
- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读
- 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移
- 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试

Co-Authored-By: Codex GPT-5 <codex@openai.com>
2026-07-09 14:59:49 +08:00

139 lines
4.9 KiB
TypeScript

'use client';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useProductStore } from '@/stores/useProductStore';
import { useVersionPlanStore } from '@/stores/useVersionPlanStore';
import { useRequirementStore } from '@/stores/useRequirementStore';
import { useDevTaskStore } from '@/stores/useDevTaskStore';
import { useTestCaseStore } from '@/stores/useTestCaseStore';
import { useBugStore } from '@/stores/useBugStore';
import { useAuthStore } from '@/stores/useAuthStore';
import { flattenVersions } from '@/lib/derive';
import { aggregateWorkItems } from '@/lib/workspace-engine';
import { loadV22WorkspaceData, type V22WorkspaceData } from '@/lib/v22-api';
import { selectWorkspaceCollections } from '@/lib/workspace-v22-source';
export function useWorkspaceWorkItems({ autoFetch = true }: { autoFetch?: boolean } = {}) {
const { overview, fetchOverview } = useProductStore();
const { plans, fetchPlans } = useVersionPlanStore();
const { requirements, fetchRequirements } = useRequirementStore();
const { tasks: devTasks, fetchTasks } = useDevTaskStore();
const { testCases, fetchTestCases } = useTestCaseStore();
const { bugs, fetchBugs } = useBugStore();
const user = useAuthStore((s) => s.user);
const [v22WorkspaceData, setV22WorkspaceData] = useState<V22WorkspaceData | null>(null);
const [v22WorkspaceLoaded, setV22WorkspaceLoaded] = useState(false);
const [v22WorkspaceFailed, setV22WorkspaceFailed] = useState(false);
useEffect(() => { if (autoFetch) fetchOverview(); }, [autoFetch, fetchOverview]);
const userId = user?.id ?? '';
const userName = user?.name ?? '';
const workspaceUserKey = userId || userName;
const workspaceUserRefs = useMemo(() => [userName, userId].filter(Boolean), [userId, userName]);
const allVersions = useMemo(() => flattenVersions(overview), [overview]);
const hydrateWorkspaceStoreFallback = useCallback(() => {
for (const version of allVersions) {
void fetchRequirements({ productId: version.productId, versionId: version.id });
void fetchPlans({ versionId: version.id });
void fetchTasks({ versionId: version.id });
void fetchTestCases({ versionId: version.id });
void fetchBugs({ versionId: version.id });
}
}, [allVersions, fetchBugs, fetchPlans, fetchRequirements, fetchTasks, fetchTestCases]);
useEffect(() => {
if (!autoFetch || !workspaceUserKey.trim()) {
setV22WorkspaceData(null);
setV22WorkspaceLoaded(false);
setV22WorkspaceFailed(false);
return;
}
let cancelled = false;
setV22WorkspaceLoaded(false);
setV22WorkspaceFailed(false);
loadV22WorkspaceData(workspaceUserKey)
.then((data) => {
if (cancelled) return;
setV22WorkspaceData(data);
setV22WorkspaceLoaded(true);
})
.catch(() => {
if (cancelled) return;
setV22WorkspaceData(null);
setV22WorkspaceFailed(true);
});
return () => {
cancelled = true;
};
}, [autoFetch, workspaceUserKey]);
useEffect(() => {
if (!autoFetch || !workspaceUserKey.trim() || !v22WorkspaceFailed) return;
hydrateWorkspaceStoreFallback();
}, [
autoFetch,
hydrateWorkspaceStoreFallback,
v22WorkspaceFailed,
workspaceUserKey,
]);
const versionMap = useMemo(() => {
const map = new Map<string, { id: string; name: string; productId: string; productName: string; projectName: string }>();
allVersions.forEach((version) => {
map.set(version.id, {
id: version.id,
name: version.name,
productId: version.productId,
productName: version.productName,
projectName: version.projectName,
});
});
return map;
}, [allVersions]);
const requirementVersionMap = useMemo(() => {
const map = new Map<string, string>();
requirements.forEach((requirement) => {
if (requirement.versionId) map.set(requirement.id, requirement.versionId);
});
return map;
}, [requirements]);
const workspaceCollections = useMemo(
() => selectWorkspaceCollections({
v22Loaded: v22WorkspaceLoaded,
v22Failed: v22WorkspaceFailed,
v22Data: v22WorkspaceData,
storeData: { plans, devTasks, testCases, bugs },
}),
[bugs, devTasks, plans, testCases, v22WorkspaceData, v22WorkspaceFailed, v22WorkspaceLoaded],
);
const workItems = useMemo(
() => aggregateWorkItems(
workspaceUserRefs,
workspaceCollections.versionPlans,
workspaceCollections.devTasks,
workspaceCollections.testCases,
workspaceCollections.bugs,
versionMap,
requirementVersionMap,
),
[workspaceUserRefs, workspaceCollections, versionMap, requirementVersionMap],
);
return {
userName,
allVersions,
versionMap,
requirementVersionMap,
workItems,
devTasks: workspaceCollections.devTasks,
testCases: workspaceCollections.testCases,
bugs: workspaceCollections.bugs,
};
}