From 10131f9db744ac5fce3c214555a668e41b51bbc2 Mon Sep 17 00:00:00 2001 From: Script Generator Date: Mon, 15 Jun 2026 17:07:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=8E=E6=88=91=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=8A=A0=E5=AE=BD=E5=B8=83=E5=B1=80=20+=20=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=8F=AF=E7=9B=B4=E6=8E=A5=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 加宽两栏布局: - 左一(树):w-52 → w-64 - 左二(环节):w-48 → w-56 - 右侧更舒适,不再拥挤 2. 待办任务可直接在工作台完成,无需跳转: - 调研/产品方案/UI:开始 → 完成 - 开发任务:开始 → 提测 → 完成 - 测试用例:通过 / 失败 - Bug:修复中 → 已修复 → 关闭 - 每个状态显示对应的下一步操作按钮 - 已完成的不显示操作按钮 Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web/app/workspace/page.tsx | 81 +++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/apps/web/app/workspace/page.tsx b/apps/web/app/workspace/page.tsx index ed52ed8..d117e2f 100644 --- a/apps/web/app/workspace/page.tsx +++ b/apps/web/app/workspace/page.tsx @@ -39,11 +39,11 @@ const PLAN_STATUS_LABEL: Record = { pending: '未开始', in_pro export default function WorkspacePage() { const router = useRouter(); const { overview, fetchOverview } = useProductStore(); - const { plans, fetchPlans } = useVersionPlanStore(); + const { plans, fetchPlans, updatePlan } = useVersionPlanStore(); const { requirements, fetchRequirements } = useRequirementStore(); - const { tasks: devTasks, fetchTasks } = useDevTaskStore(); - const { testCases, fetchTestCases } = useTestCaseStore(); - const { bugs, fetchBugs } = useBugStore(); + const { tasks: devTasks, fetchTasks, updateTask } = useDevTaskStore(); + const { testCases, fetchTestCases, updateTestCase } = useTestCaseStore(); + const { bugs, fetchBugs, updateBug } = useBugStore(); const user = useAuthStore((s) => s.user); const [activeTab, setActiveTab] = useState('all'); const [showCompleted, setShowCompleted] = useState(true); @@ -121,10 +121,31 @@ export default function WorkspacePage() { const pendingCount = pendingByTab.all; const completedCount = (selectedVersionId ? workItems.filter((i) => i.versionId === selectedVersionId) : workItems).filter((i) => i.completed).length; + const handleItemAction = (item: WorkItem, action: string) => { + if (item.type === 'plan_research' || item.type === 'plan_product' || item.type === 'plan_ui') { + if (action === 'start') updatePlan(item.id, { status: 'in_progress' }); + if (action === 'complete') updatePlan(item.id, { status: 'completed', completedAt: new Date().toISOString() }); + } + if (item.type === 'devTask') { + if (action === 'start') updateTask(item.id, { status: 'in_progress' }); + if (action === 'testing') updateTask(item.id, { status: 'testing' }); + if (action === 'submit') updateTask(item.id, { status: 'submitted', completedAt: new Date().toISOString() }); + } + if (item.type === 'testCase') { + if (action === 'pass') updateTestCase(item.id, { status: 'passed', completedAt: new Date().toISOString() }); + if (action === 'fail') updateTestCase(item.id, { status: 'failed' }); + } + if (item.type === 'bug') { + if (action === 'fix') updateBug(item.id, { status: 'fixing' }); + if (action === 'fixed') updateBug(item.id, { status: 'fixed' }); + if (action === 'close') updateBug(item.id, { status: 'closed', closedAt: new Date().toISOString() }); + } + }; + return (
{/* 左侧第一列:产品/项目/版本树 */} -
+

与我相关

@@ -146,7 +167,7 @@ export default function WorkspacePage() {
{/* 左侧第二列:环节分类 */} -
+
待办 {pendingCount} @@ -201,7 +222,12 @@ export default function WorkspacePage() { ) : (
{filteredItems.map((item) => ( - item.versionId && router.push(`/versions/${item.versionId}`)} /> + item.versionId && router.push(`/versions/${item.versionId}`)} + onAction={(action) => handleItemAction(item, action)} + /> ))}
)} @@ -261,8 +287,9 @@ function ProjectNode({ name, versions, selectedVersionId, onSelect }: { ); } -function WorkItemCard({ item, onNavigate }: { item: WorkItem; onNavigate: () => void }) { +function WorkItemCard({ item, onNavigate, onAction }: { item: WorkItem; onNavigate: () => void; onAction: (action: string) => void }) { const statusBadge = getStatusBadge(item); + const actions = getActions(item); return (
@@ -282,6 +309,16 @@ function WorkItemCard({ item, onNavigate }: { item: WorkItem; onNavigate: () => {BUG_SEVERITY_LABEL[item.extra.severity as keyof typeof BUG_SEVERITY_LABEL] || ''} )} + {/* 操作按钮 */} + {actions.length > 0 && ( +
+ {actions.map((a) => ( + + ))} +
+ )} @@ -299,6 +336,34 @@ function WorkItemCard({ item, onNavigate }: { item: WorkItem; onNavigate: () => ); } +function getActions(item: WorkItem): { key: string; label: string; style: string }[] { + if (item.completed) return []; + + if (item.type === 'plan_research' || item.type === 'plan_product' || item.type === 'plan_ui') { + if (item.status === 'pending') return [{ key: 'start', label: '开始', style: 'text-blue-600 hover:bg-blue-50 border border-blue-200' }]; + if (item.status === 'in_progress') return [{ key: 'complete', label: '完成', style: 'text-emerald-600 hover:bg-emerald-50 border border-emerald-200' }]; + } + if (item.type === 'devTask') { + if (item.status === 'todo') return [{ key: 'start', label: '开始', style: 'text-blue-600 hover:bg-blue-50 border border-blue-200' }]; + if (item.status === 'in_progress') return [{ key: 'testing', label: '提测', style: 'text-purple-600 hover:bg-purple-50 border border-purple-200' }]; + if (item.status === 'testing') return [{ key: 'submit', label: '完成', style: 'text-emerald-600 hover:bg-emerald-50 border border-emerald-200' }]; + } + if (item.type === 'testCase') { + if (item.status === 'pending' || item.status === 'running' || item.status === 'failed') { + return [ + { key: 'pass', label: '通过', style: 'text-emerald-600 hover:bg-emerald-50 border border-emerald-200' }, + { key: 'fail', label: '失败', style: 'text-red-600 hover:bg-red-50 border border-red-200' }, + ]; + } + } + if (item.type === 'bug') { + if (item.status === 'open') return [{ key: 'fix', label: '修复中', style: 'text-blue-600 hover:bg-blue-50 border border-blue-200' }]; + if (item.status === 'fixing') return [{ key: 'fixed', label: '已修复', style: 'text-purple-600 hover:bg-purple-50 border border-purple-200' }]; + if (item.status === 'fixed' || item.status === 'verifying') return [{ key: 'close', label: '关闭', style: 'text-emerald-600 hover:bg-emerald-50 border border-emerald-200' }]; + } + return []; +} + function getStatusBadge(item: WorkItem) { if (item.type === 'devTask') { return (