创建租户改为事务化一站式操作:自动复制 gdlib 权限模板 + 补充基础管理权限, 创建 tenant_admin 角色和管理员用户,支持自定义账号密码。 前端表单增加管理员输入区块,成功弹窗展示凭据并支持一键复制。 同步实现 menuIds 菜单分配(消除原 TODO)。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
161 lines
5.6 KiB
Markdown
161 lines
5.6 KiB
Markdown
# 租户创建自动生成管理员账号 — 设计方案
|
||
|
||
> 所属端:超管端
|
||
> 状态:已完成
|
||
> 创建日期:2026-04-02
|
||
> 最后更新:2026-04-02
|
||
|
||
---
|
||
|
||
## 1. 背景与问题
|
||
|
||
超管端创建新租户(机构)后,需要**手动**到用户管理页面另行创建该租户的管理员账号、角色、权限,流程割裂且容易遗漏,导致新建的租户无法登录使用。
|
||
|
||
核心问题:
|
||
- 创建租户与创建管理员是分离的两步操作,缺乏原子性
|
||
- 新租户没有默认角色和权限,管理员账号无法正常使用
|
||
- 菜单分配(menuIds)也未实现(后端标记为 TODO)
|
||
|
||
## 2. 现状分析
|
||
|
||
### 2.1 创建租户接口
|
||
|
||
- `POST /api/tenants` → `SysTenantServiceImpl.createTenant()`
|
||
- 仅创建 `t_sys_tenant` 记录,不创建用户、角色、权限、菜单关联
|
||
- menuIds 参数存在但未处理(TODO 注释)
|
||
|
||
### 2.2 初始化脚本的做法
|
||
|
||
`backend/scripts/init-dev-tenants.ts`(Node 版,已移除)中,创建租户时会一并完成:
|
||
1. 创建租户 → 2. 创建权限 → 3. 创建角色 → 4. 角色绑定权限 → 5. 创建 admin 用户 → 6. 用户绑定角色 → 7. 分配菜单
|
||
|
||
`init.sql` 中每个租户也都有对应的 admin 用户和角色。
|
||
|
||
### 2.3 涉及的数据表
|
||
|
||
| 表名 | 说明 |
|
||
|------|------|
|
||
| `t_sys_tenant` | 租户 |
|
||
| `t_sys_user` | 用户 |
|
||
| `t_sys_role` | 角色 |
|
||
| `t_sys_permission` | 权限(按租户隔离) |
|
||
| `t_sys_user_role` | 用户-角色关联 |
|
||
| `t_sys_role_permission` | 角色-权限关联 |
|
||
| `t_sys_tenant_menu` | 租户-菜单关联 |
|
||
|
||
## 3. 设计方案
|
||
|
||
### 3.1 整体思路
|
||
|
||
创建租户时在同一事务中自动完成:创建租户 → 复制权限模板 → 创建管理员角色 → 创建管理员用户 → 绑定关联关系 → 分配菜单。接口返回租户信息 + 管理员凭据。
|
||
|
||
### 3.2 权限模板策略
|
||
|
||
- **模板来源**:运行时从广东省图租户(code=`gdlib`,tenant_id=9)复制权限,该租户拥有 26 项业务权限,覆盖活动、报名、评审、作品、公告等核心模块
|
||
- **补充基础管理权限**:模板中缺少的 7 项基础权限自动补充:
|
||
- `user:update`、`user:delete` — 用户管理
|
||
- `role:create`、`role:update`、`role:delete`、`role:assign` — 角色管理
|
||
- `permission:read` — 权限查看
|
||
- 新租户最终获得 **33 项权限**(26 模板 + 7 补充)
|
||
|
||
### 3.3 前端页面设计
|
||
|
||
**创建表单改动**:
|
||
- 基本信息 Tab 增加「管理员账号」区块(用分割线分隔)
|
||
- 新增两个输入框:管理员账号(默认 admin)、管理员密码(默认 admin@{编码})
|
||
- 仅新建时显示,编辑时隐藏
|
||
|
||
**成功弹窗改动**:
|
||
- 原先:提示"创建成功"+ 跳转用户管理页按钮
|
||
- 现在:展示管理员账号、初始密码、登录地址
|
||
- 新增「复制账号信息」按钮,一键复制全部信息到剪贴板
|
||
|
||
### 3.4 后端改动
|
||
|
||
**`CreateTenantDto`** — 新增字段:
|
||
- `adminUsername`(String,可选,默认 "admin")
|
||
- `adminPassword`(String,可选,默认 "admin@{tenantCode}")
|
||
|
||
**`ISysTenantService.createTenant()`** — 返回值改为 `Map<String, Object>`
|
||
|
||
**`SysTenantServiceImpl.createTenant()`** — 核心改动,事务内完成 7 步:
|
||
1. 创建租户记录
|
||
2. `copyTemplatePermissions()` — 复制 gdlib 权限 + 补充基础权限
|
||
3. 创建 `tenant_admin` 角色
|
||
4. 批量绑定角色-权限
|
||
5. 创建管理员用户(密码 BCrypt 加密)
|
||
6. 绑定用户-角色
|
||
7. 处理 menuIds 菜单分配
|
||
|
||
新增私有方法 `copyTemplatePermissions(Long newTenantId)`:
|
||
- 查询 gdlib 租户的全部权限,逐条复制(替换 tenantId)
|
||
- 对比已有权限编码,补充缺失的基础管理权限
|
||
|
||
**`SysTenantServiceImpl.updateTenant()`** — 同步实现 menuIds 更新(先删后增)
|
||
|
||
**`SysTenantController.create()`** — 返回类型从 `Result<SysTenant>` 改为 `Result<Map<String, Object>>`
|
||
|
||
### 3.5 接口响应格式
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"tenant": {
|
||
"id": 13,
|
||
"name": "测试图书馆",
|
||
"code": "test-lib",
|
||
"tenantType": "library",
|
||
...
|
||
},
|
||
"admin": {
|
||
"username": "libadmin",
|
||
"password": "Lib@2026",
|
||
"userId": 32,
|
||
"nickname": "测试图书馆管理员"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.6 前端改动
|
||
|
||
**`src/api/tenants.ts`**:
|
||
- `CreateTenantForm` 新增 `adminUsername`、`adminPassword`
|
||
- 新增 `CreateTenantResult` 接口
|
||
- `createTenant()` 返回类型改为 `CreateTenantResult`
|
||
|
||
**`src/views/system/tenants/Index.vue`**:
|
||
- 表单 reactive 新增 `adminUsername`、`adminPassword`
|
||
- 模板增加管理员输入区块
|
||
- 成功弹窗展示管理员信息卡片 + 复制按钮
|
||
- 移除 `useRouter`、`useAuthStore` 无用依赖
|
||
|
||
## 4. 改动范围
|
||
|
||
### 后端(Java)
|
||
|
||
| 操作 | 文件 |
|
||
|------|------|
|
||
| 修改 | `modules/sys/dto/CreateTenantDto.java` |
|
||
| 修改 | `modules/sys/service/ISysTenantService.java` |
|
||
| 修改 | `modules/sys/service/impl/SysTenantServiceImpl.java` |
|
||
| 修改 | `modules/sys/controller/SysTenantController.java` |
|
||
|
||
### 前端
|
||
|
||
| 操作 | 文件 |
|
||
|------|------|
|
||
| 修改 | `src/api/tenants.ts` |
|
||
| 修改 | `src/views/system/tenants/Index.vue` |
|
||
|
||
## 5. 实施记录
|
||
|
||
### 2026-04-02 — 初版实现
|
||
|
||
- 完成后端事务化创建租户 + 管理员 + 角色 + 权限 + 菜单分配
|
||
- 权限模板使用 gdlib 租户(26项)+ 7项基础管理权限补充
|
||
- 前端表单增加管理员账号/密码输入,成功弹窗展示凭据信息
|
||
- 测试验证:创建租户 → 管理员登录成功 → 获得 97 项权限(含 gdlib 完整业务权限 + 补充权限)
|
||
- 同步实现了 `updateTenant` 的 menuIds 更新(消除 TODO)
|