6.15 首页与个人中心
概述
index 模块(无表,聚合 user/menu)提供个人中心五接口:当前用户信息(超管返回通配权限)、菜单树、修改密码、更新个人信息。路由前缀 /api/index,登录即可(无 permission 节点)。
接口清单
| 方法 | 路由 | 权限 | 说明 |
|---|---|---|---|
| GET | /api/index/getUser | 登录即可 | 当前用户信息(超管返回 *:*:*) |
| GET | /api/index/getMenus | 登录即可 | 当前用户菜单树(前端 common 菜单调用) |
| GET | /api/index/getMenus/:id | 登录即可 | 同上(system/menu 页面调用) |
| PUT | /api/index/updatePassword | 登录即可 | 修改个人密码(旧密码校验) |
| PUT | /api/index/updateProfile | 登录即可 | 更新个人信息 |
GetUser(当前用户信息)
text
数据来源与安全边界:
* 用户行经 dao.User.Ctx(自动过滤软删/租户);password/salt 永不返回
* Roles/Perms 优先取 JWT 中间件注入的 ctx(与鉴权同源),为空时回源 LoadIdentity
* 超管强制 perms=["*:*:*"](前端据此放开全部按钮)
* 头像经 upload.GetFileUrl 补域名
* 城市编码四列(province/city/district/street_code)组装为 city[] 数组;
city_info 为空时用 ResolveCityNames 按编码回填名称GetMenus(菜单树)
text
两条路由共用 getMenuTree:
* 仅取 type=0(目录/菜单)且 status=0 且 hide=0 的节点
——按钮权限节点不进菜单树,由 GetUser.permissions 下发
* 超管全量;其余 user→user_role→role_menu→menu.id IN(...) 授权过滤
* 无角色返回空树([] 非 null)
* 挂树规则:父节点不在授权集合内(未授权/顶级)一律挂根,避免菜单丢失
* 排序 sort,id(根级再按 sort+id 兜底稳定排序)UpdatePassword(修改密码)
text
流程:
1) 只取 id/password/salt 三列
2) 旧密码 IsBcrypt + VerifyPassword 校验(错误 1012 原密码错误)
3) 事务外 GenerateSalt + HashPassword(CPU 密集预计算)
4) Update 覆盖 password/salt(update_user/time 由 hooks 盖章)
注意:改密后未强制下线(令牌仍有效至过期);
如需立即失效可配合在线用户强退(见 6.16 在线用户监控)UpdateProfile(更新个人信息)
text
流程:
* 头像 SaveFileField(avatar, "user") 临时转正
* 城市优先由编码数组经 ResolveCityNames 解析名称覆盖 city_info
* 四列编码经 cityCodeAt(req.City, i) 取值写入
安全边界:不触达 username/password/tenant 等敏感列前端消费
text
登录后首页 dashboard:调 getUser(头像/名称/权限)+ getMenus(侧边菜单)
路由守卫:动态路由由 getMenus 生成(见 9.5 路由与动态菜单)
个人中心页:updateProfile(资料)/ updatePassword(改密)排障
| 症状 | 原因 |
|---|---|
| 菜单为空 | 无角色或角色未勾选菜单;超管应返回全量 |
| getUser 权限缺失 | 身份缓存异常;超管应返回 *:*:* |
| 改密后旧令牌仍可用 | 设计预期(不强制下线);配合在线用户强退 |
| 头像不显示 | upload.GetFileUrl 域名配置(file.domainUrl)与静态服务根 |