From dfcbcb0ecf70f1c86f0413628c02f6345950a0c0 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Thu, 21 May 2026 09:08:20 +0800 Subject: [PATCH] auto-sync: 2026-05-21 09:08:20 --- src/frontend/src/components/TaskModal.tsx | 114 +++++++++++++++------- 1 file changed, 81 insertions(+), 33 deletions(-) diff --git a/src/frontend/src/components/TaskModal.tsx b/src/frontend/src/components/TaskModal.tsx index 2b4f88f..8409b11 100644 --- a/src/frontend/src/components/TaskModal.tsx +++ b/src/frontend/src/components/TaskModal.tsx @@ -98,32 +98,72 @@ function StatusButtons({ status, taskId, onAction }: { status: string; taskId: s const selectedProjectId = useStore((s) => s.selectedProjectId); const projects = useStore((s) => s.projects); const loadV2Tasks = useStore((s) => s.loadV2Tasks); - const transitions = VALID_TRANSITIONS[status] || []; const [loading, setLoading] = useState(null); - const btnMap: Record = { - claimed: { label: '认领任务', icon: '👤', bg: '#a07aff22', color: '#a07aff', border: '#a07aff44' }, - working: { label: '开始执行', icon: '⚔️', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }, - review: { label: '提交审查', icon: '🔍', bg: '#818cf822', color: '#818cf8', border: '#818cf844' }, - done: { label: '标记完成', icon: '✅', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }, - failed: { label: '标记失败', icon: '❌', bg: '#ff527022', color: '#ff5270', border: '#ff527044' }, - blocked: { label: '标记阻塞', icon: '🚧', bg: '#f59e0b22', color: '#f59e0b', border: '#f59e0b44' }, - pending: { label: '重置待认领', icon: '🔄', bg: '#7a9aff22', color: '#7a9aff', border: '#7a9aff44' }, - paused: { label: '暂停', icon: '⏸', bg: '#818cf822', color: '#818cf8', border: '#818cf844' }, - escalated: { label: '升级', icon: '⚠️', bg: '#ff527022', color: '#ff5270', border: '#ff527044' }, - cancelled: { label: '取消任务', icon: '🚫', bg: '#6b728022', color: '#6b7280', border: '#6b728044' }, + const [showAdvanced, setShowAdvanced] = useState(false); + + // AI Native:只显示人需要做的动作 + const PRIMARY_ACTIONS: Record> = { + working: [{ target: 'paused', label: '暂停任务', icon: '⏸', bg: '#818cf822', color: '#818cf8', border: '#818cf844' }], + waiting_human: [ + { target: 'done', label: '确认完成', icon: '✅', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }, + { target: 'working', label: '拒绝,继续做', icon: '🔄', bg: '#7a9aff22', color: '#7a9aff', border: '#7a9aff44' }, + ], + escalated: [ + { target: 'working', label: '继续执行', icon: '▶', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }, + { target: 'pending', label: '重新分配', icon: '🔄', bg: '#7a9aff22', color: '#7a9aff', border: '#7a9aff44' }, + ], + failed: [{ target: 'pending', label: '重试', icon: '🔄', bg: '#7a9aff22', color: '#7a9aff', border: '#7a9aff44' }], + blocked: [{ target: 'pending', label: '解除阻塞', icon: '🔓', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }], + paused: [ + { target: 'working', label: '继续执行', icon: '▶', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }, + { target: 'cancelled', label: '取消任务', icon: '🚫', bg: '#6b728022', color: '#6b7280', border: '#6b728044' }, + ], + done: [{ target: '__archive', label: '归档', icon: '📦', bg: '#6b728022', color: '#6b7280', border: '#6b728044' }], + cancelled: [{ target: '__archive', label: '归档', icon: '📦', bg: '#6b728022', color: '#6b7280', border: '#6b728044' }], }; + // 高级操作(手动干预用) + const ADVANCED_ACTIONS: Record> = { + working: [ + { target: 'review', label: '手动提交审查', icon: '🔍', bg: '#818cf822', color: '#818cf8', border: '#818cf844' }, + { target: 'cancelled', label: '取消', icon: '🚫', bg: '#6b728022', color: '#6b7280', border: '#6b728044' }, + ], + review: [ + { target: 'done', label: '手动通过', icon: '✅', bg: '#2ecc8a22', color: '#2ecc8a', border: '#2ecc8a44' }, + { target: 'pending', label: '打回重做', icon: '🔄', bg: '#7a9aff22', color: '#7a9aff', border: '#7a9aff44' }, + ], + failed: [ + { target: 'cancelled', label: '取消', icon: '🚫', bg: '#6b728022', color: '#6b7280', border: '#6b728044' }, + ], + }; + + const primary = PRIMARY_ACTIONS[status] || []; + const advanced = ADVANCED_ACTIONS[status] || []; + + if (primary.length === 0 && advanced.length === 0) { + // Agent 自动流转的状态,提示用户 + const autoMsg: Record = { + pending: '⏳ 等待 Agent 自动认领...', + claimed: '⏳ Agent 已认领,即将开始...', + review: '🔍 Agent 审查中,请等待审查结果...', + }; + return
{autoMsg[status] || ''}
; + } + const handleClick = async (targetStatus: string) => { setLoading(targetStatus); try { - const result = await api.taskStatusUpdate(taskId, targetStatus); - if (result.ok) { - toast(`${targetStatus} 操作成功`, 'ok'); - loadV2TaskDetail(taskId); - loadAll(); - onAction?.(); + if (targetStatus === '__archive') { + const pid = selectedProjectId || ''; + const res = await fetch(`/api/projects/${pid}/tasks/${taskId}`, { + method: 'PATCH', headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ archived: 1 }), + }); + if (res.ok) { toast('📦 已归档'); loadV2Tasks(); } else toast('归档失败', 'err'); } else { - toast(result.error || '操作失败', 'err'); + const result = await api.taskStatusUpdate(taskId, targetStatus); + if (result.ok) { toast(`${targetStatus} 操作成功`, 'ok'); loadV2TaskDetail(taskId); loadAll(); onAction?.(); } + else toast(result.error || '操作失败', 'err'); } } catch (e: any) { toast(e.message || '⚠️ 操作失败', 'err'); @@ -132,22 +172,30 @@ function StatusButtons({ status, taskId, onAction }: { status: string; taskId: s } }; - if (transitions.length === 0) return null; + const btn = (b: typeof primary[0]) => ( + + ); return ( -
- {transitions.map(t => { - const b = btnMap[t]; - if (!b) return null; - const isLoading = loading === t; - return ( - - ); - })} +
+
{primary.map(b => btn(b))}
+ {advanced.length > 0 && ( +
+ {!showAdvanced ? ( + + ) : ( +
+ {advanced.map(b => btn(b))} + +
+ )} +
+ )}
); }