Files
ftb-project-management/docs/superpowers/specs/2026-06-16-overtime-versions-projects-tweaks-design.md
Script Generator c2f2fed82c feat: 加班/版本/项目调整 + 角色权限设计
加班记录:
- 加班人默认回显当前用户且不可改
- 列表加创建日期列
- 移除编辑功能(创建即提交,仅可删除)
- 提交时校验结束>开始

版本列表:
- 移除顶部 9 个状态 tab + 表格状态列
- 仅保留搜索、项目、优先级筛选

项目列表:
- 行内显示进度未达 100% 的版本(与版本页同源算法)
- 新增 lib/version-progress.ts 抽出公共进度计算

角色权限:
- RoleItem 加 permissions 字段
- 新建 lib/permissions.ts: 14 组 37 个权限点 + 默认 5 角色映射 + hasPermission
- 角色表单内嵌权限矩阵(主模块 4 件套 + Tab 二档 + Bug Tab 4 档)+ 全选/反选/仅查看快捷
- 新建 components/auth/Guard.tsx: RouteGuard + PermissionGuard + useHasPermission + AccessDenied
- Sidebar 菜单按 view 权限过滤
- 7 个主路由(products/projects/versions/requirements/overtime/admin/members/roles)包 RouteGuard
- 版本详情 Tab 按 view 权限过滤,自动跳转到第一个有权限的 Tab
- 默认未登录/无角色按只读最严格
- 超管 role-admin: ['*'] 通配符,permissions 不可改

通用:
- 新建 components/FieldError.tsx 统一表单错误文案
- PlanTab 提交时校验结束>开始

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-16 19:15:28 +08:00

6.0 KiB
Raw Permalink Blame History

加班/版本/项目模块小幅调整设计

Context

针对已上线的加班记录、版本列表、项目列表、全局日期校验做一组明确的小幅调整。所有需求点边界已通过澄清确认,方案直接,无需架构层面权衡。

决策摘要

决策
加班"已提交"定义 创建即提交,所有记录不可编辑只可删除
"创建日期"取值 OvertimeRecord.createdAt(表单提交日期)
加班人字段 默认回显 useAuthStore 当前用户 + disabled 不可改
版本列表移除范围 顶部 9 个状态 tab + 表格"状态"列
项目页"未达 100%"取值 整体进度(与版本页同源算法) < 100%
日期校验提示 提交时验证 + 表单项下方红色文案

1. 加班记录模块(apps/web/app/overtime/page.tsx

字段调整

  • OvertimeModaluseAuthStore 引用,初始化 person = useAuthStore(s => s.user?.name) ?? ''
  • 加班人 input 加 disabled + 灰底(bg-zinc-50
  • 编辑时仍以 record 的 person 为准(虽然这条路径会被移除)

列表表头

  • 在"备注"列前插入"创建日期"列
  • 单元格读 r.createdAt,已是 YYYY-MM-DD 格式直接显示

编辑功能移除

  • 删除:editing state、handleEdit 函数、表格"编辑"按钮、OvertimeModalinitial 编辑分支(保留 initial: null 用于校验空表单状态,或直接简化签名移除 initial
  • handleCreate 简化为 setShowModal(true)
  • OvertimeModal props 删除 initial,简化为新建专用

日期校验

  • 提交时检查 endTime > startTime,失败设 formError = '结束时间必须晚于开始时间'
  • 在结束时间 input 下方显示红色文案 <p className="text-[11px] text-red-500 mt-1">{formError}</p>

2. 全局日期校验

通用错误提示组件:新增 apps/web/components/FieldError.tsx

interface Props { message?: string }
export function FieldError({ message }: Props) {
  if (!message) return null;
  return <p className="mt-1 text-[11px] text-red-500">{message}</p>;
}

应用范围(提交时校验,下方红色文案):

  • apps/web/app/overtime/page.tsx — OvertimeModal 结束时间下方
  • apps/web/components/version/PlanTab.tsx — 计划开始/结束日期对(按现有结构定位)
  • apps/web/components/dev-task/DevTaskCreateModal.tsx — 已有 startBeforeEnd 校验,统一改为用 <FieldError> 显示在预计截止下方
  • 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 useVersionPlanStoreuseDevTaskStoreuseTestCaseStoreuseRequirementStoreSTATUS_PROGRESSgetEstimateHours
  • 抽出公共函数 apps/web/lib/version-progress.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<string, number>;

把 versions/page.tsx 现有逻辑替换为调用这个工具,避免两份。

ProjectRow 改动

  • 接收 versionProgressMap: Record<string, number> 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<versionId, percent>
         │
         ├── 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 已完成"