From 6d2f6d8b9f281caa448c65d62fd7e0c608886975 Mon Sep 17 00:00:00 2001 From: Script Generator Date: Tue, 16 Jun 2026 12:40:10 +0800 Subject: [PATCH] =?UTF-8?q?docs+fix:=204=E4=BB=BD=E6=A0=B8=E5=BF=83?= =?UTF-8?q?=E6=96=87=E6=A1=A3=20+=20=E9=A1=B9=E7=9B=AE=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E8=AE=B0=E5=BD=95=E6=95=B0=E6=8D=AE=E5=85=A8?= =?UTF-8?q?=E8=81=94=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 文档: - architecture.md - 整体架构、心智模型、关键设计原则 - decisions.md - 16条关键决策记录(含为什么) - workflow.md - 工作流程和协作偏好 - roadmap.md - V1/V2/V3 路线图和已完成清单 修复项目详情版本记录: 1. 状态胶囊数据联动(开发中分支也补传 stageProgress) 2. 日期数据联动: - 实际开始 = 取所有阶段最早 actualStartAt/startDate/startedAt - 实际截止 = 取所有阶段最晚 completedAt/closedAt - 数据完全和版本详情一致 VersionCard 的 versionData useMemo 增加 actualStart/actualEnd 派生字段, 两种状态分支(developing/released)都使用派生值,不再用静态 version.startDate Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web/app/projects/[id]/page.tsx | 27 ++++- docs/architecture.md | 136 ++++++++++++++++++++++++ docs/decisions.md | 157 ++++++++++++++++++++++++++++ docs/roadmap.md | 100 ++++++++++++++++++ docs/workflow.md | 118 +++++++++++++++++++++ 5 files changed, 534 insertions(+), 4 deletions(-) create mode 100644 docs/architecture.md create mode 100644 docs/decisions.md create mode 100644 docs/roadmap.md create mode 100644 docs/workflow.md diff --git a/apps/web/app/projects/[id]/page.tsx b/apps/web/app/projects/[id]/page.tsx index 58517ea..d03010a 100644 --- a/apps/web/app/projects/[id]/page.tsx +++ b/apps/web/app/projects/[id]/page.tsx @@ -77,6 +77,15 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ vTCs.forEach((c) => { if (c.startedAt) startDates.push(c.startedAt); }); const earliestStart = startDates.length > 0 ? startDates.sort()[0] : version.startDate; + const actualStartDisplay = startDates.length > 0 ? startDates.sort()[0].slice(0, 10) : (version.startDate ?? null); + + // 实际截止:取所有阶段最晚完成 + const endDates: string[] = []; + vPlans.forEach((p) => { if (p.completedAt) endDates.push(p.completedAt); }); + vDevTasks.forEach((t) => { if (t.completedAt) endDates.push(t.completedAt); }); + vTCs.forEach((c) => { if (c.completedAt) endDates.push(c.completedAt); }); + vBugs.forEach((b) => { if (b.closedAt) endDates.push(b.closedAt); }); + const actualEndDisplay = endDates.length > 0 ? endDates.sort().reverse()[0].slice(0, 10) : null; let totalDays = 0; if (earliestStart) { @@ -87,7 +96,7 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ totalDays = Math.max(0, Math.floor((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24))); } - return { vPlans, vDevTasks, vTCs, vBugs, totalDays }; + return { vPlans, vDevTasks, vTCs, vBugs, totalDays, actualStart: actualStartDisplay, actualEnd: actualEndDisplay }; }, [version, plans, devTasks, testCases, bugs, requirements]); // 状态胶囊数据 — 与版本详情一致 @@ -185,7 +194,9 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ {displayStatus} - {version.startDate ?? '-'} → {version.releaseDate ?? '-'} + {versionData.actualStart ?? version.startDate ?? '-'} + + {versionData.actualEnd ?? version.releaseDate ?? '-'} 共 {totalDays} 天 @@ -212,11 +223,19 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ {progress}% -
+
- {version.startDate ?? '-'} → 预计 {version.expectedReleaseDate ?? '-'} + {versionData.actualStart ?? version.startDate ?? '-'} + + 预计 {version.expectedReleaseDate ?? '-'} + {versionData.actualEnd && ( + <> + | + 实际 {versionData.actualEnd} + + )} 已耗时 {totalDays} 天 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..8b3edfa --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,136 @@ +# FTB 智能项目管理系统 — 架构文档 + +## 项目定位 + +FTB 是一个面向中小型研发团队的项目管理平台,集成 AI 能力辅助决策。核心层级: + +``` +产品(Product) → 项目(Project) → 版本(Version) → 需求/任务/用例/Bug +``` + +不是给测试团队的工具,也不是 Jira 替代品。**核心目标是让产品/项目经理在一个页面看到:"开发完了吗 → 验收过了吗 → 还有多少 BUG → 能不能发布"**。 + +## 心智模型(重要) + +系统设计遵循**三条维度线**的分离: + +``` +语义线(Why) 执行线(How) 质量线(Quality) +───────────────── ───────────────── ──────────────── +Requirement Version TestCase +解释为什么做 驱动状态流转 └─ Bug +不参与流程 所有状态看版本 质量闭环 +``` + +**Requirement(需求)= 语义层**,解释功能范围和业务原因,不驱动流程。 +**Version(版本)= 执行主线**,所有任务归属版本,状态由版本派生。 +**TestCase + Bug = 质量闭环**,挂在版本上验收。 + +## 技术栈 + +| 层 | 技术 | 说明 | +|---|------|------| +| 前端 | Next.js 14 (App Router) | TypeScript + 客户端组件为主 | +| UI | Tailwind CSS + Shadcn/ui | 紧凑信息密度、现代风格 | +| 状态 | Zustand | 每个领域一个 store | +| 持久化 | localStorage(V1) | 后端 NestJS + Prisma 已搭好但未启用 | +| 后端 | NestJS + Prisma + PostgreSQL(V2) | 暂未启用 | +| AI | Anthropic SDK(V3 远景) | 健康度/风险预警/排期建议 | + +## 模块结构 + +``` +apps/web/ +├── app/ +│ ├── products/ # 产品列表 + 详情(点击项目可跳转) +│ ├── projects/[id]/ # 项目详情:版本卡片/状态胶囊 +│ ├── versions/ # 版本列表 + 详情 +│ ├── requirements/ # 需求池 +│ ├── workspace/ # 与我相关(聚合工作台) +│ └── admin/ # 系统管理(任务类型字典等) +├── components/ +│ ├── product/ # 产品组件 +│ ├── version/ # 版本组件(PlanTab, CapsuleStages, MemberChips...) +│ ├── dev-task/ # 开发任务组件 +│ ├── test-case/ # 测试用例组件 +│ ├── bug/ # Bug 组件 +│ └── requirement/ # 需求组件 +├── lib/ +│ ├── derive.ts # 派生数据(flattenVersions/flattenProjects) +│ ├── linkage-engine.ts # 跨模块联动引擎(需求↔DevTask 派生状态) +│ ├── workspace-engine.ts # 工作台聚合引擎(统一WorkItem) +│ ├── version-status.ts # 版本执行态推导 +│ ├── version-plan.ts # 计划任务(调研/产品/UI) +│ ├── dev-task.ts # 开发任务 +│ ├── test-case.ts # 测试用例 +│ ├── bug.ts # Bug +│ └── requirement.ts # 需求 +└── stores/ # Zustand stores(每个领域独立) +``` + +## 关键架构原则 + +### 1. 引擎模式(关键) + +跨模块的数据派生通过**引擎层**处理,不是各 store 互相调用: + +- **linkage-engine.ts**:从 DevTask 状态派生需求"实际进度",新建模块只需在此聚合 +- **workspace-engine.ts**:聚合 WorkItem 给"与我相关"页面用 + +引擎是**纯函数**,输入多个 store 数据,输出统一视图。引擎使应用各模块松耦合,新增模块时不需要改其他模块的代码。 + +### 2. 派生胜过存储 + +时间字段、状态、进度都尽量从底层数据派生,而不是手填: + +- 实际工时 = `startDate → completedAt` 时间差(精确到 0.5h) +- 阶段耗时 = 所有阶段任务的最早开始 → 最晚完成 +- 需求开发状态 = 从 DevTask 状态聚合 +- 版本执行态 = 从所有 DevTask + TestCase + Bug 聚合 +- 阶段进度 = 已完成子任务/总子任务 + +### 3. 时间戳精确到分钟 + +所有"实际开始/完成"时间都是 ISO 时间戳(含时分秒),不是日期。展示时统一 `slice(0, 16).replace('T', ' ')`。 + +### 4. 数据联动 + +修改 A 影响 B 时,**B 通过 filter A 派生**,不要双向写。例: +- 需求关联到版本:需求设 `versionId`,版本详情 `requirements.filter(r => r.versionId === id)` +- 删除版本:清理孤儿数据(PlanTask/DevTask/TestCase/Bug + 释放 Requirement.versionId) + +## 状态机概览 + +| 实体 | 状态流转 | +|------|---------| +| Requirement | pending_review → adopted → planned → developing → testing → released → closed(rejected 可回 pending_review)| +| VersionPlan | pending → in_progress → completed | +| DevTask | todo → in_progress → testing → submitted(终态,提测=已完成)| +| TestCase | pending → running → passed/failed/blocked | +| Bug | open → fixing → fixed → verifying → closed/rejected | + +DevTask 没有"已完成"状态,"已提测"就是终态——开发交付完成,后续 Bug 单独流转。 + +## 数据持久化 + +**V1(当前):** 全部 localStorage,每个 store 独立 key +- `ftb_overview_v1` - 产品/项目/版本树 +- `ftb_requirements_v3` +- `ftb_version_plans_v1` +- `ftb_dev_tasks_v1` +- `ftb_test_cases_v1` +- `ftb_bugs_v1` +- `ftb_overtime_v1` +- `ftb_task_categories_v1` + +**V2(计划):** NestJS + Prisma + PostgreSQL,Schema 已设计但尚未运行 migration。 + +## 权限模型(轻量) + +V1 仅做前端校验,无后端鉴权: +- 版本 `members` 字段限定参与者 +- 版本列表/详情按 `members.contains(currentUser)` 过滤 +- 创建版本时自动加入创建者 +- 版本 `members` 为空时所有人可见(兼容旧数据) + +V2 接入后端后改为基于 `ProjectMember` 表的 RBAC(Owner/Admin/Member/Viewer)。 diff --git a/docs/decisions.md b/docs/decisions.md new file mode 100644 index 0000000..9262fe3 --- /dev/null +++ b/docs/decisions.md @@ -0,0 +1,157 @@ +# 关键设计决策记录 + +每条决策都包含**为什么这么做**,避免后续模型重新讨论或推翻。 + +## 1. 进度计算 — 由状态推导,不要手填百分比 + +**问题**:Jira/TAPD 等系统让开发手填进度(20%/35%/50%),数据完全主观,不可靠。 + +**决策**:DevTask 进度由 `status` 推导: +- `todo` → 0% +- `in_progress` → 50% +- `testing` → 80% +- `submitted` → 100% + +**理由**:客观、不允许造假。需求级/版本级进度 = `Σ(estimateHours × 状态推导%) / Σ(estimateHours)`。 + +## 2. 实际工时 — 由开始/完成时间戳计算 + +**问题**:让人手填工时太粗糙(一天 8h 真的全部花在这个任务吗?)。 + +**决策**:精确到 0.5h 的时间差计算 +``` +实际工时 = (completedAt - startDate) / 3600000,精确到 0.5h +``` + +**理由**:状态流转时自动记录精确时间戳,工时直接派生。 + +## 3. DevTask "已提测" = 终态 + +**问题**:原本有 `submitted → done`,但开发提测之后就交付完成了,后续测试结果不应该回过来改 DevTask 状态。 + +**决策**:去掉 `done`,`submitted` 是终态。测试通过/失败产生 Bug,不影响 DevTask。 + +**理由**:DevTask 的责任是"开发到提测",验收是 TestCase 的职责。 + +## 4. 调研/产品/UI — 自动开始 + 手动提前开始 + +**问题**:到了计划开始日期,状态还是 pending 不合理。 + +**决策**: +- 当前时间 ≥ `startTime` 时自动视为 in_progress +- 用户可在计划日期前手动点"开始" +- 自动开始时记录 `actualStartAt`(精确到分钟) + +**理由**:减少冗余操作但保留灵活性。 + +## 5. TestCase 主归属版本,需求是可选标签 + +**问题**:早期把测试用例挂在需求上,但同一需求跨版本迭代时用例难以管理。 + +**决策**: +- TestCase.versionId 必填(执行归属) +- TestCase.requirementId 可选(语义标签) +- 测试人员从"我的测试用例"看到的就是当前版本的用例 + +**理由**:测试是按版本执行的,不是按需求;但需求作为思考维度仍然有用。 + +## 6. Bug 直接挂版本 + +**问题**:早期通过 `Bug → TestCase → Requirement → Version` 四级反查,太绕。 + +**决策**:Bug 增加 `versionId` 字段,直接挂版本。`testCaseId` 保留作为来源追溯。 + +**理由**:判断"能不能发布"的唯一维度是版本,必须 O(1) 查询。 + +## 7. 跨模块通信 — 引擎层,不是事件总线 + +**问题**:模块多了,A store 改动影响 B 的派生数据,散落各处难维护。 + +**决策**:建立**纯函数引擎**: +- `linkage-engine.ts`:从 DevTask 状态派生需求"实际进度" +- `workspace-engine.ts`:聚合所有 store 数据为统一 WorkItem + +**理由**:事件总线过度设计,纯函数派生更可预测。新增模块只需在引擎中添加聚合逻辑。 + +## 8. 时间字段统一 ISO 时间戳到分钟 + +**问题**:日期(`YYYY-MM-DD`) vs 时间戳混用,UI 展示不一致。 + +**决策**:所有"实际开始/完成"用 `new Date().toISOString()`,展示统一 `slice(0, 16).replace('T', ' ')`。 + +**理由**:时间戳到分钟够精确,不像秒/毫秒那么噪。 + +## 9. 任务类型字典化 + 分组 + +**问题**:早期 enum 写死类型(前端/后端/大数据/其他),新增类型需改代码。 + +**决策**:建 TaskCategory 字典表 + group(development/implementation/other),管理员可增删。 + +**理由**:业务变化快,配置 > 写死。group 方便统计(开发工时 vs 实施工时)。 + +## 10. 阻塞正交标记,不是状态值 + +**问题**:`status: blocked` 会丢信息——`开发中+阻塞` ≠ `自测+阻塞`。 + +**决策**: +- `status: todo|in_progress|testing|submitted` +- `isBlocked: boolean` + `blockReason: string` + `blockedById: string` + +**理由**:阻塞和状态正交。工作台筛选 `isBlocked=true` 一键拉出所有阻塞项,跨状态。 + +## 11. 加班原因可选,且去掉"其他" + +**问题**:可选"其他"会让人逃避思考具体原因。 + +**决策**:变更原因/加班原因严格定义有限选项,**没有"其他"**。 + +**理由**:强制具体化,统计才有意义。 + +## 12. 项目维度 vs 个人维度耗时分开计算 + +**问题**:多个开发并行做任务,简单加总会重复计算时间。 + +**决策**: +- **个人耗时**:每个任务独立累加(`Σ(end - start)`) +- **项目维度阶段耗时**:`min(start)` → `max(end)` 日历跨度(不重复) + +**理由**:两个维度回答不同问题——"谁花了多少时间" vs "这个阶段拖了多久"。 + +## 13. 删除版本时清理孤儿数据 + +**问题**:删版本只删 version 实体,留下 PlanTask/DevTask/TestCase/Bug 变成孤儿数据。 + +**决策**:删除版本时级联清理: +1. 释放需求 versionId(回需求池) +2. 删除 PlanTask +3. 删除 DevTask(通过需求 ID) +4. 删除 TestCase +5. 删除 Bug + +**理由**:localStorage 没外键约束,必须手动级联。 + +## 14. 工作台数据点击 → 侧边详情 + 可操作 + +**问题**:早期工作台只显示信息,操作要跳转到版本详情。 + +**决策**:点击卡片打开 Drawer(复用版本详情用的同一组件),可在 Drawer 内完成状态流转、转交、提 Bug 等。 + +**理由**:减少跳转,工作台一站式处理。Drawer 顶部显示"产品/项目/版本"上下文,不会迷失。 + +## 15. UI 阴影统一 shadow-2xl + +**问题**:各 Drawer 阴影不一致(有些 `shadow-lg` 有些 `shadow-2xl`)。 + +**决策**:全局 Drawer 用 `shadow-2xl`。 + +**理由**:视觉权重明显,且一致。 + +## 16. 不进入 Brainstorm 模式的判定 + +**约定**:以下情况直接修复,**不强制走 brainstorming 流程**: +1. Bug fix(明确 bug,方案直接) +2. 已批准方案的 in-progress 延续 +3. 用户已通过 AskUserQuestion 选择了方案 +4. 简单文案/样式调整 + +**理由**:brainstorming 适合新功能设计,bug fix 强行套流程浪费时间。 diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..77f8ad8 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,100 @@ +# 开发路线图 + +## 当前阶段:V1 — 前端 Mock + 业务流程打磨 + +所有数据用 localStorage 持久化,重点验证业务模型和交互。 + +### 已完成(按时间倒序) + +**2026-06-16** +- 项目模块顶部卡片(总版本数/已开发/需求数/Bug 总数) +- 项目模块版本记录与版本详情数据联动(耗时 + 状态胶囊) +- 4 份核心文档:architecture / decisions / workflow / roadmap + +**2026-06-15** +- 与我相关:产品/项目/版本树筛选 + 红色待办徽标 +- 与我相关:点击卡片打开 Drawer(PlanDetailDrawer 新建,DevTask/TestCase/Bug 复用) +- 全局 Drawer 阴影统一 shadow-2xl + 顶部上下文条 +- 测试用例提 Bug 流程:drawer 内点击 → BugCreateModal +- DevTask + TestCase 转交功能(人员离职场景) +- 需求池:录入人员自动取当前用户 + 状态列改名(业务状态 / 实际进度) +- 产品页面:去掉规划中、项目名/版本胶囊可点击跳转 + +**2026-06-14** +- 需求变更模块:变更人员/原因/概述/详细 + 概览统计(变更人员排名 + 原因占比饼图) +- 计划任务转交(未开始/进行中可转交,从参与人员选) +- 关联需求增强:描述列 hover 完整内容、需求类型/变更原因/添加日期列 +- 计划时间精确到分钟(datetime-local)+ 到期自动开始 +- 阶段耗时 + 个人耗时排名(涵盖调研/产品/UI/开发/测试 5 类工作) + +**2026-06-13** +- DevTask 状态简化:去掉 done,submitted 是终态 +- 实际工时改为精确时间戳计算(精确到 0.5h) +- TestCase 主归属版本,requirement 改为可选标签 +- Bug 直接挂版本(versionId 字段) +- linkage-engine(需求 ↔ DevTask 派生) +- workspace-engine(统一 WorkItem 聚合) + +**2026-06-12 及更早** +- 完整模块:需求池/版本管理/计划任务(调研/产品/UI)/开发任务/测试用例/Bug +- 加班记录 + 排名 + 原因占比饼图 +- 健康度计算 + 风险标签 +- 版本执行态自动推导 + +### 进行中 + +- 项目详情页 VersionCard 状态胶囊数据联动(部分已完成) + +## V2 — 后端接入 + +NestJS + Prisma + PostgreSQL Schema 已设计,等业务流程稳定后开始迁移。 + +### 关键任务 + +1. **运行 Prisma migration**:把现有的 lib/*.ts 类型转为 Prisma schema +2. **API 层**:每个 store 对应一组 CRUD endpoint +3. **localStorage → API 切换**:保留 localStorage 作为离线缓存 +4. **认证**:NextAuth.js + JWT +5. **权限**:RBAC(Owner/Admin/Member/Viewer),按项目/版本级别 + +### 数据迁移策略 + +提供管理员脚本把当前用户的 localStorage 数据导出为 SQL,导入到 PostgreSQL。 + +## V3 — AI 集成 + +### 已规划场景 + +1. **需求智能分解**:输入需求描述,AI 拆解为子任务(技术分析+UI 调整+联调+测试) +2. **风险预警**:自动识别延期/阻塞集中/工时偏差大的任务,提前预警 +3. **排期建议**:基于成员负载和历史耗时,建议下一阶段任务分配 +4. **需求转任务**:需求采纳后一键生成 DevTask 草稿 +5. **健康度智能解读**:把数据指标转化为自然语言报告 + +### 落地方式 + +`apps/server/src/modules/ai/`: +- `AiGateway` — 统一 prompt 管理、token 计量、降级 +- `AiTaskService.decompose(description)` +- `AiRiskService.analyze(projectId)` +- `AiScheduleService.suggest(projectId)` +- `AiLog` 表存调用记录,便于审计 + +## 不在路线图(明确不做) + +- **Jira/TAPD 替代品**:定位是产品/项目经理视角,不是开发任务管理 +- **测试套件/测试计划**:测试用例是版本验收手段,不做完整测试管理 +- **Gantt 甘特图**:现有的胶囊状态条 + 阶段耗时已经够用 +- **看板视图**:DevTask 列表 + 筛选 + 状态流转已够用 +- **回归测试**:测试用例不做版本间复用 +- **客户/合同管理**:超出研发管理边界 + +## 关键里程碑 + +| 节点 | 状态 | +|------|------| +| V1 业务流程打磨 | 进行中 | +| V1 朋友试用反馈 | 持续中 | +| V2 后端接入 | 等 V1 稳定 | +| V3 AI 集成 | 等 V2 数据沉淀 | +| 公开发布 | TBD | diff --git a/docs/workflow.md b/docs/workflow.md new file mode 100644 index 0000000..6e992f8 --- /dev/null +++ b/docs/workflow.md @@ -0,0 +1,118 @@ +# 工作流程 + +记录用户的协作偏好和系统化流程,方便后续模型理解项目运作方式。 + +## 用户协作风格 + +- **直接修复明确 bug**,不强制走 brainstorming 流程 +- **方案确认后立即执行**,不重复讨论 +- **不喜欢自动 push**:commit 由模型完成,**push 需要用户明说"推/push"** +- **要求高级开发思维**:考虑数据联动、引擎层抽象,而不是分散写 ad-hoc 逻辑 +- **重视一致性**:所有 Drawer 阴影、所有时间格式、所有状态计算都要统一 +- **省略多余对话**:能直接做的不要问,只在真有歧义时用 AskUserQuestion 给选项 +- **Brainstorming 适用于新功能**,bug fix 和已批准方案的延续不走 brainstorming + +## 实际工时计算流程 + +所有"实际开始时间"和"实际完成时间"都是 ISO 时间戳: + +``` +状态变更时机: +- DevTask: todo → in_progress 时记 startDate + testing → submitted 时记 completedAt +- TestCase: pending → running 时记 startedAt + running → passed/failed/blocked 时记 completedAt +- VersionPlan: pending → in_progress 时记 actualStartAt + in_progress → completed 时记 completedAt + +计算: +- 实际工时 = (completedAt - startDate) / 3600000,精确到 0.5h +- 阶段日历耗时 = min(start) → max(end) 跨度(项目维度,不重复) +- 个人耗时 = 每个任务独立累加(个人维度) +``` + +## 数据联动检查清单 + +新加模块或字段时,检查以下点: + +- [ ] 是否需要在 `linkage-engine.ts` 加派生函数? +- [ ] 是否需要在 `workspace-engine.ts` 加聚合? +- [ ] 删除版本时是否需要清理这类数据? +- [ ] 工作台 / 版本详情 / 项目详情三处的统计是否同步? +- [ ] localStorage 旧数据是否需要兼容处理? + +## Drawer(侧边详情)规范 + +所有侧边详情遵循: + +- `fixed inset-0 z-50 flex justify-end` +- 背景 `bg-black/40` +- Drawer 容器 `w-full max-w-md h-full bg-[var(--bg)] border-l shadow-2xl flex flex-col` +- 顶部上下文条(可选):`px-5 py-2 bg-[var(--bg-subtle)] text-[11px]` +- 顶栏:`h-14 border-b bg-[var(--bg-card)]` +- 操作按钮按颜色编码:blue=进行/转交、emerald=完成、red=删除/失败、orange=关闭/提BUG + +## Modal(弹窗)规范 + +- 居中 `flex items-center justify-center bg-black/40` +- `rounded-2xl bg-[var(--bg-card)] border shadow-md` +- 提交 BUG 等图片密集型用 `max-w-2xl`,普通表单 `max-w-md` 或 `max-w-lg` + +## 字段命名规范 + +- 实际开始:`startDate` (DevTask) / `startedAt` (TestCase) / `actualStartAt` (VersionPlan) +- 实际完成:`completedAt`(统一) +- 派生进度:在 lib 层提供函数,不存储 + +历史原因导致命名不完全一致(DevTask 用 startDate 是因为最早是日期字段),但行为一致。 + +## 提交信息规范 + +- 中文 commit message +- 格式:`类型(模块): 描述` + - feat / fix / refactor / docs / test +- 描述列出关键改动点,特别是跨模块影响 +- Co-Authored-By 行带版本号 + +## 文档维护流程 + +- **新增/改动核心架构** → 更新 `architecture.md` +- **关键设计决策** → 追加到 `decisions.md`,包含"为什么" +- **新功能/路线图变更** → 更新 `roadmap.md` +- **不影响架构的功能性改动** → 不需要更新文档 + +## Bug 排查流程 + +朋友拉新代码出现"显示问题"时,按顺序排查: + +1. 旧 localStorage 数据格式不兼容 → 让朋友清缓存 +2. 类型定义和实际数据不一致(缺字段) +3. 列宽溢出导致裁切 +4. 派生计算错误(filter 条件错) +5. 跨模块联动断了(store 的 store.getState() 调用时机) + +## 测试 / 验证流程 + +- 改动后必须 `npx tsc --noEmit` 通过 +- 涉及 UI 改动:`curl http://localhost:3000/` 检查 200 +- 不会自动跑 dev server,假定它已经运行 + +## 与我相关(Workspace)数据流 + +``` +useProductStore → versions +useRequirementStore → requirements (with versionId) +useDevTaskStore → tasks (with requirementId) +useTestCaseStore → testCases (with versionId) +useBugStore → bugs (with versionId) +useVersionPlanStore → plans (with versionId, owner) +useAuthStore → user (filter by current user) + ↓ +workspace-engine.aggregateWorkItems(...) + ↓ +WorkItem[] (统一格式) + ↓ +Workspace 页面(树筛选 + tab 筛选 + 已完成开关) +``` + +新增模块时,只需在 `aggregateWorkItems` 中添加聚合逻辑,工作台自动展示。