feat(版本详情): 完善流程日志与需求覆盖

This commit is contained in:
Script Generator
2026-06-30 11:00:07 +08:00
parent d754585fe0
commit 1cd595c42e
38 changed files with 4123 additions and 237 deletions

View File

@@ -23,6 +23,7 @@ export interface TestCase {
estimateHours?: number;
aiEstimateHours?: number;
plannedTestAt?: string;
plannedEndAt?: string;
startedAt?: string;
completedAt?: string;
executedAt?: string;
@@ -98,6 +99,7 @@ export function normalizeTestCase(testCase: Partial<TestCase>, index = 0): TestC
estimateHours: typeof testCase.estimateHours === 'number' && testCase.estimateHours > 0 ? testCase.estimateHours : undefined,
aiEstimateHours: typeof testCase.aiEstimateHours === 'number' && testCase.aiEstimateHours > 0 ? testCase.aiEstimateHours : undefined,
plannedTestAt: testCase.plannedTestAt,
plannedEndAt: testCase.plannedEndAt,
startedAt: testCase.startedAt,
completedAt: testCase.completedAt,
executedAt: testCase.executedAt,
@@ -172,6 +174,7 @@ export function copyTestCaseToRound(source: TestCase, roundNo: number, createdBy
estimateHours: source.estimateHours,
aiEstimateHours: source.aiEstimateHours,
plannedTestAt: source.plannedTestAt,
plannedEndAt: source.plannedEndAt,
assigneeId: source.assigneeId,
startedAt: undefined,
completedAt: undefined,
@@ -224,6 +227,23 @@ export function getTestCaseEstimateHours(tc: TestCase): number {
return 0;
}
export function needsTestCaseClaim(testCase: Pick<TestCase, 'assigneeId'>): boolean {
return !testCase.assigneeId?.trim();
}
export function hasTestCasePlan(testCase: Pick<TestCase, 'plannedTestAt' | 'plannedEndAt'>): boolean {
if (!testCase.plannedTestAt || !testCase.plannedEndAt) return false;
const start = new Date(testCase.plannedTestAt).getTime();
const end = new Date(testCase.plannedEndAt).getTime();
return Number.isFinite(start) && Number.isFinite(end) && end > start;
}
export function canStartTestCase(
testCase: Pick<TestCase, 'assigneeId' | 'plannedTestAt' | 'plannedEndAt'>,
): boolean {
return !needsTestCaseClaim(testCase) && hasTestCasePlan(testCase);
}
export function getTestCaseActualHours(tc: TestCase, now: Date = new Date()): number {
if (!tc.startedAt) return 0;
const isTerminal = tc.status === 'passed' || tc.status === 'failed' || tc.status === 'blocked';