16 KiB
入口模块绑定最终设计方案
适用项目:
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. 这份文档解决什么问题
本方案要解决的是:
- 老系统“入口模块”到底是什么语义
- 新系统里
entry_modules / document_types / sys_routes / role_route各自该负责什么 - 首页入口模块应该由谁来组装
- 现有逻辑有哪些遗漏和隐患
- 下一步如何把它收口成一套稳定方案
这份文档的目标不是直接讲实现细节,而是先把边界、语义、数据流、遗漏点固定下来,避免后续继续前后端双写规则。
2. 结论先行
2.1 核心结论
老系统里的“入口模块”不是权限系统,而是首页业务入口编排系统。
它的职责是:
- 决定首页显示哪些入口卡片
- 给每个入口卡片绑定一组文档类型
- 按地区启用/禁用入口
它不负责:
- 控制用户是否可以访问某个页面
- 控制用户是否可以调用某个 API
- 替代 RBAC 路由菜单系统
真正的权限系统始终是:
sys_routesrole_routepermissionsrole_permissions
2.2 新系统必须收口的总原则
新系统应该明确分成三层:
-
首页入口层
- 数据源:
leaudit_entry_modules - 作用:决定首页显示什么入口
- 数据源:
-
业务归类层
- 数据源:
leaudit_document_types.entry_module_id - 作用:决定某入口下挂哪些文档类型
- 数据源:
-
权限控制层
- 数据源:
sys_routes / role_route / permissions / role_permissions - 作用:决定用户是否真的能访问页面和动作
- 数据源:
2.3 当前已落地接口口径
当前首页入口已经统一走:
GET /api/home/entry-modules
当前返回结构核心字段包括:
idnamedescriptiontargetPathroutePathiconPathsortOrderrequiresDocumentTypesareasdocumentTypes
当前过滤顺序为:
leaudit_entry_modules.is_enabled = trueleaudit_entry_modules.deleted_at is null- 地区过滤
- 若目标页面已存在于
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
实际链路
老系统首页逻辑本质是:
- 查
entry_modules - 按
areas做地区过滤 - 对每个入口模块,再查
document_types where entry_module_id = module.id - 拼成首页卡片
- 点击卡片后跳转目标页面
- 目标页面再走 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_routesrole_route
动作/API 权限来源是:
permissionsrole_permissions
这意味着在老系统中可能出现:
- 首页能看到某个入口模块
- 点击后跳到某个页面
- 页面又因为 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 建议字段
当前表建议正式化为以下语义:
idmodule_keynamedescriptionicon_pathtarget_pathroute_pathmodule_typeallow_empty_typesareassort_orderis_enabledcreate_timeupdate_time
字段解释
module_key
稳定的业务标识,用于程序判断,不可依赖 name。
示例:
contractcase_reviewassistantcross_review
icon_path
首页卡片图标/图片路径。
应从旧的 path 语义中剥离出来,单独承担展示职责。
target_path
用户点击首页卡片后实际跳转的前端路径。
示例:
/contract-template/search/home/chat-with-llm/chat/cross-checking
route_path
与 RBAC 路由树关联的目标页面路径,用于做“当前用户是否真的有访问权限”的判断。
通常可与 target_path 相同,但不强制必须相同。
module_type
建议枚举:
documentassistantcross_reviewsettings_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 接口职责
后端统一完成:
- 识别当前用户
- 读取用户角色
- 读取用户地区
- 查询可用入口模块
- 按地区过滤
- 按页面权限做一次 RBAC 二次过滤
- 挂载该入口下的文档类型
- 返回最终首页可见入口列表
6.2 建议返回结构
{
"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可查看所有启用入口模块
地市管理员 / 普通用户
admincommon
仅可看到 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 排序规则
建议优先级:
areas[].sort_order(如果当前地区有配置)leaudit_entry_modules.sort_orderid
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_pathtarget_path
9.3 特殊模块没有文档类型时会被误过滤
如果首页统一规则是“模块下必须有文档类型”,那么:
- 智慧法务助手
- 交叉评查
这类模块会被错误隐藏。
结论
必须引入:
module_typeallow_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 首页入口上下文仍然需要保留
即使首页入口最终完全由后端返回,前端仍然建议保留:
selectedModuleIdselectedModuleNamedocumentTypeIds
写入 sessionStorage
原因
后续页面仍然需要知道:
- 当前用户是从哪个入口进入的
- 当前模块下允许哪些文档类型
10. 新系统最终推荐方案
10.1 强约束
新系统正式规则建议固定如下:
- 首页入口只认
leaudit_entry_modules - 文档类型归属只认
leaudit_document_types.entry_module_id - 页面访问权限只认
sys_routes + role_route - API/动作权限只认
permissions + role_permissions - 首页入口列表必须由后端统一接口生成
- 前端只能消费最终结果,不再自己拼规则
10.2 最终推荐模型
模块主数据
leaudit_entry_modules
文档类型归属
leaudit_document_types.entry_module_id
页面访问权限
sys_routesrole_route
动作/API 权限
permissionsrole_permissions
10.3 首页统一接口
GET /api/home/entry-modules
由后端返回:
- 当前用户可见的入口模块
- 每个入口模块的目标跳转路径
- 每个入口模块挂载的文档类型列表
11. 后续代码改造建议
本次先定方案,代码实现建议按以下顺序推进。
阶段 1:后端收口
- 新增首页入口接口
- 后端实现地区过滤
- 后端实现 RBAC 二次过滤
- 后端挂载
document_types
阶段 2:前端收口
- 首页改为只调用后端统一接口
- 删除前端拼
entry_modules + document_types的逻辑 - 删除按模块名硬编码跳转
- 删除前端默认注入“智慧法务助手”
阶段 3:表结构正式化
- 给
leaudit_entry_modules增加:module_keytarget_pathroute_pathmodule_typeallow_empty_types
- 若历史字段
path仍在使用,则明确其迁移方向:- 老
path->icon_path
- 老
12. 当前审阅建议
本方案建议你重点审阅以下 5 个点:
- 是否同意“入口模块不是权限系统”的边界
- 是否同意首页入口改为后端统一生成
- 是否同意给
entry_modules新增module_key / target_path / route_path / module_type / allow_empty_types - 是否同意“智慧法务助手”这类特殊入口也必须正式落表
- 是否同意“首页可见”和“页面可访问”保留两层校验,但由后端首页接口统一兜一次
13. 一句话版最终结论
新系统应把“首页入口模块”正式定义为首页业务入口编排层,把“文档类型绑定”定义为业务归类层,把“页面/API权限”继续留在 RBAC 层,并由后端统一输出首页入口列表,彻底结束前端自己拼入口、自己判地区、自己硬编码跳转的旧模式。