fix: 胶囊进度按子任务加权 + 调研任务清单必填+预设选项
1. 胶囊进度计算改为子任务加权:
- 分子 = 所有plan中已完成的子任务数
- 分母 = 所有plan的子任务总数
- completed的plan视为其子任务全部完成
- 没有子任务的plan按1项计算(不会导致分母为0)
- 例:4个completed(共8子任务) + 1个pending(2子任务)
= 8/(8+2) = 80%
2. 调研任务清单必须至少1项:
- handleSubmit 加校验:tasks.length === 0 时 return
- 红色提示:"请至少添加一项任务"
3. 预设可选任务选项(空列表时显示):
- 竞品分析、用户访谈、数据调研
- 技术可行性分析、市场调研、需求分析
- 点击即添加,也可自定义输入
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -252,6 +252,7 @@ function PlanFormModal({ initial, planType, versionId, versionDeadline, currentU
|
||||
e.preventDefault();
|
||||
if (!title.trim() || !endTime) return;
|
||||
if (isOverdue && !overdueReason.trim()) return;
|
||||
if (planType === 'research' && tasks.length === 0) return;
|
||||
onSubmit({
|
||||
versionId,
|
||||
type: planType,
|
||||
@@ -326,7 +327,25 @@ function PlanFormModal({ initial, planType, versionId, versionDeadline, currentU
|
||||
)}
|
||||
{planType === 'research' && (
|
||||
<div>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">任务清单</label>
|
||||
<label className="text-[12px] font-medium text-[var(--ink-soft)] mb-1.5 block">
|
||||
任务清单 <span className="text-red-500">*</span>
|
||||
<span className="text-[10px] text-[var(--ink-muted)] ml-1">至少添加一项</span>
|
||||
</label>
|
||||
{/* 预设选项 */}
|
||||
{tasks.length === 0 && (
|
||||
<div className="flex flex-wrap gap-1.5 mb-2">
|
||||
{['竞品分析', '用户访谈', '数据调研', '技术可行性分析', '市场调研', '需求分析'].map((preset) => (
|
||||
<button
|
||||
key={preset}
|
||||
type="button"
|
||||
onClick={() => setTasks([...tasks, { id: `task-${Date.now()}-${Math.random().toString(36).slice(2, 5)}`, title: preset, status: 'pending' }])}
|
||||
className="h-6 px-2.5 rounded-md text-[11px] border border-dashed border-[var(--line)] text-[var(--ink-soft)] hover:border-[var(--accent)] hover:text-[var(--accent)] transition-colors"
|
||||
>
|
||||
+ {preset}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="space-y-1.5 mb-2">
|
||||
{tasks.map((task, i) => (
|
||||
<div key={task.id} className="flex items-center gap-2 rounded-lg bg-[var(--bg-subtle)] px-3 py-1.5">
|
||||
@@ -340,11 +359,14 @@ function PlanFormModal({ initial, planType, versionId, versionDeadline, currentU
|
||||
value={newTaskTitle}
|
||||
onChange={(e) => setNewTaskTitle(e.target.value)}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); if (newTaskTitle.trim()) { setTasks([...tasks, { id: `task-${Date.now()}`, title: newTaskTitle.trim(), status: 'pending' }]); setNewTaskTitle(''); } } }}
|
||||
placeholder="输入任务名称,回车添加"
|
||||
placeholder="自定义任务名称,回车添加"
|
||||
className="flex-1 h-8 rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[12px] focus:border-[var(--accent)] focus:outline-none"
|
||||
/>
|
||||
<button type="button" onClick={() => { if (newTaskTitle.trim()) { setTasks([...tasks, { id: `task-${Date.now()}`, title: newTaskTitle.trim(), status: 'pending' }]); setNewTaskTitle(''); } }} className="h-8 px-3 rounded-lg text-[12px] font-medium bg-[var(--bg-subtle)] text-[var(--ink-soft)] hover:bg-[var(--line)]">添加</button>
|
||||
</div>
|
||||
{tasks.length === 0 && (
|
||||
<div className="text-[11px] text-red-500 mt-1">请至少添加一项任务</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user