diff --git a/apps/web/components/test-case/TestCaseDetailDrawer.tsx b/apps/web/components/test-case/TestCaseDetailDrawer.tsx index 1220cdc..5d87e70 100644 --- a/apps/web/components/test-case/TestCaseDetailDrawer.tsx +++ b/apps/web/components/test-case/TestCaseDetailDrawer.tsx @@ -8,6 +8,7 @@ import { useTestCaseStore } from '@/stores/useTestCaseStore'; import { useBugStore } from '@/stores/useBugStore'; import { useRequirementStore } from '@/stores/useRequirementStore'; import { TC_ALLOWED_TRANSITIONS, TEST_CASE_STATUS_LABEL } from '@/lib/test-case'; +import { calcActualHoursByDates } from '@/lib/dev-task'; import { BUG_SEVERITY_LABEL, BUG_SEVERITY_COLOR } from '@/lib/bug'; import type { TestCaseStatus } from '@/lib/test-case'; @@ -126,6 +127,9 @@ export function TestCaseDetailDrawer({ testCaseId, onClose, onCreateBug }: Props
负责人:{tc.assigneeId || '-'}
创建人:{tc.createdBy}
创建日期:{tc.createdAt.slice(0, 10)}
+ {tc.startedAt &&
开始执行:{tc.startedAt}
} + {tc.completedAt &&
执行完成:{tc.completedAt}
} + {tc.startedAt &&
测试耗时:{calcActualHoursByDates(tc.startedAt, tc.completedAt)}h
} diff --git a/apps/web/components/test-case/TestCaseRow.tsx b/apps/web/components/test-case/TestCaseRow.tsx index 8741eba..ae9f454 100644 --- a/apps/web/components/test-case/TestCaseRow.tsx +++ b/apps/web/components/test-case/TestCaseRow.tsx @@ -1,8 +1,8 @@ 'use client'; import { TestCaseStatusBadge } from './TestCaseStatusBadge'; +import { calcActualHoursByDates } from '@/lib/dev-task'; import type { TestCase } from '@/lib/test-case'; -import type { Bug } from '@/lib/bug'; interface Props { testCase: TestCase; @@ -24,6 +24,9 @@ export function TestCaseRow({ testCase, bugCount, onClick }: Props) { {testCase.caseNo} {testCase.title} + {testCase.startedAt && ( + {calcActualHoursByDates(testCase.startedAt, testCase.completedAt)}h + )} {bugCount > 0 && ( {bugCount} Bug )} diff --git a/apps/web/lib/test-case.ts b/apps/web/lib/test-case.ts index 34aae9d..baebb07 100644 --- a/apps/web/lib/test-case.ts +++ b/apps/web/lib/test-case.ts @@ -12,6 +12,8 @@ export interface TestCase { priority: Priority; assigneeId?: string; status: TestCaseStatus; + startedAt?: string; + completedAt?: string; executedAt?: string; executedBy?: string; failReason?: string; diff --git a/apps/web/stores/useTestCaseStore.ts b/apps/web/stores/useTestCaseStore.ts index 35fbf7c..5fc7d65 100644 --- a/apps/web/stores/useTestCaseStore.ts +++ b/apps/web/stores/useTestCaseStore.ts @@ -76,12 +76,17 @@ export const useTestCaseStore = create((set, get) => ({ } const today = new Date().toISOString().slice(0, 10); const patch: Partial = { status: to }; + // 开始执行时间 + if (to === 'running' && !tc.startedAt) patch.startedAt = today; + // 执行完成时间(通过/失败/阻塞都算执行完成) + if (to === 'passed' || to === 'failed' || to === 'blocked') patch.completedAt = today; if (to === 'running' || to === 'passed' || to === 'failed' || to === 'blocked') { patch.executedAt = today; } + // 回退到执行中时清除完成时间 + if (to === 'running') { patch.failReason = undefined; patch.blockReason = undefined; patch.completedAt = undefined; } if (to === 'failed' && extra?.failReason) patch.failReason = extra.failReason; if (to === 'blocked' && extra?.blockReason) patch.blockReason = extra.blockReason; - if (to === 'running') { patch.failReason = undefined; patch.blockReason = undefined; } get().updateTestCase(id, patch); return { ok: true }; },