Files
leaudit-platform-backend/docs/入口模块/入口模块绑定最终设计方案.md
2026-05-09 20:04:08 +08:00

763 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 入口模块绑定最终设计方案
> 适用项目:`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 层**,并由后端统一输出首页入口列表,彻底结束前端自己拼入口、自己判地区、自己硬编码跳转的旧模式。