一、超管端设计优化 - 文档管理SOP体系建立,docs目录重组 - 统一用户管理:跨租户全局视角,合并用户管理+公众用户 - 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作) - 菜单精简:移除评委管理/评审规则/通知管理 - Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一 二、UGC绘本创作社区P0 - 数据库:10张新表(user_works/user_work_pages/work_tags等) - 子女账号独立化:Child升级为独立User,家长切换+独立登录 - 用户作品库:CRUD+发布审核,8个API - AI创作流程:提交→生成→保存到作品库,4个API - 作品广场:首页改造为推荐流,标签+搜索+排序 - 内容审核(超管端):作品审核+作品管理+标签管理 - 活动联动:WorkSelector作品选择器 - 布局改造:底部5Tab(发现/创作/活动/作品库/我的) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.9 KiB
5.9 KiB
租户登录使用指南
概述
系统已完整支持多租户登录功能,每个租户可以独立访问系统,数据完全隔离。
租户识别方式
系统支持以下方式识别租户:
1. URL参数方式(推荐)
在登录页面URL中添加 tenant 参数:
http://your-domain.com/login?tenant=tenant-a
登录页面会自动识别租户编码,并在登录时自动发送。
2. 登录表单输入
如果URL中没有租户参数,登录页面会显示租户编码输入框,用户可以手动输入。
3. 请求头方式
前端会自动将租户信息添加到所有API请求的请求头中:
X-Tenant-Code: 租户编码X-Tenant-Id: 租户ID
使用流程
方式一:通过URL参数访问(推荐)
-
访问租户登录页面
http://your-domain.com/login?tenant=tenant-a -
输入用户名和密码
- 用户名:租户内的用户名
- 密码:用户密码
- 租户编码:已自动填充(从URL参数)
-
登录成功
- 系统自动保存租户信息到 localStorage
- 后续所有API请求都会自动携带租户信息
- 用户只能看到和操作自己租户的数据
方式二:手动输入租户编码
-
访问登录页面
http://your-domain.com/login -
输入租户信息
- 租户编码:输入租户编码(如:
tenant-a) - 用户名:租户内的用户名
- 密码:用户密码
- 租户编码:输入租户编码(如:
-
登录成功
- 系统保存租户信息
- 后续请求自动携带租户信息
后端API使用
登录接口
请求:
POST /api/auth/login
Content-Type: application/json
{
"username": "user1",
"password": "password123",
"tenantCode": "tenant-a" // 可选,也可以从请求头获取
}
或者通过请求头:
POST /api/auth/login
X-Tenant-Code: tenant-a
Content-Type: application/json
{
"username": "user1",
"password": "password123"
}
响应:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"username": "user1",
"nickname": "用户1",
"email": "user1@example.com",
"tenantId": 2,
"tenantCode": "tenant-a",
"roles": ["admin"],
"permissions": ["user:read", "user:create", ...]
}
}
其他API请求
登录后,所有API请求都会自动携带租户信息(通过JWT Token或请求头),后端会自动过滤数据:
GET /api/users
Authorization: Bearer <token>
X-Tenant-Code: tenant-a # 自动添加
返回的数据只会包含该租户的用户。
前端实现细节
1. 登录页面自动识别租户
登录页面 (Login.vue) 会:
- 从URL参数
?tenant=xxx获取租户编码 - 如果URL中没有,从 localStorage 读取之前保存的租户编码
- 如果都没有,显示租户输入框
2. 请求拦截器自动添加租户信息
所有API请求都会自动添加租户信息到请求头:
// utils/request.ts
service.interceptors.request.use((config) => {
const tenantCode = getTenantCode();
const tenantId = getTenantId();
if (tenantCode) {
config.headers['X-Tenant-Code'] = tenantCode;
}
if (tenantId) {
config.headers['X-Tenant-Id'] = tenantId;
}
return config;
});
3. 登录后保存租户信息
登录成功后,系统会自动保存:
- Token
- 租户编码 (tenantCode)
- 租户ID (tenantId)
这些信息保存在 localStorage 中,页面刷新后仍然有效。
示例场景
场景1:租户A的用户登录
- 访问:
http://your-domain.com/login?tenant=tenant-a - 输入用户名和密码
- 登录后只能看到租户A的数据
场景2:租户B的用户登录
- 访问:
http://your-domain.com/login?tenant=tenant-b - 输入用户名和密码
- 登录后只能看到租户B的数据
- 租户A的数据完全不可见
场景3:超级租户管理员登录
- 访问:
http://your-domain.com/login?tenant=super - 使用超级管理员账号登录
- 可以管理所有租户
注意事项
- 租户编码必须唯一:每个租户都有唯一的编码(code)
- 用户属于特定租户:用户只能登录到自己所属的租户
- 数据完全隔离:不同租户的数据完全隔离,无法互相访问
- 租户信息持久化:登录后租户信息保存在 localStorage,刷新页面不会丢失
- 切换租户:如果需要切换租户,需要先登出,然后使用新的租户编码登录
故障排查
问题1:登录时提示"无法确定租户信息"
原因:没有提供租户编码或租户ID
解决:
- 在URL中添加
?tenant=xxx参数 - 或者在登录表单中输入租户编码
- 或者通过请求头
X-Tenant-Code提供
问题2:登录时提示"用户不属于该租户"
原因:用户不属于指定的租户
解决:
- 确认租户编码是否正确
- 确认用户是否属于该租户
- 联系管理员检查用户和租户的关联关系
问题3:登录后看不到数据
原因:可能是租户信息没有正确传递
解决:
- 检查浏览器控制台的网络请求,确认请求头中是否包含
X-Tenant-Code - 检查 localStorage 中是否保存了租户信息
- 确认后端是否正确识别了租户
开发建议
- 使用URL参数方式:这是最用户友好的方式,用户只需要记住租户的访问链接
- 提供租户选择器:如果系统需要支持租户切换,可以在前端添加租户选择器
- 错误提示优化:当租户信息缺失时,提供清晰的错误提示
- 租户信息显示:在用户界面显示当前租户信息,让用户知道自己在哪个租户下操作