feat(版本): 记录计划需求进展活动
关键改动: - 记录产品/UI 计划需求覆盖进展,并写入工作活动与实体日志 - 日报和小宝预警补充需求进展活动证据 - 调整版本列表与需求覆盖面板展示,并补充测试 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -10,7 +10,6 @@ import { getVersionDetail } from '@/lib/derive';
|
||||
import type { Role } from '@/lib/stage';
|
||||
import { CapsuleStages } from '@/components/version/CapsuleStages';
|
||||
import { FilterSelect } from '@/components/FilterSelect';
|
||||
import { calcHealthScore, getHealthLevel, calcRiskTags, HEALTH_LEVEL_LABEL, getTagStyle } from '@/lib/health';
|
||||
import { CHANGE_REASON_LABEL } from '@/lib/requirement';
|
||||
import { OVERTIME_REASON_LABEL } from '@/lib/overtime';
|
||||
import { VersionRequirementsTab } from '@/components/version/VersionRequirementsTab';
|
||||
@@ -168,9 +167,6 @@ export default function VersionDetailPage() {
|
||||
);
|
||||
}
|
||||
|
||||
const healthScore = calcHealthScore(version.status, version.startDate, version.expectedReleaseDate, version.progress);
|
||||
const healthLevel = getHealthLevel(healthScore);
|
||||
const riskTags = calcRiskTags(version.status, version.startDate, version.expectedReleaseDate, version.progress, version.currentStage, version.members);
|
||||
const recommendationVersionReqs = requirements.filter((requirement) => requirement.versionId === version.id);
|
||||
const recommendationVersionReqIds = new Set(recommendationVersionReqs.map((requirement) => requirement.id));
|
||||
const recommendationVersionDevTasks = devTasks.filter((task) => recommendationVersionReqIds.has(task.requirementId));
|
||||
@@ -325,30 +321,7 @@ export default function VersionDetailPage() {
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{/* 1. 风险详情 - 最上方 */}
|
||||
{riskTags.length > 0 && (
|
||||
<div className="rounded-xl border border-orange-200 bg-orange-50/40 p-4 max-h-[200px] overflow-y-auto">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="text-[12px] font-semibold text-orange-700">风险详情</span>
|
||||
<span className="text-[10px] text-orange-600">健康度 {healthScore} · {HEALTH_LEVEL_LABEL[healthLevel]}</span>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{riskTags.map((tag) => (
|
||||
<div key={tag.key} className="flex gap-2.5 pb-2 border-b border-orange-100 last:border-b-0 last:pb-0">
|
||||
<span className={`shrink-0 inline-flex items-center rounded border px-1.5 py-0.5 text-[10px] font-medium h-fit mt-0.5 ${getTagStyle(tag.severity)}`}>
|
||||
{tag.label}
|
||||
</span>
|
||||
<div className="flex-1 space-y-0.5 text-[11px]">
|
||||
{tag.reason && <div className="text-[var(--ink-soft)]"><span className="text-[var(--ink-muted)]">原因:</span>{tag.reason}</div>}
|
||||
{tag.suggestion && <div className="text-[var(--ink-soft)]"><span className="text-[var(--ink-muted)]">建议:</span>{tag.suggestion}</div>}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 2. 阶段概览 */}
|
||||
{/* 阶段概览 */}
|
||||
{(() => {
|
||||
const researchPlans = versionPlans.filter((p) => p.type === 'research');
|
||||
const productPlans = versionPlans.filter((p) => p.type === 'product');
|
||||
@@ -843,12 +816,6 @@ export default function VersionDetailPage() {
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
|
||||
{/* 健康趋势 - 暂时不显示 */}
|
||||
{/* <div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4 max-w-[320px]">
|
||||
<span className="text-[11px] font-medium text-[var(--ink-muted)] mb-2 block">健康趋势</span>
|
||||
<HealthTrend data={generateMockTrend(healthScore, 7)} />
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
})()
|
||||
|
||||
Reference in New Issue
Block a user