Files
workspace/code/fms/字段权限与字段个性化设计.md
T
2026-09-04 17:31:36 +08:00

8.4 KiB
Raw Blame History

字段权限与字段个性化设计

状态:设计定稿,未实现。创建于 2026-09-04。 关联文档:FMS新系统核心表结构设计.md(其中 s_power / s_role_power 部分)

1. 背景与目标

系统已有全局的字段显示配置(s_field_view / s_field_edit,在模块设计器中维护,对所有人生效)。本设计解决两个新需求:

  1. 字段权限:管理员(高权限角色)控制某个人/某些人能不能看到某些字段;
  2. 字段个性化:用户自己调整列表的字段顺序、列宽、显示/隐藏,且只影响自己、跨设备持久化。

范围约定:

  • 个性化只作用于列表(查看态列表 + 可编辑列表两套配置),表单不参与顺序/布局个性化;
  • 单公司系统(无多租户维度),后续如需多公司再扩展;
  • 不考虑旧数据迁移难度。

2. 三层模型

第 1 层  默认配置(模板)      s_field_view / s_field_edit      模块设计器维护,管理员设定
第 2 层  字段权限(谁能看)    s_power(field型) + s_role_power   管理员按角色控制可见性
第 3 层  个人偏好(怎么摆)    s_user_field_pref(新表)         用户自己拖拽,只影响自己

职责边界是本设计的核心原则:

  • 权限决定"全集":deny 的字段对用户不存在(列表不渲染、后端不返回);
  • 偏好只决定"排列":顺序、宽度、个人显隐,永远在权限允许的范围内生效,无法越过权限;
  • 终端用户能控制的只有自己的布局,可见性的控制权始终在管理员手里。

两层独立演化:将来权限规则变化,偏好数据不需要清洗(偏好里残留无权限字段只是无效数据,不构成越权)。

3. 数据结构

3.1 新表:s_user_field_pref(个人偏好)

一人 × 一模块 × 一字段 × 一模式 一行。每字段一行(而非 JSON 快照),可直接复用现有通用 CRUD(DataService)。

CREATE TABLE s_user_field_pref (
  b_id        VARCHAR(32) PRIMARY KEY,
  b_user_id   VARCHAR(32) NOT NULL,
  b_module_id VARCHAR(32) NOT NULL,
  b_field_id  VARCHAR(32) NOT NULL,
  b_mode      VARCHAR(10) NOT NULL,   -- 'view' 查看列表 / 'edit' 可编辑列表
  b_visible   TINYINT DEFAULT 1,      -- 个人显隐(1 显示,0 隐藏)
  b_xh        INT,                    -- 个人顺序号
  b_width     INT,                    -- 个人列宽
  b_update_time DATETIME,
  UNIQUE KEY uk_user_field (b_user_id, b_module_id, b_field_id, b_mode)
);

说明:

  • 用户没有保存过偏好的字段不产生行,解析时落回默认配置(s_field_view / s_field_edit);
  • 保存过布局 = 该用户该模块该 mode 存在偏好行,此后默认布局变更对该用户不再生效(保持用户自主摆放的稳定性),可通过"恢复默认"删除偏好行回到跟随默认;
  • "恢复默认" = 删除该用户 + 该模块 + 该 mode 的全部行。

3.2 权限层:复用已有表 + 一张用户级覆盖表

  • s_power(field 型:b_module_id + b_field_id + b_operation[view/edit])与 s_role_power(b_effect allow/deny)沿用现有表结构,见 FMS新系统核心表结构设计.md;
  • 新增用户级覆盖表,用于个别用户的特例(平时应为空表,只为"开小灶"使用,不值得建角色时用它):
CREATE TABLE s_user_power (
  b_id         VARCHAR(32) PRIMARY KEY,
  b_user_id    VARCHAR(32) NOT NULL,
  b_module_id  VARCHAR(32) NOT NULL,
  b_field_id   VARCHAR(32) NOT NULL,
  b_operation  VARCHAR(10) NOT NULL,  -- 'view' / 'edit'
  b_effect     VARCHAR(10) NOT NULL,  -- 'allow' / 'deny'
  UNIQUE KEY uk_user_field_op (b_user_id, b_module_id, b_field_id, b_operation)
);

4. 解析算法

4.1 字段可见性(权限链)

