From 5bbcf02962de2f790d2c1d22c2bad6ab16e9a7c7 Mon Sep 17 00:00:00 2001 From: Script Generator Date: Mon, 15 Jun 2026 15:31:21 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=AE=A1=E5=88=92=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=8B=BE=E9=80=89=E9=80=BB=E8=BE=91=20+=20=E8=83=B6=E5=9B=8A?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E8=AE=A1=E7=AE=97=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 必须点击"开始"后才能勾选任务: - 调研/产品方案/UI设计的 checkbox 加 disabled 判断 - plan.status !== 'in_progress' 时不可交互 2. 调研勾选改为二态(与产品/UI一致): - 去掉三态循环(pending→in_progress→completed) - 改为 toggle:未完成 ↔ 已完成 - 显示文字也简化为"已完成"/"未完成" 3. 胶囊进度百分比计算修正: - 旧逻辑:所有子任务合并计算(新建空任务导致分母为0返回0%) - 新逻辑:以 plan 为单位加权计算 - completed 的 plan = 权重 1 - in_progress 的 plan = 子任务完成率 - pending 的 plan = 权重 0 - 公式:sum(weights) / plan_count * 100 - 新建一个 pending 的 plan 不会把已完成的 100% 打回 0% Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web/app/versions/[id]/page.tsx | 36 ++++++++++++++----------- apps/web/components/version/PlanTab.tsx | 15 ++++++----- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/apps/web/app/versions/[id]/page.tsx b/apps/web/app/versions/[id]/page.tsx index 07dde5e..b51e332 100644 --- a/apps/web/app/versions/[id]/page.tsx +++ b/apps/web/app/versions/[id]/page.tsx @@ -303,23 +303,27 @@ export default function VersionDetailPage() { const calcGroupProgress = (group: typeof vPlans, type: 'research' | 'product' | 'ui') => { if (group.length === 0) return 0; - if (type === 'research') { - const totals = group.reduce((acc, p) => { - const tasks = p.tasks || []; - acc.total += tasks.length; - acc.done += tasks.filter((t) => t.status === 'completed').length; - return acc; - }, { total: 0, done: 0 }); - return totals.total > 0 ? Math.round((totals.done / totals.total) * 100) : 0; + // 每个 plan 按权重贡献进度:completed=1, in_progress=子任务完成率, pending=0 + let totalWeight = 0; + for (const p of group) { + if (p.status === 'completed') { + totalWeight += 1; + } else if (p.status === 'in_progress') { + if (type === 'research') { + const tasks = p.tasks || []; + if (tasks.length > 0) { + totalWeight += tasks.filter((t) => t.status === 'completed').length / tasks.length; + } + } else { + const linked = p.linkedRequirementIds || []; + const completed = p.completedRequirementIds || []; + if (linked.length > 0) { + totalWeight += completed.filter((id) => linked.includes(id)).length / linked.length; + } + } + } } - const totals = group.reduce((acc, p) => { - const linked = p.linkedRequirementIds || []; - const completed = p.completedRequirementIds || []; - acc.total += linked.length; - acc.done += completed.filter((id) => linked.includes(id)).length; - return acc; - }, { total: 0, done: 0 }); - return totals.total > 0 ? Math.round((totals.done / totals.total) * 100) : 0; + return Math.round((totalWeight / group.length) * 100); }; const getPlanStatus = (group: typeof vPlans): 'idle' | 'active' | 'done' => { diff --git a/apps/web/components/version/PlanTab.tsx b/apps/web/components/version/PlanTab.tsx index 2dd4e99..9a9ad2b 100644 --- a/apps/web/components/version/PlanTab.tsx +++ b/apps/web/components/version/PlanTab.tsx @@ -106,19 +106,20 @@ export function PlanTab({ plans, versionId, versionDeadline, currentUserName, pl {plan.tasks.map((task) => (
{task.title} - - {task.status === 'completed' ? '已完成' : task.status === 'in_progress' ? '进行中' : '未开始'} + + {task.status === 'completed' ? '已完成' : '未完成'}
))} @@ -141,12 +142,14 @@ export function PlanTab({ plans, versionId, versionDeadline, currentUserName, pl return req ? (