用 VITE_MOCK_* 系列环境变量替换全局 VITE_USE_MOCK,各模块独立控制演示数据 启用,并新增 src/utils/mock-flags.ts 统一解析缺省值。文档库关闭演示库时 如实提示接口待接入,避免静默沿用本地数据或覆盖已保存内容。
8.8 KiB
8.8 KiB
用户与权限接口核验与接入说明
核验基准:本机后端
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. 仍需后端确认或前端后续补齐的事项
- OpenAPI 给出了权限资源和动作枚举,但没有给出完整的权限编码初始化清单。前端目前使用已存在于权限目录 Mock/约定中的
system:user:query做用户页菜单与路由门控;system:user:create、system:user:update、system:user:disable、角色及权限关系的最终编码需要以后端权限中心实际数据为准。 - 当前页面已经能分配角色 API 权限,但 API 权限目录本身的新增、编辑、停用尚未做独立管理页面;对应 API 封装已存在。
- 后端提供了
POST /api/v1/auth/password/change,当前只完成请求类型和 API 封装,尚未在本轮新增强制改密弹窗。passwordChangeRequired已保留在登录和当前用户模型中,产品若要求登录后强制改密,应补充全局改密流程。 - 导入任务契约当前状态为
PREVIEWED、COMMITTED、EXPIRED、FAILED;如果未来改为真正异步处理,应在后端扩展状态和前端轮询策略,不能由前端猜测完成状态。 - 所有管理接口仍必须由后端执行
401/403、数据范围、角色/权限状态和审计校验。前端隐藏菜单或按钮只改善体验,不能作为安全边界。
5. 联调验收
真实接口模式:
VITE_MOCK_USERS=false npm run dev
至少验证以下场景:
- 登录后 Network 中所有业务请求带
X-Token,并能看到一次/api/v1/auth/me; - 用户详情显示后端角色名称,编辑角色后刷新列表仍保持;
LOCKED用户显示为锁定而不是启用;- 未修改脱敏联系方式时编辑不会覆盖原值,清空时发送清除标记;
- 重置密码不出现在任何响应、列表或前端日志;
- 导入存在错误时不能提交,零错误预览才允许提交并显示任务号;
- 角色 API 权限保存后重新读取,确认
permissionIds是完整替换结果; - 模板权限可选择单个用户,直接权限可删除,继承权限保持不可删除;
- 无用户查询权限的账号不能通过菜单或直接 URL进入用户页,后端
403仍是最终判断。
6. 验证命令
本轮修改后应在 clinical-web 目录执行:
npm run lint
npm run format:check
npx vue-tsc --noEmit
npm run build -- --outDir /tmp/clinical-web-build-<date>