关键改动: - 增加需求排序和版本只读状态规则及测试 - 完善版本概览阶段耗时、项目页和工作台展示 - 优化小宝预警请求节流、建议状态和风险过滤 Co-Authored-By: Codex GPT-5 <codex@openai.com>
122 lines
3.4 KiB
TypeScript
122 lines
3.4 KiB
TypeScript
import { VersionStatus } from './version-status';
|
|
import type { Stage, Role } from './stage';
|
|
|
|
export interface VersionMember {
|
|
role: Role;
|
|
name: string;
|
|
}
|
|
|
|
export interface RoleProgress {
|
|
role: Role;
|
|
percent: number;
|
|
daysSpent: number;
|
|
}
|
|
|
|
export type Priority = 'P0' | 'P1' | 'P2' | 'P3' | 'P4';
|
|
|
|
export interface VersionLinks {
|
|
research?: string;
|
|
prototype?: string;
|
|
ui?: string;
|
|
}
|
|
|
|
interface ProductOverviewLike {
|
|
id: string;
|
|
name: string;
|
|
projects: { id: string; name: string; description: string; createdAt: string; status?: string }[];
|
|
versions: {
|
|
id: string; name: string; status?: string; releaseDate: string | null; createdAt: string;
|
|
currentStage?: Stage; startDate?: string | null; expectedReleaseDate?: string | null;
|
|
members?: VersionMember[]; progress?: RoleProgress[];
|
|
priority?: Priority; links?: VersionLinks;
|
|
}[];
|
|
}
|
|
|
|
export interface ProjectWithContext {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
createdAt: string;
|
|
status?: string;
|
|
productId: string;
|
|
productName: string;
|
|
versions: VersionWithContext[];
|
|
}
|
|
|
|
export interface VersionWithContext {
|
|
id: string;
|
|
name: string;
|
|
status: VersionStatus;
|
|
releaseDate: string | null;
|
|
createdAt: string;
|
|
productId: string;
|
|
productName: string;
|
|
projectId: string;
|
|
projectName: string;
|
|
projectStatus?: string;
|
|
currentStage?: Stage;
|
|
startDate?: string | null;
|
|
expectedReleaseDate?: string | null;
|
|
members?: VersionMember[];
|
|
progress?: RoleProgress[];
|
|
priority?: Priority;
|
|
links?: VersionLinks;
|
|
}
|
|
|
|
export function flattenProjects(overview: ProductOverviewLike[]): ProjectWithContext[] {
|
|
const result: ProjectWithContext[] = [];
|
|
for (const product of overview) {
|
|
for (const project of product.projects) {
|
|
const versions = product.versions
|
|
.filter((v) => v.name.toLowerCase().startsWith(project.name.toLowerCase()))
|
|
.map((v) => ({
|
|
...v,
|
|
status: (v.status || 'released') as VersionStatus,
|
|
productId: product.id,
|
|
productName: product.name,
|
|
projectId: project.id,
|
|
projectName: project.name,
|
|
projectStatus: project.status,
|
|
}));
|
|
result.push({
|
|
...project,
|
|
productId: product.id,
|
|
productName: product.name,
|
|
versions,
|
|
});
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export function flattenVersions(overview: ProductOverviewLike[]): VersionWithContext[] {
|
|
const result: VersionWithContext[] = [];
|
|
for (const product of overview) {
|
|
for (const version of product.versions) {
|
|
const project = product.projects.find((p) =>
|
|
version.name.toLowerCase().startsWith(p.name.toLowerCase()),
|
|
);
|
|
result.push({
|
|
...version,
|
|
status: (version.status || 'released') as VersionStatus,
|
|
productId: product.id,
|
|
productName: product.name,
|
|
projectId: project?.id || '',
|
|
projectStatus: project?.status,
|
|
projectName: project?.name || '未关联',
|
|
});
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export function getProjectDetail(overview: ProductOverviewLike[], projectId: string): ProjectWithContext | null {
|
|
const projects = flattenProjects(overview);
|
|
return projects.find((p) => p.id === projectId) || null;
|
|
}
|
|
|
|
export function getVersionDetail(overview: ProductOverviewLike[], versionId: string): VersionWithContext | null {
|
|
const versions = flattenVersions(overview);
|
|
return versions.find((v) => v.id === versionId) || null;
|
|
}
|