feat(需求池): 调整需求池布局与详情展示
This commit is contained in:
70
apps/web/lib/requirement-scope.ts
Normal file
70
apps/web/lib/requirement-scope.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { Requirement, RequirementStatus } from './requirement';
|
||||
|
||||
export type RequirementScopeSelection =
|
||||
| { type: 'all' }
|
||||
| { type: 'product'; productId: string }
|
||||
| { type: 'project'; projectId: string };
|
||||
|
||||
export interface RequirementScopeCount {
|
||||
total: number;
|
||||
byStatus: Partial<Record<RequirementStatus, number>>;
|
||||
}
|
||||
|
||||
export interface RequirementProjectScopeNode {
|
||||
id: string;
|
||||
name: string;
|
||||
count: RequirementScopeCount;
|
||||
}
|
||||
|
||||
export interface RequirementProductScopeNode {
|
||||
id: string;
|
||||
name: string;
|
||||
count: RequirementScopeCount;
|
||||
projects: RequirementProjectScopeNode[];
|
||||
}
|
||||
|
||||
export function filterRequirementsByScope(
|
||||
requirements: Requirement[],
|
||||
scope: RequirementScopeSelection,
|
||||
): Requirement[] {
|
||||
if (scope.type === 'product') {
|
||||
return requirements.filter((requirement) => requirement.productId === scope.productId);
|
||||
}
|
||||
if (scope.type === 'project') {
|
||||
return requirements.filter((requirement) => requirement.projectId === scope.projectId);
|
||||
}
|
||||
return requirements;
|
||||
}
|
||||
|
||||
export function buildRequirementScopeTree(
|
||||
overview: { id: string; name: string; projects: { id: string; name: string }[] }[],
|
||||
requirements: Requirement[],
|
||||
): RequirementProductScopeNode[] {
|
||||
return overview.map((product) => {
|
||||
const productRequirements = requirements.filter((requirement) => requirement.productId === product.id);
|
||||
return {
|
||||
id: product.id,
|
||||
name: product.name,
|
||||
count: countRequirements(productRequirements),
|
||||
projects: product.projects.map((project) => {
|
||||
const projectRequirements = requirements.filter((requirement) => requirement.projectId === project.id);
|
||||
return {
|
||||
id: project.id,
|
||||
name: project.name,
|
||||
count: countRequirements(projectRequirements),
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function countRequirements(requirements: Requirement[]): RequirementScopeCount {
|
||||
const byStatus: Partial<Record<RequirementStatus, number>> = {};
|
||||
for (const requirement of requirements) {
|
||||
byStatus[requirement.status] = (byStatus[requirement.status] ?? 0) + 1;
|
||||
}
|
||||
return {
|
||||
total: requirements.length,
|
||||
byStatus,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user