# 加班/版本/项目模块小幅调整设计 ## Context 针对已上线的加班记录、版本列表、项目列表、全局日期校验做一组明确的小幅调整。所有需求点边界已通过澄清确认,方案直接,无需架构层面权衡。 ## 决策摘要 | 项 | 决策 | |---|---| | 加班"已提交"定义 | 创建即提交,所有记录不可编辑只可删除 | | "创建日期"取值 | `OvertimeRecord.createdAt`(表单提交日期) | | 加班人字段 | 默认回显 `useAuthStore` 当前用户 + `disabled` 不可改 | | 版本列表移除范围 | 顶部 9 个状态 tab + 表格"状态"列 | | 项目页"未达 100%"取值 | 整体进度(与版本页同源算法) < 100% | | 日期校验提示 | 提交时验证 + 表单项下方红色文案 | ## 1. 加班记录模块(`apps/web/app/overtime/page.tsx`) **字段调整**: - `OvertimeModal` 加 `useAuthStore` 引用,初始化 `person = useAuthStore(s => s.user?.name) ?? ''` - 加班人 input 加 `disabled` + 灰底(`bg-zinc-50`) - 编辑时仍以 record 的 `person` 为准(虽然这条路径会被移除) **列表表头**: - 在"备注"列前插入"创建日期"列 - 单元格读 `r.createdAt`,已是 `YYYY-MM-DD` 格式直接显示 **编辑功能移除**: - 删除:`editing` state、`handleEdit` 函数、表格"编辑"按钮、`OvertimeModal` 的 `initial` 编辑分支(保留 `initial: null` 用于校验空表单状态,或直接简化签名移除 initial) - `handleCreate` 简化为 `setShowModal(true)` - `OvertimeModal` props 删除 `initial`,简化为新建专用 **日期校验**: - 提交时检查 `endTime > startTime`,失败设 `formError = '结束时间必须晚于开始时间'` - 在结束时间 input 下方显示红色文案 `

{formError}

` ## 2. 全局日期校验 **通用错误提示组件**:新增 `apps/web/components/FieldError.tsx` ```tsx interface Props { message?: string } export function FieldError({ message }: Props) { if (!message) return null; return

{message}

; } ``` **应用范围**(提交时校验,下方红色文案): - `apps/web/app/overtime/page.tsx` — OvertimeModal 结束时间下方 - `apps/web/components/version/PlanTab.tsx` — 计划开始/结束日期对(按现有结构定位) - `apps/web/components/dev-task/DevTaskCreateModal.tsx` — 已有 `startBeforeEnd` 校验,统一改为用 `` 显示在预计截止下方 - `apps/web/components/dev-task/DevTaskDetailDrawer.tsx` — 详情抽屉编辑(如有日期对编辑) **跳过**: - `apps/web/app/versions/page.tsx` 的 NewVersionModal 仅有截止日期,无开始 - `apps/web/components/dev-task/WorklogPanel.tsx` 仅单 date 字段 ## 3. 版本列表(`apps/web/app/versions/page.tsx`) **移除**: - `STATUS_TABS` 常量(line 39-50) - 顶部状态 tab JSX 块(line 275-281) - 表头"状态"列(line 346) - 表格"状态"单元格(line 419-424) - `statusFilter` state 和过滤分支(保留 search/projectFilter/priorityFilter 三个) **保留**:项目筛选下拉、优先级筛选下拉、搜索框 **整体进度** 列保留——它本身就反映状态信息。 ## 4. 项目页(`apps/web/app/projects/page.tsx`) **计算 versionProgressMap**: - `ProjectsPage` 加同款 `versionProgressMap` useMemo(与 versions/page.tsx line 141-212 同源算法) - 需要 import `useVersionPlanStore`、`useDevTaskStore`、`useTestCaseStore`、`useRequirementStore`、`STATUS_PROGRESS`、`getEstimateHours` - 抽出公共函数 `apps/web/lib/version-progress.ts`: ```ts export function calcVersionProgress( versionId: string, plans: VersionPlan[], requirements: Requirement[], devTasks: DevTask[], testCases: TestCase[], ): number; export function buildVersionProgressMap( versions: VersionWithContext[], plans, requirements, devTasks, testCases, ): Record; ``` 把 versions/page.tsx 现有逻辑替换为调用这个工具,避免两份。 **ProjectRow 改动**: - 接收 `versionProgressMap: Record` prop - `activeVersions = filter(v => (versionProgressMap[v.id] ?? 0) < 100)` - `releasedCount` 改为 `completedCount = filter(v => (versionProgressMap[v.id] ?? 0) >= 100)` - "+N 已发布"改为"+N 已完成" **Legend 调整**: - 现有图例 `开发中 / 规划中 / 已发布` 颜色与版本状态绑定,VersionChip 也是。继续保留 chip 内部颜色逻辑,仅过滤维度变了。Legend 文案保持不变(这是 chip 颜色含义说明)。 ## 数据流 ``` overview / requirements / plans / devTasks / testCases │ └── lib/version-progress.ts │ ├── buildVersionProgressMap(versions, ...) │ └── Record │ ├── versions/page.tsx 整体进度列 └── projects/page.tsx ProjectRow 过滤未完成版本 ``` ## 实施清单 新增: - `apps/web/components/FieldError.tsx` - `apps/web/lib/version-progress.ts` 修改: - `apps/web/app/overtime/page.tsx`(加班人禁用 + 创建日期列 + 移除编辑 + 日期校验) - `apps/web/components/version/PlanTab.tsx`(日期校验) - `apps/web/components/dev-task/DevTaskCreateModal.tsx`(统一校验文案样式) - `apps/web/components/dev-task/DevTaskDetailDrawer.tsx`(如有日期对编辑则加校验) - `apps/web/app/versions/page.tsx`(移除状态 tab/列 + 改用 version-progress.ts) - `apps/web/app/projects/page.tsx`(加 progressMap + 改 ProjectRow 过滤口径) ## 验证 1. `pnpm type-check` 0 错误 2. `pnpm build` 14 个页面成功 3. 加班记录:新建表单加班人为当前登录用户名且不可改;列表有"创建日期"列;任何记录无"编辑"按钮,仅"删除" 4. 加班/计划/开发任务表单:截止 < 开始时提交,下方显示红色文案,不能提交 5. 版本列表:顶部无状态 tab;表头无状态列;只有项目+优先级两个下拉 6. 项目列表:每行显示进度未达 100% 的版本 chip,已完成数量在末尾"+N 已完成"