Files
2026-10-20 21:19:44 +08:00

3.3 KiB
Raw Permalink Blame History

6.15 首页与个人中心

:::tip 概述 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(当前用户信息)

数据来源与安全边界:
  * 用户行经 dao.User.Ctx(自动过滤软删/租户);password/salt 永不返回
  * Roles/Perms 优先取 JWT 中间件注入的 ctx(与鉴权同源),为空时回源 LoadIdentity
  * 超管强制 perms=["*:*:*"](前端据此放开全部按钮)
  * 头像经 upload.GetFileUrl 补域名
  * 城市编码四列(province/city/district/street_code)组装为 city[] 数组;
    city_info 为空时用 ResolveCityNames 按编码回填名称

GetMenus(菜单树)

两条路由共用 getMenuTree:
  * 仅取 type=0(目录/菜单)且 status=0 且 hide=0 的节点
    ——按钮权限节点不进菜单树,由 GetUser.permissions 下发
  * 超管全量;其余 user→user_role→role_menu→menu.id IN(...) 授权过滤
  * 无角色返回空树([] 非 null)
  * 挂树规则:父节点不在授权集合内(未授权/顶级)一律挂根,避免菜单丢失
  * 排序 sort,id(根级再按 sort+id 兜底稳定排序)

UpdatePassword(修改密码)

流程:
  1) 只取 id/password/salt 三列
  2) 旧密码 IsBcrypt + VerifyPassword 校验(错误 1012 原密码错误)
  3) 事务外 GenerateSalt + HashPassword(CPU 密集预计算)
  4) Update 覆盖 password/salt(update_user/time 由 hooks 盖章)

注意:改密后未强制下线(令牌仍有效至过期);
     如需立即失效可配合在线用户强退(见 6.16 在线用户监控)

UpdateProfile(更新个人信息)

流程:
  * 头像 SaveFileField(avatar, "user") 临时转正
  * 城市优先由编码数组经 ResolveCityNames 解析名称覆盖 city_info
  * 四列编码经 cityCodeAt(req.City, i) 取值写入
安全边界:不触达 username/password/tenant 等敏感列

前端消费

登录后首页 dashboard:调 getUser(头像/名称/权限)+ getMenus(侧边菜单)
路由守卫:动态路由由 getMenus 生成(见 9.5 路由与动态菜单)
个人中心页:updateProfile(资料)/ updatePassword(改密)

排障

症状 原因
菜单为空 无角色或角色未勾选菜单;超管应返回全量
getUser 权限缺失 身份缓存异常;超管应返回 *:*:*
改密后旧令牌仍可用 设计预期(不强制下线);配合在线用户强退
头像不显示 upload.GetFileUrl 域名配置(file.domainUrl)与静态服务根