feat(工作台): 细化计划进展工时证据
关键改动: - 支持需求覆盖和调研方向开始工作记录 - 日报按计划记录开始时间和进度下次开始时间计算证据 - 更新版本编辑校验、项目展示和 workflow 说明 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -47,6 +47,7 @@ export interface PlanTask {
|
||||
status: PlanTaskStatus;
|
||||
completedContent?: string;
|
||||
remainingContent?: string;
|
||||
currentWorkStartedAt?: string;
|
||||
updatedAt?: string;
|
||||
updatedBy?: string;
|
||||
}
|
||||
@@ -76,6 +77,7 @@ export interface VersionPlanRequirementCoverage {
|
||||
status: RequirementCoverageStatus;
|
||||
completedContent?: string;
|
||||
remainingContent?: string;
|
||||
currentWorkStartedAt?: string;
|
||||
updatedAt: string;
|
||||
updatedBy: string;
|
||||
}
|
||||
@@ -93,28 +95,43 @@ export interface VersionPlanLog {
|
||||
coverageStatus?: RequirementCoverageStatus;
|
||||
completedContent?: string;
|
||||
remainingContent?: string;
|
||||
workStartedAt?: string;
|
||||
directionTaskId?: string;
|
||||
directionTitle?: string;
|
||||
aiTarget?: AgentDecomposeTarget;
|
||||
aiStatus?: AiDecomposeLogStatus;
|
||||
}
|
||||
|
||||
export interface RequirementCoverageWorkStartInput {
|
||||
requirementId: string;
|
||||
startedAt?: string;
|
||||
updatedBy: string;
|
||||
}
|
||||
|
||||
export interface RequirementCoverageUpdateInput {
|
||||
requirementId: string;
|
||||
status: RequirementCoverageStatus;
|
||||
completedContent?: string;
|
||||
remainingContent?: string;
|
||||
workStartedAt?: string;
|
||||
updatedAt?: string;
|
||||
updatedBy: string;
|
||||
requirementCode?: string;
|
||||
requirementTitle?: string;
|
||||
}
|
||||
|
||||
export interface ResearchDirectionWorkStartInput {
|
||||
taskId: string;
|
||||
startedAt?: string;
|
||||
updatedBy: string;
|
||||
}
|
||||
|
||||
export interface ResearchDirectionProgressUpdateInput {
|
||||
taskId: string;
|
||||
status: Extract<RequirementCoverageStatus, 'partial' | 'completed'>;
|
||||
completedContent?: string;
|
||||
remainingContent?: string;
|
||||
workStartedAt?: string;
|
||||
updatedAt?: string;
|
||||
updatedBy: string;
|
||||
}
|
||||
@@ -250,7 +267,9 @@ export function canSaveRequirementCoverageDraft(
|
||||
status: RequirementCoverageStatus,
|
||||
completedContent?: string,
|
||||
remainingContent?: string,
|
||||
workStartedAt?: string,
|
||||
): boolean {
|
||||
if (!workStartedAt?.trim()) return false;
|
||||
if (status === 'completed') return true;
|
||||
if (status === 'partial') {
|
||||
return Boolean(completedContent?.trim()) && Boolean(remainingContent?.trim());
|
||||
@@ -290,11 +309,37 @@ export function getPlanLogsForPlans(plans: VersionPlan[]): VersionPlanLogView[]
|
||||
.sort((a, b) => getPlanLogCreatedAtTime(b) - getPlanLogCreatedAtTime(a));
|
||||
}
|
||||
|
||||
export function startRequirementCoverageWork(
|
||||
plan: VersionPlan,
|
||||
input: RequirementCoverageWorkStartInput,
|
||||
): Pick<VersionPlan, 'requirementCoverage'> {
|
||||
const startedAt = input.startedAt ?? new Date().toISOString();
|
||||
const existing = getRequirementCoverage(plan, input.requirementId);
|
||||
const nextCoverage: VersionPlanRequirementCoverage = {
|
||||
requirementId: input.requirementId,
|
||||
status: existing?.status ?? 'not_started',
|
||||
completedContent: existing?.completedContent,
|
||||
remainingContent: existing?.remainingContent,
|
||||
currentWorkStartedAt: startedAt,
|
||||
updatedAt: startedAt,
|
||||
updatedBy: input.updatedBy,
|
||||
};
|
||||
|
||||
return {
|
||||
requirementCoverage: [
|
||||
nextCoverage,
|
||||
...(plan.requirementCoverage ?? []).filter((item) => item.requirementId !== input.requirementId),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function updateRequirementCoverage(
|
||||
plan: VersionPlan,
|
||||
input: RequirementCoverageUpdateInput,
|
||||
): Pick<VersionPlan, 'requirementCoverage' | 'completedRequirementIds' | 'logs'> {
|
||||
const updatedAt = input.updatedAt ?? new Date().toISOString();
|
||||
const existingCoverage = plan.requirementCoverage?.find((item) => item.requirementId === input.requirementId);
|
||||
const workStartedAt = input.workStartedAt?.trim() || existingCoverage?.currentWorkStartedAt;
|
||||
const nextCoverage: VersionPlanRequirementCoverage = {
|
||||
requirementId: input.requirementId,
|
||||
status: input.status,
|
||||
@@ -333,10 +378,31 @@ export function updateRequirementCoverage(
|
||||
coverageStatus: input.status,
|
||||
completedContent: nextCoverage.completedContent,
|
||||
remainingContent: nextCoverage.remainingContent,
|
||||
workStartedAt,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export function startResearchDirectionWork(
|
||||
plan: VersionPlan,
|
||||
input: ResearchDirectionWorkStartInput,
|
||||
): Pick<VersionPlan, 'tasks'> {
|
||||
const tasks = plan.tasks ?? [];
|
||||
const startedAt = input.startedAt ?? new Date().toISOString();
|
||||
const nextTasks = tasks.map((task) => {
|
||||
if (task.id !== input.taskId || task.status === 'completed') return task;
|
||||
return {
|
||||
...task,
|
||||
status: 'in_progress' as const,
|
||||
currentWorkStartedAt: startedAt,
|
||||
updatedAt: startedAt,
|
||||
updatedBy: input.updatedBy,
|
||||
};
|
||||
});
|
||||
|
||||
return { tasks: nextTasks };
|
||||
}
|
||||
|
||||
export function updateResearchDirectionProgress(
|
||||
plan: VersionPlan,
|
||||
input: ResearchDirectionProgressUpdateInput,
|
||||
@@ -351,6 +417,7 @@ export function updateResearchDirectionProgress(
|
||||
}
|
||||
|
||||
const updatedAt = input.updatedAt ?? new Date().toISOString();
|
||||
const workStartedAt = input.workStartedAt?.trim() || target.currentWorkStartedAt;
|
||||
const nextStatus: PlanTaskStatus = input.status === 'completed' ? 'completed' : 'in_progress';
|
||||
const completedContent = input.status === 'partial' ? input.completedContent?.trim() || undefined : undefined;
|
||||
const remainingContent = input.status === 'partial' ? input.remainingContent?.trim() || undefined : undefined;
|
||||
@@ -360,6 +427,7 @@ export function updateResearchDirectionProgress(
|
||||
status: nextStatus,
|
||||
completedContent,
|
||||
remainingContent,
|
||||
currentWorkStartedAt: undefined,
|
||||
updatedAt,
|
||||
updatedBy: input.updatedBy,
|
||||
}
|
||||
@@ -382,6 +450,7 @@ export function updateResearchDirectionProgress(
|
||||
coverageStatus: input.status,
|
||||
completedContent,
|
||||
remainingContent,
|
||||
workStartedAt,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user