# FMS 权限与功能实例简化设计 ## 1. 设计原则 - 客户按菜单查找功能,但权限不绑定菜单位置。 - `s_feature` 表示客户能理解的业务功能或页面区域,是入口和显示权限边界。 - `s_module` 是技术数据对象,负责字段、数据范围和默认数据能力,不直接出现在客户菜单树中。 - 同一模块被多个功能使用时,模块默认能力只配置一次。 - 某个功能使用同一模块但权限更严时,增加功能-模块例外,只能收紧,不能扩大权限。 - 同一物理表但业务语义、字段或数据范围完全不同,拆成不同逻辑模块。 - 公共 Vue 页面、路由和组件可以复用,但不同业务场景使用不同 `s_feature`。 ## 2. 对象关系 ```text 菜单(既有表) └── 引用 s_feature.b_code,只负责导航 s_feature └── 技术配置:使用哪些 s_module、模板、页面区域或报表卡片 s_module └── 字段、默认数据能力、默认数据范围 s_power ├── feature.* 功能入口、区域/卡片显示、功能专属动作 └── module.* 模块默认数据能力 s_user_power └── 用户对 feature.* / module.* 的授权 s_user_feature_module_override └── 某用户在某功能使用某模块时的收紧例外 ``` ## 3. 表结构 ### 3.1 s_feature(业务功能实例) ```sql create table dbo.s_feature ( b_code varchar(100) not null, b_name nvarchar(200) not null, b_feature_type varchar(20) not null, -- page / panel / report_card b_parent_code varchar(100) null, b_template_code varchar(100) null, b_canuse tinyint not null default 1, b_xh int not null default 0, primary key (b_code) ); ``` 菜单、模块及功能-模块关系属于既有技术配置表,本文件只约定语义,不重复定义其表结构。 ### 3.2 s_power(权限点) ```sql create table dbo.s_power ( b_code varchar(180) not null, b_scope_type varchar(20) not null, -- feature / module b_scope_code varchar(100) not null, -- feature_code 或 module_id b_name nvarchar(200) not null, b_capability varchar(30) not null, -- access/read/create/update/delete/export/业务动作 b_i18n varchar(220) null, b_canuse tinyint not null default 1, b_xh int not null default 0, primary key (b_code) ); ``` 业务层校验 `b_code`、`b_scope_type`、`b_scope_code` 和 `b_capability` 的组合关系。权限编码由系统生成,创建后不可修改。 ### 3.3 s_user_power(用户默认授权) ```sql create table dbo.s_user_power ( b_user_id varchar(50) not null, b_power_code varchar(180) not null, b_canuse tinyint not null default 1, b_updatedatetime datetime2 null, primary key (b_user_id, b_power_code), foreign key (b_power_code) references dbo.s_power(b_code) ); ``` ### 3.4 s_user_feature_module_override(功能-模块收紧例外) ```sql create table dbo.s_user_feature_module_override ( b_user_id varchar(50) not null, b_feature_code varchar(100) not null, b_module_id varchar(50) not null, b_capability varchar(30) not null, -- read/create/update/delete/export b_canuse tinyint not null default 0, -- 0 表示在该场景禁止 b_updatedatetime datetime2 null, primary key (b_user_id, b_feature_code, b_module_id, b_capability) ); ``` 该表只保存例外限制,不保存默认允许记录,也不能用于突破 `s_user_power` 的模块权限。 字段和数据范围仍按逻辑模块配置: ```text s_user_field_permission(user_id, module_id, field, ...) s_user_data_scope(user_id, module_id, operation, ...) ``` 如果某功能需要不同字段或数据范围,可将例外表扩展为功能-模块维度;仍只允许收紧权限。 ## 4. 权限计算 ### 4.1 入口和显示 ```text 页面进入 = feature..access 页面区域显示 = 父页面已进入 + feature..access 报表卡片显示 = 父看板已进入 + feature..access ``` ### 4.2 模块操作 ```text 模块读取 = feature.access + module..read 模块新增 = feature.access + module..create 模块修改 = feature.access + module..update 模块删除 = feature.access + module..delete 模块导出 = feature.access + module..export ``` 如果存在 `s_user_feature_module_override` 对应的禁止记录,则该功能场景下的能力被收紧。 ```text 最终模块能力 = 功能入口 ∩ 用户模块能力 ∩ 功能-模块例外 ``` ### 4.3 功能专属动作 审核、反审核、核销等不属于通用 CRUD 的动作,直接绑定功能实例: ```text feature.sea_detail.audit feature.cw_fee_list.settle ``` ## 5. Demo 数据 ### 5.1 功能实例 | b_code | b_name | b_feature_type | b_parent_code | b_template_code | | --- | --- | --- | --- | --- | | sea_detail | 海运详细 | page | null | DetailPage | | sea_detail_container | 海运详细-装箱区域 | panel | sea_detail | DetailPanel | | container_query | 装箱查询 | page | null | CommonListPage | | cw_fee_list | 费用列表 | page | null | CommonListPage | | finance_dashboard | 财务看板 | page | null | DashboardPage | | ar_aging_card | 应收账龄 | report_card | finance_dashboard | ReportCard | ### 5.2 功能使用的模块 | b_feature_code | b_module_id | b_usage_type | b_required | | --- | --- | --- | ---: | | sea_detail | sea_main | main | 1 | | sea_detail | cw_fee | detail | 0 | | sea_detail_container | container_main | detail | 0 | | container_query | container_main | main | 1 | | cw_fee_list | cw_fee | main | 1 | | ar_aging_card | finance_main | source | 1 | ### 5.3 权限点 | b_code | b_scope_type | b_scope_code | b_capability | b_name | | --- | --- | --- | --- | --- | | feature.sea_detail.access | feature | sea_detail | access | 进入海运详细 | | feature.sea_detail.audit | feature | sea_detail | audit | 海运审核 | | feature.sea_detail_container.access | feature | sea_detail_container | access | 显示装箱区域 | | feature.container_query.access | feature | container_query | access | 进入装箱查询 | | feature.cw_fee_list.access | feature | cw_fee_list | access | 进入费用列表 | | feature.finance_dashboard.access | feature | finance_dashboard | access | 进入财务看板 | | feature.ar_aging_card.access | feature | ar_aging_card | access | 显示应收账龄 | | feature.ar_aging_card.export | feature | ar_aging_card | export | 导出应收账龄 | | module.sea_main.read | module | sea_main | read | 查看海运主表 | | module.cw_fee.read | module | cw_fee | read | 查看费用 | | module.cw_fee.create | module | cw_fee | create | 新增费用 | | module.cw_fee.update | module | cw_fee | update | 修改费用 | | module.cw_fee.export | module | cw_fee | export | 导出费用 | | module.container_main.read | module | container_main | read | 查看装箱 | | module.container_main.export | module | container_main | export | 导出装箱 | ### 5.4 用户默认授权 | b_user_id | b_power_code | b_canuse | | --- | --- | ---: | | zhangsan | feature.sea_detail.access | 1 | | zhangsan | feature.sea_detail_container.access | 1 | | zhangsan | feature.container_query.access | 1 | | zhangsan | feature.cw_fee_list.access | 1 | | zhangsan | module.sea_main.read | 1 | | zhangsan | module.container_main.read | 1 | | zhangsan | module.cw_fee.read | 1 | | zhangsan | module.cw_fee.create | 1 | | zhangsan | module.cw_fee.update | 1 | | lisi | feature.sea_detail.access | 1 | | lisi | feature.sea_detail_container.access | 1 | | lisi | feature.container_query.access | 1 | | lisi | feature.cw_fee_list.access | 1 | | lisi | feature.finance_dashboard.access | 1 | | lisi | feature.ar_aging_card.access | 1 | | lisi | module.sea_main.read | 1 | | lisi | module.container_main.read | 1 | | lisi | module.container_main.export | 1 | | lisi | module.cw_fee.read | 1 | | lisi | module.cw_fee.create | 1 | | lisi | module.cw_fee.update | 1 | | lisi | module.cw_fee.export | 1 | ### 5.5 功能-模块例外 李四可以在费用列表维护费用,但海运详细中的费用只读: | b_user_id | b_feature_code | b_module_id | b_capability | b_canuse | | --- | --- | --- | --- | ---: | | lisi | sea_detail | cw_fee | create | 0 | | lisi | sea_detail | cw_fee | update | 0 | | lisi | sea_detail | cw_fee | export | 0 | 结果: ```text 费用列表:可查看、新增、修改、导出 海运详细:可查看费用,不可新增、修改、导出 ``` ## 6. 运行规则 ```text 请求 -> 服务端确定 feature_code -> 检查 feature..access -> 按功能配置取得允许的 module_id -> 检查 module.. -> 检查功能-模块例外 -> 应用字段权限和数据范围 -> 执行查询、写入或导出 ``` - 菜单只负责定位功能实例,同一功能挂在多个菜单时只授权一次。 - 同一公共页面模板对应不同功能实例时,权限按功能实例区分。 - 同一模块被多个功能使用时,模块默认能力只配置一次。 - 功能场景差异通过例外限制表达,例外只能收紧。 - 页面内可独立隐藏的区域定义为 `panel` 功能实例;看板卡片定义为 `report_card`。 - 前端传入的 `module_id` 必须经过当前功能的模块白名单校验。 - 后端接口必须重复校验 `access`、模块操作权限和例外限制,不能只依赖前端按钮隐藏。