Files
ftb-project-management/apps/web/lib/linkage-engine.ts
2026-06-29 15:07:07 +08:00

62 lines
2.2 KiB
TypeScript

import type { DevTask, DevTaskStatus } from './dev-task';
export type ReqDevStatus = 'unscheduled' | 'todo' | 'developing' | 'completed';
export const REQ_DEV_STATUS_LABEL: Record<ReqDevStatus, string> = {
unscheduled: '未排期',
todo: '待开发',
developing: '开发中',
completed: '已完成',
};
export const REQ_DEV_STATUS_COLOR: Record<ReqDevStatus, string> = {
unscheduled: 'bg-zinc-100 text-zinc-500',
todo: 'bg-amber-50 text-amber-600',
developing: 'bg-blue-50 text-blue-600',
completed: 'bg-emerald-50 text-emerald-600',
};
/**
* 推导需求的开发状态
* 规则:根据关联的 devTasks 状态聚合推导
*/
export function deriveReqDevStatus(reqId: string, devTasks: DevTask[]): ReqDevStatus {
const tasks = devTasks.filter((t) => t.requirementId === reqId);
if (tasks.length === 0) return 'unscheduled';
if (tasks.every((t) => t.status === 'submitted')) return 'completed';
if (tasks.some((t) => t.status === 'in_progress' || t.status === 'testing')) return 'developing';
return 'todo';
}
/**
* 需求是否可编辑
* 规则:开发中(有 in_progress 或 testing 的任务)不可编辑
*/
export function canEditRequirement(reqId: string, devTasks: DevTask[]): boolean {
const status = deriveReqDevStatus(reqId, devTasks);
return !isRequirementExecutionLocked(status);
}
export function canCloseRequirement(reqId: string, devTasks: DevTask[]): boolean {
const status = deriveReqDevStatus(reqId, devTasks);
return !isRequirementExecutionLocked(status);
}
function isRequirementExecutionLocked(status: ReqDevStatus): boolean {
return status === 'developing' || status === 'completed';
}
/**
* 需求设置 versionId 的副作用检查
* 当需求已有关联的开发任务时,换版本是高风险操作
*/
export function checkVersionChangeRisk(reqId: string, devTasks: DevTask[]): { safe: boolean; reason?: string } {
const tasks = devTasks.filter((t) => t.requirementId === reqId);
if (tasks.length === 0) return { safe: true };
const activeTasks = tasks.filter((t) => t.status !== 'submitted');
if (activeTasks.length > 0) {
return { safe: false, reason: `该需求有 ${activeTasks.length} 个未完成的开发任务,变更版本可能导致数据不一致` };
}
return { safe: true };
}