fix: 调研/产品/UI 改为手动点击"开始"触发计时
去掉"到了计划日期自动变进行中"的逻辑,改为用户手动点击: - pending 状态显示蓝色"开始"按钮 - 点击后记录 actualStartAt(精确时间戳) - 进行中才显示"完成"按钮 跟开发/测试逻辑一致:状态由用户主动触发,时间戳准确。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Plus, Pencil, Trash2, X, Check, ExternalLink, FileUp, Link2 } from 'lucide-react';
|
||||
import { Plus, Pencil, Trash2, X, Check, ExternalLink, FileUp, Link2, Play } from 'lucide-react';
|
||||
import type { VersionPlan, PlanTask } from '@/lib/version-plan';
|
||||
import { calcPlanDuration, formatDuration, calcTotalDuration, calcPlanProgress, calcLinkedReqProgress } from '@/lib/version-plan';
|
||||
|
||||
@@ -56,19 +56,11 @@ export function PlanTab({ plans, versionId, versionDeadline, currentUserName, pl
|
||||
<div className="space-y-3">
|
||||
{typePlans.map((plan) => {
|
||||
const now = new Date().toISOString();
|
||||
const nowDate = now.slice(0, 10);
|
||||
// 自动进入进行中(到了计划开始日期)
|
||||
const shouldAutoStart = plan.status === 'pending' && plan.startTime <= nowDate;
|
||||
if (shouldAutoStart && !plan.actualStartAt) {
|
||||
onUpdate(plan.id, { status: 'in_progress' });
|
||||
}
|
||||
const effectiveStatus = shouldAutoStart ? 'in_progress' : plan.status;
|
||||
// 耗时用实际时间戳计算
|
||||
const actualStart = plan.actualStartAt || (shouldAutoStart ? now : null);
|
||||
const dur = effectiveStatus === 'completed' && plan.completedAt && actualStart
|
||||
? calcPlanDuration(actualStart, plan.completedAt)
|
||||
: effectiveStatus === 'in_progress' && actualStart
|
||||
? calcPlanDuration(actualStart, now)
|
||||
const dur = plan.status === 'completed' && plan.completedAt && plan.actualStartAt
|
||||
? calcPlanDuration(plan.actualStartAt, plan.completedAt)
|
||||
: plan.status === 'in_progress' && plan.actualStartAt
|
||||
? calcPlanDuration(plan.actualStartAt, now)
|
||||
: { days: 0, hours: 0 };
|
||||
const durText = dur.days > 0 || dur.hours > 0 ? formatDuration(dur.days, dur.hours) : '-';
|
||||
return (
|
||||
@@ -77,8 +69,8 @@ export function PlanTab({ plans, versionId, versionDeadline, currentUserName, pl
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2 mb-1.5">
|
||||
<span className="text-[13px] font-medium text-[var(--ink)]">{plan.title}</span>
|
||||
<span className={`inline-flex items-center rounded-md px-2 py-0.5 text-[10px] font-medium border ${STATUS_STYLE[effectiveStatus]}`}>
|
||||
{STATUS_LABEL[effectiveStatus]}
|
||||
<span className={`inline-flex items-center rounded-md px-2 py-0.5 text-[10px] font-medium border ${STATUS_STYLE[plan.status]}`}>
|
||||
{STATUS_LABEL[plan.status]}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-[12px] text-[var(--ink-soft)]">
|
||||
@@ -164,7 +156,7 @@ export function PlanTab({ plans, versionId, versionDeadline, currentUserName, pl
|
||||
) : null;
|
||||
})}
|
||||
</div>
|
||||
{calcLinkedReqProgress(plan.linkedRequirementIds, plan.completedRequirementIds) === 100 && effectiveStatus !== 'completed' && (
|
||||
{calcLinkedReqProgress(plan.linkedRequirementIds, plan.completedRequirementIds) === 100 && plan.status !== 'completed' && (
|
||||
<div className="mt-2 rounded-lg bg-green-50 border border-green-200 px-3 py-2 flex items-center justify-between">
|
||||
<span className="text-[12px] text-green-700">所有需求已完成,请提交原型成果</span>
|
||||
<button onClick={() => setCompletingPlan(plan)} className="text-[11px] font-medium text-green-700 hover:text-green-900 underline">提交</button>
|
||||
@@ -174,11 +166,18 @@ export function PlanTab({ plans, versionId, versionDeadline, currentUserName, pl
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 ml-3">
|
||||
{effectiveStatus !== 'completed' && (
|
||||
{plan.status === 'pending' && (
|
||||
<button onClick={() => onUpdate(plan.id, { status: 'in_progress' })} className="h-7 px-2 flex items-center gap-1 rounded-md text-[11px] font-medium text-blue-600 hover:bg-blue-50 border border-blue-200" title="开始">
|
||||
<Play className="h-3 w-3" />开始
|
||||
</button>
|
||||
)}
|
||||
{plan.status !== 'completed' && plan.status !== 'pending' && (
|
||||
<button onClick={() => setCompletingPlan(plan)} className="h-7 w-7 flex items-center justify-center rounded-md text-green-600 hover:bg-green-50" title="标记完成">
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
)}
|
||||
{plan.status !== 'completed' && (
|
||||
<>
|
||||
<button onClick={() => setCompletingPlan(plan)} className="h-7 w-7 flex items-center justify-center rounded-md text-green-600 hover:bg-green-50" title="标记完成">
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button onClick={() => setEditingPlan(plan)} className="h-7 w-7 flex items-center justify-center rounded-md text-[var(--ink-muted)] hover:bg-[var(--bg-subtle)]" title="编辑">
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user