# 01 · 模块注册模型:模块怎么存、表怎么归属到模块 Type: grilling Status: resolved ## Question 数据权限的「业务模块」(线索/商机/客户/项目,可扩展)在系统里以什么形式存在, 受控表(`OwnedEntity` + `@DataScope`)又如何归属到某个模块? 要定的点: - 模块本身存哪:新建字典/注册表(如 `sys_data_scope_module`:id, code, name, sort), 还是复用 `crm-dict`,还是别的?「可扩展」要求它数据驱动,不能把四个模块写死在枚举里。 - 表→模块的关联方向: - A:`@DataScope` 注解上加 `module` 属性,实体自报家门; - B:模块注册表里登记「本模块含哪些表名」; - C:其他。 - 一个模块含多张表(如「客户」含客户+联系人+跟进记录)共享同一档——关联模型要支持一对多。 - 未标模块 / 未接入模块的受控表如何处理(沿用某默认档?不过滤?拒绝启动?)。 这是整张地图的地基,后续存储/计算/上下文/拦截器都依赖它先定。 ## Answer ### 1. 模块注册表:专用注册表 `sys_data_scope_module` 新建表,字段:`id` / `code`(全局唯一,稳定标识,如 `lead`/`opportunity`/`customer`/`project`)/ `name`(展示名)/ `sort` / `status`(enabled/disabled)/ `builtin`(boolean,内置模块不可删除)。 - 模块列表数据驱动,管理员通过端点 CRUD,不写死在枚举/代码里。 - `code` 是稳定标识——注解和角色配置都引用 `code`,不引用 `id`。 - `builtin=true` 的模块由初始化脚本导入,不可删除(可改 name/sort/启停),与 `SysRole.builtin` 语义一致。 ### 2. 表→模块关联:`@DataScope` 注解加 `module` 属性(实体自报) 注解新增 `String module()`,**无默认值(必填)**: ```java @DataScope(module = "customer", ownerColumn = "owner_id", deptColumn = "dept_id") public class Customer extends OwnedEntity { ... } ``` - 启动扫描时 `PermissionConfig` 建表 table→(moduleCode, ownerColumn, deptColumn) 映射。 - 与 ownerColumn/deptColumn 同源,不引入第二处事实来源。 - 一个模块含多张表(如「客户」含客户+联系人+跟进记录):多个实体标同一 `module` code 即可,拦截器按表名查到模块后取同一份 `VisibilityScope`。无需额外机制。 ### 3. 未标模块 / 注册表查不到:module 必填 + 拒绝启动 - `@DataScope` 的 `module` 属性为必填(编译期无默认值)。 - 启动扫描时 `PermissionConfig` 校验:每个 `@DataScope` 注解的 `module` code 必须在 `sys_data_scope_module` 注册表里存在。 - 校验失败 → 抛异常,拒绝启动(与 ADR-0006「不存在设了一半」一致)。 ### 对下游工单的影响 - **02(存储)**:角色对每个模块的档位建议存 `sys_role_data_scope(role_id, module_code, data_scope)`——module 用 `code`(string)引用而非 `id`,与 crm-dict「业务数据只存字典编码」的约定一致。角色对某模块未配档位时的默认语义、CUSTOM(5) 是否保留等由 02 定。 - **04(上下文值对象)**:`DataVisibilityContext` 从放一份 `DataVisibility` 变为放 `module code → DataVisibility` 的映射。部门集合/子树展开只算一次、各模块档位复用(部门集合不随模块变)。 - **05(拦截器)**:`DataScopeInterceptor` 查表名 → 拿 module code → 从上下文取该模块的 `VisibilityScope` → 注入 SQL。`PermissionResolverImpl.resolve` 对每个模块各自在所有角色的该模块档位里取最宽。 - **03(迁移)**:现有 `sys_role.data_scope` 单列需迁移到新存储(具体规则由 03 定,依赖 02)。 - **06(写侧)**:写侧 owner/dept 填充与档位无关,不受模块概念影响,待 06 票确认。 ### 新增域术语 - **数据权限模块**:数据权限按业务模块分别配置时的「业务模块」概念,存在于 `sys_data_scope_module` 注册表中,用 `code` 标识。一个角色对每个模块各有一档数据范围档位,多角色对每个模块各自取最宽。模块可由管理员扩展(数据驱动),受控实体通过 `@DataScope(module = "...")` 注解声明所属模块。