Files
cn-rdms/CLAUDE.md
hongawen 8f6b762bf3 feat(system): 扩展用户部门权限功能
- 在 AdminUserService 中新增 listEnabledUserIdsByDeptIds 方法获取指定部门集合下启用且未离职的用户 ID 集合
- 在 DeptService 中新增 listDescendantDeptIds 方法获得指定部门集合及其所有子孙部门的 ID 集合
- 在 DeptService 中新增 listCodesByIds 方法按 id 集合批量查询部门 code 集合
- 在 OrgLeaderRelationService 中新增 listEffectiveDeptIdsByUserId 方法查询指定用户当前生效的负责人关系所对应的 dept_id 集合
- 在 PermissionApi 中新增 isSuperAdmin 接口判断用户是否超管
- 在 ObjectPermissionApi 中新增 getObjectRolePermissionDetailMerged 接口按 roleId 列表聚合菜单 + 权限码
- 扩展 ProductContextRoleRespVO 添加多角色场景的附加角色名称列表
- 扩展 ProductCreateWithTeamReqVO 支持创建时添加关心人用户 ID 列表
- 优化 ProductMemberServiceImpl 支持同一用户多角色显示,区分主角色和附加角色
- 新增 MEMBER_ACTION_REACTIVATE 复活动作类型用于处理 INACTIVE 成员行重新激活场景
- 在 ObjectStatusModelDO 中新增 progressExcludedFlag 字段控制是否参与上层进度统计
- 更新 AGENTS.md 和 CLAUDE.md 添加 Git 操作纪律规范
- 在 rdms-project-api 中新增多个错误码常量支持角色转移和内置角色配置验证
2026-05-14 13:58:40 +08:00

13 KiB
Raw Blame History

CLAUDE.md

本文件为 Claude Code 在 C:\code\gitea\rdms\cn-rdms 仓库工作时的常驻指引,等价并补充 AGENTS.md。两份文件冲突时以本文件为准;本文件未覆盖的细节回退到 AGENTS.md

工作方式

  • 默认先给执行方案:目标、涉及模块、改动点、验证方式。用户明确同意前不要直接动手修改、编译、测试、打包。
  • 用户只要分析或评审时,停在分析层;不要顺手开工。
  • 描述仓库现状以当前代码、配置、文档可验证的事实为准;不要拿历史实现、过渡方案或已废弃模型解释当前状态。
  • 回答保持精简,先给结论、改动点、必要风险;细节等用户追问。
  • 不要废话:默认极简输出,不展开背景、不复述需求、不堆叠章节标题;能用一两句讲清就别写成清单;用户主动追问再展开。
  • 回答问题时不要过多代码层面的描述:默认用自然语言给结论、判断、影响面;除非用户明确要看实现细节,不要大段贴代码片段、不要逐行解读、不要把分析写成"先看 xxx.java 第 N 行"的形式。涉及代码定位时用 file_path:line_number 引用即可。

本机环境

  • JDK必须使用 JDK 17,路径 C:\Program Files\Java\jdk-17。不要使用 JDK 8 / 11 / 其他版本。
  • MavenC:\software\apache-maven-3.8.9,命令优先用完整路径 C:\software\apache-maven-3.8.9\bin\mvn.cmd。不要假设 mvn 在 PATH。
  • 执行任何 Maven / java 命令前,先确认当前 shell 的 JAVA_HOME 指向 JDK 17java -version 输出 17否则在该命令上下文中显式切换。
  • 只有在用户已明确同意执行编译/测试/打包等命令时,才使用上述路径执行。日常默认不跑任何会实际运行项目的命令。

仓库结构

多模块 Maven 单仓库Java 17Spring Boot 3.5.9,根模块打包 pom

顶层模块:

  1. rdms-system — 系统域(用户/组织/岗位/菜单/角色/权限)
  2. rdms-project — RDMS 核心交付域(项目集/项目/产品/需求/任务/工单/执行)
  3. rdms-framework — 共享框架与内部 starter
  4. rdms-gateway — Spring Cloud Gateway 网关

每个业务模块按 xxx-api + xxx-boot 拆分:

  • *-api:对外 RPC/Feign 接口、DTO、错误码、枚举、常量
  • *-boot启动类、controller、service、dal、convert、api 实现、模块级 framework 配置

主包/启动类:

  • rdms-system-bootcom.njcn.rdms.module.system.SystemServerApplication
  • rdms-project-bootcom.njcn.rdms.module.project.ProjectServerApplication
  • rdms-gatewaycom.njcn.rdms.gateway.GatewayServerApplication

rdms-framework 子模块:rdms-common 及一组 rdms-spring-boot-starter-*envwebrpcsecuritymybatisredismqwebsocketexcelprotectiontestbiz-ip)。

模块演进判断

