docs: reorganize by module

This commit is contained in:
wren
2026-05-09 20:04:08 +08:00
parent 29873eaecd
commit c9d7a693b8
23 changed files with 2161 additions and 197 deletions
@@ -0,0 +1,762 @@
# 入口模块绑定最终设计方案
> 适用项目:`leaudit-platform`
>
> 参考来源:
> - 老系统:`/home/wren-dev/Porject/docauditai`
> - 新前端:`/home/wren-dev/Porject/leaudit-platform/new_doc_review`
> - 新后端:`/home/wren-dev/Porject/leaudit-platform/fastapi_modules`
---
## 1. 这份文档解决什么问题
本方案要解决的是:
1. 老系统“入口模块”到底是什么语义
2. 新系统里 `entry_modules / document_types / sys_routes / role_route` 各自该负责什么
3. 首页入口模块应该由谁来组装
4. 现有逻辑有哪些遗漏和隐患
5. 下一步如何把它收口成一套稳定方案
这份文档的目标不是直接讲实现细节,而是先把**边界、语义、数据流、遗漏点**固定下来,避免后续继续前后端双写规则。
---
## 2. 结论先行
### 2.1 核心结论
老系统里的“入口模块”**不是权限系统**,而是**首页业务入口编排系统**。
它的职责是:
- 决定首页显示哪些入口卡片
- 给每个入口卡片绑定一组文档类型
- 按地区启用/禁用入口
它**不负责**
- 控制用户是否可以访问某个页面
- 控制用户是否可以调用某个 API
- 替代 RBAC 路由菜单系统
真正的权限系统始终是:
- `sys_routes`
- `role_route`
- `permissions`
- `role_permissions`
### 2.2 新系统必须收口的总原则
新系统应该明确分成三层:
1. **首页入口层**
- 数据源:`leaudit_entry_modules`
- 作用:决定首页显示什么入口
2. **业务归类层**
- 数据源:`leaudit_document_types.entry_module_id`
- 作用:决定某入口下挂哪些文档类型
3. **权限控制层**
- 数据源:`sys_routes / role_route / permissions / role_permissions`
- 作用:决定用户是否真的能访问页面和动作
### 2.3 当前已落地接口口径
当前首页入口已经统一走:
- `GET /api/home/entry-modules`
当前返回结构核心字段包括:
- `id`
- `name`
- `description`
- `targetPath`
- `routePath`
- `iconPath`
- `sortOrder`
- `requiresDocumentTypes`
- `areas`
- `documentTypes`
当前过滤顺序为:
1. `leaudit_entry_modules.is_enabled = true`
2. `leaudit_entry_modules.deleted_at is null`
3. 地区过滤
4. 若目标页面已存在于 `sys_routes`,则继续做 `role_route` 权限过滤
这意味着首页入口已经不是前端自己拼装,而是后端统一组装后返回。
---
## 3. 老系统深度分析结论
## 3.1 首页入口不是从 sys_routes 直接来
老系统首页入口不是直接根据 RBAC 路由树生成,而是单独查询入口模块配置。
对应证据:
- 老系统入口模块服务:
- `/home/wren-dev/Porject/docauditai/app/services/entry_module_service.py`
- 老系统入口模块路由:
- `/home/wren-dev/Porject/docauditai/app/routes/entry_modules.py`
- 老系统文档类型服务:
- `/home/wren-dev/Porject/docauditai/app/services/document_type_service.py`
### 实际链路
老系统首页逻辑本质是:
1.`entry_modules`
2.`areas` 做地区过滤
3. 对每个入口模块,再查 `document_types where entry_module_id = module.id`
4. 拼成首页卡片
5. 点击卡片后跳转目标页面
6. 目标页面再走 RBAC 校验
所以首页入口和页面权限本来就是两套体系。
---
## 3.2 老系统中 entry_modules 的真实职责
老系统 `entry_modules` 本质上存的是“首页业务入口卡片配置”。
典型字段语义:
- `id`:入口模块主键
- `name`:入口名称
- `description`:说明
- `path`:旧系统里语义不稳定,常被当成资源/图片路径使用
- `areas`:地区配置
- `created_at / updated_at`
### 关键观察
老系统里 `path` 不是一个稳定可靠的“点击后跳转路由字段”。
也就是说:
- 它并不总是纯前端路由
- 它常常承担资源路径、展示配置、模块图片等混合语义
这也是老系统最容易让后续维护者误解的地方之一。
---
## 3.3 文档类型和入口模块的关系
老系统文档类型是通过 `entry_module_id` 绑定到入口模块的。
这说明:
- 一个入口模块下面挂很多文档类型
- 一个文档类型归属于一个入口模块
这个设计本身是合理的,属于“业务归类关系”,不属于“权限关系”。
### 当前判断
除非未来明确出现“一个文档类型必须出现在多个入口模块”的业务需求,否则:
- 新系统应继续保留 `entry_module_id`
- 没必要提前拆成中间表
---
## 3.4 真正的页面权限来自 RBAC
老系统页面权限来源一直是:
- `sys_routes`
- `role_route`
动作/API 权限来源是:
- `permissions`
- `role_permissions`
这意味着在老系统中可能出现:
1. 首页能看到某个入口模块
2. 点击后跳到某个页面
3. 页面又因为 RBAC 不通过而拒绝访问
这是老系统长期存在的结构性问题,不是 Bug,而是设计分层没有被清楚说明。
---
## 4. 新系统最终语义边界
## 4.1 `leaudit_entry_modules`
### 负责
- 首页显示哪些业务入口
- 每个入口的名称、图标、排序、地区启用规则
- 每个入口点击后去哪
### 不负责
- 页面访问权限
- API 权限
- 替代路由表
---
## 4.2 `leaudit_document_types`
### 负责
- 定义系统支持的文档类型
- 通过 `entry_module_id` 归属到某个入口模块
### 不负责
- 决定首页是否展示入口模块
- 决定菜单权限
---
## 4.3 `sys_routes / role_route`
### 负责
- 页面路由菜单权限
- 用户可访问哪些页面
### 不负责
- 首页模块展示编排
- 文档类型归类
---
## 4.4 `permissions / role_permissions`
### 负责
- API 权限
- 动作按钮权限
- 数据范围权限
### 不负责
- 首页入口展示
- 文档类型归属
---
## 5. 新系统最终数据模型建议
## 5.1 `leaudit_entry_modules` 建议字段
当前表建议正式化为以下语义:
- `id`
- `module_key`
- `name`
- `description`
- `icon_path`
- `target_path`
- `route_path`
- `module_type`
- `allow_empty_types`
- `areas`
- `sort_order`
- `is_enabled`
- `create_time`
- `update_time`
### 字段解释
#### `module_key`
稳定的业务标识,用于程序判断,不可依赖 `name`
示例:
- `contract`
- `case_review`
- `assistant`
- `cross_review`
#### `icon_path`
首页卡片图标/图片路径。
应从旧的 `path` 语义中剥离出来,单独承担展示职责。
#### `target_path`
用户点击首页卡片后实际跳转的前端路径。
示例:
- `/contract-template/search`
- `/home`
- `/chat-with-llm/chat`
- `/cross-checking`
#### `route_path`
与 RBAC 路由树关联的目标页面路径,用于做“当前用户是否真的有访问权限”的判断。
通常可与 `target_path` 相同,但不强制必须相同。
#### `module_type`
建议枚举:
- `document`
- `assistant`
- `cross_review`
- `settings_link`
#### `allow_empty_types`
控制“没有绑定文档类型时是否仍然允许显示”。
建议:
- 文档类模块:`false`
- 助手类模块:`true`
- 交叉评查类模块:`true`
---
## 5.2 `leaudit_document_types`
继续保留:
- `entry_module_id`
表示“该文档类型归属哪个入口模块”。
### 当前不建议做的事
暂不建议改成:
- `leaudit_entry_module_document_type_bindings`
因为当前没有明确“一种文档类型要同时挂多个入口”的需求。
---
## 6. 首页统一接口最终设计
建议新增:
- `GET /api/home/entry-modules`
由后端直接根据当前登录用户返回首页入口列表。
前端不再自己拼 `entry_modules + document_types + area + 跳转规则`
---
## 6.1 接口职责
后端统一完成:
1. 识别当前用户
2. 读取用户角色
3. 读取用户地区
4. 查询可用入口模块
5. 按地区过滤
6. 按页面权限做一次 RBAC 二次过滤
7. 挂载该入口下的文档类型
8. 返回最终首页可见入口列表
---
## 6.2 建议返回结构
```json
{
"code": 200,
"message": "ok",
"data": {
"items": [
{
"id": 1,
"moduleKey": "contract",
"name": "合同管理",
"description": "合同智能审核与模板管理",
"iconPath": "static/modules/contract.png",
"targetPath": "/contract-template/search",
"routePath": "/contract-template/search",
"moduleType": "document",
"allowEmptyTypes": false,
"sortOrder": 10,
"documentTypes": [
{
"id": 9,
"code": "contract.sale",
"name": "买卖合同"
}
]
}
]
}
}
```
---
## 7. 首页统一接口的推荐过滤规则
## 7.1 基础过滤
必须满足:
- `is_enabled = true`
---
## 7.2 地区过滤
### 省级管理员
- `provincial_admin` 可查看所有启用入口模块
### 地市管理员 / 普通用户
- `admin`
- `common`
仅可看到 `areas` 中当前 `user.area``enabled = true` 的模块。
### 重要约束
地区过滤必须在后端完成,不能信前端传 area。
---
## 7.3 RBAC 二次过滤
如果入口模块配置了 `route_path`,则需要再检查当前用户是否有该页面的访问权限。
### 目的
避免出现:
- 首页看得到入口
- 点进去却被 RBAC 拒绝
### 推荐做法
基于当前用户角色集合,查询:
- `sys_routes.route_path = route_path`
- 是否被 `role_route` 授权
若未授权,则该入口模块不返回。
---
## 7.4 文档类型过滤
### 对 `module_type = document`
必须至少有一个启用中的文档类型,否则不返回。
### 对 `module_type = assistant / cross_review`
允许没有文档类型,只要模块本身启用并通过权限检查即可返回。
---
## 7.5 排序规则
建议优先级:
1. `areas[].sort_order`(如果当前地区有配置)
2. `leaudit_entry_modules.sort_order`
3. `id`
---
## 8. 前端必须删掉的旧逻辑
## 8.1 不能再由前端自己查 `entry_modules`
当前旧逻辑:
- 前端查入口模块
- 前端按地区过滤
- 前端再查文档类型
这会导致规则散落在前端,不利于后端统一治理。
应改为:
- 前端只调用 `GET /api/home/entry-modules`
---
## 8.2 不能再按模块名硬编码跳转
当前风险逻辑:
- 模块名包含“合同” -> `/contract-template/search`
- 模块名是“智慧法务助手” -> `/chat-with-llm/chat`
这类逻辑必须移除。
应改为直接使用后端返回的:
- `targetPath`
---
## 8.3 不能再在前端默认硬塞特殊模块
例如:
- “智慧法务助手”
不应再由前端强行 `push()` 到入口列表里。
必须和普通模块一样进入 `leaudit_entry_modules` 正式配置。
这样做的好处:
- 权限统一
- 排序统一
- 是否启用统一
- 图标统一
- 后台管理统一
---
## 9. 当前逻辑遗漏点深度检查
下面是本次分析中确认存在或高概率会出现的遗漏点。
## 9.1 首页可见 ≠ 页面可访问
这是老系统就存在的问题。
如果首页只按 `entry_modules` 过滤,不按 RBAC 再过滤,就会出现:
- 首页看到入口
- 点进去又被页面权限拦住
### 结论
首页接口必须做 RBAC 二次过滤。
---
## 9.2 `path` 字段语义不稳定
老系统里 `entry_modules.path` 混杂:
- 图片路径
- 资源路径
- 可能被误当成前端路由
### 结论
新系统不能继续复用一个 `path` 字段承担两种含义。
必须拆成:
- `icon_path`
- `target_path`
---
## 9.3 特殊模块没有文档类型时会被误过滤
如果首页统一规则是“模块下必须有文档类型”,那么:
- 智慧法务助手
- 交叉评查
这类模块会被错误隐藏。
### 结论
必须引入:
- `module_type`
- `allow_empty_types`
---
## 9.4 省级管理员是否应该看到所有模块
这个规则必须固定,不然以后省级账号行为会不一致。
### 建议
- `provincial_admin` 看全部已启用入口
- 但仍需受目标页面 RBAC 权限约束
---
## 9.5 文档类型全部停用后,文档类入口是否显示
如果一个“合同管理”模块下面一个启用文档类型都没有,继续显示没有意义。
### 建议
- `module_type = document` 且无可用文档类型 -> 不显示
- `assistant / cross_review` 不受此规则影响
---
## 9.6 入口模块与左侧菜单不是同一概念
首页入口模块是“业务入口卡片”,左侧菜单是“页面路由树”。
如果不写清楚,后面会经常出现误解:
- 为什么首页有入口,但侧边栏没有?
- 为什么有路由权限,但首页不显示?
### 结论
文档中必须明确:
- 首页入口 = 业务编排
- 左侧菜单 = RBAC 路由
---
## 9.7 交叉评查专属模式不应混入入口模块业务规则
当前前端已有:
- `CROSS_CHECKING_ONLY_MODE`
它本质上是部署态开关,不是入口模块自身规则。
### 结论
该逻辑应作为部署模式单独处理,不要污染 `entry_modules` 基础语义。
---
## 9.8 首页入口上下文仍然需要保留
即使首页入口最终完全由后端返回,前端仍然建议保留:
- `selectedModuleId`
- `selectedModuleName`
- `documentTypeIds`
写入 `sessionStorage`
### 原因
后续页面仍然需要知道:
- 当前用户是从哪个入口进入的
- 当前模块下允许哪些文档类型
---
## 10. 新系统最终推荐方案
## 10.1 强约束
新系统正式规则建议固定如下:
1. 首页入口只认 `leaudit_entry_modules`
2. 文档类型归属只认 `leaudit_document_types.entry_module_id`
3. 页面访问权限只认 `sys_routes + role_route`
4. API/动作权限只认 `permissions + role_permissions`
5. 首页入口列表必须由后端统一接口生成
6. 前端只能消费最终结果,不再自己拼规则
---
## 10.2 最终推荐模型
### 模块主数据
- `leaudit_entry_modules`
### 文档类型归属
- `leaudit_document_types.entry_module_id`
### 页面访问权限
- `sys_routes`
- `role_route`
### 动作/API 权限
- `permissions`
- `role_permissions`
---
## 10.3 首页统一接口
- `GET /api/home/entry-modules`
由后端返回:
- 当前用户可见的入口模块
- 每个入口模块的目标跳转路径
- 每个入口模块挂载的文档类型列表
---
## 11. 后续代码改造建议
本次先定方案,代码实现建议按以下顺序推进。
### 阶段 1:后端收口
1. 新增首页入口接口
2. 后端实现地区过滤
3. 后端实现 RBAC 二次过滤
4. 后端挂载 `document_types`
### 阶段 2:前端收口
1. 首页改为只调用后端统一接口
2. 删除前端拼 `entry_modules + document_types` 的逻辑
3. 删除按模块名硬编码跳转
4. 删除前端默认注入“智慧法务助手”
### 阶段 3:表结构正式化
1.`leaudit_entry_modules` 增加:
- `module_key`
- `target_path`
- `route_path`
- `module_type`
- `allow_empty_types`
2. 若历史字段 `path` 仍在使用,则明确其迁移方向:
-`path` -> `icon_path`
---
## 12. 当前审阅建议
本方案建议你重点审阅以下 5 个点:
1. 是否同意“入口模块不是权限系统”的边界
2. 是否同意首页入口改为后端统一生成
3. 是否同意给 `entry_modules` 新增 `module_key / target_path / route_path / module_type / allow_empty_types`
4. 是否同意“智慧法务助手”这类特殊入口也必须正式落表
5. 是否同意“首页可见”和“页面可访问”保留两层校验,但由后端首页接口统一兜一次
---
## 13. 一句话版最终结论
新系统应把“首页入口模块”正式定义为**首页业务入口编排层**,把“文档类型绑定”定义为**业务归类层**,把“页面/API权限”继续留在 **RBAC 层**,并由后端统一输出首页入口列表,彻底结束前端自己拼入口、自己判地区、自己硬编码跳转的旧模式。