# 6.13 租户管理 :::tip 概述 租户模块(goframe_tenant,平台级表)管理多租户生命周期:状态/过期、用户上限、事务化开户(Account,code 按 T+ID 规则回填)。隔离机制详见 [5.8 多租户隔离](../core/tenant)。 ::: ## 接口清单 | 方法 | 路由 | 权限 | 说明 | |------|------|------|------| | GET | /api/tenant/page | sys:tenant:page | 分页(平台专属视图,带用户数统计) | | GET | /api/tenant/list | sys:tenant:list | 列表 | | GET | /api/tenant/detail/:id | sys:tenant:detail | 详情 | | POST | /api/tenant/add | sys:tenant:add | 新增 | | PUT | /api/tenant/update | sys:tenant:update | 修改 | | PUT | /api/tenant/status | sys:tenant:status | 状态切换 | | DELETE | /api/tenant/delete/:id | sys:tenant:delete | 软删 | | DELETE | /api/tenant/batchDelete | sys:tenant:batchDelete | 批量删除 | | POST | /api/tenant/account | sys:tenant:add | 创建租户账号(开户) | | GET | /api/tenant/users/:tenantId | sys:tenant:users | 查询租户用户 | ## 编码规则(T%04d,自增 ID 回填) ```text code 为 NOT NULL + 唯一键,插入时无法预知 ID → 1) 先写临时占位编码(T%010d,纳秒取模防撞) 2) Insert 后按 LastInsertId 修正为 "T"+4 位ID(如 T0001) Add 与 Account 均遵循此模式;显式传 code 时查重后直接使用不回填 ``` ## 开户事务(tenant.Account,真实流程) ```text bcrypt 在事务外预计算(短事务纪律)→ WithTrans 内三段原子写: ① Insert 租户(status=1,hooks 填审计列) ② 修正 code = T%04d(tenantId) ③ 以 tenantCtx(WithTenantID(txCtx, tenantId))Insert 初始管理员: code = "{code}-000001"(首用户序号),tenant_id 显式传入, password/salt 为预计算值 返回 {tenantId, code, userId} 角色分配未含在开户事务内(按需另行调用) 事务纪律:事务内不做 HTTP/文件 IO,bcrypt 等 CPU 计算事务外预计算 ``` ## 状态与缓存 ```text tenantFilter:列表为平台专属视图(超管可见全部,带每租户用户数统计) fillUserCount:每租户用户数(对照 max_user_num 判断容量) clearCache:状态/过期变更后 Del tenant:info:{id} (Tenant 中间件 60s 摘要缓存——变更后最多 60s 生效,Del 后即时生效) ``` ## 关联约束 + 用户数上限:user.Add 的 checkTenantUserMax 对照 max_user_num(1007) + 租户用户列表:GET /api/tenant/users/:tenantId + 租户删除前应清空/迁移该租户用户与业务数据(软删租户不级联) ## 管理建议 + expire_time 为 nil 表示永不过期;到期前 30 天关注续期 + max_user_num 控制容量;调大即时生效(user.Add 实时校验) + 禁用租户(status=2)立即拦截该租户全部用户请求(等 60s 缓存或 Del 即时) + 开户后记得为初始管理员分配角色(Account 不含角色分配)