用 VITE_MOCK_* 系列环境变量替换全局 VITE_USE_MOCK,各模块独立控制演示数据 启用,并新增 src/utils/mock-flags.ts 统一解析缺省值。文档库关闭演示库时 如实提示接口待接入,避免静默沿用本地数据或覆盖已保存内容。
97 lines
8.8 KiB
Markdown
97 lines
8.8 KiB
Markdown
# 用户与权限接口核验与接入说明
|
||
|
||
> 核验基准:本机后端 `http://127.0.0.1:18080/v3/api-docs`(接口前缀为 `/api`)。浏览器请求仍统一使用 `/api`,认证请求头为 `X-Token`。
|
||
|
||
## 1. 核验结论
|
||
|
||
后端当前已经提供用户、角色、API 权限关系和模板权限所需的主要接口。前端原实现的主要问题不是代理地址,而是把已经存在的接口误判为缺失,导致角色显示、密码重置、批量导入和角色权限分配没有真正接通。
|
||
|
||
本轮已完成以下接入:
|
||
|
||
- 用户列表和详情正确映射后端 `LOCKED` 状态、角色摘要、院区/科室名称、版本号和首次改密标记;
|
||
- 新增用户提交 `roleIds`,编辑用户使用聚合管理接口完整替换资料和角色,并提交 `expectedVersion`;
|
||
- 角色卡片改用 `GET /api/v1/roles/summary` 获取服务端人数统计;
|
||
- 重置密码使用 `POST /api/v1/users/{userId}/password/reset`,前端校验 12 位密码并支持下次登录改密;
|
||
- 批量导入使用预览、确认提交和任务查询三段流程,不展示或记录密码、手机号和邮箱;
|
||
- 用户与角色的 API 权限分配使用 `GET/PUT /api/v1/roles/{roleId}/permissions`,不再把权限目录 CRUD 当成关系接口;
|
||
- 模板文档权限页支持 `USER` 授权对象,可对单个用户增加或删除模板权限;
|
||
- 登录后的受保护路由会刷新 `/api/v1/auth/me`,用户页菜单和路由至少按 `system:user:query` 做体验层门控,最终权限仍由后端校验。
|
||
|
||
## 2. 后端契约与前端映射
|
||
|
||
| 页面能力 | 后端接口 | 前端状态 | 关键约束 |
|
||
| -------------- | ------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------- |
|
||
| 用户列表 | `GET /api/v1/users` | 已接入 | `page` 从 1 开始,`size` 传后端分页参数;支持 `keyword`、`campusId` |
|
||
| 用户详情 | `GET /api/v1/users/{id}` | 已接入 | 角色从 `roles` 摘要映射为角色名称和 ID |
|
||
| 新增用户 | `POST /api/v1/users` | 已接入 | `username`、`password`、`displayName`、`campusId` 必填;密码至少 8 位;可传 `roleIds` |
|
||
| 编辑用户资料 | `PUT /api/v1/users/{id}` | API 已封装 | 不接收用户名和密码;支持 `clearPhone`、`clearEmail`、`expectedVersion` |
|
||
| 编辑用户与角色 | `PUT /api/v1/users/{id}/management` | 已接入 | 一次提交资料、数据范围和完整 `roleIds`;使用版本号避免覆盖并发修改 |
|
||
| 读取用户角色 | `GET /api/v1/users/{userId}/roles` | API 已封装 | 返回角色摘要、关系版本和更新时间 |
|
||
| 覆盖用户角色 | `PUT /api/v1/users/{userId}/roles` | API 已封装 | `roleIds` 是完整替换集合,可选 `expectedVersion` |
|
||
| 停用用户 | `DELETE /api/v1/users/{id}` | 已接入 | 后端语义为软停用,前端保留二次确认 |
|
||
| 重置密码 | `POST /api/v1/users/{userId}/password/reset` | 已接入 | `newPassword` 至少 12 位;响应不返回密码 |
|
||
| 导入预览 | `POST /api/v1/users/import/preview` | 已接入 | `multipart/form-data`,字段为 `file`,可选默认 `campusId` |
|
||
| 确认导入 | `POST /api/v1/users/import/commit` | 已接入 | 仅提交预览返回的 `importId`;预览存在错误时前端禁止提交 |
|
||
| 导入任务 | `GET /api/v1/users/import/jobs/{jobId}` | 已接入 | 展示服务端任务状态,不把文件内容写入日志 |
|
||
| 角色分页 | `GET /api/v1/roles` | 已接入 | `RoleResponse` 不含 `userCount`,只用于角色选项和基础信息 |
|
||
| 角色人数 | `GET /api/v1/roles/summary` | 已接入 | 人数由服务端统计,支持可选 `campusId` |
|
||
| API 权限目录 | `GET/POST/PUT/DELETE /api/v1/permissions` | API 已封装 | 这是权限定义目录,不是角色关系 |
|
||
| 角色 API 权限 | `GET/PUT /api/v1/roles/{roleId}/permissions` | 已接入 | `permissionIds` 完整替换,可选 `expectedVersion` |
|
||
| 当前用户 | `GET /api/v1/auth/me` | 已接入 | 刷新 `permissions`、角色、数据范围和 `passwordChangeRequired` |
|
||
| 模板权限 | `GET/POST/DELETE /api/v1/templates/{templateId}/permissions` | 已接入 | `subjectType` 支持 `ROLE`、`DEPARTMENT`、`USER`;继承记录不可直接删除 |
|
||
|
||
## 3. 重要 DTO 规则
|
||
|
||
### 3.1 用户状态和并发版本
|
||
|
||
后端用户状态为 `ENABLED`、`DISABLED`、`LOCKED`。此前前端把除 `DISABLED` 外的所有值都当成启用,已修复为三态映射;锁定用户不能建立会话,不能仅按“停用”展示。
|
||
|
||
用户编辑响应带有 `version`。聚合编辑会将该版本作为 `expectedVersion` 提交,服务端返回并发冲突时前端不会自行覆盖新数据。
|
||
|
||
### 3.2 脱敏联系方式
|
||
|
||
详情可能返回脱敏手机号或邮箱。前端未修改脱敏字段时不回传该字段;用户明确清空时才提交 `clearPhone: true` 或 `clearEmail: true`。完整手机号、邮箱和密码不写入日志或审计展示。
|
||
|
||
### 3.3 批量导入
|
||
|
||
预览响应只包含行号、校验状态、错误、用户名和姓名,不包含手机号、邮箱或密码。前端只有在 `invalidRows === 0` 时才启用确认按钮,提交后展示 `jobId` 和服务端状态。
|
||
|
||
## 4. 仍需后端确认或前端后续补齐的事项
|
||
|
||
1. OpenAPI 给出了权限资源和动作枚举,但没有给出完整的权限编码初始化清单。前端目前使用已存在于权限目录 Mock/约定中的 `system:user:query` 做用户页菜单与路由门控;`system:user:create`、`system:user:update`、`system:user:disable`、角色及权限关系的最终编码需要以后端权限中心实际数据为准。
|
||
2. 当前页面已经能分配角色 API 权限,但 API 权限目录本身的新增、编辑、停用尚未做独立管理页面;对应 API 封装已存在。
|
||
3. 后端提供了 `POST /api/v1/auth/password/change`,当前只完成请求类型和 API 封装,尚未在本轮新增强制改密弹窗。`passwordChangeRequired` 已保留在登录和当前用户模型中,产品若要求登录后强制改密,应补充全局改密流程。
|
||
4. 导入任务契约当前状态为 `PREVIEWED`、`COMMITTED`、`EXPIRED`、`FAILED`;如果未来改为真正异步处理,应在后端扩展状态和前端轮询策略,不能由前端猜测完成状态。
|
||
5. 所有管理接口仍必须由后端执行 `401/403`、数据范围、角色/权限状态和审计校验。前端隐藏菜单或按钮只改善体验,不能作为安全边界。
|
||
|
||
## 5. 联调验收
|
||
|
||
真实接口模式:
|
||
|
||
```bash
|
||
VITE_MOCK_USERS=false npm run dev
|
||
```
|
||
|
||
至少验证以下场景:
|
||
|
||
- 登录后 Network 中所有业务请求带 `X-Token`,并能看到一次 `/api/v1/auth/me`;
|
||
- 用户详情显示后端角色名称,编辑角色后刷新列表仍保持;
|
||
- `LOCKED` 用户显示为锁定而不是启用;
|
||
- 未修改脱敏联系方式时编辑不会覆盖原值,清空时发送清除标记;
|
||
- 重置密码不出现在任何响应、列表或前端日志;
|
||
- 导入存在错误时不能提交,零错误预览才允许提交并显示任务号;
|
||
- 角色 API 权限保存后重新读取,确认 `permissionIds` 是完整替换结果;
|
||
- 模板权限可选择单个用户,直接权限可删除,继承权限保持不可删除;
|
||
- 无用户查询权限的账号不能通过菜单或直接 URL进入用户页,后端 `403` 仍是最终判断。
|
||
|
||
## 6. 验证命令
|
||
|
||
本轮修改后应在 `clinical-web` 目录执行:
|
||
|
||
```bash
|
||
npm run lint
|
||
npm run format:check
|
||
npx vue-tsc --noEmit
|
||
npm run build -- --outDir /tmp/clinical-web-build-<date>
|
||
```
|