feat(版本详情): 优化任务统计与测试轮次
This commit is contained in:
@@ -12,9 +12,10 @@ import { BugDetailDrawer } from './BugDetailDrawer';
|
||||
import { Pagination, usePagination } from '@/components/Pagination';
|
||||
import { SearchInput, matchTitleOrNo } from '@/components/SearchInput';
|
||||
import { useDebouncedValue } from '@/hooks/useDebouncedValue';
|
||||
import { BUG_STATUS_LABEL, BUG_SEVERITY_LABEL, bugIntervals } from '@/lib/bug';
|
||||
import { formatWorkHours, calcTwoMetrics } from '@/lib/work-hours';
|
||||
import { BUG_STATUS_LABEL, BUG_SEVERITY_LABEL, aggregateBugActualHours, bugIntervals } from '@/lib/bug';
|
||||
import { calcTwoMetrics } from '@/lib/work-hours';
|
||||
import { isMemberReference, resolveMemberDisplayName } from '@/lib/member-system';
|
||||
import { buildEffortSummaryMetrics, sumPositiveHours } from '@/lib/effort-summary';
|
||||
import type { BugStatus, BugSeverity } from '@/lib/bug';
|
||||
|
||||
interface Props {
|
||||
@@ -43,7 +44,17 @@ export function BugTab({ versionId, requirementIds }: Props) {
|
||||
const closedCount = versionBugs.filter((b) => b.status === 'closed' || b.status === 'rejected').length;
|
||||
const criticalCount = versionBugs.filter((b) => b.severity === 'critical' && b.status !== 'closed' && b.status !== 'rejected').length;
|
||||
const resolveRate = versionBugs.length > 0 ? Math.round(((fixedCount + closedCount) / versionBugs.length) * 100) : 0;
|
||||
const { calendarHours: bugCalendarHours, manhours: bugManhours } = useMemo(() => calcTwoMetrics(bugIntervals(versionBugs)), [versionBugs]);
|
||||
const bugActualHours = useMemo(() => aggregateBugActualHours(versionBugs), [versionBugs]);
|
||||
const { manhours: bugManhours } = useMemo(() => calcTwoMetrics(bugIntervals(versionBugs)), [versionBugs]);
|
||||
const effortMetrics = useMemo(
|
||||
() => buildEffortSummaryMetrics({
|
||||
aiEstimateHours: sumPositiveHours(versionBugs, (bug) => bug.aiEstimateHours),
|
||||
estimateHours: sumPositiveHours(versionBugs, (bug) => bug.estimateHours),
|
||||
actualHours: bugActualHours,
|
||||
manhours: bugManhours,
|
||||
}),
|
||||
[versionBugs, bugActualHours, bugManhours],
|
||||
);
|
||||
|
||||
const [filterAssignee, setFilterAssignee] = useState('');
|
||||
const [filterStatus, setFilterStatus] = useState('');
|
||||
@@ -97,9 +108,11 @@ export function BugTab({ versionId, requirementIds }: Props) {
|
||||
<span className="text-[11px] text-red-600 bg-red-50 px-1.5 py-0.5 rounded font-medium">{criticalCount} 致命</span>
|
||||
)}
|
||||
<span className="text-[11px] text-[var(--ink-muted)]">解决率 {resolveRate}%</span>
|
||||
{bugManhours > 0 && (
|
||||
<span className="text-[11px] text-[var(--ink-muted)]">日历 {formatWorkHours(bugCalendarHours)} / 人力 {formatWorkHours(bugManhours)}</span>
|
||||
)}
|
||||
{effortMetrics.map((metric) => (
|
||||
<span key={metric.label} className="text-[11px] text-[var(--ink-muted)] shrink-0">
|
||||
{metric.label} <span className="tabular-nums text-[var(--ink)]">{metric.value}</span>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 px-1 flex-wrap">
|
||||
|
||||
Reference in New Issue
Block a user