20260904173136

This commit is contained in:
oneao committed 2026-09-04 17:31:36 +08:00
1 parent 0928437c67
commit 4e167df0f0
40 files changed
+3471 -2314

No files matched your search

@@ -0,0 +1,159 @@
# 字段权限与字段个性化设计
> 状态:设计定稿,未实现。创建于 2026-09-04。
> 关联文档:[FMS新系统核心表结构设计.md](./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)。
```sql
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](./FMS新系统核心表结构设计.md);
- 新增用户级覆盖表,用于个别用户的特例(平时应为空表,只为"开小灶"使用,不值得建角色时用它):
```sql
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 优先,默认全可见,用户级覆盖兜底)→ 个人偏好(仅列表的顺序/列宽/显隐,权限范围内生效,未设置走默认)。