新增能力时先判断落点

  • 落在现有 rdms-system 子域 → 沿用 controller/admin|appservicedal/dataobjectdal/mysqlconvert 的现有结构,跨模块暴露时在 rdms-system-api 补 API/DTO/错误码/枚举。
  • 落在现有 rdms-project 子域 → 同理,跨模块走 rdms-project-api
  • 已具备独立服务边界(如未来的 rdms-workflow)→ 新建 rdms-xxx + rdms-xxx-api + rdms-xxx-boot,根 pom.xml 加聚合,包路径 / spring.application.name / ApiConstants / RpcConstants / rdms.info.base-package 保持一致。

不要:

  • 把后续业务长期堆进 rdms-system
  • 为新增子域引入一套平行的 application/domain/infrastructure/adapter 分层。
  • 让外部模块直接依赖 *-boot 的 service 或 mapper必须走 *-api)。

分层职责

职责 红线
rdms-framework 基础能力 不承载业务语义;除非框架级缺陷或全局基础设施,不要把业务判断塞进来
rdms-gateway 入口、令牌校验、登录用户透传、路由、横切 不要在这里承载组织/成员/负责人/项目/产品/工作流状态/数据可见性
Controller HTTP 暴露、参数校验、权限注解、结果封装 不要编排复杂业务流程,不要直接操作多个 mapperReqVO/RespVO,不要直接暴露 DO
Service 业务规则、事务、缓存、领域编排 已有领域优先扩展,不要为"整齐"平移;不要把规则散到 controller / mapper / util
DAL DO + Mapper Mapper 继承 BaseMapperX<T>;查询优先 LambdaQueryWrapperX 与默认方法封装;非必要不回退 XML不承担领域校验
Convert 已有 convert 风格继续沿用,简单场景直接 BeanUtils 不要强推全员 MapStruct也不要反过来把已有 convert 全删

认证与跨模块调用

  • 默认沿用 OAuth2 / Token / LoginUser / login-user 透传主链。不要另造 ThreadLocal / Session / 自定义 header。
  • 跨模块/跨服务必须通过 *-api 模块定义契约;不要直接依赖别人的 *-boot

鉴权:必须按"全域 / 对象域"分通道挂

系统有两条互不交叉的权限通道,挂错通道 = 永远 403。新增/修改接口前必须先判断它属于哪一域:

通道 适用场景 注解 / 实现 角色与菜单
全域 global 传统 RBAC 顶层菜单与"项目管理界面"——选择对象之前的所有动作(建项目、列项目、菜单/角色/用户管理等) Controller 上 @PreAuthorize("@ss.hasPermission('xxx')"),由 PermissionServiceImpl.hasAnyPermissions 处理 system_role.scope_type='global' + system_menu.scope_type='global'
对象域 object 用户已选择某个对象(如某个项目/产品)后,对象内部的一切操作(任务、执行、工时、协办人、需求、成员维护等) Service 上 @CheckObjectPermission(objectType=..., objectId="#xxxId", permission="..."),由 ObjectPermissionAspectObjectPermissionService.checkPermission 处理 system_role.scope_type='object' + system_menu.scope_type='object' + object_type

