feat(工作台): 细化计划进展工时证据
关键改动: - 支持需求覆盖和调研方向开始工作记录 - 日报按计划记录开始时间和进度下次开始时间计算证据 - 更新版本编辑校验、项目展示和 workflow 说明 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -47,6 +47,13 @@ function defaultPlanEndLocal(): string {
|
||||
return isoToLocal(d.toISOString());
|
||||
}
|
||||
|
||||
function defaultProgressNextStartLocal(): string {
|
||||
const d = new Date();
|
||||
d.setDate(d.getDate() + 1);
|
||||
d.setHours(9, 30, 0, 0);
|
||||
return isoToLocal(d.toISOString());
|
||||
}
|
||||
|
||||
export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel, readOnly = false }: Props) {
|
||||
const { tasks, changeStatus, setBlocked, deleteTask, updateTask } = useDevTaskStore();
|
||||
const addProgressNote = useWorkActivityStore((s) => s.addProgressNote);
|
||||
@@ -65,6 +72,7 @@ export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel,
|
||||
const [progressBlocker, setProgressBlocker] = useState('');
|
||||
const [progressHelperId, setProgressHelperId] = useState('');
|
||||
const [progressDelayRisk, setProgressDelayRisk] = useState('');
|
||||
const [progressNextStartLocal, setProgressNextStartLocal] = useState(() => defaultProgressNextStartLocal());
|
||||
|
||||
const task = tasks.find((t) => t.id === taskId);
|
||||
if (!task) return null;
|
||||
@@ -92,6 +100,10 @@ export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel,
|
||||
const planEndISO = localToISO(planEndLocal);
|
||||
const planStartBeforeEnd = Boolean(planStartISO && planEndISO && planStartISO < planEndISO);
|
||||
const planEstimateHours = planStartBeforeEnd ? calcWorkHours(planStartISO, planEndISO) : 0;
|
||||
const progressNextStartISO = localToISO(progressNextStartLocal);
|
||||
const canRecordProgress = Boolean(
|
||||
(progressNote.trim() || progressBlocker.trim() || progressDelayRisk.trim()) && progressNextStartISO,
|
||||
);
|
||||
|
||||
const openPlanInput = () => {
|
||||
if (readOnly) return;
|
||||
@@ -160,6 +172,10 @@ export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel,
|
||||
const blocker = progressBlocker.trim();
|
||||
const delayRisk = progressDelayRisk.trim();
|
||||
if (!note && !blocker && !delayRisk) return;
|
||||
if (!progressNextStartISO) {
|
||||
alert('请填写下次开始时间');
|
||||
return;
|
||||
}
|
||||
|
||||
addProgressNote({
|
||||
actorId: task.assigneeId,
|
||||
@@ -167,6 +183,7 @@ export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel,
|
||||
sourceId: task.id,
|
||||
title: task.title,
|
||||
note: note || '今日进展已更新',
|
||||
nextStartAt: progressNextStartISO,
|
||||
blocker: blocker || undefined,
|
||||
helperId: progressHelperId || undefined,
|
||||
delayRisk: delayRisk || undefined,
|
||||
@@ -175,6 +192,7 @@ export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel,
|
||||
setProgressBlocker('');
|
||||
setProgressHelperId('');
|
||||
setProgressDelayRisk('');
|
||||
setProgressNextStartLocal(defaultProgressNextStartLocal());
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -381,11 +399,25 @@ export function DevTaskDetailDrawer({ taskId, allTaskIds, onClose, contextLabel,
|
||||
placeholder="延期风险"
|
||||
className="h-8 w-full rounded-lg border border-[var(--line)] bg-[var(--bg)] px-2 text-[12px] focus:border-orange-400 focus:outline-none"
|
||||
/>
|
||||
<div className="flex justify-end">
|
||||
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-end gap-2">
|
||||
<div>
|
||||
<label className="mb-1 flex items-center gap-1 text-[11px] text-[var(--ink-muted)]">
|
||||
下次开始时间
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<WorkDateTimePicker
|
||||
value={progressNextStartLocal}
|
||||
onChange={setProgressNextStartLocal}
|
||||
placeholder="选择下次开始时间"
|
||||
defaultHour={9}
|
||||
popoverAlign="right"
|
||||
className="bg-[var(--bg)]"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleProgressNote}
|
||||
disabled={!progressNote.trim() && !progressBlocker.trim() && !progressDelayRisk.trim()}
|
||||
className="h-8 px-3 rounded-lg text-[12px] font-medium bg-[var(--accent)] text-white hover:bg-[var(--accent-hover)] disabled:opacity-50"
|
||||
disabled={!canRecordProgress}
|
||||
className="h-9 px-3 rounded-lg text-[12px] font-medium bg-[var(--accent)] text-white hover:bg-[var(--accent-hover)] disabled:opacity-50"
|
||||
>
|
||||
记录进展
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user