可见性 = 用户级覆盖(s_user_power,有配置则生效,优先级最高)
       ↓ 该用户该字段无配置
       角色合并(该用户所有角色的 s_role_power,deny 优先:任一角色 deny 即 deny)
       ↓ 无任何角色配置
       默认可见(allow)

要点:

  • 默认全部可见,黑名单式配置:只为敏感字段配 deny,不为普通字段配 allow,维护量最小;
  • deny 优先(而非 allow 优先):敏感字段场景下更安全。

4.2 列表最终配置(合并链)

对查看列表和可编辑列表分别执行(mode = view / edit):

最终配置 = 默认配置(s_field_view / s_field_edit,含 b_canuse 过滤)
         → 剔除权限 deny 的字段
         → 用个人偏好覆盖 b_xh / b_width / b_visible
         → 偏好中没有的字段,按默认配置的顺序追加补全

有效显示 = 权限可见 && 字段可用(b_canuse=1) && 个人未隐藏。

补全规则保证:新增字段、默认配置新启用的字段,即使用户保存过布局也会按默认顺序出现在列表尾部,不会"消失"。

4.3 顺序合并细节

偏好只覆盖出现过的字段;用户保存布局后管理员再调默认顺序,对已保存用户无效(见 3.1)。

5. 边界场景约定

场景 行为
字段 b_canuse=0(下架) 不进入候选集,即使偏好表里有该字段的行也不显示(偏好行成无效数据,暂不清理,量大后在字段下架入口顺带删除)
新增字段 所有用户可见:无偏好则按默认顺序出现在尾部
权限从 allow 变 deny 字段对用户消失;偏好数据保留,权限恢复后用户的自定义布局自动恢复
用户隐藏字段 vs 权限隐藏字段 是两回事:个人隐藏 = 有权看但暂时不显示,"栏位设置"弹窗可随时勾回;权限隐藏 = 对该用户不存在,弹窗中不展示无权限字段
必填字段被用户隐藏(可编辑列表) 待定,见第 8 节

6. 交互设计

  • 列表列头拖拽排序、拖拽调宽(能力已有:FmsTable.vue);
  • 拖拽结束后防抖保存(约 500ms)upsert 到 s_user_field_pref;
  • 菜单保留"保存/恢复栏位设置",语义从全局改为个人:"恢复"即删除偏好行;
  • "栏位设置"弹窗:排序 + 个人显隐 + 列宽统一管理;不展示无权限字段;
  • 可选:管理员入口"保存为全局默认",仍写 s_field_view / s_field_edit。

7. 改动范围(实现清单)

位置 改动
migration 新增 s_user_field_pref、s_user_power 建表
后端 DataService ① 字段权限过滤:deny 字段从查询结果中剔除(设计文档既定要求,目前后端零过滤)② 偏好表 CRUD 复用现有通用机制
前端 stores/permissions.js 新增 canField(moduleId, fieldId, operation):用户级 → 角色合并(deny 优先)→ 默认 allow
前端 FmsModuleListPage.vue loadData 中实现合并链(默认 → 权限过滤 → 偏好覆盖 → 补全);saveColumnSettings 保存目标从 s_field_view/s_field_edit 改为 s_user_field_pref
权限管理 UI 模块管理 ModuleFieldsPanel 旁新增"字段权限"页签:选角色 × 勾字段(view/edit);入口本身由现有模块/按钮权限(canPower)控制,实现"高权限的人才能配"
用户级覆盖 UI 可后置:先支持直接改 s_user_power 数据,界面后续补

关键实现纪律:合并偏好的代码必须在权限过滤之后执行,保证偏好永远无法越过权限。

8. 待定事项

必填字段被用户隐藏后的校验策略(可编辑列表场景):

方案 规则 适用
A. 所见即所验 隐藏后跳过必填校验 "必填"只是引导性要求,空值可接受;且权限隐藏与用户隐藏行为天然统一,无需特殊分支
B. 必填不可藏 可编辑列表中必填字段置灰、禁止隐藏 "必填"是业务硬规则,字段空值会损害下游使用

判断标准:该字段空着,会不会有人受害。会 → B;不会 → A。权限隐藏(管理员 deny)场景下无论选哪个方案,行为都与 A 一致(用户"没有这个字段",天然不校验)。


结论摘要:默认配置(全局模板)→ 字段权限(管理员按角色控制可见性,deny 优先,默认全可见,用户级覆盖兜底)→ 个人偏好(仅列表的顺序/列宽/显隐,权限范围内生效,未设置走默认)。