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

3.7 KiB
Raw Permalink Blame History

6.1 用户管理

:::tip 概述 用户模块(goframe_user,租户级表)是机制最全的模块:唯一校验(按行现租户)、租户用户上限、角色全量重写、城市编解码、Excel 导入导出、数据权限接线、批量名称回填。路由前缀 /api/user。 :::

接口清单

方法 路由 权限 说明
GET /api/user/page sys:user:page 分页(关键词/状态/部门/角色/职级/岗位筛选)
GET /api/user/list sys:user:list 全量列表(下拉选择用)
GET /api/user/detail/:id sys:user:detail 详情(含角色 ID 数组与四级区划编码)
POST /api/user/add sys:user:add 新增(返回新记录 ID)
PUT /api/user/update sys:user:update 修改(密码留空不改)
PUT /api/user/status sys:user:status 状态切换
PUT /api/user/resetPwd sys:user:resetPwd 重置密码(logType=reset)
DELETE /api/user/delete/:id sys:user:delete 软删(清理 user_role)
DELETE /api/user/batchDelete sys:user:batchDelete 批量删除
POST /api/user/import sys:user:import Excel 导入
GET /api/user/export sys:user:export Excel 导出
GET /api/user/document/:id sys:user:detail 打印信息

核心机制

唯一校验(手写,按行现租户)

usernameExists / mobileExists 按 (username|mobile, tenant_id, 排除自身) 查;
Update 时先读被改行的 tenant_id 再校验——校验范围必须等于
uk_tenant_username / uk_tenant_mobile 索引范围(含 del_flag 由 dao.Ctx 恒过滤保证)。

历史教训:用 GetTenantID(超管=默认租户)会漏报 1062——必须按行现租户。

角色同步(AssignRoles)

AssignRoles(userId, roleIds):全量重写 user_role(先删后插)
  → clearIdentityCache(userId)
Add/Update 均经此方法;Update 改 dept_id 也在该路径清缓存——部门变更即时生效
(数据权限无需等 300s 缓存过期)

租户用户上限(checkTenantUserMax)

统计租户现有用户数 vs tenant.max_user_num,超限返回 1007。在 user.Add 生效。

用户编码(genUserCode)

前缀=租户 code(平台/超管为 "SYS"),序号=该租户现有用户数+1
格式 "{prefix}-%06d",如 T0001-000001

数据权限接线

userSpec 声明 DataScope: ApplyDataScope("dept_id")——user 是当前唯一接线模块(全库仅 user 表有 dept_id 列)。

列表名称回填(userExpandNames)

列表行批量补 dept/level/position/role 名称与城市文本(namesById/dictName 批查防 N+1)。

导入导出

Import(POST /api/user/import):
  excel.ReadSheet → 表头映射 → 逐行:唯一校验 / 租户上限 / 默认密码 bcrypt
  (事务外预计算)/ 角色与城市解析 → 批量插入 → 返回成功/失败统计
  城市列经 ResolveCityCodes(名称串) 转编码入库

Export(GET /api/user/export):
  与列表同筛选(userFilter + DataScope,applyFilters 同链)
  → ChunkQuery 500/页 → excel.WriteSheet
  导出可见集 = 列表可见集(导出=所见)

城市编解码接入

Add/Update/Import/Detail 均接入包级函数:写侧 ResolveCityCodes(名称串 → 四级编码入库),读侧 ResolveCityNames(编码 → 名称还原)。机制见 6.9 行政区划管理。

字段与安全边界

password/salt:bcrypt 双重加盐;接口永不返回
密码留空 = 不修改(Update 语义)
删除守卫:userDeleteGuard / 关联清理(user_role)
SerializeMaps:status → user_status({field}Text 字典填充)
FileFields: avatar + FileSaveDir: "user"(两段式上传自动转正)