红线:

  • 对象内接口绝不能挂 @PreAuthorize("@ss.hasPermission(...)")。该注解走的链路在 PermissionServiceImpl 里强制按 GLOBAL 取角色line 343-347+ 强制按 GLOBAL 查菜单line 92-94对象域角色与对象域菜单都进不来即使授权配置完全正确也必然 403。
  • 对象域权限校验必须落在 Service 层 @CheckObjectPermission,原因:路径里 objectId 通常以 #projectId/#productId 等 SpEL 解析Controller 的参数校验前置阶段不便复用;与同模块(ProjectMemberServiceImpl / ProjectExecutionServiceImpl / ProjectExecutionAssigneeServiceImpl / ProjectTaskServiceImpl)保持一致。
  • 同一接口不要两条通道叠加。要么全域,要么对象域;叠加只会让对象域用户被全域那条卡死。
  • 列表/详情这类对象内读路径目前未挂 @CheckObjectPermission(属已识别负债,台账 TD-001新增读接口暂沿用现状即可不要顺手改造等独立立项。

判定口诀:URL 里有 {projectId} / {productId} 等对象 ID → 对象域;没有 → 全域

接口语义(HTTP 动词)

本仓库 update 类接口默认按 RESTful 标准用 HTTP 动词区分语义,前后端必须按下表对齐,避免"前端没传字段"和"前端想清空"在后端无法区分的歧义。

动词 语义 字段处理规则
PUT 全资源替换 前端必须把表单完整状态回传(读到的非必填字段也要原样回传)。后端按字段值落库:有值=更新,null=清空。DO 字段加 @TableField(updateStrategy = FieldStrategy.ALWAYS) 跳过全局 NOT_NULLnull 真的写库
PATCH 部分字段更新 本仓库暂不引入 PATCH 接口。如果有"只改一两个字段"的需求,用专门的子动作接口(参考 assignees/{id}/inactivestatus 这种语义化路径),不要在 update 接口里靠旁路标记(如 clearXxx: true)模拟 PATCH
DELETE 资源删除 软删走全局 deleted 列,不需要参数 body

红线:

  • 不要在 update 类接口的 ReqVO 里加 clearXxx: Boolean 这种旁路标记来模拟 PATCH —— 等于承认接口是"伪 PATCH",会让所有非必填字段都需要类似标记,长期污染 API 设计。需要部分更新就拆子动作接口。
  • 新增 update 接口时,必须在 API 文档对应章节明示"PUT 全字段回传"约定;DO 上对允许 null 的字段补 FieldStrategy.ALWAYS 注解,并加注释说明语义来源(指向本节)。
  • 历史接口若是稀疏 PATCH 风格(传 null = 不动),保留现状但不要拓展;遇到清空诉求时按 PUT 方向重构。

数据与 SQL

  • 新表 DO 复用现有 BaseDO / 审计字段风格,不要再引一套审计基类(除非该表本身明确不需要逻辑删除)。
  • 不要假设运行时自动数据库迁移:依赖新表/新字段/新索引时,必须同步补 SQL 脚本与文档。
  • SQL 放在目标模块 src/main/resources/sql/...,可审阅、可单独执行。
  • 缓存/日志/审计变更优先沿用既有机制,不要绕开登录上下文与审计字段填充。

注释与编码

  • 关键字段、关键分支、关键约束、非直观实现补简洁中文注释。
  • 不要为省事删除原有有效注释;也不要写无信息量的注释。
  • 中文写入必须 UTF-8并自查显示是否正常不要用"改成英文"规避乱码。
  • superpowers 产出的功能文档(设计/实施/联调默认中文落地代码标识、文件路径、接口路径、SQL、命令保持原样不意译。

工作规则(执行前对照)

  1. 优先做有边界的模块内改动,避免跨模块扩散。
  2. 业务逻辑落 *-boot;可复用契约落 *-api;可复用框架能力落 rdms-framework
  3. 不要修改 application-local.yaml / application-dev.yaml,除非任务本身就是环境配置调整。
  4. 把本地 YAML 当作可能带机器差异的文件,改前先查 git 状态。
  5. 包结构:controller / service / dal / convert,保持不变。
  6. 新增共享能力优先扩展现有 rdms-spring-boot-starter-*,不要在业务服务里重复堆配置。
  7. 改跨模块 API 时,提供方实现与对应 *-api 契约同步更新。
  8. 未经用户明确同意,不执行任何 mvn、启动命令、脚本等会实际运行项目的命令。

Git 操作纪律

默认不引导分支管理(首要

用户在本仓库长期固定在 main 上工作。开发流程中:

  • 不要主动建议建 feature 分支git checkout -b feat/xxxgit switch -c ...)。
  • 不要把"先切到 xxx 分支再操作"作为方案前置步骤
  • 一切围绕 main 展开:直接在 main 上改、main 上提交、main 上推。
  • 例外:用户明确要求建分支、或涉及多人协作 / PR 评审 / 大规模重构(此时仍只是"提一句作为可选",不强推)。

理由:这次差点丢用户 3 天工作的事故,根因就是分支管理本身——某次操作意外把文件名当成分支名(建出 用户行动清单.md 分支),后续"切回 main + git branch -D 删怪分支"流程里就把未推送 commit 8bad989 干掉了。少走分支 = 少埋雷

破坏性 git 命令必须先核实

任何会丢工作的 git 命令——branch -Dreset --hardclean -fdpush --force / --force-with-leasecheckout / switch 带未提交改动、rebase 在已推送分支上、直接动 .git/ 内部文件(refs/HEADpacked-refs)——给出建议前必须先核实,不得凭"看起来安全"就甩命令:

  1. 目标 ref 上是否有未推送 / 未合并 commit:让用户跑 git log --oneline -5 <ref>git log <主线>..<ref> 把输出贴回来。
  2. 工作区是否干净git status
  3. 先挂救生圈:建议用 git tag backup-xxx <sha> 锁定当前 SHA再执行破坏性命令。
  4. 明示翻车回滚路径:例如"如果不对,git reset --hard backup-xxx 即可回到此处"。

与 memory feedback_no_git_commands.mdfeedback_main_branch_workflow.md 衔接:用户已要求"不主动跑 git 子命令(含只读)"+"在 main 上工作";本节进一步约束——即使是让用户执行的建议命令,也必须先满足上述核实清单。

验证默认动作

先定义验证方式,再做修改。默认静态验证:

  • 调用链是否闭环、是否符合模块边界
  • 配置项 / 接口契约 / 权限标识 / 路由 / 资源注册前后是否一致
  • 改动是否控制在最小集合
  • 文档 / SQL / 配置 / 接口说明是否需要同步更新

如果改动涉及 Spring 配置、序列化、安全、路由、RPC 契约、MyBatis 行为或跨模块 API必须显式区分哪些是已静态检查、哪些尚未实际运行验证。

给后续我自己的提醒

  • 仓库可能有未提交的本地改动,不要顺手覆盖与当前任务无关的编辑。
  • docs/ 是当前工作上下文的一部分,不是归档;架构级修改前先查阅。
  • pom.xml 统一版本与依赖;版本调整改根 pom不要散落到子模块。
  • 推荐使用 Glob / Grep / Read 等专用工具,避免用 Bash 做文件搜索/读取/编辑。