perf(web): 优化大数据量页面切换与聚合性能

This commit is contained in:
Script Generator
2026-07-03 09:43:36 +08:00
parent 554ab520d1
commit a509bb4922
32 changed files with 1087 additions and 360 deletions

View File

@@ -0,0 +1,144 @@
import type { Bug } from './bug';
import type { DevTask } from './dev-task';
import type { OvertimeRecord } from './overtime';
import type { Requirement } from './requirement';
import type { TestCase } from './test-case';
import type { VersionPlan } from './version-plan';
export interface VersionDataScope {
requirements: Requirement[];
requirementIds: string[];
requirementIdSet: Set<string>;
plans: VersionPlan[];
plansByType: Record<VersionPlan['type'], VersionPlan[]>;
devTasks: DevTask[];
testCases: TestCase[];
bugs: Bug[];
overtimeRecords: OvertimeRecord[];
}
interface VersionDataScopeInput {
versionId: string;
requirements: Requirement[];
plans: VersionPlan[];
devTasks: DevTask[];
testCases: TestCase[];
bugs: Bug[];
overtimeRecords?: OvertimeRecord[];
}
interface VersionDataScopeMapInput extends Omit<VersionDataScopeInput, 'versionId'> {
versionIds: string[];
}
export function buildVersionDataScope(input: VersionDataScopeInput): VersionDataScope {
const {
versionId,
requirements,
plans,
devTasks,
testCases,
bugs,
overtimeRecords = [],
} = input;
const scopedRequirements: Requirement[] = [];
const requirementIds: string[] = [];
const requirementIdSet = new Set<string>();
for (const requirement of requirements) {
if (requirement.versionId !== versionId) continue;
scopedRequirements.push(requirement);
requirementIds.push(requirement.id);
requirementIdSet.add(requirement.id);
}
const scopedPlans: VersionPlan[] = [];
const plansByType: Record<VersionPlan['type'], VersionPlan[]> = {
research: [],
product: [],
ui: [],
};
for (const plan of plans) {
if (plan.versionId !== versionId) continue;
scopedPlans.push(plan);
plansByType[plan.type].push(plan);
}
return {
requirements: scopedRequirements,
requirementIds,
requirementIdSet,
plans: scopedPlans,
plansByType,
devTasks: devTasks.filter((task) => task.versionId === versionId || (!task.versionId && requirementIdSet.has(task.requirementId))),
testCases: testCases.filter((testCase) => testCase.versionId === versionId),
bugs: bugs.filter((bug) => bug.versionId === versionId),
overtimeRecords: overtimeRecords.filter((record) => record.versionId === versionId),
};
}
export function buildVersionDataScopeMap(input: VersionDataScopeMapInput): Record<string, VersionDataScope> {
const scopes: Record<string, VersionDataScope> = {};
const targetVersionIds = new Set(input.versionIds);
for (const versionId of input.versionIds) {
scopes[versionId] = createEmptyScope();
}
const requirementVersionMap = new Map<string, string>();
for (const requirement of input.requirements) {
const versionId = requirement.versionId;
if (!versionId) continue;
requirementVersionMap.set(requirement.id, versionId);
const scope = scopes[versionId];
if (!scope) continue;
scope.requirements.push(requirement);
scope.requirementIds.push(requirement.id);
scope.requirementIdSet.add(requirement.id);
}
for (const plan of input.plans) {
const scope = scopes[plan.versionId];
if (!scope) continue;
scope.plans.push(plan);
scope.plansByType[plan.type].push(plan);
}
for (const task of input.devTasks) {
const versionId = task.versionId || requirementVersionMap.get(task.requirementId);
if (!versionId || !targetVersionIds.has(versionId)) continue;
scopes[versionId]?.devTasks.push(task);
}
for (const testCase of input.testCases) {
scopes[testCase.versionId]?.testCases.push(testCase);
}
for (const bug of input.bugs) {
scopes[bug.versionId]?.bugs.push(bug);
}
for (const record of input.overtimeRecords ?? []) {
if (!record.versionId) continue;
scopes[record.versionId]?.overtimeRecords.push(record);
}
return scopes;
}
function createEmptyScope(): VersionDataScope {
return {
requirements: [],
requirementIds: [],
requirementIdSet: new Set<string>(),
plans: [],
plansByType: {
research: [],
product: [],
ui: [],
},
devTasks: [],
testCases: [],
bugs: [],
overtimeRecords: [],
};
}