249 lines
8.3 KiB
Markdown
249 lines
8.3 KiB
Markdown
# 模块管理实施计划
|
||
|
||
## 目标
|
||
|
||
使用 `fms-api/config/dbconfigs/g3hd.properties` 指向的新数据库建立模块管理表结构,并将 `ModuleManageDemo.vue` 改造成真实页面。
|
||
|
||
本阶段只实现《新数据库结构.md》中的六张表,不实现 `select` 的选项来源和模块关联。
|
||
|
||
## 实施原则
|
||
|
||
- 不新增模块管理专用后端接口。
|
||
- 查询复用 `/data/loaddata` 和 `/data/page`。
|
||
- 保存复用 `/data/saveobjt`,一次请求完成多表事务。
|
||
- 雪花 ID 复用 `/data/nextid`。
|
||
- 不使用 `/data/loaddatabysql` 拼接模块管理 SQL。
|
||
- 只操作 `g3hd.properties` 指向的 `fms` 数据库,不修改旧数据库。
|
||
- 真实页面沿用 Demo 的左树右工作区和 Antdv Next Tree、Form、Table 设计。
|
||
|
||
## 第一阶段:建立数据库
|
||
|
||
### 建表脚本
|
||
|
||
新增:
|
||
|
||
```text
|
||
fms-api/config/migrations/001_module_management.sql
|
||
fms-api/config/migrations/002_module_order_condition.sql
|
||
fms-api/config/migrations/003_module_surrogate_key.sql
|
||
```
|
||
|
||
按以下顺序建立表:
|
||
|
||
1. `s_module`
|
||
2. `s_module_field`
|
||
3. `s_module_power`
|
||
4. `b_user_module`
|
||
5. `b_user_power`
|
||
6. `b_i18n`
|
||
|
||
脚本包含:
|
||
|
||
- 主键、外键和唯一约束。
|
||
- 模块树、字段列表和个人权限所需索引。
|
||
- `XACT_ABORT ON` 和显式事务。
|
||
- `IF NOT EXISTS`,保证脚本可以重复执行。
|
||
- 不删除、不修改任何已有业务表。
|
||
|
||
### 初始化数据
|
||
|
||
初始化:
|
||
|
||
| 模块 | 类型 | 路由 |
|
||
| --- | --- | --- |
|
||
| `m_system` | `directory` | - |
|
||
| `m_module` | `page` | `/system/modules` |
|
||
|
||
为 `m_module` 初始化按钮:
|
||
|
||
```text
|
||
create 新增模块
|
||
update 修改模块
|
||
delete 删除模块
|
||
grant 用户授权
|
||
```
|
||
|
||
根据明确的管理员账号从 `b_user` 取得用户雪花 ID,写入该用户的 `b_user_module` 和四项 `b_user_power`。找不到管理员时终止初始化,不能默认给所有用户授权。
|
||
|
||
### 执行和验证
|
||
|
||
- 从 `g3hd.properties` 读取连接信息,密码不打印到日志。
|
||
- 使用 PowerShell `.NET SqlClient` 执行脚本(本机旧版 `sqlcmd` 无法完成 TLS 握手)。
|
||
- 执行前确认目标为 `118.89.70.199:1433 / fms`。
|
||
- 连续执行两次,第二次不得重复建表或重复初始化。
|
||
- 查询 SQL Server 系统表核对字段、约束、外键和索引。
|
||
|
||
## 第二阶段:登录用户信息
|
||
|
||
当前 JWT 使用登录账号,新权限表使用 `b_user.b_id`,需要调整:
|
||
|
||
- 登录时同时保留用户雪花 ID、账号和姓名。
|
||
- JWT 继续使用账号作为会话标识。
|
||
- 登录响应返回 `id`、`account` 和 `name`。
|
||
|
||
本阶段不修改通用查询和保存接口的请求格式,也不在后端执行模块权限校验。
|
||
|
||
## 第三阶段:使用通用接口完成数据闭环
|
||
|
||
### 数据加载
|
||
|
||
页面通过现有接口加载:
|
||
|
||
| 数据 | 接口 | 数据源 |
|
||
| --- | --- | --- |
|
||
| 模块树 | `/data/loaddata` | `s_module` |
|
||
| 模块字段 | `/data/loaddata` | `s_module_field` |
|
||
| 操作权限定义 | `/data/loaddata` | `s_module_power` |
|
||
| 多语言 | `/data/loaddata` | `b_i18n` |
|
||
| 删除依赖检查 | `/data/loaddata` | `b_user_module`、`b_user_power` |
|
||
|
||
配置数据量较小,模块、字段和操作权限可以一次加载后在前端按 `b_module_id` 分组,减少来回请求。
|
||
|
||
### 雪花 ID
|
||
|
||
新增以下数据前调用 `/data/nextid`:
|
||
|
||
- `s_module_field.b_id`
|
||
- `s_module_power.b_id`
|
||
- `b_i18n.b_id`
|
||
- `s_module.b_id`
|
||
|
||
`s_module.b_id` 使用不可变雪花 ID;可修改的小写模块编码保存在 `s_module.b_code`。
|
||
|
||
### 模块保存
|
||
|
||
前端维护服务器快照和编辑副本,计算 inserts、updates、deletes,然后一次调用 `/data/saveobjt` 保存:
|
||
|
||
```text
|
||
s_module
|
||
s_module_field
|
||
s_module_power
|
||
b_i18n
|
||
```
|
||
|
||
通用保存请求示意:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"table": "s_module",
|
||
"key_field": "b_id",
|
||
"updates": []
|
||
},
|
||
{
|
||
"table": "s_module_field",
|
||
"key_field": "b_id",
|
||
"inserts": [],
|
||
"updates": [],
|
||
"deletes": []
|
||
}
|
||
]
|
||
```
|
||
|
||
前端保存前校验:
|
||
|
||
- 模块代码使用小写字母、数字和下划线,且在模块间唯一。
|
||
- 父节点存在且不会形成循环。
|
||
- 目录、页面、数据模块字段组合合法。
|
||
- 同一模块字段名和按钮编码不重复。
|
||
- 表名、视图名和字段名只允许合法数据库标识符。
|
||
|
||
数据库外键和唯一约束负责最后兜底,任一表失败时由现有 `DataSaveService` 回滚整个请求。
|
||
|
||
### 模块删除
|
||
|
||
- `m_system` 和 `m_module` 在前端禁止删除。
|
||
- 存在下级模块时禁止删除。
|
||
- 普通模块删除时,一次 `/data/saveobjt` 按依赖顺序删除:
|
||
|
||
```text
|
||
b_user_power
|
||
b_user_module
|
||
s_module_power
|
||
s_module_field
|
||
b_i18n
|
||
s_module
|
||
```
|
||
|
||
## 第四阶段:将 Demo 改为真实页面
|
||
|
||
### 页面结构
|
||
|
||
路由由 `/demo/modules` 改为 `/system/modules`,删除“前端原型”标识和 mock 数据。
|
||
|
||
建议拆分:
|
||
|
||
```text
|
||
views/module-management/ModuleManagementView.vue
|
||
views/module-management/components/ModuleTreePanel.vue
|
||
services/moduleManagement.js
|
||
```
|
||
|
||
`services/moduleManagement.js` 只组合现有 `loadDataApi`、`saveObjectApi` 和 `nextIdApi`,不增加新的后端地址。
|
||
|
||
### 页面功能
|
||
|
||
- 左侧模块树支持搜索、新增目录和新增模块。
|
||
- 左侧模块树只保留单个新增菜单,不直接显示目录、页面、数据三个按钮。
|
||
- 模块管理界面只区分目录和普通模块:目录使用独立表单,新增目录使用 Dialog。
|
||
- 页面模块和数据模块共用普通模块编辑器;配置页面路由时保存为 `page`,否则保存为 `data`,不直接编辑模块类型。
|
||
- 基本信息、字段、操作权限和多语言全部读取真实数据库。
|
||
- 字段、操作权限和多语言内容区独立滚动,页面外层不随数据量滚动。
|
||
- 字段和操作权限采用点击行进入编辑、离开行退出编辑的单行编辑方式。
|
||
- 字段名称支持在字段行内快速维护多语言文本。
|
||
- 增加保存、取消和删除操作,当前阶段不显示未保存提示。
|
||
- 保存失败时保留编辑内容并显示后端错误。
|
||
- 字段编码、操作权限编码和模块代码使用明确的表单校验。
|
||
- 删除字段、操作权限和模块使用确认框。
|
||
- 修复 Demo 菜单预览使用不存在 `id` 作为 Vue key 的问题。
|
||
- 保存成功后重新加载模块树和当前模块。
|
||
|
||
### 菜单
|
||
|
||
`AppSidebar` 通过现有通用查询接口读取当前用户的 `b_user_module` 和可用的 `s_module`,在前端构建菜单树。
|
||
|
||
- 只显示 `b_canmenu = 1`、`b_canuse = 1` 且用户有权限的页面。
|
||
- 上级目录根据可访问下级页面自动显示。
|
||
- 路由组件仍由前端白名单注册,数据库路由不能动态加载任意组件文件。
|
||
- 通用接口加载失败时保留现有静态菜单作为降级。
|
||
|
||
### 前端权限
|
||
|
||
- 数据型路由通过 `meta.dataCode` 声明核心数据编码,权限仓库根据数据节点的 `b_parent_id` 解析页面权限;尚未配置数据节点的系统页面暂时兼容 `meta.moduleCode`。
|
||
- 用户没有 `b_user_module` 记录时禁止进入对应页面。
|
||
- 页面操作根据 `b_user_power` 中的 `create`、`update`、`delete` 权限禁用。
|
||
- 本阶段不改通用后端接口,也不做后端权限拦截;后端校验后续单独实施。
|
||
|
||
## 第五阶段:测试与验收
|
||
|
||
### 后端
|
||
|
||
- JWT 能正确取得用户雪花 ID。
|
||
- 多表保存失败时整体回滚。
|
||
- 非法表名和字段名被现有通用接口拒绝,权限引用由数据库外键约束兜底。
|
||
- `bigint` 仍以字符串返回前端。
|
||
|
||
### 前端
|
||
|
||
- 模块、字段、操作权限和多语言可以新增、修改、删除并刷新恢复。
|
||
- 模块树搜索、切换和取消操作正常。
|
||
- 加载失败、保存失败和空状态显示正确。
|
||
|
||
### G3HD 验收
|
||
|
||
1. 使用管理员账号登录 G3HD。
|
||
2. 进入 `/system/modules`。
|
||
3. 新建临时模块,配置两个字段和新增、修改、删除操作权限。
|
||
4. 保存并刷新,确认所有配置重新加载。
|
||
5. 删除临时模块,确认相关明细和已有个人权限全部清理。
|
||
|
||
## 完成标准
|
||
|
||
- 六张表已建立在 `g3hd.properties` 指向的新数据库。
|
||
- 页面不再依赖 `moduleDemo.js`。
|
||
- 没有新增模块管理专用后端接口。
|
||
- 所有查询、保存、取号均复用现有通用接口。
|
||
- 模块、字段、操作权限和多语言可以真实保存并重新加载。
|
||
- 模块管理页面不提供用户授权功能。
|
||
- 前端权限控制正常。
|