Files
rxthinkcmf-wiki/RXThinkCMF_ThinkPhp8_AntdVue/zh/modules/tenant.md
T
2026-09-29 10:14:04 +08:00

214 lines
6.9 KiB
Markdown

# 6.13 租户管理
:::tip 概述
租户管理是多租户体系的核心,支持租户的 CRUD、创建租户账号、查看租户用户。继承 BaseLogic(系统共享,租户表本身不隔离)。
:::
## 模块特点
| 特性 | 说明 |
|------|------|
| 基类 | BaseLogic(系统共享,租户表不隔离) |
| 特殊接口 | account(创建租户账号)、users(查看租户用户) |
| 删除校验 | beforeDelete 检查用户数 + 保护默认租户 |
| 编码生成 | afterAdd 自动生成租户编码(T+4位ID) |
| 状态校验 | TenantMiddleware 校验租户状态和过期时间 |
## API 接口
| 方法 | 路径 | 权限码 | 说明 |
|------|------|--------|------|
| GET | `/api/tenant/page` | sys:tenant:page | 分页列表 |
| GET | `/api/tenant/list` | sys:tenant:list | 全量列表 |
| GET | `/api/tenant/detail/:id` | sys:tenant:detail | 详情 |
| GET | `/api/tenant/users/:tenantId` | - | 租户用户列表 |
| POST | `/api/tenant/add` | sys:tenant:add | 新增租户 |
| POST | `/api/tenant/account` | sys:tenant:add | 创建租户账号 |
| PUT | `/api/tenant/update` | sys:tenant:update | 修改租户 |
| DELETE | `/api/tenant/delete/:id` | sys:tenant:delete | 删除租户 |
| DELETE | `/api/tenant/batchDelete` | sys:tenant:batchDelete | 批量删除 |
## 核心代码
```php
// app/logic/TenantLogic.php
class TenantLogic extends BaseLogic
{
/**
* 关联的模型类
*
* @var string
*/
protected string $modelClass = Tenant::class;
/**
* LIKE 模糊匹配字段
*
* @var array
*/
protected array $pageLikeFields = ['name', 'code', 'contact'];
/**
* 精确匹配字段
*
* @var array
*/
protected array $pageEqFields = ['status'];
/**
* 默认排序规则
*
* @var array
*/
protected array $pageOrderBy = ['field' => 'id', 'type' => 'desc'];
/**
* 枚举显示名映射
*
* @var array
*/
protected array $serializeMaps = ['status' => 'tenant_status'];
/**
* 修改前处理:禁止修改编码
*
* @param int $id 租户 ID
* @param array $data 待更新的数据
* @return array 过滤后的数据
*/
protected function beforeUpdate(int $id, array $data): array
{
// 租户编码由系统自动生成(T+4位ID),不允许手动修改
unset($data['code']);
return $data;
}
/**
* 新增后处理:自动生成租户编码
*
* @param int $id 新增的租户 ID
* @param array $data 新增时提交的原始数据
* @return void
*/
protected function afterAdd(int $id, array $data): void
{
// 编码格式:T + 4位ID左补零,如 T0001、T0002;因为依赖自增ID,所以在新增完成后回写
$code = 'T' . str_pad((string)$id, 4, '0', STR_PAD_LEFT);
Tenant::where('id', $id)->update(['code' => $code]);
}
/**
* 删除前处理:保护默认租户 + 检查用户数
*
* @param int $id 待删除的租户 ID
* @return void
* @throws \Exception 当为默认租户或存在用户时抛出
*/
protected function beforeDelete(int $id): void
{
// 默认租户不可删除
if ($id == 1) {
throw new \Exception('默认租户不可删除');
}
$userCount = User::where('tenant_id', $id)->where('is_delete', 0)->count();
if ($userCount > 0) {
throw new \Exception('该租户下存在用户,不可删除');
}
}
/**
* 列表查询后处理:批量补充租户用户数
*
* @param array &$records 记录列表(引用传递)
* @param array $params 查询参数
* @return void
*/
protected function afterPageList(array &$records, array $params): void
{
if (empty($records)) return;
// 一次性查询当前页所有租户的用户数量,避免 N+1
$tenantIds = array_column($records, 'id');
$counts = User::where('is_delete', 0)
->whereIn('tenant_id', $tenantIds)
->group('tenant_id')
->column('count(*)', 'tenant_id');
foreach ($records as &$record) {
$record['userCount'] = $counts[$record['id']] ?? 0;
}
}
}
```
### 列表返回 userCount
`/api/tenant/page` 和 `/api/tenant/list` 接口返回的每条记录中自动包含 `userCount` 字段,表示该租户下的用户数量。
:::tip 实现方式
通过 `BaseLogic::afterPageList` 钩子实现,使用 `whereIn` + `group` 批量查询,避免 N+1 问题。
:::
### 创建租户账号
```php
// TenantLogic::createAccount()
// 处理流程:
// 1. 校验租户存在 + 用户数限制
// 2. 注入租户ID,调用 UserLogic::add() 完成标准创建
// (含编码自动生成、密码加密、头像处理、角色关联)
```
:::tip 用户编码由 UserLogic 统一生成
创建租户账号时不再由 TenantLogic 直接生成用户编码,
而是通过 UserLogic::beforeAdd 统一生成,确保所有用户创建路径(直接添加、租户账号、导入)编码规则一致。
:::
:::warning 默认租户保护
默认租户(id=1)不可删除,编码不可修改。超级管理员(tenant_id=0)不受租户隔离限制,创建租户隔离数据时自动代入默认租户(tenant_id=1)。详见 [多租户隔离](/zh/core/tenant.html)。
:::
## 套餐化角色预置
系统内置三套租户角色模板,分配不同的菜单权限,用于按套餐等级快速授权:
| 角色名称 | 定位 | 菜单范围 |
|----------|------|----------|
| 租户-标准版 | 基础功能 | 核心业务模块 |
| 租户-专业版 | 进阶功能 | 核心 + 高级模块 |
| 租户-旗舰版 | 全功能 | 全部菜单(最全) |
**使用方式:** 创建租户后,通过「角色管理 → 授权菜单」为对应角色分配菜单权限。创建租户管理员账号时,选择对应套餐角色即可完成授权。
:::tip 设计意图
套餐角色解决了"每个租户都要手动配一遍菜单"的重复工作。管理员创建租户时只需选择套餐,角色权限即刻生效。
:::
## 演示数据
系统内置一组演示数据,可直接登录体验多租户效果:
### 平台级
| 账号 | 密码 | 角色 | 说明 |
|------|------|------|------|
| admin | 123456 | 超级管理员 | 平台管理,可管理所有租户 |
### 租户级
| 账号 | 密码 | 所属租户 | 角色 | 说明 |
|------|------|----------|------|------|
| tenant001 | 123456 | 客户租户A | 租户管理员 | 可体验租户视角的功能与数据隔离 |
:::warning 演示环境注意
以上账号仅用于开发和演示环境,生产环境部署后请立即修改密码或删除演示数据。
:::
## 租户状态
| 字段 | 说明 |
|------|------|
| `status` | 0=禁用 1=启用 |
| `expire_time` | 过期时间,过期后 TenantMiddleware 返回 403 |
| `max_user_num` | 最大用户数限制 |