3133 lines
143 KiB
Markdown
3133 lines
143 KiB
Markdown
# SaaS 多租户平台需求文档
|
||
|
||
> 版本:v3.6.0
|
||
> 最后更新:2026-06-03
|
||
|
||
---
|
||
|
||
# Part 1:平台架构与基础设施
|
||
|
||
---
|
||
|
||
## 1. 概述
|
||
|
||
### 1.1 背景
|
||
|
||
FastapiAdmin 是一个基于 FastAPI + SQLAlchemy 的管理后台框架,需要支持 SaaS 多租户模式。平台提供完善的多租户隔离和授权体系,包含平台管理端、套餐体系、租户独立授权、插件系统、工单系统等能力。
|
||
|
||
### 1.2 核心目标
|
||
|
||
1. **数据隔离**:不同租户间的业务数据严格隔离,通过 `tenant_id` 行级过滤实现
|
||
2. **权限分层**:平台层(菜单/套餐/插件)→ 租户层(可见菜单/配额/配置)→ 用户层(角色/数据权限)
|
||
3. **灵活授权**:通过套餐体系预设权限 + 自定义授权相结合,简化租户开通流程
|
||
4. **资源管控**:租户配额管理(用户数/角色数/存储空间等)防止资源滥用
|
||
|
||
### 1.3 角色定义
|
||
|
||
| 角色 | 说明 | 租户范围 |
|
||
|------|------|---------|
|
||
| **超级管理员 (Super Admin)** | 平台拥有者,管理所有租户和套餐,不受租户过滤 | 平台 |
|
||
| **租户管理员 (Tenant Admin)** | 被指定为租户的 owner/admin,管理租户内部资源 | 单个租户 |
|
||
| **租户用户 (Tenant User)** | 普通业务用户,使用租户内的功能 | 单个租户 |
|
||
|
||
### 1.4 模块总览
|
||
|
||
| 模块 | 类型 | 租户隔离 | 核心用途 |
|
||
|------|------|---------|---------|
|
||
| Auth | 系统 | 无 | 登录认证、OAuth、JWT |
|
||
| User | 系统 | ✅ TenantMixin | 用户管理、角色/岗位分配 |
|
||
| Role | 系统 | ✅ TenantMixin | 角色定义、菜单/部门权限分配 |
|
||
| Dept | 系统 | ✅ TenantMixin | 树形部门管理 |
|
||
| Position | 系统 | ✅ TenantMixin | 岗位管理 |
|
||
| Menu | 系统 | **无** | 平台菜单树(纯平台资源) |
|
||
| Dict | 系统 | ✅ TenantMixin(平台共享) | 字典类型+数据 |
|
||
| Notice | 系统 | ✅ TenantMixin | 通知公告 |
|
||
| Params | 系统 | ✅ TenantMixin | 系统参数配置 |
|
||
| LoginLog | 平台 | **无** | 登录日志(平台级) |
|
||
| OperationLog | 系统 | ✅ TenantMixin | 操作日志(租户级) |
|
||
| Tenant | 平台 | **无**(自身为租户定义) | 租户管理 |
|
||
| Package | 平台 | **无** | 套餐管理 |
|
||
| Ticket | 系统 | ✅ TenantMixin | 工单反馈 |
|
||
| Plugin | 平台 | **无**(平台资源) | 插件注册表 |
|
||
| Cronjob | 插件 | ✅ TenantMixin | 定时任务 |
|
||
| Workflow | 插件 | ✅ TenantMixin | 工作流引擎 |
|
||
| AI Chat | 插件 | ✅ TenantMixin | AI 对话 |
|
||
| CodeGen | 插件 | ✅ TenantMixin | 代码生成器 |
|
||
| Invoice | 平台 | **无**(关联 order) | 发票管理(普票/专票) |
|
||
| AuditLog | 平台 | **无** | 审计日志(不可篡改) |
|
||
| Dashboard | 平台 | **无** | 运营数据大盘 |
|
||
|
||
---
|
||
|
||
## 2. 平台架构
|
||
|
||
### 2.1 整体架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ Controller 层 │
|
||
│ 路由定义 / 参数校验 / 响应封装 / 操作日志 │
|
||
├─────────────────────────────────────────────────┤
|
||
│ Service 层 │
|
||
│ 业务逻辑编排 / 数据校验 / 权限检查 │
|
||
├─────────────────────────────────────────────────┤
|
||
│ CRUD 层 │
|
||
│ CRUDBase 通用增删改查 / 租户过滤 / 权限过滤 │
|
||
├─────────────────────────────────────────────────┤
|
||
│ Model 层 │
|
||
│ SQLAlchemy ORM / Mixin 体系 / 关系定义 │
|
||
├─────────────────────────────────────────────────┤
|
||
│ DB (MySQL/PgSQL/SQLite) │ Redis 缓存 │
|
||
└─────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 2.2 请求链路
|
||
|
||
```
|
||
请求 → Middleware链 → 租户中间件(解析token,设置ContextVar) →
|
||
路由匹配 → 依赖注入(DI) → Controller → Service → CRUD →
|
||
ORM(自动注入tenant_id) → DB → 反向响应 → ContextVar清理
|
||
```
|
||
|
||
### 2.3 模块目录结构
|
||
|
||
每个业务模块遵循统一结构:
|
||
|
||
```
|
||
module_xxx/
|
||
├── __init__.py
|
||
├── controller.py # API 路由定义
|
||
├── service.py # 业务逻辑
|
||
├── crud.py # 数据操作(继承 CRUDBase)
|
||
├── model.py # SQLAlchemy 模型
|
||
└── schema.py # Pydantic 请求/响应模型
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 数据隔离模型
|
||
|
||
### 3.1 核心设计原则
|
||
|
||
```
|
||
平台资源(无 tenant_id)
|
||
├── platform_menu ← 菜单定义,纯平台资源
|
||
├── platform_package ← 套餐定义
|
||
├── platform_plugin ← 插件注册表
|
||
└── platform_tenant ← 租户定义
|
||
|
||
租户资源(含 tenant_id,ORM 自动过滤)
|
||
├── sys_user ← 用户
|
||
├── sys_role ← 角色
|
||
├── sys_dept ← 部门
|
||
├── sys_position ← 岗位
|
||
├── sys_notice ← 通知公告
|
||
├── sys_param ← 系统参数
|
||
├── sys_log ← 日志
|
||
├── platform_ticket ← 工单
|
||
└── 插件业务表
|
||
|
||
平台共享资源(tenant_id=1 的平台数据对所有租户可读)
|
||
├── sys_dict_type ← 字典类型
|
||
└── sys_dict_data ← 字典数据
|
||
```
|
||
|
||
### 3.2 三层隔离机制
|
||
|
||
| 层级 | 实现文件 | 机制说明 |
|
||
|------|---------|---------|
|
||
| **ORM 事件层** | `tenant_filter.py` | SQLAlchemy `do_orm_execute` 事件自动注入 `WHERE tenant_id = ?` |
|
||
| **CRUD 层** | `base_crud.py` | `__build_conditions` / `__tenant_condition` 二次确认 |
|
||
| **权限策略层** | `permission.py` | 基于角色 `data_scope` 字段精细化控制 |
|
||
|
||
#### ORM 事件层行为
|
||
|
||
| 操作 | 超管 | 普通用户 |
|
||
|------|------|---------|
|
||
| SELECT | 不过滤 | 自动追加 `WHERE tenant_id = ?`(`__platform_data_shared__` 模型跳过此层过滤,由 CRUD 层处理) |
|
||
| INSERT | 不自动设置 | 自动设置 `tenant_id = 当前租户` |
|
||
| UPDATE/DELETE | 不过滤 | 自动追加 `WHERE tenant_id = ?` |
|
||
| 系统表(platform_tenant) | 不过滤 | 不过滤 |
|
||
|
||
> **⚠️ 特别注意**:标记了 `__platform_data_shared__ = True` 的模型(DictType/DictData),ORM 事件层**跳过**自动 tenant_id 过滤,由 CRUD 层的 `__tenant_condition(read_mode=True)` 统一处理 `WHERE tenant_id = current OR tenant_id = 1` 逻辑。防止 ORM 事件层覆盖了"平台共享"读取策略。
|
||
|
||
#### 权限策略层
|
||
|
||
| 策略 | 枚举值 | 说明 | 适用模型 |
|
||
|------|--------|------|---------|
|
||
| `ROLE_BASED` | 1 | 仅显示用户角色授权的数据 | Menu |
|
||
| `DEPT_BASED` | 2 | 基于部门范围过滤 | Dept |
|
||
| `USER_ROLE` | 3 | 仅显示用户绑定的角色 | Role |
|
||
| `SELF_ONLY` | 4 | 仅本人数据 | 预留 |
|
||
| `DATA_SCOPE` | 5 | 基于 data_scope 字段 | Tenant(通用) |
|
||
|
||
#### data_scope 数据范围
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| 1 | 仅本人数据 |
|
||
| 2 | 本部门数据 |
|
||
| 3 | 本部门及以下数据 |
|
||
| 4 | 全部数据 |
|
||
| 5 | 自定义数据(通过 sys_role_depts 指定可见部门) |
|
||
|
||
### 3.3 Mixin 体系
|
||
|
||
```
|
||
MappedBase (声明式基类)
|
||
├── ModelMixin (id, uuid, status, description, 时间戳, 软删除)
|
||
├── TenantMixin (tenant_id FK → platform_tenant.id, NOT NULL, default=1, ON DELETE RESTRICT)
|
||
└── UserMixin (created_id, updated_id, deleted_id FK → sys_user)
|
||
```
|
||
|
||
#### ModelMixin 通用字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | Integer PK AI | 主键 |
|
||
| `uuid` | String(64) UNIQUE | UUID 全局唯一标识 |
|
||
| `status` | Integer | default=0 | 状态(0:启动 1:停用) |
|
||
| `description` | Text nullable | 备注/描述 |
|
||
| `created_time` | DateTime | 创建时间 |
|
||
| `updated_time` | DateTime | 更新时间(onupdate) |
|
||
| `is_deleted` | Boolean default=False | 软删除标记 |
|
||
| `deleted_time` | DateTime nullable | 删除时间 |
|
||
|
||
#### __platform_data_shared__ 机制
|
||
|
||
标记了 `__platform_data_shared__ = True` 的模型(DictType/DictData),在 CRUD 层查询时:
|
||
- 超管:不过滤,可查看/修改所有租户的数据
|
||
- 普通用户:`WHERE tenant_id = current_tenant_id OR tenant_id = 1`
|
||
|
||
---
|
||
|
||
# Part 2:核心业务模块需求
|
||
|
||
---
|
||
|
||
## 4. Auth 认证模块
|
||
|
||
### 4.1 业务描述
|
||
|
||
提供用户认证、授权、会话管理功能,支持多种登录方式(密码登录、OAuth2 第三方登录),支持验证码安全校验。
|
||
|
||
### 4.2 业务流程
|
||
|
||
```
|
||
登录请求 → 验证码校验(启用时) → 用户认证(用户名+密码) →
|
||
检查用户状态 → 更新最后登录时间 → 查询用户关联租户列表 →
|
||
判断租户数量:
|
||
├── 单租户: 直接生成 JWT(含 tenant_id) → 返回 token
|
||
└── 多租户: 生成临时 JWT(不含 tenant_id, 仅限调用 /auth/select-tenant) →
|
||
返回 租户选择 token + 租户列表 →
|
||
用户选择 → /auth/select-tenant/{id} → 生成含 tenant_id 的正式 token
|
||
记录在线会话 → 返回正式 token
|
||
```
|
||
|
||
> **多租户登录说明**:
|
||
> - **临时 token**(不含 tenant_id):仅能调用 `POST /auth/select-tenant/{id}`,其他任何接口均返回 403
|
||
> - **正式 token**(含 tenant_id):正常访问所有已授权的 API
|
||
> - 超管用户跳过租户选择,直接生成含 `is_super_admin=True` 的正式 token(不绑定任何 tenant_id)
|
||
|
||
### 4.3 核心规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **验证码** | 配置控制是否启用,API 文档请求(docs/redoc)跳过验证码 |
|
||
| **密码校验** | Bcrypt 哈希比对 |
|
||
| **状态检查** | 用户 status="1"(禁用)时拒绝登录 |
|
||
| **JWT 载荷** | 包含 session_id, user_id, tenant_id, is_super_admin, 登录信息 |
|
||
| **Token 刷新** | refresh_token 专用,不可用 access_token 刷新 |
|
||
| **多租户登录** | 登录后判断:单租户用户直接签发含 tenant_id 的正式 token;多租户用户签**临时 token**(不含 tenant_id,仅可访问 `POST /auth/select-tenant/{id}`),选择租户后签正式 token |
|
||
| **在线记录** | 登录成功后 Redis 记录在线会话,含 IP/OS/浏览器/登录位置 |
|
||
| **日志记录** | 操作日志路由类自动记录登录日志 |
|
||
|
||
### 4.4 数据模型
|
||
|
||
无独立数据表,使用 Redis 存储会话和验证码。
|
||
|
||
### 4.5 用户自助注册
|
||
|
||
```
|
||
POST /auth/register
|
||
├── 接收:username, password, email, tenant_name(可选)
|
||
├── 校验:用户名/邮箱唯一性
|
||
├── 创建租户记录(platform_tenant)
|
||
│ ├── name = tenant_name 或 "{username}的租户"(默认名)
|
||
│ ├── code = 自动生成(基于 name 拼音首字母 + 4位随机数)
|
||
│ ├── package_id → 取全局默认套餐(platform_package.is_default=true 的第一条,若无则 id=1)
|
||
│ ├── end_time = now + trial_days(取套餐的 trial_days,默认 7 天)
|
||
│ ├── max_users/max_roles/max_depts → 取套餐配额默认值(见 §16.2)
|
||
│ └── status = 0(active)
|
||
├── 创建用户记录(sys_user,tenant_id=新租户ID)
|
||
├── 创建 owner 角色(sys_role,code="owner")
|
||
├── 将用户绑定到 owner 角色
|
||
├── 将租户可用菜单全量分配给 owner 角色
|
||
└── 返回注册成功(用户需邮箱验证后激活)
|
||
```
|
||
|
||
> **默认套餐获取优先级**:套餐 `is_default=true` > id=1 > 无套餐(仅自定义菜单)。若平台未配置任何套餐,新租户仅有自定义菜单体系,需超管后续手动配置。
|
||
|
||
### 4.6 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/auth/login` | 登录(多租户用户返回临时 token + 租户列表) |
|
||
| POST | `/auth/token/refresh` | 刷新 token |
|
||
| POST | `/auth/logout` | 退出登录(清除 Redis 会话) |
|
||
| GET | `/auth/captcha` | 获取验证码(Base64 图片) |
|
||
| POST | `/auth/register` | 用户注册(创建用户 → 自动创建默认租户并设为 owner) |
|
||
| POST | `/auth/select-tenant/{id}` | 选择/切换租户(生成含 tenant_id 的正式 token) |
|
||
| POST | `/auth/forgot-password` | 忘记密码(发送重置邮件) |
|
||
| GET | `/auth/auto-login/{token}` | 免登录(用于邮件/消息免登链接) |
|
||
| GET | `/auth/oauth/{provider}/login` | OAuth2 授权跳转 |
|
||
| GET | `/auth/oauth/{provider}/callback` | OAuth2 回调处理(需用户预绑定第三方账号;首次 OAuth 登录不绑定租户,需选择/创建租户) |
|
||
|
||
---
|
||
|
||
## 5. User 用户模块
|
||
|
||
### 5.1 业务描述
|
||
|
||
管理平台和租户下的用户账号,支持角色分配、岗位分配、部门归属、密码管理、Excel 导入导出。用户数据按租户严格隔离。
|
||
|
||
### 5.2 数据模型
|
||
|
||
**表名**:`sys_user`(TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `username` | String(64) | NOT NULL, UNIQUE(tenant_id) | 用户名/登录账号 |
|
||
| `password` | String(255) | NOT NULL | Bcrypt 密码哈希 |
|
||
| `name` | String(32) | NOT NULL | 昵称/姓名 |
|
||
| `mobile` | String(11) | nullable | 手机号 |
|
||
| `email` | String(64) | nullable | 邮箱 |
|
||
| `gender` | String(1) | default="2" | 性别(0:男 1:女 2:未知) |
|
||
| `avatar` | String(255) | nullable | 头像 URL |
|
||
| `is_superuser` | Boolean | default=False | 是否超级管理员 |
|
||
| `last_login` | DateTime | nullable | 最后登录时间 |
|
||
| `dept_id` | FK→sys_dept.id | nullable, ON DELETE SET NULL | 所属部门 |
|
||
| `gitee_login` | String(32) | nullable | Gitee 第三方登录 |
|
||
| `github_login` | String(32) | nullable | Github 第三方登录 |
|
||
| `wx_login` | String(32) | nullable | 微信第三方登录 |
|
||
| `qq_login` | String(32) | nullable | QQ 第三方登录 |
|
||
|
||
**关联关系**:
|
||
|
||
| 关联表 | 关系类型 | 说明 |
|
||
|--------|---------|------|
|
||
| `sys_user_roles` | 多对多 | 用户 ↔ 角色 |
|
||
| `sys_user_positions` | 多对多 | 用户 ↔ 岗位 |
|
||
| `platform_user_tenant` | 多对多 | 用户 ↔ 租户(跨租户支持) |
|
||
|
||
### 5.3 业务规则
|
||
|
||
| 类别 | 规则 |
|
||
|------|------|
|
||
| **创建** | username 字母开头、3~32位;不允许创建超管;username/mobile/email 唯一 |
|
||
| **修改** | 不可修改超管;username/mobile/email 唯一性检查;部门必须存在且可用 |
|
||
| **删除** | 仅已禁用(status=1)用户可删除;不可删除超管;不可删除当前登录用户 |
|
||
| **密码** | Bcrypt 加密存储;修改需验证原密码;重置不可操作超管 |
|
||
| **导入导出** | 支持 Excel 导入导出;导入时密码字段处理策略:密码列为空 → 系统自动生成12位随机密码并通过邮件发送给用户;密码列有值 → Bcrypt 加密后存储,首次登录强制修改密码 |
|
||
| **状态** | 批量启用/禁用;不可操作超管 |
|
||
|
||
### 5.4 当前用户菜单权限
|
||
|
||
```
|
||
get_current_user_info_service:
|
||
├── 超管 → 返回全部 PC 端菜单(type=1/2/4, client=pc)
|
||
└── 普通用户:
|
||
├── 收集角色菜单 ID(角色→菜单,去重)
|
||
├── 与租户可用菜单取交集
|
||
└── 构建菜单树返回
|
||
```
|
||
|
||
### 5.5 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/user/detail/{id}` | 用户详情 |
|
||
| GET | `/user/list` | 用户列表 |
|
||
| POST | `/user/create` | 创建用户 |
|
||
| PUT | `/user/update/{id}` | 更新用户 |
|
||
| DELETE | `/user/delete` | 删除用户(批量) |
|
||
| PATCH | `/user/status/batch` | 批量设置用户状态 |
|
||
| GET | `/user/current/info` | 获取当前用户信息(含菜单树) |
|
||
| PUT | `/user/current/update` | 更新当前用户信息 |
|
||
| PUT | `/user/current/password/change` | 修改密码(本人操作,需验证原密码) |
|
||
| PUT | `/user/password/reset` | 重置密码(管理员操作,跳过原密码) |
|
||
| POST | `/user/import` | 导入用户(Excel) |
|
||
| POST | `/user/export` | 导出用户(Excel) |
|
||
|
||
---
|
||
|
||
## 6. Role 角色模块
|
||
|
||
### 6.1 业务描述
|
||
|
||
角色是权限分配的核心载体,每个角色可绑定多个菜单(功能权限)和多个部门(数据权限)。角色数据按租户严格隔离。
|
||
|
||
### 6.2 数据模型
|
||
|
||
**表名**:`sys_role`(TenantMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(64) | NOT NULL | 角色名称 |
|
||
| `code` | String(64) | NOT NULL, UNIQUE(tenant_id) | 角色编码 |
|
||
| `order` | Integer | default=999 | 显示排序 |
|
||
| `data_scope` | Integer | default=1 | 数据权限范围(1~5) |
|
||
|
||
**关联关系**:
|
||
|
||
| 关联表 | 关系类型 | 说明 |
|
||
|--------|---------|------|
|
||
| `sys_role_menus` | 多对多 | 角色 ↔ 菜单 |
|
||
| `sys_role_depts` | 多对多 | 角色 ↔ 部门(仅 data_scope=5 时使用) |
|
||
| `sys_user_roles` | 多对多 | 用户 ↔ 角色 |
|
||
|
||
### 6.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **编码规则** | 字母开头,仅含字母/数字/下划线 |
|
||
| **租户唯一** | (tenant_id, code) 唯一约束 |
|
||
| **权限策略** | `USER_ROLE` — 非超管用户只能看到自己绑定的角色 |
|
||
| **菜单约束** | 非超管只能为角色分配租户可用菜单内的菜单,越权时抛出异常含菜单名称 |
|
||
| **数据范围** | 1=仅本人 2=本部门 3=本部门及以下 4=全部 5=自定义(绑定部门) |
|
||
| **默认 owner 角色** | 创建租户时自动创建 code="owner" 的角色,不可删除、不可禁用。自动分配租户全部可用菜单 |
|
||
|
||
### 6.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/role/detail/{id}` | 角色详情 |
|
||
| GET | `/role/list` | 角色列表 |
|
||
| POST | `/role/create` | 创建角色 |
|
||
| PUT | `/role/update/{id}` | 更新角色 |
|
||
| DELETE | `/role/delete` | 删除角色(批量) |
|
||
| PATCH | `/role/status/batch` | 批量设置角色状态 |
|
||
| PUT | `/role/menus` | 设置角色菜单 |
|
||
| PUT | `/role/permission` | 设置角色权限(含数据范围+部门) |
|
||
|
||
---
|
||
|
||
## 7. Dept 部门模块
|
||
|
||
### 7.1 业务描述
|
||
|
||
部门是组织架构的核心,采用树形结构支持无限层级。部门数据按租户严格隔离。
|
||
|
||
### 7.2 数据模型
|
||
|
||
**表名**:`sys_dept`(TenantMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(64) | NOT NULL | 部门名称 |
|
||
| `code` | String(64) | NOT NULL, UNIQUE(tenant_id, code) | 部门编码 |
|
||
| `parent_id` | Integer FK | nullable | 父级部门 |
|
||
| `order` | Integer | default=999 | 显示排序 |
|
||
| `leader` | String(32) | nullable | 负责人 |
|
||
| `phone` | String(20) | nullable | 联系电话 |
|
||
| `email` | String(128) | nullable | 邮箱 |
|
||
|
||
### 7.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **树形结构** | parent_id 自引用,支持无限层级。创建/更新 parent_id 时需检测循环引用 |
|
||
| **编码规则** | 字母开头,仅含字母/数字/下划线 |
|
||
| **租户唯一** | (tenant_id, code) 唯一约束 |
|
||
| **权限策略** | `DEPT_BASED` — 基于部门范围过滤 |
|
||
| **删除约束** | 有子部门的父部门不可删除 |
|
||
| **状态级联** | 父部门禁用时子部门同步禁用(业务层实现) |
|
||
|
||
### 7.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/dept/detail/{id}` | 部门详情 |
|
||
| GET | `/dept/list` | 部门列表(树形) |
|
||
| POST | `/dept/create` | 创建部门 |
|
||
| PUT | `/dept/update/{id}` | 更新部门 |
|
||
| DELETE | `/dept/delete` | 删除部门(批量) |
|
||
| PATCH | `/dept/status/batch` | 批量设置部门状态 |
|
||
|
||
---
|
||
|
||
## 8. Position 岗位模块
|
||
|
||
### 8.1 业务描述
|
||
|
||
岗位用于定义用户在组织内的职务角色,一个用户可绑定多个岗位。
|
||
|
||
### 8.2 数据模型
|
||
|
||
**表名**:`sys_position`(TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(64) | NOT NULL | 岗位名称 |
|
||
| `order` | Integer | default=1 | 显示排序 |
|
||
|
||
### 8.3 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/position/detail/{id}` | 岗位详情 |
|
||
| GET | `/position/list` | 岗位列表 |
|
||
| POST | `/position/create` | 创建岗位 |
|
||
| PUT | `/position/update/{id}` | 更新岗位 |
|
||
| DELETE | `/position/delete` | 删除岗位(批量) |
|
||
| PATCH | `/position/status/batch` | 批量设置岗位状态 |
|
||
|
||
---
|
||
|
||
## 9. Menu 菜单模块
|
||
|
||
### 9.1 业务描述
|
||
|
||
菜单是系统功能权限的基础定义单元,属于**平台级资源**(无 tenant_id),由超级管理员统一管理。菜单以树形结构组织,支撑前端动态路由和后端权限控制。
|
||
|
||
### 9.2 数据模型
|
||
|
||
**表名**:`platform_menu`(ModelMixin,**无 TenantMixin**)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(50) | NOT NULL | 菜单名称 |
|
||
| `type` | Integer | NOT NULL, default=2 | 类型(1:目录 2:菜单 3:按钮 4:外链) |
|
||
| `order` | Integer | NOT NULL, default=999 | 显示排序 |
|
||
| `permission` | String(100) | nullable | 权限标识(如 `system:user:query`) |
|
||
| `icon` | String(50) | nullable | 菜单图标 |
|
||
| `route_name` | String(100) | nullable | 路由名称 |
|
||
| `route_path` | String(200) | nullable | 路由路径(以 `/` 开头) |
|
||
| `component_path` | String(200) | nullable | 组件路径(不能以 `/` 开头) |
|
||
| `redirect` | String(200) | nullable | 重定向地址 |
|
||
| `hidden` | Boolean | default=False | 是否隐藏 |
|
||
| `keep_alive` | Boolean | default=True | 是否缓存 |
|
||
| `always_show` | Boolean | default=False | 是否始终显示 |
|
||
| `title` | String(50) | nullable | 菜单标题 |
|
||
| `params` | JSON | nullable | 路由参数 |
|
||
| `affix` | Boolean | default=False | 是否固定标签页 |
|
||
| `client` | String(20) | NOT NULL, default="pc" | 终端(pc/app) |
|
||
| `parent_id` | FK→platform_menu.id | nullable, ON DELETE SET NULL | 父菜单 |
|
||
|
||
### 9.3 菜单类型
|
||
|
||
| 类型 | 说明 | 路由 | 前端行为 |
|
||
|------|------|------|---------|
|
||
| 1 | 目录 | 无 | 展开项,不可点击 |
|
||
| 2 | 菜单 | 有 | 可点击进入页面 |
|
||
| 3 | 按钮/权限 | 无 | 页面内操作权限标识 |
|
||
| 4 | 外部链接 | 有 | 跳转外部 URL |
|
||
|
||
### 9.4 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **平台资源** | 无 tenant_id,所有租户共享菜单池 |
|
||
| **路由规则** | `route_path` 以 `/` 开头,`component_path` 不能以 `/` 开头 |
|
||
| **类型校验** | ge=1, le=4 |
|
||
| **client 过滤** | 前端菜单渲染仅取 `client="pc"` 的菜单 |
|
||
| **权限策略** | `ROLE_BASED` — 非超管用户按角色菜单过滤 |
|
||
| **树形结构** | parent_id 自引用,children 按 order 排序。创建/更新 parent_id 时需检测循环引用(如 A→B→C→A),禁止导致循环的操作 |
|
||
|
||
### 9.5 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/menu/detail/{id}` | 菜单详情 |
|
||
| GET | `/menu/list` | 菜单列表(树形) |
|
||
| POST | `/menu/create` | 创建菜单 |
|
||
| PUT | `/menu/update/{id}` | 更新菜单 |
|
||
| DELETE | `/menu/delete` | 删除菜单(批量) |
|
||
| PATCH | `/menu/status/batch` | 批量设置菜单状态 |
|
||
|
||
---
|
||
|
||
## 10. Dict 字典模块
|
||
|
||
### 10.1 业务描述
|
||
|
||
字典模块提供统一的类型-数据管理,用于维护系统中固定的下拉选项和枚举值。字典数据支持**平台共享**(tenant_id=1 的平台字典对所有租户可读)。
|
||
|
||
### 10.2 数据模型
|
||
|
||
#### DictType(sys_dict_type)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `dict_name` | String(64) | NOT NULL | 字典名称 |
|
||
| `dict_type` | String(255) | NOT NULL, UNIQUE(tenant_id) | 字典类型编码 |
|
||
|
||
**平台共享**:`__platform_data_shared__ = True`
|
||
|
||
#### DictData(sys_dict_data)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `dict_sort` | Integer | default=0 | 排序 |
|
||
| `dict_label` | String(255) | NOT NULL | 字典标签 |
|
||
| `dict_value` | String(255) | NOT NULL | 字典键值 |
|
||
| `css_class` | String(255) | nullable | 样式属性 |
|
||
| `list_class` | String(255) | nullable | 表格回显样式 |
|
||
| `is_default` | Boolean | default=False | 是否默认 |
|
||
| `dict_type` | String(255) | NOT NULL | 字典类型(冗余字段) |
|
||
| `dict_type_id` | FK→sys_dict_type.id | NOT NULL, ON DELETE CASCADE | 字典类型 ID |
|
||
|
||
### 10.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **平台共享** | tenant_id=1 的字典对所有租户可读。**写保护**:修改/删除 tenant_id=1 的平台字典数据时,仅允许超管操作,普通租户管理员不可修改平台字典 |
|
||
| **编码规则** | dict_type 以小写字母开头,仅含小写字母/数字/下划线 |
|
||
| **级联删除** | 删除 DictType 时,关联的 DictData 自动级联删除 |
|
||
| **双关联** | DictData 同时保留 dict_type(字符串冗余)和 dict_type_id(FK)双重关联。`dict_type` 为冗余字段,用于避免频繁 JOIN DictType 表获取类型编码。两者应保持一致,业务层插入时自动填充 dict_type 并与 dict_type_id 对应 |
|
||
| **唯一约束** | DictData 表:`UNIQUE(tenant_id, dict_type_id, dict_value)`,同一字典类型下不可有重复的 dict_value |
|
||
|
||
### 10.4 API 端点
|
||
|
||
#### 字典类型
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/dict/type/detail/{id}` | 字典类型详情 |
|
||
| GET | `/dict/type/list` | 字典类型列表 |
|
||
| POST | `/dict/type/create` | 创建字典类型 |
|
||
| PUT | `/dict/type/update/{id}` | 更新字典类型 |
|
||
| DELETE | `/dict/type/delete` | 删除字典类型(批量) |
|
||
| PATCH | `/dict/type/status/batch` | 批量设置字典类型状态 |
|
||
|
||
#### 字典数据
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/dict/data/detail/{id}` | 字典数据详情 |
|
||
| GET | `/dict/data/list` | 字典数据列表 |
|
||
| POST | `/dict/data/create` | 创建字典数据 |
|
||
| PUT | `/dict/data/update/{id}` | 更新字典数据 |
|
||
| DELETE | `/dict/data/delete` | 删除字典数据(批量) |
|
||
| PATCH | `/dict/data/status/batch` | 批量设置字典数据状态 |
|
||
|
||
---
|
||
|
||
## 11. Notice 通知公告模块
|
||
|
||
### 11.1 业务描述
|
||
|
||
管理租户内部的通知和公告发布。通知数据按租户严格隔离。
|
||
|
||
### 11.2 数据模型
|
||
|
||
**表名**:`sys_notice`(TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `notice_title` | String(64) | NOT NULL | 公告标题 |
|
||
| `notice_type` | String(1) | NOT NULL | 类型(1:通知 2:公告) |
|
||
| `notice_content` | Text | nullable | 公告内容(富文本,XSS 过滤) |
|
||
|
||
**已读状态表**:`sys_notice_read`(按租户隔离)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `user_id` | FK→sys_user.id | PK, ON DELETE CASCADE | 用户ID |
|
||
| `notice_id` | FK→sys_notice.id | PK, ON DELETE CASCADE | 通知ID |
|
||
| `read_time` | DateTime | NOT NULL, default=now | 已读时间 |
|
||
|
||
> 唯一约束:`UNIQUE(user_id, notice_id)`。未建立记录即代表未读。
|
||
|
||
### 11.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **类型校验** | 仅支持 "1"(通知) 和 "2"(公告) |
|
||
| **XSS 防护** | notice_content 经过 `sanitize_html` 清洗 |
|
||
| **已读追踪** | 使用后端 `sys_notice_read` 表记录已读状态(多设备同步)。未读数量通过 LEFT JOIN 统计;通知列表返回未读数量标记 |
|
||
|
||
### 11.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/notice/detail/{id}` | 公告详情 |
|
||
| GET | `/notice/list` | 公告列表 |
|
||
| POST | `/notice/create` | 创建公告 |
|
||
| PUT | `/notice/update/{id}` | 更新公告 |
|
||
| DELETE | `/notice/delete` | 删除公告(批量) |
|
||
| PATCH | `/notice/status/batch` | 批量设置公告状态 |
|
||
| POST | `/notice/read/{id}` | 标记已读(写入 sys_notice_read) |
|
||
| POST | `/notice/read-all` | 全部标记已读 |
|
||
| GET | `/notice/unread-count` | 获取当前用户未读通知数量 |
|
||
|
||
---
|
||
|
||
## 12. Params 系统参数模块
|
||
|
||
### 12.1 业务描述
|
||
|
||
管理系统级别的配置参数,支持区分系统内置参数(不可删除)和自定义参数。参数数据按租户隔离。
|
||
|
||
### 12.2 数据模型
|
||
|
||
**表名**:`sys_param`(TenantMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `config_name` | String(64) | NOT NULL | 参数名称 |
|
||
| `config_key` | String(500) | NOT NULL | 参数键名 |
|
||
| `config_value` | String(500) | nullable | 参数键值 |
|
||
| `config_type` | Boolean | default=False | 是否系统内置 |
|
||
|
||
### 12.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **键名规则** | 小写字母开头,仅含小写字母/数字/_.- |
|
||
| **系统内置** | config_type=True 的参数不允许删除(业务层实现) |
|
||
|
||
### 12.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/params/detail/{id}` | 参数详情 |
|
||
| GET | `/params/list` | 参数列表 |
|
||
| POST | `/params/create` | 创建参数 |
|
||
| PUT | `/params/update/{id}` | 更新参数 |
|
||
| DELETE | `/params/delete` | 删除参数(批量) |
|
||
|
||
---
|
||
|
||
## 13. LoginLog 登录日志模块
|
||
|
||
### 13.1 业务描述
|
||
|
||
记录用户登录行为,用于安全审计和登录统计。登录日志为平台级资源,不受租户隔离限制,平台管理员可查看所有租户的登录记录。
|
||
|
||
### 13.2 数据模型
|
||
|
||
**表名**:`platform_login_log`(ModelMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `status` | Integer | NOT NULL, default=1 | 登录状态(1:成功 2:失败) |
|
||
| `login_ip` | String(50) | nullable | 登录 IP |
|
||
| `login_location` | String(255) | nullable | 登录位置 |
|
||
| `request_os` | String(64) | nullable | 操作系统 |
|
||
| `request_browser` | String(64) | nullable | 浏览器 |
|
||
| `msg` | String(255) | nullable | 提示消息 |
|
||
|
||
### 13.3 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/platform/loginlog/detail/{id}` | 登录日志详情 | 平台管理员 |
|
||
| GET | `/platform/loginlog/list` | 登录日志列表 | 平台管理员 |
|
||
| DELETE | `/platform/loginlog/delete` | 删除登录日志(批量) | 平台管理员 |
|
||
|
||
---
|
||
|
||
## 14. OperationLog 操作日志模块
|
||
|
||
### 14.1 业务描述
|
||
|
||
记录系统的操作日志,用于审计和问题追踪。通过 `OperationLogRoute` 路由类自动记录操作日志。日志数据按租户隔离,租户管理员仅能查看本租户的操作日志。
|
||
|
||
### 14.2 数据模型
|
||
|
||
**表名**:`sys_operation_log`(ModelMixin, TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `request_path` | String(255) | NOT NULL | 请求路径 |
|
||
| `request_method` | String(10) | NOT NULL | 请求方法 |
|
||
| `request_payload` | LONGTEXT/TEXT | nullable | 请求体 |
|
||
| `request_ip` | String(50) | nullable | 请求 IP |
|
||
| `request_os` | String(64) | nullable | 操作系统 |
|
||
| `request_browser` | String(64) | nullable | 浏览器 |
|
||
| `response_code` | Integer | NOT NULL | 响应状态码 |
|
||
| `response_json` | LONGTEXT/TEXT | nullable | 响应体 |
|
||
| `process_time` | String(20) | nullable | 处理耗时 |
|
||
|
||
### 14.3 存储适配
|
||
|
||
| 数据库 | 大字段类型 |
|
||
|--------|-----------|
|
||
| MySQL | LONGTEXT |
|
||
| PostgreSQL | TEXT |
|
||
| SQLite | Text |
|
||
|
||
### 14.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/system/operationlog/detail/{id}` | 操作日志详情 | 租户管理员 |
|
||
| GET | `/system/operationlog/list` | 操作日志列表 | 租户管理员 |
|
||
| DELETE | `/system/operationlog/delete` | 删除操作日志(批量) | 租户管理员 |
|
||
|
||
### 14.5 日志保留策略
|
||
|
||
操作日志表数据量大(生产环境可能每天数十万条),需配置自动清理机制:
|
||
|
||
| 配置项 | 说明 | 默认值 |
|
||
|--------|------|--------|
|
||
| `operation_log_retention_days` | 日志保留天数 | 90 天 |
|
||
| `operation_log_cleanup_enabled` | 是否启用自动清理 | true |
|
||
| `operation_log_cleanup_cron` | 定时清理 cron 表达式 | 每天凌晨 3:00 |
|
||
|
||
- 定时任务 `cleanup_operation_log` 删除 `create_time < now - retention_days` 的记录
|
||
- 清理前可选归档到外部存储(OSS/本地文件),由 `operation_log_archive_enabled` 控制
|
||
- 登录日志(`platform_login_log`)同样受此策略管理
|
||
|
||
---
|
||
|
||
## 15. Tenant 租户管理模块
|
||
|
||
### 15.1 业务描述
|
||
|
||
租户是 SaaS 平台的核心概念,代表一个独立的组织。租户管理包含:租户定义、配额管理、配置管理、用户关联、自定义菜单授权。
|
||
|
||
### 15.2 数据模型
|
||
|
||
#### 核心表:platform_tenant(ModelMixin,无 TenantMixin)- **单一大表设计**
|
||
|
||
将配额和配置字段直接集成到主表,简化结构便于管理。
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(100) | NOT NULL, UNIQUE | 租户名称 |
|
||
| `code` | String(100) | NOT NULL, UNIQUE | 租户编码(字母数字) |
|
||
| `contact_name` | String(64) | nullable | 联系人 |
|
||
| `contact_phone` | String(20) | nullable | 联系电话 |
|
||
| `contact_email` | String(128) | nullable | 联系邮箱 |
|
||
| `address` | String(255) | nullable | 地址 |
|
||
| `domain` | String(255) | nullable | 自定义域名 |
|
||
| `logo_url` | String(500) | nullable | Logo URL |
|
||
| `description` | Text | nullable | 租户描述 |
|
||
| `version` | String(20) | nullable | 版本号 |
|
||
| `sort` | Integer | default=0 | 排序 |
|
||
| `status` | Integer | NOT NULL, default=0 | 生命周期:0=active(正常) 1=grace(宽限期) 2=suspended(暂停) 3=frozen(冻结) 4=expired(过期) 5=archived(归档) |
|
||
| `package_id` | FK→platform_package.id | nullable, ON DELETE SET NULL | 关联套餐 |
|
||
| `start_time` | DateTime | nullable | 开始时间 |
|
||
| `end_time` | DateTime | nullable | 结束时间 |
|
||
| `grace_period_days` | Integer | default=7, ge=0 | 宽限期天数(到期后延迟禁用天数) |
|
||
| `grace_start_time` | DateTime | nullable | 宽限期开始时间(自动写入) |
|
||
| `max_users` | Integer | default=50, ge=1 | 最大用户数 |
|
||
| `max_roles` | Integer | default=20, ge=1 | 最大角色数 |
|
||
| `max_storage_mb` | Integer | default=500, ge=1 | 最大存储(MB) |
|
||
| `max_depts` | Integer | default=50, ge=1 | 最大部门数 |
|
||
| `favicon` | String(500) | nullable | 网站图标 |
|
||
| `login_bg` | String(500) | nullable | 登录背景图 |
|
||
| `copyright` | String(255) | nullable | 版权信息 |
|
||
| `help_doc` | String(500) | nullable | 帮助文档地址 |
|
||
| `privacy` | String(500) | nullable | 隐私政策地址 |
|
||
| `clause` | String(500) | nullable | 服务条款地址 |
|
||
| `keep_record` | String(100) | nullable | ICP 备案号 |
|
||
| `git_code` | String(500) | nullable | 源码地址 |
|
||
|
||
#### 关联表(必要的多对多关系)
|
||
|
||
| 表名 | 说明 | 关键字段 |
|
||
|------|------|---------|
|
||
| `platform_user_tenant` | 用户-租户关联 | user_id, tenant_id, role(owner/admin/member), is_default |
|
||
| `platform_tenant_menu` | 租户自定义菜单 | tenant_id, menu_id, UNIQUE(tenant_id, menu_id) |
|
||
|
||
### 15.3 核心业务流程
|
||
|
||
#### 创建租户
|
||
|
||
```
|
||
POST /tenant/create
|
||
├── 创建租户记录(platform_tenant)
|
||
├── 生成初始管理员:{code}_admin + 随机12位密码(含特殊字符)
|
||
├── 密码不返回、不记录日志;生成一次性密码重置链接(含时效 Token,有效期24小时)
|
||
├── 向 contact_email 发送重置链接邮件(若未填 contact_email 则跳过,超管需手动处理)
|
||
├── 创建默认 owner 角色(sys_role),编码固定为 "owner"
|
||
├── 将初始管理员绑定到 owner 角色(sys_user_roles)
|
||
├── 将租户可用菜单(套餐菜单 + 自定义授权菜单)全量分配给 owner 角色(sys_role_menus)
|
||
├── 初始化租户配额(默认值写入 platform_tenant 主表)
|
||
└── 返回租户信息(不含密码)
|
||
```
|
||
|
||
> **安全说明**:初始管理员密码仅通过邮件中的一次性链接设置,不通过日志、API 响应等任何渠道明文传递。首次登录强制修改密码。
|
||
|
||
#### 删除租户
|
||
|
||
```
|
||
DELETE /tenant/delete
|
||
├── 系统租户(id=1)不可删除
|
||
├── 仅支持删除 archived 状态的租户
|
||
├── 有关联数据时拒绝删除,提示需先清理
|
||
└── 通过则物理删除(不可恢复)
|
||
```
|
||
|
||
#### 租户生命周期状态机
|
||
|
||
```
|
||
┌── 冻结 ──┐
|
||
↓ │
|
||
创建 → active(0) ──┤ ├→ archived(5) → deleted(已删除)
|
||
│ │ ↑
|
||
└→ grace(1) → suspended(2) → expired(4) ┘
|
||
↑ │
|
||
└── 续期 ←──┘
|
||
```
|
||
|
||
**状态说明**:
|
||
|
||
| 状态 | 编码 | 触发方式 | 说明 |
|
||
|------|------|---------|------|
|
||
| `active` | 0 | 创建/续期/恢复 | 正常访问,读写开放 |
|
||
| `grace` | 1 | 到期后自动 | 宽限期:可登录但提示续费,功能正常 |
|
||
| `suspended` | 2 | 宽限期结束后自动 | 暂停:禁止写操作,仅可查看数据 |
|
||
| `expired` | 4 | 暂停超过保留期后自动 | 过期:禁止登录,数据保留待归档 |
|
||
| `frozen` | 3 | 超管手动冻结 | 冻结:立即禁止访问(不经过宽限期),可恢复为 active。保留全部数据 |
|
||
| `archived` | 5 | 冻结/过期后定时归档 | 归档:禁止访问,数据保留。唯一可被物理删除的状态 |
|
||
| `deleted` | — | 物理删除 | 已移除记录,不可逆 |
|
||
|
||
**冻结/归档/删除操作流**:
|
||
```
|
||
冻结(PATCH /tenant/status/batch → status=3)
|
||
├── 仅超管可操作
|
||
├── 系统租户(id=1)不可冻结
|
||
├── 仅 active(0) 状态可冻结
|
||
└── 租户内所有用户 session 失效(Redis token 缓存清除)
|
||
|
||
归档(定时任务自动或手动)
|
||
├── 扫描 status=3 且冻结超过 archive_after_days(默认30天) 的租户
|
||
├── 扫描 status=4 且过期超过 archive_after_days 的租户
|
||
└── 自动将 status 设置为 5(archived)
|
||
|
||
物理删除(DELETE /tenant/delete)
|
||
├── 仅 archived(status=5)状态的租户可删除
|
||
├── 系统租户(id=1)不可删除
|
||
├── 检查关联数据:用户/部门/角色/岗位
|
||
├── 有关联数据时拒绝删除,提示需先清理
|
||
└── 无关联数据 → 物理删除
|
||
```
|
||
|
||
#### 套餐变更影响预览
|
||
|
||
套餐变更前,系统返回影响预览,超管确认后再执行:
|
||
|
||
```
|
||
PUT /tenant/update/{id} (package_id 变更)
|
||
├── 仅超管可操作
|
||
├── 调用预检接口 GET /tenant/{id}/package-change-preview?new_package_id=xxx
|
||
│ 返回:
|
||
│ - 受影响的角色列表(名称、用户数)
|
||
│ - 将被移除的菜单清单(名称、路径)
|
||
│ - 配额变化对比(max_users/max_roles/max_depts 当前值 → 新值)
|
||
│ - 受影响用户数总计
|
||
├── 前端展示影响明细,超管确认
|
||
├── 更新 tenant.package_id
|
||
├── 获取新可用菜单 ID(套餐菜单 ∪ 自定义菜单)
|
||
├── 清理角色中不在可用菜单内的 RoleMenus 记录
|
||
├── 更新租户配额(max_users/max_roles/max_depts 同步为新套餐限制值)
|
||
│ ├── 升级:配额只增不减(新值 > 旧值时才更新)
|
||
│ └── 降级:当前使用量 > 新配额时降级操作可执行但不缩减已有数据,仅限制后续新增
|
||
├── 发送通知给租户管理员(站内信,列出被回收的菜单和配额变化)
|
||
└── 完成
|
||
```
|
||
|
||
> 预检接口:`GET /platform/tenant/{id}/package-change-preview?new_package_id={id}`
|
||
> 通知内容:本次套餐变更收回了 X 个菜单权限,涉及 Y 个角色,请知悉。
|
||
|
||
### 15.4 业务规则
|
||
|
||
| 类别 | 规则 |
|
||
|------|------|
|
||
| **系统租户** | id=1 不可删除、禁用(冻结/归档)、修改编码 |
|
||
| **编码** | 仅含字母和数字,用于生成初始管理员用户名 |
|
||
| **初始管理员** | 自动创建,用户名 `{code}_admin`,密码 12 位随机(含特殊字符)。同时自动创建 owner 角色,将初始管理员绑定为 owner,并将租户当前可用菜单(套餐菜单 ∪ 自定义菜单)全量分配给该角色。初始管理员登录后即可看到完整的租户菜单,无需超管手动介入 |
|
||
| **配额** | 创建租户时,配额默认值从所选套餐的 max_users/max_roles/max_depts 复制到 platform_tenant 主表。无套餐时使用硬编码默认值(users=10, roles=5, depts=10)。超管可在租户管理页手动调整 |
|
||
| **owner 保护** | 每个租户至少保留一个 owner。从租户移除用户时,检查该用户是否为该租户的唯一 owner,是则拒绝移除。修改用户租户角色时,禁止将最后一个 owner 降级为 member。默认 owner 角色(code="owner")不可删除、不可禁用,确保租户始终有可用角色来管理 |
|
||
| **配额执行** | 租户配额在创建资源时执行检查。UserCRUD.create 检查 max_users,RoleCRUD.create 检查 max_roles,DeptCRUD.create 检查 max_depts。达到上限时拒绝创建并提示 |
|
||
| **默认租户** | 用户首次加入的租户自动设为默认,设置新默认时清除旧默认 |
|
||
| **多租户** | 一个用户可关联多个租户 |
|
||
| **生命周期** | 租户状态流转:active(0)→grace(1)→suspended(2)→expired(4)→archived(5)→物理删除。超管可人工冻结 active→frozen(3)→archived(5)。frozen 可恢复为 active。仅 archived 状态可物理删除。expired/frozen 超过 archive_after_days(默认30天) 后由定时任务自动归档为 archived(5) |
|
||
| **冻结后失效** | 租户冻结后,Redis 中该租户所有用户的 token 缓存立即清除,用户下次请求时因 token 无效被拒绝访问 |
|
||
| **续期** | active/grace/suspended 状态的租户可通过 `PUT /tenant/renew/{id}` 续期,传入 `end_time` 延长有效期并恢复为 active(0);expired/frozen/archived 状态不可续期 |
|
||
|
||
### 15.5 配置缓存策略
|
||
|
||
| 机制 | 说明 |
|
||
|------|------|
|
||
| **缓存 key** | `tenant_config:{tenant_id}:{config_key}` |
|
||
| **读取策略** | 优先读 Redis,未命中回源 DB 并写回缓存 |
|
||
| **更新策略** | 更新后自动同步刷新 Redis |
|
||
| **预热** | 应用启动时 `init_tenant_config_cache` 预加载所有配置 |
|
||
|
||
### 15.6 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/tenant/detail/{id}` | 租户详情 |
|
||
| GET | `/tenant/list` | 租户列表 |
|
||
| POST | `/tenant/create` | 创建租户(自动配管理员) |
|
||
| PUT | `/tenant/update/{id}` | 修改租户 |
|
||
| DELETE | `/tenant/delete` | 删除租户(仅 archived 状态可删) |
|
||
| PATCH | `/tenant/status/batch` | 批量修改状态(含冻结/恢复) |
|
||
| PUT | `/tenant/status/{id}` | 启/禁用(冻结/恢复) |
|
||
| PUT | `/tenant/renew/{id}` | 续期(延长 end_time) |
|
||
| GET | `/tenant/{id}/users` | 获取租户用户列表 |
|
||
| POST | `/tenant/{id}/users` | 向租户添加用户 |
|
||
| DELETE | `/tenant/{id}/users/{uid}` | 从租户移除用户 |
|
||
| GET | `/tenant/{id}/quota` | 获取租户配额 |
|
||
| PUT | `/tenant/{id}/quota` | 修改租户配额 |
|
||
| GET | `/tenant/{id}/config` | 获取租户配置 |
|
||
| GET | `/tenant/{id}/config/info` | 获取租户配置(公开,缓存) |
|
||
| PUT | `/tenant/{id}/config` | 批量更新配置 |
|
||
| GET | `/tenant/{id}/menus` | 获取租户自定义菜单 |
|
||
| PUT | `/tenant/{id}/menus` | 设置租户自定义菜单 |
|
||
|
||
---
|
||
|
||
## 16. Package 套餐模块(module_package)
|
||
|
||
### 16.1 业务描述
|
||
|
||
套餐模块是独立的功能模块,用于管理租户的功能套餐配置。套餐是预定义的功能菜单集合,用于标准化租户授权流程。通过套餐体系可以减少逐个分配菜单的工作量,实现基础版/专业版/企业版等分级授权。
|
||
|
||
### 16.2 数据模型
|
||
|
||
#### platform_package
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(100) | NOT NULL, UNIQUE | 套餐名称 |
|
||
| `code` | String(100) | NOT NULL, UNIQUE | 套餐编码 |
|
||
| `status` | Integer | default=0 | 状态(0:启动 1:停用) |
|
||
| `is_default` | Boolean | default=False | 是否为默认套餐(自助注册时自动选用) |
|
||
| `price` | Integer | default=0 | 价格(分),0=免费 |
|
||
| `period` | String(10) | nullable | 计费周期:month/year/once |
|
||
| `trial_days` | Integer | default=0 | 试用天数,0=无试用 |
|
||
| `max_users` | Integer | default=10 | 套餐用户数上限 |
|
||
| `max_roles` | Integer | default=5 | 套餐角色数上限 |
|
||
| `max_depts` | Integer | default=10 | 套餐部门数上限 |
|
||
| `max_tenants` | Integer | nullable | 该套餐最大租户数限制(平台运营管控),null=不限制 |
|
||
| `sort` | Integer | default=0 | 排序 |
|
||
|
||
#### platform_package_menu
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `package_id` | FK→platform_package.id | PK, ON DELETE CASCADE | 套餐 ID |
|
||
| `menu_id` | FK→platform_menu.id | PK, ON DELETE CASCADE | 菜单 ID |
|
||
|
||
唯一约束:`(package_id, menu_id)`
|
||
|
||
### 16.3 核心流程
|
||
|
||
#### 租户可用菜单合并逻辑
|
||
|
||
```
|
||
get_tenant_available_menu_ids(tenant_id):
|
||
可用菜单 = set()
|
||
|
||
# 1. 如果租户关联了套餐,取出套餐的所有菜单
|
||
if tenant.package_id:
|
||
可用菜单.add(套餐菜单...)
|
||
|
||
# 2. 取出租户自定义授权菜单(platform_tenant_menu)
|
||
可用菜单.add(自定义菜单...)
|
||
|
||
return list(可用菜单) # 并集
|
||
```
|
||
|
||
#### 套餐变更后清理
|
||
|
||
```
|
||
套餐变更 → 取新可用菜单 ID →
|
||
查询该租户所有角色 → 删除角色中不在可用菜单内的 RoleMenus 记录 → 完成
|
||
```
|
||
|
||
### 16.4 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **套餐变更** | 仅超管可操作 |
|
||
| **删除约束** | 删除前检查是否有租户使用,有则拒绝 |
|
||
| **级联策略** | 套餐删除时,租户 package_id SET NULL |
|
||
| **菜单设置** | 套餐菜单全量替换(先删后插) |
|
||
| **套餐禁用** | 套餐 status=1 时,已关联该套餐的租户在 `get_tenant_available_menu_ids` 中**不再计入**套餐菜单,仅保留租户自定义菜单(platform_tenant_menu)。恢复 status=0 后套餐菜单自动恢复 |
|
||
| **套餐已删** | 套餐被删除(package_id SET NULL)后,租户降级为仅有自定义菜单,需及时为受影响租户迁移或补配权限 |
|
||
|
||
### 16.5 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/platform/package/detail/{id}` | 套餐详情 |
|
||
| GET | `/platform/package/list` | 套餐列表 |
|
||
| POST | `/platform/package/create` | 创建套餐 |
|
||
| PUT | `/platform/package/update/{id}` | 修改套餐 |
|
||
| DELETE | `/platform/package/delete` | 删除套餐 |
|
||
| GET | `/platform/package/{id}/menus` | 获取套餐菜单 |
|
||
| PUT | `/platform/package/{id}/menus` | 设置套餐菜单(全量替换) |
|
||
|
||
---
|
||
|
||
## 17. Ticket 工单模块
|
||
|
||
### 17.1 业务描述
|
||
|
||
工单系统用于用户提交反馈、建议和缺陷报告,支持指派处理人进行跟踪处理。工单数据按租户隔离。
|
||
|
||
### 17.2 数据模型
|
||
|
||
**表名**:`platform_ticket`(TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `title` | String(200) | NOT NULL | 工单标题 |
|
||
| `ticket_content` | Text | nullable | 工单内容(富文本) |
|
||
| `summary` | Text | nullable | 工单内容(纯文本摘要) |
|
||
| `ticket_type` | String(20) | NOT NULL, default="suggestion" | 类型(suggestion/bug/optimize/other) |
|
||
| `status` | Integer | NOT NULL, default=0 | 状态(0:待处理 1:处理中 2:已完成 3:已关闭) |
|
||
| `images` | Text | nullable | 图片 URL 列表(JSON 数组) |
|
||
| `reply` | Text | nullable | 回复内容 |
|
||
| `assigned_id` | FK→sys_user.id | nullable, ON DELETE SET NULL | 处理人 |
|
||
|
||
### 17.3 状态流转
|
||
|
||
```
|
||
待处理(0) → 处理中(1) → 已完成(2)
|
||
↑ │
|
||
└──── 已关闭(3)
|
||
```
|
||
|
||
#### 状态转换规则
|
||
|
||
| 源状态 | 目标状态 | 允许角色 | 说明 |
|
||
|-------|---------|---------|------|
|
||
| 待处理(0) | 处理中(1) | 创建人/处理人/超管 | 确认受理 |
|
||
| 待处理(0) | 已关闭(3) | 创建人/超管 | 取消提交 |
|
||
| 处理中(1) | 已完成(2) | 处理人/超管 | 处理完成 |
|
||
| 处理中(1) | 已关闭(3) | 创建人/处理人/超管 | 强行关闭(需填写原因) |
|
||
| 已完成(2) | 已关闭(3) | 创建人/超管 | 确认关闭 |
|
||
| 已关闭(3) | 待处理(0) | 超管 | 仅超管可重新打开 |
|
||
|
||
> 非法转换(如已完成→处理中)应在 Service 层校验并拒绝 |
|
||
|
||
### 17.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/ticket/detail/{id}` | 工单详情 |
|
||
| GET | `/ticket/list` | 工单列表 |
|
||
| POST | `/ticket/create` | 创建工单 |
|
||
| PUT | `/ticket/update/{id}` | 更新工单 |
|
||
| DELETE | `/ticket/delete` | 删除工单(批量) |
|
||
| PUT | `/ticket/batch/status` | 批量更新工单状态 |
|
||
|
||
---
|
||
|
||
## 18. Plugin 插件模块
|
||
|
||
### 18.1 业务描述
|
||
|
||
插件系统是平台的扩展机制。`platform_plugin` 作为插件注册表(平台级资源),记录所有可用插件的元数据。租户通过 `platform_tenant_plugin` 关联表安装插件。
|
||
|
||
### 18.2 数据模型
|
||
|
||
#### platform_plugin(平台资源,无 TenantMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(100) | NOT NULL, UNIQUE | 插件名称 |
|
||
| `code` | String(50) | NOT NULL, UNIQUE | 插件编码(module_xxx) |
|
||
| `description` | Text | nullable | 插件描述 |
|
||
| `version` | String(20) | NOT NULL, default="1.0.0" | 版本号 |
|
||
| `author` | String(100) | nullable | 作者 |
|
||
| `icon` | String(500) | nullable | 图标 URL |
|
||
| `category` | String(20) | NOT NULL, default="tool" | 分类(tool/ai/monitor/business) |
|
||
| `price` | Integer | NOT NULL, default=0 | 价格(分,0=免费) |
|
||
| `menu_path` | String(200) | nullable | 菜单路径(安装后显示) |
|
||
| `permission_prefix` | String(100) | nullable | 权限前缀 |
|
||
| `dependencies` | Text | nullable | 依赖插件编码(JSON 数组) |
|
||
| `sort` | Integer | NOT NULL, default=0 | 排序 |
|
||
|
||
#### platform_tenant_plugin
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `tenant_id` | FK→platform_tenant.id | NOT NULL, ON DELETE CASCADE | 租户 ID |
|
||
| `plugin_id` | FK→platform_plugin.id | NOT NULL, ON DELETE CASCADE | 插件 ID |
|
||
| `enabled` | String(1) | NOT NULL, default="1" | 启用(1:启用 0:禁用) |
|
||
| `installed_time` | DateTime | NOT NULL | 安装时间 |
|
||
|
||
唯一约束:`(tenant_id, plugin_id)`
|
||
|
||
### 18.3 插件目录结构
|
||
|
||
```
|
||
plugin/module_xxx/
|
||
├── __init__.py
|
||
├── plugin.toml # 插件元数据(名称、版本、路由前缀等)
|
||
├── controller.py
|
||
├── service.py
|
||
├── crud.py
|
||
├── model.py
|
||
└── schema.py
|
||
```
|
||
|
||
已内置插件:
|
||
- `module_ai/chat` — AI 对话
|
||
- `module_example/demo` — 示例
|
||
- `module_generator/gencode` — 代码生成器
|
||
- `module_task/cronjob` — 定时任务
|
||
- `module_task/workflow` — 工作流引擎
|
||
|
||
### 18.4 API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/plugin/detail/{id}` | 插件详情 |
|
||
| GET | `/plugin/list` | 插件列表(含当前租户安装状态) |
|
||
| POST | `/plugin/create` | 创建插件 |
|
||
| PUT | `/plugin/update/{id}` | 更新插件 |
|
||
| DELETE | `/plugin/delete` | 删除插件(批量) |
|
||
| POST | `/plugin/install` | 租户安装插件 |
|
||
| POST | `/plugin/uninstall` | 租户卸载插件 |
|
||
|
||
---
|
||
|
||
## 19. 到期处理
|
||
|
||
### 19.1 到期阶段定义
|
||
|
||
租户到期后分三个阶段处理,避免粗暴直接禁用(编码与 §15.2 生命周期统一):
|
||
|
||
| 阶段 | 编码 | 说明 |
|
||
|------|------|------|
|
||
| `active` | 0 | 正常,在有效期内 |
|
||
| `grace` | 1 | 宽限期:到期后可登录但每次登录提示续费,功能正常 |
|
||
| `suspended` | 2 | 暂停:宽限期结束后禁用写操作,仅可查看数据 |
|
||
| `expired` | 4 | 过期:暂停超过保留期后,禁止登录 |
|
||
|
||
**阶段流转**(与生命周期统一):
|
||
```
|
||
active(0) → grace(1) → suspended(2) → expired(4) → archived(5)
|
||
↑ │ │
|
||
└── 续期 ←──┘────────────┘
|
||
```
|
||
|
||
### 19.2 自动处理逻辑
|
||
|
||
定时任务 `check_tenant_expiry` 定期扫描所有正常状态的租户:
|
||
|
||
1. 遍历 status=0(active) 或 status=1(grace) 或 status=2(suspended) 的租户
|
||
2. **未到达生效时间**:`start_time` 存在且 `start_time > now` → 暂不处理,登录时提示"租户尚未生效"
|
||
3. **进入宽限期**:status=0 且 `end_time` 存在且 `now > end_time` → 设 `status=1`,记录 `grace_start_time`
|
||
4. **进入暂停**:status=1(grace) 且 `now > grace_start_time + grace_period_days`(默认7天)→ 设 `status=2`(suspended)
|
||
5. **进入过期**:status=2(suspended) 且暂停超过 `expire_after_days`(默认30天)→ 设 `status=4`(expired)
|
||
6. **宽限期内续期**:若 status=1/2 时发现 `end_time` 已续期至未来 → 恢复 `status=0`(active),清除 `grace_start_time`
|
||
7. **即将到期提醒**:`end_time` 在 30天/7天/1天 内 → 触发到期提醒
|
||
|
||
### 19.3 各阶段行为
|
||
|
||
| 阶段 | 登录 | 读操作 | 写操作 | 提示 |
|
||
|------|------|--------|--------|------|
|
||
| active(0) | ✅ | ✅ | ✅ | 无 |
|
||
| grace(1) | ✅ | ✅ | ✅ | 每次登录弹窗提示"您的租户已到期,请尽快续费" |
|
||
| suspended(2) | ✅ | ✅ | ❌ 拒绝写入 | 提示"租户已暂停,请联系管理员续费" |
|
||
| expired(4) | ❌ | — | — | 提示"租户已过期" |
|
||
|
||
### 19.4 到期配置参数
|
||
|
||
| 字段 | 位置 | 说明 |
|
||
|------|------|------|
|
||
| `grace_period_days` | `platform_tenant` 表,Integer,default=7 | 宽限期天数 |
|
||
| `expire_after_days` | 全局配置,Integer,default=30 | 暂停→过期天数(suspended 超过此天数后自动标记为 expired) |
|
||
| `archive_after_days` | 全局配置,Integer,default=30 | frozen/expired 超过此天数后自动归档为 archived(5) |
|
||
|
||
### 19.5 提醒方式
|
||
|
||
| 触点 | 触发时机 | 渠道 |
|
||
|------|---------|------|
|
||
| 30天前 | `end_time - 30d <= now` | 站内信(sys_notice) |
|
||
| 7天前 | `end_time - 7d <= now` | 站内信 + 邮件(contact_email) |
|
||
| 1天前 | `end_time - 1d <= now` | 站内信 + 邮件 + 短信(contact_phone,可选) |
|
||
| 已到期(grace) | 每次登录 | 弹窗提示 |
|
||
|
||
当前邮件/短信为预留扩展点,未配置渠道时降级为站内信。
|
||
|
||
---
|
||
|
||
# Part 3:附录
|
||
|
||
---
|
||
|
||
## 20. API 接口汇总
|
||
|
||
### 20.1 认证模块
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/auth/login` | 登录 |
|
||
| POST | `/auth/token/refresh` | 刷新 token |
|
||
| POST | `/auth/logout` | 退出登录 |
|
||
| GET | `/auth/captcha` | 验证码 |
|
||
| POST | `/auth/register` | 用户注册(自动创建默认租户) |
|
||
| POST | `/auth/select-tenant/{id}` | 选择租户(生成正式 token) |
|
||
| GET | `/auth/tenants` | 获取可选租户列表 |
|
||
| POST | `/auth/forgot-password` | 忘记密码 |
|
||
| GET | `/auth/auto-login/users` | 获取免登录用户列表 |
|
||
| POST | `/auth/auto-login/token` | 获取免登录Token |
|
||
| POST | `/auth/auto-login` | 免登录 |
|
||
| GET | `/auth/oauth/{provider}/login` | OAuth2 授权跳转 |
|
||
| GET | `/auth/oauth/{provider}/callback` | OAuth2 回调处理 |
|
||
|
||
### 20.2 用户模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/user/detail/{id}` | user:query | 详情 |
|
||
| GET | `/user/list` | user:query | 列表 |
|
||
| POST | `/user/create` | user:create | 创建 |
|
||
| PUT | `/user/update/{id}` | user:update | 更新 |
|
||
| DELETE | `/user/delete` | user:delete | 删除 |
|
||
| PATCH | `/user/status/batch` | user:patch | 批量设状态 |
|
||
| GET | `/user/current/info` | - | 当前用户信息 |
|
||
| PUT | `/user/current/info/update` | - | 更新当前用户 |
|
||
| PUT | `/user/password/change` | - | 改密码(本人操作) |
|
||
| PUT | `/user/password/reset/{id}` | user:update | 重置密码(管理员操作) |
|
||
| GET | `/user/import/template` | user:download | 导入模板 |
|
||
| POST | `/user/import/data` | user:import | 导入 |
|
||
| POST | `/user/export` | user:query | 导出 |
|
||
|
||
### 20.3 角色模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/role/detail/{id}` | role:query | 详情 |
|
||
| GET | `/role/list` | role:query | 列表 |
|
||
| POST | `/role/create` | role:create | 创建 |
|
||
| PUT | `/role/update/{id}` | role:update | 更新 |
|
||
| DELETE | `/role/delete` | role:delete | 删除 |
|
||
| PATCH | `/role/status/batch` | role:patch | 批量设状态 |
|
||
| PUT | `/role/menus` | role:update | 设置菜单 |
|
||
| PUT | `/role/permission` | role:update | 设置权限 |
|
||
|
||
### 20.4 部门模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/dept/detail/{id}` | dept:query | 详情 |
|
||
| GET | `/dept/list` | dept:query | 列表 |
|
||
| POST | `/dept/create` | dept:create | 创建 |
|
||
| PUT | `/dept/update/{id}` | dept:update | 更新 |
|
||
| DELETE | `/dept/delete` | dept:delete | 删除 |
|
||
| PATCH | `/dept/status/batch` | dept:patch | 批量设状态 |
|
||
|
||
### 20.5 岗位模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/position/detail/{id}` | position:query | 详情 |
|
||
| GET | `/position/list` | position:query | 列表 |
|
||
| POST | `/position/create` | position:create | 创建 |
|
||
| PUT | `/position/update/{id}` | position:update | 更新 |
|
||
| DELETE | `/position/delete` | position:delete | 删除 |
|
||
| PATCH | `/position/status/batch` | position:patch | 批量设状态 |
|
||
|
||
### 20.6 菜单模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/menu/detail/{id}` | menu:query | 详情 |
|
||
| GET | `/menu/list` | menu:query | 列表 |
|
||
| POST | `/menu/create` | menu:create | 创建 |
|
||
| PUT | `/menu/update/{id}` | menu:update | 更新 |
|
||
| DELETE | `/menu/delete` | menu:delete | 删除 |
|
||
| PATCH | `/menu/status/batch` | menu:patch | 批量设状态 |
|
||
|
||
### 20.7 字典模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/dict/type/detail/{id}` | dict:query | 字典类型详情 |
|
||
| GET | `/dict/type/list` | dict:query | 字典类型列表 |
|
||
| POST | `/dict/type/create` | dict:create | 创建字典类型 |
|
||
| PUT | `/dict/type/update/{id}` | dict:update | 更新字典类型 |
|
||
| DELETE | `/dict/type/delete` | dict:delete | 删除字典类型 |
|
||
| PATCH | `/dict/type/status/batch` | dict:patch | 批量设状态 |
|
||
| GET | `/dict/data/detail/{id}` | dict:query | 字典数据详情 |
|
||
| GET | `/dict/data/list` | dict:query | 字典数据列表 |
|
||
| POST | `/dict/data/create` | dict:create | 创建字典数据 |
|
||
| PUT | `/dict/data/update/{id}` | dict:update | 更新字典数据 |
|
||
| DELETE | `/dict/data/delete` | dict:delete | 删除字典数据 |
|
||
|
||
### 20.8 通知公告
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/notice/detail/{id}` | notice:query | 详情 |
|
||
| GET | `/notice/list` | notice:query | 列表 |
|
||
| POST | `/notice/create` | notice:create | 创建 |
|
||
| PUT | `/notice/update/{id}` | notice:update | 更新 |
|
||
| DELETE | `/notice/delete` | notice:delete | 删除 |
|
||
| PATCH | `/notice/status/batch` | notice:patch | 批量设状态 |
|
||
|
||
### 20.9 系统参数
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/param/detail/{id}` | params:query | 详情 |
|
||
| GET | `/param/list` | params:query | 列表 |
|
||
| POST | `/param/create` | params:create | 创建 |
|
||
| PUT | `/param/update/{id}` | params:update | 更新 |
|
||
| DELETE | `/param/delete` | params:delete | 删除 |
|
||
| PATCH | `/param/status/batch` | params:patch | 批量设置状态 |
|
||
|
||
### 20.10 登录日志模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/platform/loginlog/detail/{id}` | module_platform:loginlog:query | 详情 |
|
||
| GET | `/platform/loginlog/list` | module_platform:loginlog:query | 列表 |
|
||
| DELETE | `/platform/loginlog/delete` | module_platform:loginlog:delete | 删除(批量) |
|
||
|
||
### 20.11 操作日志模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/system/operationlog/detail/{id}` | module_system:operationlog:query | 详情 |
|
||
| GET | `/system/operationlog/list` | module_system:operationlog:query | 列表 |
|
||
| DELETE | `/system/operationlog/delete` | module_system:operationlog:delete | 删除(批量) |
|
||
|
||
### 20.12 工单模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/ticket/detail/{id}` | ticket:query | 详情 |
|
||
| GET | `/ticket/list` | ticket:query | 列表 |
|
||
| POST | `/ticket/create` | ticket:create | 创建 |
|
||
| PUT | `/ticket/update/{id}` | ticket:update | 更新 |
|
||
| DELETE | `/ticket/delete` | ticket:delete | 删除 |
|
||
| PATCH | `/ticket/status/batch` | ticket:patch | 批量设置状态 |
|
||
|
||
### 20.13 插件模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/plugin/detail/{id}` | plugin:query | 详情 |
|
||
| GET | `/plugin/list` | plugin:query | 列表 |
|
||
| POST | `/plugin/create` | plugin:create | 创建 |
|
||
| PUT | `/plugin/update/{id}` | plugin:update | 更新 |
|
||
| DELETE | `/plugin/delete` | plugin:delete | 删除 |
|
||
| PATCH | `/plugin/status/batch` | plugin:patch | 批量设置状态 |
|
||
| POST | `/plugin/install` | - | 安装插件 |
|
||
| POST | `/plugin/uninstall` | - | 卸载插件 |
|
||
|
||
### 20.14 租户模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/tenant/detail/{id}` | tenant:query | 详情 |
|
||
| GET | `/tenant/list` | tenant:query | 列表 |
|
||
| POST | `/tenant/create` | tenant:create | 创建 |
|
||
| PUT | `/tenant/update/{id}` | tenant:update | 更新 |
|
||
| DELETE | `/tenant/delete` | tenant:delete | 删除 |
|
||
| PATCH | `/tenant/status/batch` | tenant:patch | 批量设置状态 |
|
||
| PUT | `/tenant/status/{id}` | tenant:update | 启/禁用 |
|
||
| GET | `/tenant/{id}/users` | tenant:query | 用户列表 |
|
||
| POST | `/tenant/{id}/users` | tenant:update | 添加用户 |
|
||
| DELETE | `/tenant/{id}/users/{uid}` | tenant:update | 移除用户 |
|
||
| GET | `/tenant/{id}/quota` | tenant:query | 获取配额 |
|
||
| PUT | `/tenant/{id}/quota` | tenant:update | 修改配额 |
|
||
| GET | `/tenant/{id}/config` | tenant:query | 获取配置 |
|
||
| PUT | `/tenant/{id}/config` | tenant:update | 更新配置 |
|
||
|
||
### 20.15 套餐模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/platform/package/detail/{id}` | package:query | 详情 |
|
||
| GET | `/platform/package/list` | package:query | 列表 |
|
||
| POST | `/platform/package/create` | package:create | 创建 |
|
||
| PUT | `/platform/package/update/{id}` | package:update | 更新 |
|
||
| DELETE | `/platform/package/delete` | package:delete | 删除 |
|
||
| GET | `/platform/package/{id}/menus` | package:query | 获取菜单 |
|
||
| PUT | `/platform/package/{id}/menus` | package:update | 设置菜单 |
|
||
|
||
### 20.16 监控模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/monitor/online/list` | module_monitor:online:query | 在线用户列表 |
|
||
| DELETE | `/monitor/online/delete` | module_monitor:online:delete | 强制下线 |
|
||
| DELETE | `/monitor/online/clear` | module_monitor:online:delete | 清空所有在线用户 |
|
||
| GET | `/monitor/cache/info` | module_monitor:cache:query | 获取缓存监控统计 |
|
||
| GET | `/monitor/cache/get/names` | module_monitor:cache:query | 获取缓存名称列表 |
|
||
| GET | `/monitor/cache/get/keys/{cache_name}` | module_monitor:cache:query | 获取缓存键名列表 |
|
||
| GET | `/monitor/cache/get/value/{cache_name}/{cache_key}` | module_monitor:cache:query | 获取缓存值 |
|
||
| DELETE | `/monitor/cache/delete/name/{cache_name}` | module_monitor:cache:delete | 清除指定缓存名称 |
|
||
| DELETE | `/monitor/cache/delete/key/{cache_key}` | module_monitor:cache:delete | 清除指定缓存键 |
|
||
| DELETE | `/monitor/cache/clear` | module_monitor:cache:delete | 清除所有缓存 |
|
||
| GET | `/monitor/resource/list` | module_monitor:resource:query | 目录列表(分页) |
|
||
| POST | `/monitor/resource/upload` | module_monitor:resource:upload | 上传文件 |
|
||
| GET | `/monitor/resource/download` | module_monitor:resource:download | 下载文件 |
|
||
| DELETE | `/monitor/resource/delete` | module_monitor:resource:delete | 删除文件 |
|
||
| POST | `/monitor/resource/move` | module_monitor:resource:move | 移动文件 |
|
||
| POST | `/monitor/resource/copy` | module_monitor:resource:copy | 复制文件 |
|
||
| POST | `/monitor/resource/rename` | module_monitor:resource:rename | 重命名文件 |
|
||
| POST | `/monitor/resource/mkdir` | module_monitor:resource:mkdir | 创建目录 |
|
||
| POST | `/monitor/resource/export` | module_monitor:resource:export | 导出资源列表 |
|
||
| GET | `/monitor/server/info` | module_monitor:server:query | 服务器监控信息 |
|
||
|
||
### 20.17 公共模块
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| POST | `/common/file/upload` | module_common:file:upload | 上传文件 |
|
||
| POST | `/common/file/download` | module_common:file:download | 下载文件 |
|
||
| GET | `/health` | — | 基础健康检查 |
|
||
| GET | `/health/live` | — | 存活探针 |
|
||
| GET | `/health/ready` | — | 就绪探针 |
|
||
| GET | `/metrics` | — | Prometheus 指标端点 |
|
||
|
||
### 20.18 邮件服务
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/platform/email/config` | platform:email:query | 获取 SMTP 配置 |
|
||
| PUT | `/platform/email/config` | platform:email:update | 更新 SMTP 配置 |
|
||
| POST | `/platform/email/test` | platform:email:update | 发送测试邮件 |
|
||
| GET | `/platform/email/template/list` | platform:email:query | 模板列表 |
|
||
| POST | `/platform/email/template/create` | platform:email:create | 创建模板 |
|
||
| PUT | `/platform/email/template/update/{id}` | platform:email:update | 更新模板 |
|
||
| GET | `/platform/email/log/list` | platform:email:query | 发送日志列表 |
|
||
|
||
### 20.19 订单与支付
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| POST | `/platform/order/create` | platform:order:create | 创建订单 |
|
||
| GET | `/platform/order/detail/{id}` | platform:order:query | 订单详情 |
|
||
| GET | `/platform/order/list` | platform:order:query | 订单列表 |
|
||
| POST | `/platform/order/cancel/{id}` | platform:order:update | 取消订单 |
|
||
| POST | `/platform/payment/callback/alipay` | — | 支付宝回调 |
|
||
| POST | `/platform/payment/callback/wxpay` | — | 微信支付回调 |
|
||
| GET | `/platform/payment/record/list` | platform:payment:query | 支付记录列表 |
|
||
|
||
### 20.20 租户自助服务
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/tenant/package/available` | tenant:package:query | 可选套餐列表 |
|
||
| GET | `/tenant/package/preview` | tenant:package:query | 套餐变更影响预览 |
|
||
| POST | `/tenant/order/create` | tenant:order:create | 创建自助订单 |
|
||
| GET | `/tenant/order/list` | tenant:order:query | 我的订单列表 |
|
||
| GET | `/tenant/order/detail/{id}` | tenant:order:query | 订单详情 |
|
||
|
||
### 20.21 用量统计
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/platform/api-usage/daily` | platform:api_usage:query | 按天用量统计 |
|
||
| GET | `/platform/api-usage/tenant/{id}` | platform:api_usage:query | 指定租户用量 |
|
||
| GET | `/platform/api-usage/rank` | platform:api_usage:query | 租户用量排行 |
|
||
| GET | `/platform/api-usage/anomalies` | platform:api_usage:query | 异常调用记录 |
|
||
|
||
### 20.22 用户邀请
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| POST | `/tenant/invite/send` | tenant:invite:create | 发送邀请 |
|
||
| GET | `/tenant/invite/list` | tenant:invite:query | 邀请列表 |
|
||
| DELETE | `/tenant/invite/cancel/{id}` | tenant:invite:delete | 取消邀请 |
|
||
| GET | `/invite/validate/{code}` | — | 校验邀请码(公开) |
|
||
| POST | `/invite/accept/{code}` | — | 接受邀请(需登录) |
|
||
|
||
### 20.23 发票管理
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| POST | `/tenant/invoice/apply` | tenant:invoice:create | 申请开票 |
|
||
| GET | `/tenant/invoice/list` | tenant:invoice:query | 我的发票列表 |
|
||
| GET | `/tenant/invoice/{id}/download` | tenant:invoice:download | 下载发票 PDF |
|
||
| GET | `/platform/invoice/list` | platform:invoice:query | 全部发票列表 |
|
||
| PUT | `/platform/invoice/issue/{id}` | platform:invoice:update | 开具发票 |
|
||
| PUT | `/platform/invoice/void/{id}` | platform:invoice:update | 作废发票 |
|
||
|
||
### 20.24 审计日志
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/platform/audit/list` | platform:audit:query | 审计日志列表 |
|
||
| GET | `/platform/audit/detail/{id}` | platform:audit:query | 审计日志详情 |
|
||
| GET | `/platform/audit/export` | platform:audit:export | 导出审计日志 |
|
||
|
||
### 20.25 运营大盘
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/platform/dashboard/overview` | platform:dashboard:query | 运营概览 |
|
||
| GET | `/platform/dashboard/revenue` | platform:dashboard:query | 收入趋势 |
|
||
| GET | `/platform/dashboard/tenants` | platform:dashboard:query | 租户统计 |
|
||
| GET | `/platform/dashboard/api-usage` | platform:dashboard:query | API 用量趋势 |
|
||
|
||
---
|
||
|
||
## 21. 数据库表结构
|
||
|
||
### 21.1 平台资源表(无 tenant_id)
|
||
|
||
| 表名 | 说明 | 关键索引 |
|
||
|------|------|---------|
|
||
| `platform_tenant` | 租户(单一大表,含配额+配置字段) | UNIQUE(name), UNIQUE(code) |
|
||
| `platform_package` | 套餐 | UNIQUE(name), UNIQUE(code) |
|
||
| `platform_package_menu` | 套餐-菜单关联 | UNIQUE(package_id, menu_id) |
|
||
| `platform_menu` | 菜单 | - |
|
||
| `platform_plugin` | 插件注册表 | UNIQUE(name), UNIQUE(code) |
|
||
| `platform_email_config` | 邮件 SMTP 配置 | 单例表 |
|
||
| `platform_email_template` | 邮件模板 | UNIQUE(code) |
|
||
| `platform_email_log` | 邮件发送日志 | - |
|
||
| `platform_order` | 订单 | UNIQUE(order_no) |
|
||
| `platform_payment_record` | 支付记录 | UNIQUE(transaction_id) |
|
||
|
||
### 21.2 租户关联表(FK→tenant,无独立 tenant_id 列)
|
||
|
||
| 表名 | 说明 | 关键索引 |
|
||
|------|------|---------|
|
||
| `platform_tenant_menu` | 租户自定义菜单 | UNIQUE(tenant_id, menu_id) |
|
||
| `platform_tenant_plugin` | 租户安装插件 | UNIQUE(tenant_id, plugin_id) |
|
||
| `platform_user_tenant` | 用户-租户关联 | UNIQUE(user_id, tenant_id) |
|
||
|
||
### 21.3 平台级租户关联业务表(含 tenant_id)
|
||
|
||
| 表名 | 说明 | 关键索引 |
|
||
|------|------|---------|
|
||
| `platform_invite_record` | 用户邀请记录 | UNIQUE(invite_code) |
|
||
| `platform_api_usage_daily` | API 用量日统计 | UNIQUE(tenant_id, date, api_path) |
|
||
|
||
### 21.4 租户隔离业务表(含 tenant_id)
|
||
|
||
| 表名 | 说明 | 关键索引 |
|
||
|------|------|---------|
|
||
| `sys_user` | 用户 | UNIQUE(tenant_id, username) |
|
||
| `sys_role` | 角色 | UNIQUE(tenant_id, code) |
|
||
| `sys_dept` | 部门 | UNIQUE(tenant_id, code) |
|
||
| `sys_position` | 岗位 | - |
|
||
| `sys_notice` | 通知公告 | - |
|
||
| `sys_param` | 系统参数 | - |
|
||
| `sys_operation_log` | 操作日志(租户隔离) | - |
|
||
| `platform_login_log` | 登录日志(平台级,无 tenant_id) | - |
|
||
| `platform_ticket` | 工单 | - |
|
||
|
||
### 21.4 平台共享业务表(含 tenant_id,__platform_data_shared__)
|
||
|
||
| 表名 | 说明 | 关键索引 |
|
||
|------|------|---------|
|
||
| `sys_dict_type` | 字典类型 | UNIQUE(tenant_id, dict_type) |
|
||
| `sys_dict_data` | 字典数据 | UNIQUE(tenant_id, dict_type_id, dict_value) |
|
||
|
||
### 21.5 关联表
|
||
|
||
| 表名 | 说明 | 约束 |
|
||
|------|------|------|
|
||
| `sys_user_roles` | 用户-角色关联 | PK(user_id, role_id),ON DELETE CASCADE |
|
||
| `sys_user_positions` | 用户-岗位关联 | PK(user_id, position_id),ON DELETE CASCADE |
|
||
| `sys_role_menus` | 角色-菜单关联 | PK(role_id, menu_id),ON DELETE CASCADE |
|
||
| `sys_role_depts` | 角色-部门关联 | PK(role_id, dept_id),ON DELETE CASCADE |
|
||
| `sys_notice_read` | 通知已读记录 | PK(user_id, notice_id),ON DELETE CASCADE |
|
||
|
||
### 21.6 插件表
|
||
|
||
| 表名 | 模块 | 说明 | 前缀规则 |
|
||
|------|------|------|---------|
|
||
| `task_workflow` | module_task/workflow | 工作流定义 | `task_` = module_task |
|
||
| `task_workflow_node_type` | module_task/workflow | 工作流节点类型 | `task_` = module_task |
|
||
| `task_node` | module_task/cronjob | 定时任务节点类型 | `task_` = module_task |
|
||
| `task_job` | module_task/cronjob | 任务执行日志 | `task_` = module_task |
|
||
| `gen_table` | module_generator/gencode | 代码生成表 | `gen_` = module_generator |
|
||
| `gen_table_column` | module_generator/gencode | 代码生成字段 | `gen_` = module_generator |
|
||
| `example_demo` | module_example/demo | 示例表 | `example_` = module_example |
|
||
| `example_demo01` | module_example/demo01 | 示例表01 | `example_` = module_example |
|
||
|
||
> **命名规范**:`platform_` = 平台模块,`sys_` = 系统模块,`task_` = 任务插件,`gen_` = 生成器插件,`example_` = 示例模块
|
||
|
||
### 21.7 商业运营表
|
||
|
||
| 表名 | 模块 | 说明 |
|
||
|------|------|------|
|
||
| `platform_invoice` | Invoice | 发票记录 |
|
||
| `platform_refund` | Order | 退款记录 |
|
||
| `platform_audit_log` | AuditLog | 审计日志 |
|
||
|
||
---
|
||
|
||
## 22. 安全性要求
|
||
|
||
1. **JWT 租户上下文**:从 Token 中提取 `tenant_id` 和 `is_super_admin`,通过 ContextVar 在整个请求周期传递
|
||
2. **白名单路径**:登录、验证码、健康检查等公开接口不设置租户上下文
|
||
3. **系统租户保护**:
|
||
- id=1 不可删除
|
||
- id=1 不可禁用
|
||
- id=1 的编码不可修改
|
||
4. **数据删除保护**:删除租户前检查关联数据,防止孤立记录
|
||
5. **租户 owner 保护**:每个租户至少保留一个 owner
|
||
6. **菜单越权防护**:非超管用户只能在租户可用菜单范围内分配角色菜单
|
||
7. **ContextVar 清理**:请求结束后清理 ContextVar,防止跨请求泄漏
|
||
8. **密码安全**:Bcrypt 哈希存储,不存储明文;普通用户密码最低 8 位(含字母+数字);初始管理员密码 12 位随机(含大小写字母+数字+特殊字符)
|
||
9. **XSS 防护**:通知公告内容经过 `sanitize_html` 清洗
|
||
10. **登录限流**:同一 IP/账号连续登录失败 5 次后锁定 15 分钟(Redis 计数 + TTL),防止暴力破解
|
||
11. **级联策略**:所有 FK 均有 ON DELETE/ON UPDATE 级联策略,保证数据完整性
|
||
12. **路径越权防护**:文件资源管理禁止路径遍历(`..`),防止越权访问
|
||
13. **CORS 配置**:通过白名单配置允许的来源域名,拒绝未授权的跨域请求
|
||
|
||
---
|
||
|
||
## 23. Email 邮件服务模块
|
||
|
||
### 23.1 业务描述
|
||
|
||
邮件服务是 SaaS 平台的通信基础设施,为密码重置、邀请通知、到期提醒、工单通知等业务提供统一的邮件发送能力。支持 SMTP 配置、模板管理、发送日志追踪。
|
||
|
||
### 23.2 数据模型
|
||
|
||
#### platform_email_config
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `smtp_host` | String(255) | NOT NULL | SMTP 服务器地址 |
|
||
| `smtp_port` | Integer | NOT NULL, default=465 | SMTP 端口 |
|
||
| `smtp_username` | String(255) | NOT NULL | SMTP 用户名 |
|
||
| `smtp_password` | String(255) | NOT NULL, 加密存储 | SMTP 密码 |
|
||
| `sender_name` | String(100) | NOT NULL | 发件人名称 |
|
||
| `sender_email` | String(255) | NOT NULL | 发件人邮箱 |
|
||
| `use_tls` | Boolean | default=True | 是否使用 TLS |
|
||
| `status` | Integer | default=0 | 状态(0:启用 1:禁用) |
|
||
|
||
> 单例表:仅一条记录。超管在平台配置中管理。
|
||
|
||
#### platform_email_template
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `code` | String(50) | NOT NULL, UNIQUE | 模板编码(如 `password_reset`、`tenant_invite`、`expiry_reminder`、`ticket_notify`) |
|
||
| `name` | String(100) | NOT NULL | 模板名称 |
|
||
| `subject` | String(255) | NOT NULL | 邮件主题(支持 `{变量}` 占位符) |
|
||
| `body` | Text | NOT NULL | 邮件正文(HTML,支持 `{变量}` 占位符) |
|
||
| `variables` | Text | nullable | 可用变量说明(JSON 数组,如 `["{username}", "{reset_link}"]`) |
|
||
| `status` | Integer | default=0 | 状态(0:启用 1:禁用) |
|
||
|
||
#### platform_email_log
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `template_code` | String(50) | nullable | 使用的模板编码 |
|
||
| `to_email` | String(255) | NOT NULL | 收件人邮箱 |
|
||
| `to_user_id` | FK→sys_user.id | nullable | 收件人用户 ID |
|
||
| `subject` | String(255) | NOT NULL | 实际发送的主题 |
|
||
| `body` | Text | NOT NULL | 实际发送的正文(渲染后) |
|
||
| `status` | Integer | NOT NULL, default=0 | 发送状态(0:待发送 1:成功 2:失败) |
|
||
| `error_msg` | Text | nullable | 失败原因 |
|
||
| `sent_time` | DateTime | nullable | 实际发送时间 |
|
||
| `retry_count` | Integer | default=0 | 重试次数 |
|
||
|
||
### 23.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **发送模式** | 支持同步发送和异步队列两种模式。默认异步(Redis 队列),避免阻塞主请求 |
|
||
| **重试策略** | 发送失败自动重试,最多 3 次,间隔 5 分钟。3 次仍失败则标记失败状态 |
|
||
| **频率限制** | 同一收件人同一模板 1 小时内最多发送 5 封,防止滥用 |
|
||
| **模板渲染** | 调用 `send_email(template_code, to, variables)` 时,自动从模板渲染 `subject` 和 `body` |
|
||
| **链路追踪** | 每次发送记录 `platform_email_log`,关联 `template_code` 和 `to_user_id` |
|
||
|
||
### 23.4 业务集成点
|
||
|
||
| 场景 | 模板编码 | 触发时机 | 变量 |
|
||
|------|---------|---------|------|
|
||
| **密码重置** | `password_reset` | 创建租户初始管理员 / 用户忘记密码 | `{username}`, `{reset_link}` |
|
||
| **租户邀请** | `tenant_invite` | 管理员邀请用户加入租户 | `{inviter}`, `{tenant_name}`, `{invite_link}` |
|
||
| **到期提醒(30/7/1天)** | `expiry_reminder` | 定时任务检测到期 | `{tenant_name}`, `{expire_date}`, `{days_left}` |
|
||
| **工单通知** | `ticket_notify` | 工单创建/分配/关闭 | `{ticket_title}`, `{status}`, `{assignee}` |
|
||
| **套餐变更通知** | `package_change` | 租户套餐被超管变更 | `{old_package}`, `{new_package}`, `{removed_menus}` |
|
||
|
||
### 23.5 降级策略
|
||
|
||
当邮件服务不可用时(SMTP 故障、配置缺失),自动降级为**站内信**(`sys_notice`),确保关键信息不丢失。
|
||
|
||
### 23.6 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/platform/email/config` | 获取 SMTP 配置 | 超管 |
|
||
| PUT | `/platform/email/config` | 更新 SMTP 配置 | 超管 |
|
||
| POST | `/platform/email/test` | 发送测试邮件 | 超管 |
|
||
| GET | `/platform/email/template/list` | 模板列表 | 超管 |
|
||
| POST | `/platform/email/template/create` | 创建模板 | 超管 |
|
||
| PUT | `/platform/email/template/update/{id}` | 更新模板 | 超管 |
|
||
| GET | `/platform/email/log/list` | 发送日志列表 | 超管 |
|
||
|
||
---
|
||
|
||
## 24. Order 订单与支付模块
|
||
|
||
### 24.1 业务描述
|
||
|
||
订单与支付模块是 SaaS 平台的商业化基础,覆盖订单创建、支付回调、开通激活、续费/升级的完整交易闭环。对接支付宝和微信支付,支持套餐购买、续费和升级三种业务场景。
|
||
|
||
### 24.2 业务流程
|
||
|
||
```
|
||
用户/超管选择套餐 → 生成订单 → 跳转支付 → 支付回调 → 激活/变更套餐
|
||
↓ 超时(15分钟)
|
||
订单自动取消
|
||
```
|
||
|
||
### 24.3 数据模型
|
||
|
||
#### platform_order
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `order_no` | String(32) | NOT NULL, UNIQUE | 订单号(年月日+6位随机数) |
|
||
| `tenant_id` | FK→platform_tenant.id | NOT NULL | 购买租户 |
|
||
| `package_id` | FK→platform_package.id | NOT NULL | 购买套餐 |
|
||
| `order_type` | String(20) | NOT NULL | 类型:`new`(新购) `renew`(续费) `upgrade`(升级) `downgrade`(降级) |
|
||
| `amount` | Integer | NOT NULL | 金额(分,≥0;0=免费套餐) |
|
||
| `period_count` | Integer | NOT NULL, default=1 | 购买周期数(1个月=1) |
|
||
| `status` | Integer | NOT NULL, default=0 | 状态:0=待支付 1=已支付 2=已取消 3=已退款 |
|
||
| `pay_method` | String(20) | nullable | 支付方式:`alipay`(支付宝) / `wxpay`(微信支付) |
|
||
| `pay_time` | DateTime | nullable | 支付时间 |
|
||
| `expire_time` | DateTime | NOT NULL | 订单过期时间(创建后+15分钟),超时未支付自动取消 |
|
||
|
||
#### platform_payment_record
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `order_id` | FK→platform_order.id | NOT NULL | 关联订单 |
|
||
| `transaction_id` | String(64) | nullable | 第三方交易号 |
|
||
| `pay_method` | String(20) | NOT NULL | 支付方式 |
|
||
| `amount` | Integer | NOT NULL | 支付金额(分) |
|
||
| `status` | Integer | NOT NULL | 支付结果:0=处理中 1=成功 2=失败 |
|
||
| `raw_response` | Text | nullable | 支付平台原始回调数据(JSON) |
|
||
| `pay_time` | DateTime | nullable | 支付完成时间 |
|
||
|
||
### 24.4 支付回调处理流程
|
||
|
||
```
|
||
POST /platform/payment/callback/{method}
|
||
├── IP 白名单校验(仅允许支付宝/微信支付官方 IP 段)
|
||
├── 验证签名(支付宝 RSA / 微信支付 APIv3 签名)
|
||
├── 分布式锁(Redis SETNX,key=callback_lock:{transaction_id},TTL=30s)
|
||
├── 校验金额一致性(回调金额 == 订单金额)
|
||
├── 校验订单状态(仅 status=0(待支付) 可处理,防止重复激活)
|
||
├── 更新 platform_order.status=1、pay_time=now
|
||
├── 写入 platform_payment_record(transaction_id UNIQUE 约束,第二次写入自动失败)
|
||
├── 根据 order_type 执行激活逻辑:
|
||
│ ├── new/renew → 更新 tenant.end_time、恢复 status=0(active)
|
||
│ ├── upgrade → 更新 tenant.package_id、执行套餐变更影响预览逻辑(菜单+配额同步)
|
||
│ └── downgrade → 更新 tenant.package_id、清理超出的菜单关联、更新配额
|
||
├── 发送通知给租户管理员(邮件 + 站内信)
|
||
├── 释放分布式锁
|
||
└── 返回 success 给支付平台(防止重复回调)
|
||
```
|
||
|
||
> **安全要点**:
|
||
> - IP 白名单:仅允许支付宝/微信支付的官方回调 IP,在 Nginx/LB 层配置
|
||
> - 分布式锁:解决支付平台可能同时回调多条相同交易的并发问题
|
||
> - 状态校验:status≠0 的订单拒绝处理,防止恶意/重复回调
|
||
> - 金额校验:回调金额与订单金额不一致时,标记异常并人工介入
|
||
|
||
### 24.5 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **订单号生成** | `{YYYYMMDD}{6位随机数字}`,创建时检查唯一性 |
|
||
| **过期取消** | 定时任务 `cancel_expired_orders` 每分钟扫描 status=0 且 `expire_time < now` 的订单,设为 status=2(已取消) |
|
||
| **幂等性** | 同一 `transaction_id` 的回调只处理一次(transaction_id UNIQUE 约束 + 分布式锁双重保障) |
|
||
| **金额校验** | 回调金额必须与订单金额一致,不一致则拒绝并告警 |
|
||
| **IP 白名单** | 回调接口仅允许支付宝/微信支付官方 IP 调用,在 Nginx/负载均衡层配置 |
|
||
| **免费套餐** | amount=0 时不跳转支付,直接走激活流程 |
|
||
| **退款** | 退款为预留扩展,当前仅支持手动标记 status=3 |
|
||
|
||
### 24.7 退款流程
|
||
|
||
```
|
||
租户管理员申请退款
|
||
├── POST /tenant/order/refund/apply/{order_id}
|
||
│ 条件:订单 status=1(已支付) 且支付时间在 7 天内
|
||
│ body: {reason: "误购/重复支付/服务不满意"}
|
||
├── 更新 platform_order.refund_status=1(申请中)
|
||
├── 创建 platform_refund 记录
|
||
├── 通知超管审核(站内信)
|
||
└── 返回申请结果
|
||
|
||
超管审核退款
|
||
├── GET /platform/refund/list(待审核列表)
|
||
├── PUT /platform/refund/approve/{id}
|
||
│ 触发原路退款(调用支付宝/微信退款 API)
|
||
│ 更新 platform_refund.status=2(已退款)
|
||
│ 更新 platform_order.status=3(已退款)
|
||
│ 更新租户套餐(撤销本次购买升级效果,恢复至购买前套餐/到期时间)
|
||
└── PUT /platform/refund/reject/{id}
|
||
更新 platform_refund.status=3(已驳回)
|
||
记录驳回原因
|
||
```
|
||
|
||
#### platform_refund
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `order_id` | FK→platform_order.id | NOT NULL, UNIQUE | 关联订单 |
|
||
| `refund_no` | String(32) | NOT NULL, UNIQUE | 退款单号 |
|
||
| `amount` | Integer | NOT NULL | 退款金额(分) |
|
||
| `reason` | Text | NOT NULL | 退款原因 |
|
||
| `status` | Integer | NOT NULL, default=1 | 1=申请中 2=已退款 3=已驳回 4=已取消 |
|
||
| `refund_transaction_id` | String(64) | nullable | 退款交易号(第三方返回) |
|
||
| `reviewer_id` | FK→sys_user.id | nullable | 审核人 |
|
||
| `review_time` | DateTime | nullable | 审核时间 |
|
||
| `reject_reason` | Text | nullable | 驳回原因 |
|
||
|
||
| **退款规则** | 说明 |
|
||
|------|------|
|
||
| **可退款条件** | 支付后 7 天内,订单 status=1(已支付) |
|
||
| **退款金额** | 全额退款(暂不支持部分退款) |
|
||
| **退款方式** | 原路退回(支付宝→支付宝,微信→微信) |
|
||
| **套餐回退** | 退款后恢复至购买前的套餐和到期时间(若为升级/降级订单) |
|
||
| **降级补偿** | 若退款订单为降级类型,退款后套餐回升至降级前套餐 |
|
||
| **免费套餐** | amount=0 的免费套餐订单不支持退款 |
|
||
|
||
### 24.8 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| POST | `/platform/order/create` | 创建订单 | 超管 |
|
||
| GET | `/platform/order/detail/{id}` | 订单详情 | 超管 |
|
||
| GET | `/platform/order/list` | 订单列表 | 超管 |
|
||
| POST | `/platform/order/cancel/{id}` | 取消订单 | 超管 |
|
||
| POST | `/platform/payment/callback/alipay` | 支付宝回调(外网可访问,签名验证) | 公开 |
|
||
| POST | `/platform/payment/callback/wxpay` | 微信支付回调(外网可访问,签名验证) | 公开 |
|
||
| GET | `/platform/payment/record/list` | 支付记录列表 | 超管 |
|
||
| POST | `/tenant/order/create` | 租户端创建订单(自助购买/续费/升级) | 租户管理员 |
|
||
| POST | `/tenant/order/refund/apply/{id}` | 申请退款 | 租户管理员 |
|
||
| GET | `/platform/refund/list` | 退款审核列表 | 超管 |
|
||
| PUT | `/platform/refund/approve/{id}` | 批准退款(触发原路退回) | 超管 |
|
||
| PUT | `/platform/refund/reject/{id}` | 驳回退款 | 超管 |
|
||
|
||
---
|
||
|
||
## 25. TenantSelfService 租户自助服务(代码位于 module_platform/self_service)
|
||
|
||
### 25.1 业务描述
|
||
|
||
租户管理员可在租户管理后台自助选择套餐、购买、续费或升级,无需超管介入。是 SaaS 产品商业化的核心用户侧功能。
|
||
|
||
### 25.2 自助套餐选择流程
|
||
|
||
```
|
||
GET /tenant/package/available
|
||
├── 返回所有启用的套餐列表
|
||
├── 标注当前套餐(is_current=true)
|
||
├── 展示价格/周期/试用天数/功能对比
|
||
├── 标注可执行的操作:[购买][续费][升级][降级]
|
||
└── 限制:同一套餐已是当前套餐时不展示"升级"按钮
|
||
|
||
用户选择操作 → 创建订单 → 支付 → 自动激活
|
||
```
|
||
|
||
### 25.3 套餐变更影响预览(自助版)
|
||
|
||
```json
|
||
// GET /tenant/package/preview?target_package_id=xxx 返回
|
||
{
|
||
"current_package": "basic",
|
||
"target_package": "pro",
|
||
"action": "upgrade",
|
||
"amount": 29900,
|
||
"period": "month",
|
||
"gained_menus": [
|
||
{"name": "数据报表", "path": "/report/dashboard"},
|
||
{"name": "API 管理", "path": "/api/manage"}
|
||
],
|
||
"lost_menus": [],
|
||
"affected_roles": [],
|
||
"affected_users": 0
|
||
}
|
||
```
|
||
|
||
### 25.4 自助升级/降级流程
|
||
|
||
```
|
||
POST /tenant/order/create (body: {package_id, order_type: "upgrade"})
|
||
├── 校验权限:租户管理员及以上
|
||
├── 校验租户状态:仅 active(0)/grace(1)/suspended(2) 可操作
|
||
├── 校验目标套餐:状态启用且不等于当前套餐
|
||
├── amount > 0 → 跳转支付 → 支付回调激活
|
||
├── amount = 0 → 直接激活(免费套餐切换)
|
||
└── 激活时执行套餐变更影响预览逻辑(同超管操作 §15.3)
|
||
```
|
||
|
||
### 25.5 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/tenant/package/available` | 获取可选套餐列表(含当前套餐标记和可执行操作) | 租户管理员 |
|
||
| GET | `/tenant/package/preview` | 套餐变更影响预览 | 租户管理员 |
|
||
| POST | `/tenant/order/create` | 创建自助订单(购买/续费/升级/降级) | 租户管理员 |
|
||
| GET | `/tenant/order/list` | 我的订单列表 | 租户管理员 |
|
||
| GET | `/tenant/order/detail/{id}` | 我的订单详情 | 租户管理员 |
|
||
|
||
---
|
||
|
||
## 26. APIUsage 用量统计模块
|
||
|
||
### 26.1 业务描述
|
||
|
||
租户级别 API 调用量/频率统计,按天/月聚合,支持计费挂钩、安全异常检测和运营分析。
|
||
|
||
### 26.2 数据模型
|
||
|
||
#### platform_api_usage_daily
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `tenant_id` | FK→platform_tenant.id | NOT NULL | 租户 |
|
||
| `date` | Date | NOT NULL | 统计日期 |
|
||
| `api_path` | String(255) | NOT NULL | API 路径 |
|
||
| `request_count` | Integer | NOT NULL, default=0 | 请求次数 |
|
||
| `total_duration_ms` | BigInt | NOT NULL, default=0 | 总耗时(毫秒) |
|
||
| `error_count` | Integer | NOT NULL, default=0 | 错误次数(4xx/5xx) |
|
||
|
||
> 唯一约束:`UNIQUE(tenant_id, date, api_path)`
|
||
|
||
### 26.3 统计机制
|
||
|
||
```
|
||
请求中间件(每个 API 调用)
|
||
├── 提取 tenant_id、api_path、status_code、响应时间
|
||
├── Redis 计数器原子递增:api_usage:{tenant_id}:{date}:{api_path}:count
|
||
├── Redis 计数器:api_usage:{tenant_id}:{date}:{api_path}:duration
|
||
├── 错误计数(status_code >= 400):api_usage:{tenant_id}:{date}:{api_path}:errors
|
||
└── 定时任务(每小时):读取 Redis → UPSERT 到 platform_api_usage_daily → 清理旧 Redis key
|
||
```
|
||
|
||
### 26.4 异常检测规则
|
||
|
||
| 规则 | 条件 | 动作 |
|
||
|------|------|------|
|
||
| **频率突变** | 同一 API 调用量超过过去 7 天均值的 5 倍 | 站内信告警 |
|
||
| **错误率过高** | 错误率 > 20% 且请求数 > 100 | 站内信告警 |
|
||
| **高频调用** | 单租户单 API 超过 1000 次/分钟 | 临时限流(返回 429) |
|
||
|
||
> 限流配置:`rate_limit_enabled`(全局开关),`rate_limit_threshold`(阈值),均可在平台配置中调整。
|
||
|
||
### 26.5 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/platform/api-usage/daily` | 按天用量统计(支持租户/日期范围筛选) | 超管 |
|
||
| GET | `/platform/api-usage/tenant/{id}` | 指定租户用量详情 | 超管 |
|
||
| GET | `/platform/api-usage/rank` | 租户用量排行 | 超管 |
|
||
| GET | `/platform/api-usage/anomalies` | 异常调用记录 | 超管 |
|
||
|
||
---
|
||
|
||
## 27. UserInvite 用户邀请流程
|
||
|
||
### 27.1 业务描述
|
||
|
||
租户管理员可通过邀请链接或邀请码邀请新用户加入租户。被邀请人通过邮箱接收邀请,点击链接完成注册并自动关联到指定租户和角色。
|
||
|
||
### 27.2 数据模型
|
||
|
||
#### platform_invite_record
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `invite_code` | String(32) | NOT NULL, UNIQUE | 邀请码(UUID,一次性链接参数) |
|
||
| `tenant_id` | FK→platform_tenant.id | NOT NULL | 目标租户 |
|
||
| `target_role_id` | FK→sys_role.id | NOT NULL | 预设角色 |
|
||
| `inviter_id` | FK→sys_user.id | NOT NULL | 邀请人 |
|
||
| `invitee_email` | String(255) | NOT NULL | 被邀请人邮箱 |
|
||
| `status` | Integer | NOT NULL, default=0 | 状态:0=待接受 1=已接受 2=已过期 3=已取消 |
|
||
| `expire_time` | DateTime | NOT NULL | 过期时间(创建后+7天) |
|
||
| `accepted_user_id` | FK→sys_user.id | nullable | 接受邀请后创建的用户 ID |
|
||
| `accepted_time` | DateTime | nullable | 接受时间 |
|
||
|
||
### 27.3 邀请流程
|
||
|
||
```
|
||
租户管理员发起邀请
|
||
├── POST /tenant/invite/send
|
||
│ body: {emails: [...], role_id, message?}
|
||
├── 批量创建 platform_invite_record 行,生成唯一 invite_code
|
||
├── 发送邮件(模板 `tenant_invite`,含邀请链接)
|
||
├── 邮件内容:{inviter} 邀请你加入 {tenant_name},点击链接注册
|
||
└── 链接格式:{domain}/invite/{invite_code},有效期 7 天
|
||
|
||
被邀请人接受邀请
|
||
├── 访问 /invite/{code} 页面
|
||
├── 校验邀请码:存在、未过期(expire_time > now)、未使用(status=0)
|
||
├── 如果用户已注册:
|
||
│ ├── 直接关联到租户(sys_user_tenant 插入记录)
|
||
│ ├── 分配预设角色(sys_user_role 插入记录)
|
||
│ └── 更新 invite_record.status=1
|
||
├── 如果用户未注册:
|
||
│ ├── 跳转到注册页面(邮箱已预填,不可修改)
|
||
│ ├── 用户完成注册
|
||
│ ├── 自动关联到租户,分配预设角色
|
||
│ └── 更新 invite_record.status=1, accepted_user_id
|
||
└── 通知邀请人"XXX 已接受您的邀请"
|
||
```
|
||
|
||
### 27.4 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **邀请码唯一性** | 每次生成全局唯一的 UUID,即使同一邮箱被重复邀请也不同 |
|
||
| **有效期** | 默认 7 天,到期后自动标记 status=2(过期),不再可用 |
|
||
| **重复邀请** | 同一租户内,同一邮箱有"待接受"的邀请时,提示"该邮箱已有待接受的邀请",不重复发送 |
|
||
| **角色预分配** | 被邀请人加入租户时自动获得 `target_role_id` 指定的角色 |
|
||
| **权限** | 仅租户管理员(owner/admin)可发送邀请 |
|
||
| **邀请人可见** | 可查看自己发出的邀请列表及状态 |
|
||
| **降级** | 若邮件服务不可用,邀请码可通过站内消息手动复制链接 |
|
||
|
||
### 27.5 过期清理
|
||
|
||
定时任务 `cleanup_expired_invites` 每天扫描 `status=0` 且 `expire_time < now` 的记录,标记为 status=2。
|
||
|
||
### 27.6 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| POST | `/tenant/invite/send` | 发送邀请 | 租户管理员 |
|
||
| GET | `/tenant/invite/list` | 邀请列表(含状态) | 租户管理员 |
|
||
| DELETE | `/tenant/invite/cancel/{id}` | 取消邀请 | 租户管理员 |
|
||
| GET | `/invite/validate/{code}` | 校验邀请码(公开接口,返回租户名/邀请人) | 公开 |
|
||
| POST | `/invite/accept/{code}` | 接受邀请(需登录) | 登录用户 |
|
||
|
||
---
|
||
|
||
## 28. 未来扩展建议
|
||
|
||
### 28.1 已规划(短期)
|
||
|
||
1. **知识库/帮助中心**:租户自助查阅帮助文档、常见问题。富文本编辑器管理,支持多语言
|
||
2. **数据导出/备份**:租户自助数据导出(CSV/JSON),满足 GDPR/个保法合规要求。平台级全量备份还原(数据库级)
|
||
3. **租户自定义域名**:支持通过 `domain` 字段实现租户专属域名,需配合 Nginx 反向代理配置
|
||
|
||
### 28.2 中期扩展
|
||
|
||
| 能力 | 说明 | 优先级 |
|
||
|------|------|--------|
|
||
| **单点登录(SSO)** | 支持 SAML/OIDC 协议,企业客户可使用自有 IdP(如 Okta/Azure AD/自有 LDAP)登录 | 低 |
|
||
| **多语言支持** | 租户级 i18n 配置,支持不同租户使用不同语言 | 低 |
|
||
| **Webhook 通知** | 关键事件(支付成功/到期提醒/套餐变更)的 webhook 回调,支持第三方集成 | 中 |
|
||
|
||
### 28.3 API 路径规范
|
||
|
||
| 问题 | 当前 | 建议 |
|
||
|------|------|------|
|
||
| 参数模块名不一致 | `/param/`(单数)vs 模块名 `params`(复数) | 统一为 `/param/`(与代码一致) |
|
||
| 日志层级问题 | 操作日志 `/system/operationlog/` 与其他模块不统一 | 建议保持现状。登录日志为平台级、操作日志为租户级,层级分开是合理的 |
|
||
|
||
### 28.4 非功能性需求(NFR)
|
||
|
||
| 指标 | 要求 |
|
||
|------|------|
|
||
| **API 响应时间** | P95 ≤ 500ms(查询),P95 ≤ 2s(写入/批操作) |
|
||
| **并发用户** | 单实例支持 500+ 并发租户用户(需压测验证) |
|
||
| **可用性** | 99.5%(不包含计划运维窗口) |
|
||
| **数据安全** | 传输层 TLS 1.3,存储层 Bcrypt/AES-256,日志脱敏(手机号/邮箱部分掩码) |
|
||
| **兼容性** | 支持 MySQL 8.0+ / PostgreSQL 14+ / SQLite(开发环境);Python ≥ 3.12;Node.js ≥ 20 |
|
||
| **数据库备份** | 每日全量备份(保留 30 天),每小时增量备份(保留 7 天)。备份异地存储,定期恢复演练(每季度 1 次) |
|
||
| **容灾恢复** | RTO ≤ 4 小时,RPO ≤ 1 小时。主库故障时自动切换只读副本,30 分钟内完成主从切换 |
|
||
| **版本升级策略** | 数据库迁移采用 Alembic 管理,所有 schema 变更通过 migration 脚本执行。升级前自动备份,升级失败可回滚至上一个备份点。主版本升级需提前通知租户(7 天),次版本/补丁版可灰度发布 |
|
||
| **i18n 基础** | 后端 API 错误消息统一使用 i18n key(如 `errors.user.not_found`),前端使用 vue-i18n。初始版本仅提供中文,保留英文翻译文件占位。租户级语言首选项存储在 `platform_tenant.lang` 字段(预留) |
|
||
| **缓存键命名规范** | 格式:`{namespace}:{sub_namespace}:{identifier}`。示例:`tenant:config:123`、`api:usage:456:2026-06-03`、`auth:session:abc123`。所有 key 设置 TTL,禁止无过期时间的 key |
|
||
|
||
---
|
||
|
||
## 29. 术语表(Glossary)
|
||
|
||
| 术语 | 英文 | 说明 |
|
||
|------|------|------|
|
||
| **租户** | Tenant | SaaS 平台上的一个独立组织/客户 |
|
||
| **平台资源** | Platform Resource | 无 tenant_id 的资源,所有租户共享(菜单/套餐/插件) |
|
||
| **租户资源** | Tenant Resource | 含 tenant_id 的资源,按租户隔离(用户/角色/部门等) |
|
||
| **平台共享数据** | Shared Platform Data | tenant_id=1 的字典数据,所有租户可读 |
|
||
| **超管** | Super Admin | 平台级管理员,`is_super_admin=true`,可管理所有租户 |
|
||
| **租户管理员** | Tenant Admin | 租户内的管理员,角色为 owner/admin |
|
||
| **数据权限范围** | Data Scope | 角色绑定的数据可见范围(全部/本部门及子部门/仅本部门等) |
|
||
| **RBAC** | Role-Based Access Control | 基于角色的访问控制 |
|
||
| **Mixin** | Mixin | SQLAlchemy 混入模式,用于给模型添加通用字段(如 TenantMixin 自动添加 tenant_id) |
|
||
| **处理人** | Assignee | 工单中指派的处理人员 |
|
||
| **生命周期** | Lifecycle | 租户的完整状态流转路径:active(0)→grace(1)→suspended(2)→expired(4)→archived(5)→deleted。人工冻结路径:active(0)→frozen(3)→archived(5) |
|
||
| **宽限期** | Grace Period | 租户到期后的缓冲期(默认7天),允许正常使用但提示续费 |
|
||
| **订单** | Order | 套餐购买/续费/升级的交易凭证,关联支付回调激活套餐 |
|
||
| **邀请码** | Invite Code | 租户管理员邀请用户加入的一次性链接参数(UUID,7天有效) |
|
||
| **用量统计** | API Usage | 租户级别 API 调用量按天聚合统计,用于计费和安全分析 |
|
||
| **邮件模板** | Email Template | 预定义的邮件格式(密码重置/邀请/到期提醒),支持变量占位符渲染 |
|
||
| **支付回调** | Payment Callback | 支付宝/微信支付完成后异步通知平台更新订单状态的机制 |
|
||
| **默认套餐** | Default Package | 标记 is_default=true 的套餐,自助注册时自动选用 |
|
||
| **分布式锁** | Distributed Lock | Redis SETNX 实现的并发互斥机制,防止支付回调等场景的重复处理 |
|
||
| **数据库迁移** | Database Migration | 使用 Alembic 管理的版本化 schema 变更脚本,支持升级和回滚 |
|
||
| **发票** | Invoice | 订单支付后开具的电子发票(增值税普票/专票),一单一票 |
|
||
| **审计日志** | Audit Log | 不可篡改的合规操作记录,仅超管可查阅,保留 3 年 |
|
||
| **运营大盘** | Dashboard | 平台运营数据的可视化看板,聚合租户/收入/API 用量等核心指标 |
|
||
| **原路退回** | Refund | 支付退款按原支付路径返回(支付宝→支付宝,微信→微信) |
|
||
|
||
---
|
||
|
||
## 30. 变更记录
|
||
|
||
| 版本 | 日期 | 变更内容 |
|
||
|------|------|---------|
|
||
| v3.1.0 | 2026-06-01 | 初始版本,完整的模块化需求文档 |
|
||
| v3.2.0 | 2026-06-02 | 新增 Plugin 子模块需求:AI Chat/Cronjob/Workflow/CodeGen/Demo;新增 Monitor 监控模块:Online/Cache/Resource/Server;新增 Common 公共模块:File/Health/Metrics |
|
||
| v3.2.1 | 2026-06-03 | **需求审查修复**:修复全部章节子标题编号错位;统一表名为 `platform_*` 前缀(与代码一致);移除已废弃的 `sys_tenant_quota`/`sys_tenant_config` 独立表引用;拆分 `sys_log` 为 `sys_operation_log` + `platform_login_log`;统一 Auth 端点路径;明确多租户登录临时/正式 token 机制;补充用户注册租户自动创建流程;添加 `start_time` 未生效校验;补充通知公告已读机制;补全 Tenant 模型遗漏字段(description/version/privacy 等);新增安全性要求(登录限流/密码复杂度/CORS);更新未来扩展建议 |
|
||
| v3.2.2 | 2026-06-03 | **命名规范统一**:修复文档中 `sys_login_log`→`platform_login_log`、`sys_ticket`→`platform_ticket` 两处表名错误;在 §21 新增 §21.6 插件表汇总(8 张 task_/gen_ 表);明确全模块命名规范:`platform_`=平台模块,`sys_`=系统模块,`task_`=任务插件,`gen_`=生成器插件 |
|
||
| v3.3.0 | 2026-06-03 | **SaaS 产品需求审查修订**:P0-1 租户生命周期状态机(active→frozen→archived→deleted);P0-2 定时任务/工作流代码执行安全性(任意代码→预定义处理器白名单);P0-3 套餐模型补充定价字段(price/period/trial_days/max_tenants);P0-4 初始管理员密码交付改为邮件一次性重置链接;P1-1 通知已读机制改为后端 sys_notice_read 表;P1-2 工单增加 close_reason/closed_time/closed_by 字段;P1-3 租户到期增加宽限期和阶段性处理(grace→suspended→expired);P1-4 用户导入密码处理策略;P1-5 套餐变更增加影响预览和确认流程;P2 操作日志保留策略、API 路径规范、缺失 SaaS 能力规划(用户邀请/数据导出/API用量/审计日志/SSO);新增 NFR 非功能性需求、术语表 |
|
||
| v3.4.0 | 2026-06-03 | **业务架构闭环补全**:Fix-1 统一 status 编码(String(1)→Integer,合并生命周期与到期阶段编码:0=active/1=grace/2=suspended/3=frozen/4=expired/5=archived);Fix-2 新增 §23 Email 邮件服务模块(SMTP 配置/模板管理/发送日志/5大业务集成点/站内信降级);Fix-3 新增 §24 Order 订单与支付模块(订单表/支付记录表/支付宝&微信支付回调/开通续费升级流程);Fix-4 新增 §25 TenantSelfService 租户自助服务(套餐选择/影响预览/自助升级降级);Fix-5 新增 §26 APIUsage 用量统计模块(按天聚合/Redis计数器/异常检测/限流);Fix-6 新增 §27 UserInvite 用户邀请流程(邀请码/邮件邀请/角色预分配/过期清理);Fix-7 清理残留与全面重编号(移除 §19.4 残留 TODO、§20 新增 §20.18-§20.22 API端点、§21 新增7张新表、§28-§30 重编号、§31-§37 Plugin模块重编号、§29 术语表扩充8个词条、§30 变更记录更新) |
|
||
| v3.5.0 | 2026-06-03 | **PRD 正式评审修复**:P0-1 修正 Part 4 Plugin 子模块编号(§31-§37 子节编号 25.x-31.x→31.x-37.x,共 34 处);P0-2 修复初始管理员体验断层(创建租户时自动创建 owner 角色并分配全量菜单,§6.3/§15.3/§15.4 同步更新);P0-3 统一 status 字段类型(package/ticket/order/payment/invite 全部从 String→Integer,保持与 tenant.status 一致);P1-1 标题版本号修正(v3.2.2→v3.5.0);P1-2 自助注册新增默认套餐/配额/到期时间来源(§4.5 注册流程、§16.2 is_default 字段);P1-3 套餐配额体系补充(§16.2 新增 max_users/max_roles/max_depts 配额字段);P1-4 套餐变更同步更新配额(§15.3 增加配额对比预览和升级/降级处理逻辑);P1-5 支付回调安全细节增强(§24.4/§24.5 新增 IP 白名单、分布式锁、状态校验);P2-1 API 路径规范(§16.5 套餐路径统一为 /platform/package/);P2-2 新增数据备份与容灾策略(§28.4 NFR);P2-3 新增版本升级/迁移策略(§28.4 NFR);P2-4 新增 i18n 基础设计(§28.4 NFR);P2-5 新增 Redis 缓存键命名规范(§28.4 NFR);术语表扩充 4 个词条(默认套餐/分布式锁/数据库迁移/冗余恢复) |
|
||
| v3.6.0 | 2026-06-03 | **PRD 100% 完整度达标**:Fix-1 修正 §26.2/§27.2 子节编号错误(32.2→26.2、33.2→27.2);Fix-2 修正 §28 节编号排序(28.5→28.3、删除重复 28.5);Fix-3 §24.7 新增退款流程(platform_refund 表、申请→审核→原路退回、套餐回退逻辑);Fix-4 新增 §38 Invoice 发票管理模块(普票/专票、百望云等第三方对接、一单一票、30天开票时限);Fix-5 新增 §39 AuditLog 审计日志模块(不可篡改、JSON 变更对比、13 种审计事件、3年保留策略);Fix-6 新增 §40 Dashboard 运营大盘模块(MRR/退款率/API用量/套餐分布/收入趋势 9 项指标);Fix-7 更新 §1.4 模块总览(新增 3 个模块)、§20 新增 §20.23-§20.25 API端点、§21 新增 §21.7 商业运营表、§28 移除已实现项、§29 术语表扩充 4 个词条 |
|
||
|
||
|
||
|
||
---
|
||
|
||
# Part 4:Plugin 子模块需求
|
||
|
||
---
|
||
|
||
## 31. AI Chat 聊天模块(module_ai/chat)
|
||
|
||
### 31.1 业务描述
|
||
|
||
AI 对话模块,提供用户与大模型进行对话的能力。支持多会话管理、WebSocket 流式对话、非流式对话。ChatSession 数据按租户隔离。
|
||
|
||
### 31.2 数据模型
|
||
|
||
聊天会话数据存储在 ChatService 后端(支持内存存储/Redis/数据库三种模式,由配置决定)。Schema 层定义如下:
|
||
|
||
#### ChatSessionCreateSchema
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `title` | str | NOT NULL, min_length=1, max_length=200 | 会话标题 |
|
||
|
||
#### ChatSessionUpdateSchema
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `title` | str | NOT NULL, min_length=1, max_length=200 | 会话标题 |
|
||
|
||
#### AiChatRequestSchema
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `message` | str | NOT NULL, min_length=1 | 用户消息内容 |
|
||
| `session_id` | str | nullable | 会话ID,不传则创建新会话 |
|
||
|
||
#### AiChatResponseSchema
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `response` | str | NOT NULL | AI 回复内容 |
|
||
| `session_id` | str | NOT NULL | 会话ID |
|
||
| `function_calls` | list[dict] | nullable | 函数调用信息 |
|
||
| `action` | dict | nullable | 建议执行的操作 |
|
||
|
||
### 31.3 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/chat/detail/{session_id}` | module_ai:chat:detail | 会话详情 |
|
||
| GET | `/chat/list` | module_ai:chat:query | 会话列表 |
|
||
| POST | `/chat/create` | module_ai:chat:create | 创建会话 |
|
||
| PUT | `/chat/update/{session_id}` | module_ai:chat:update | 更新会话 |
|
||
| DELETE | `/chat/delete` | module_ai:chat:delete | 删除会话 |
|
||
| POST | `/chat/ai-chat` | module_ai:chat:query | AI 对话(非流式) |
|
||
| WS | `/chat/ws` | — | WebSocket 流式对话 |
|
||
|
||
---
|
||
|
||
## 32. Cronjob 定时任务模块(module_task/cronjob)
|
||
|
||
### 32.1 业务描述
|
||
|
||
定时任务模块提供动态节点定义(NodeModel)和任务执行日志记录(JobModel)。节点定义执行代码块、触发器和参数,通过 APScheduler 调度执行。
|
||
|
||
### 32.2 数据模型
|
||
|
||
#### NodeModel(task_node,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(64) | NOT NULL | 节点名称 |
|
||
| `code` | String(32) | NOT NULL, UNIQUE(tenant_id, code) | 节点编码 |
|
||
| `jobstore` | String(64) | nullable, default="default" | 存储器 |
|
||
| `executor` | String(64) | nullable, default="default" | 执行器 |
|
||
| `trigger` | String(64) | nullable | 触发器 |
|
||
| `trigger_args` | Text | nullable | 触发器参数 |
|
||
| `func` | Text | NOT NULL | 预定义处理器标识符(如 `handlers.send_email`)。禁止租户提交任意代码 |
|
||
| `args` | Text | nullable | 位置参数 |
|
||
| `kwargs` | Text | nullable | 关键字参数 |
|
||
| `coalesce` | Boolean | nullable, default=False | 是否合并运行 |
|
||
| `max_instances` | Integer | nullable, default=1 | 最大并发实例数 |
|
||
| `start_date` | String(64) | nullable | 开始时间 |
|
||
| `end_date` | String(64) | nullable | 结束时间 |
|
||
|
||
#### JobModel(task_job,TenantMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `job_id` | String(64) | NOT NULL, index | 任务ID |
|
||
| `job_name` | String(128) | nullable | 任务名称 |
|
||
| `trigger_type` | String(32) | nullable | 触发方式:cron/interval/date/manual |
|
||
| `status` | String(16) | NOT NULL, default="pending" | 执行状态:pending/running/success/failed/timeout/cancelled |
|
||
| `next_run_time` | String(64) | nullable | 下次执行时间 |
|
||
| `job_state` | Text | nullable | 任务状态信息 |
|
||
| `result` | Text | nullable | 执行结果 |
|
||
| `error` | Text | nullable | 错误信息 |
|
||
|
||
### 32.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **Node 编码** | 字母开头,仅含字母/数字/下划线 |
|
||
| **触发器类型** | 仅支持 now/cron/interval/date |
|
||
| **非立即执行** | trigger != "now" 时必须提供 trigger_args |
|
||
| **时间校验** | end_date 不能早于 start_date |
|
||
| **func 必填** | Node 创建时 func 不能为空,须为已注册的处理器标识符 |
|
||
| **处理器白名单** | func 字段只能填写平台预注册的处理器(如 `handlers.send_email`、`handlers.call_api`),禁止填写任意代码。超管可在 `platform_handler_registry` 中注册新处理器 |
|
||
| **Job 状态** | 仅支持 pending/running/success/failed/timeout/cancelled |
|
||
| **trigger_type** | 仅支持 cron/interval/date/manual |
|
||
|
||
### 32.4 API 端点
|
||
|
||
#### Node(节点)
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/cronjob/node/detail/{id}` | module_task:cronjob:query | 节点详情 |
|
||
| GET | `/cronjob/node/list` | module_task:cronjob:query | 节点列表 |
|
||
| POST | `/cronjob/node/create` | module_task:cronjob:create | 创建节点 |
|
||
| PUT | `/cronjob/node/update/{id}` | module_task:cronjob:update | 更新节点 |
|
||
| DELETE | `/cronjob/node/delete` | module_task:cronjob:delete | 删除节点 |
|
||
| PATCH | `/cronjob/node/status/batch` | module_task:cronjob:patch | 批量设置状态 |
|
||
| POST | `/cronjob/node/execute/{id}` | module_task:cronjob:update | 执行节点 |
|
||
|
||
#### Job(执行日志)
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/cronjob/job/detail/{id}` | module_task:cronjob:query | 日志详情 |
|
||
| GET | `/cronjob/job/list` | module_task:cronjob:query | 日志列表 |
|
||
| DELETE | `/cronjob/job/delete` | module_task:cronjob:delete | 删除日志 |
|
||
|
||
---
|
||
|
||
## 33. Workflow 工作流模块(module_task/workflow)
|
||
|
||
### 33.1 业务描述
|
||
|
||
工作流模块提供可视化流程编排和执行能力。基于 Vue Flow 画布定义流程节点和连线,通过 Prefect 引擎执行。数据按租户隔离。
|
||
|
||
### 33.2 数据模型
|
||
|
||
#### WorkflowModel(task_workflow,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(128) | NOT NULL | 流程名称 |
|
||
| `code` | String(64) | NOT NULL, UNIQUE(tenant_id, code) | 流程编码 |
|
||
| `workflow_status` | String(32) | NOT NULL, default="draft" | 状态:draft/published/archived |
|
||
| `nodes` | JSON | nullable | Vue Flow nodes JSON |
|
||
| `edges` | JSON | nullable | Vue Flow edges JSON |
|
||
|
||
#### WorkflowNodeTypeModel(task_workflow_node_type,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(128) | NOT NULL | 显示名称 |
|
||
| `code` | String(64) | NOT NULL, UNIQUE(tenant_id, code) | 节点编码,对应画布 node.type |
|
||
| `category` | String(32) | NOT NULL, default="action" | 分类:trigger/action/condition/control |
|
||
| `func` | Text | NOT NULL | 预定义处理器标识符(如 `handlers.approve`、`handlers.send_http`)。禁止租户提交任意代码 |
|
||
| `args` | Text | nullable | 默认位置参数,逗号分隔 |
|
||
| `kwargs` | Text | nullable | 默认关键字参数 JSON |
|
||
| `sort_order` | Integer | NOT NULL, default=0 | 排序 |
|
||
| `is_active` | Boolean | NOT NULL, default=True | 是否启用 |
|
||
|
||
### 33.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **Workflow 编码** | 字母开头,仅含字母/数字/下划线 |
|
||
| **Workflow 状态** | 仅支持 draft(草稿)、published(已发布)、archived(已归档) |
|
||
| **NodeType 分类** | 仅支持 trigger(触发器)、action(动作)、condition(条件)、control(控制) |
|
||
| **发布流程** | 发布时可选备注(remark),由 draft → published |
|
||
| **执行流程** | 需传入 workflow_id 和可选的 variables/business_key/job_id |
|
||
| **执行结果** | 返回 completed/failed 状态及各节点执行结果 |
|
||
|
||
### 33.4 API 端点
|
||
|
||
#### Workflow(流程定义)
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/workflow/flow/detail/{id}` | module_task:workflow:query | 流程详情 |
|
||
| GET | `/workflow/flow/list` | module_task:workflow:query | 流程列表 |
|
||
| POST | `/workflow/flow/create` | module_task:workflow:create | 创建流程 |
|
||
| PUT | `/workflow/flow/update/{id}` | module_task:workflow:update | 更新流程 |
|
||
| DELETE | `/workflow/flow/delete` | module_task:workflow:delete | 删除流程 |
|
||
| POST | `/workflow/flow/publish/{id}` | module_task:workflow:update | 发布流程 |
|
||
| POST | `/workflow/flow/execute/{id}` | module_task:workflow:update | 执行流程 |
|
||
|
||
#### NodeType(节点类型)
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/workflow/nodes/detail/{id}` | module_task:workflow:query | 节点详情 |
|
||
| GET | `/workflow/nodes/list` | module_task:workflow:query | 节点列表 |
|
||
| POST | `/workflow/nodes/create` | module_task:workflow:create | 创建节点 |
|
||
| PUT | `/workflow/node-type/update/{id}` | module_task:workflow:update | 更新节点 |
|
||
| DELETE | `/workflow/node-type/delete` | module_task:workflow:delete | 删除节点 |
|
||
|
||
---
|
||
|
||
## 34. CodeGen 代码生成器模块(module_generator/gencode)
|
||
|
||
### 34.1 业务描述
|
||
|
||
代码生成器模块,通过读取数据库表结构自动生成 CRUD 代码(Python 后端 + Vue 前端 + TypeScript API 层)。支持主子表结构。数据按租户隔离。
|
||
|
||
### 34.2 数据模型
|
||
|
||
#### GenTableModel(gen_table,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `table_name` | String(200) | NOT NULL | 数据库表名 |
|
||
| `table_comment` | String(500) | nullable | 表描述 |
|
||
| `class_name` | String(100) | NOT NULL | 实体类名称 |
|
||
| `package_name` | String(100) | nullable | 生成包路径(module_xxx) |
|
||
| `module_name` | String(30) | nullable | 生成模块名 |
|
||
| `business_name` | String(30) | nullable | 功能子目录/路由段 |
|
||
| `function_name` | String(100) | nullable | 生成功能名 |
|
||
| `sub_table_name` | String(64) | nullable | 关联子表的表名 |
|
||
| `sub_table_fk_name` | String(64) | nullable | 子表关联的外键名 |
|
||
| `parent_menu_id` | Integer | nullable | 父菜单ID |
|
||
|
||
#### GenTableColumnModel(gen_table_column,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `table_id` | FK→gen_table.id | NOT NULL, ON DELETE CASCADE | 归属表ID |
|
||
| `column_name` | String(200) | NOT NULL | 列名称 |
|
||
| `column_comment` | String(500) | nullable | 列描述 |
|
||
| `column_type` | String(100) | NOT NULL | 列类型 |
|
||
| `column_length` | String(50) | nullable | 列长度 |
|
||
| `column_default` | String(200) | nullable | 列默认值 |
|
||
| `is_pk` | Boolean | NOT NULL, default=False | 是否主键 |
|
||
| `is_increment` | Boolean | NOT NULL, default=False | 是否自增 |
|
||
| `is_nullable` | Boolean | NOT NULL, default=True | 是否允许为空 |
|
||
| `is_unique` | Boolean | NOT NULL, default=False | 是否唯一 |
|
||
| `python_type` | String(100) | nullable | Python 类型 |
|
||
| `python_field` | String(200) | nullable | Python 字段名 |
|
||
| `is_insert` | Boolean | NOT NULL, default=True | 是否为新增字段 |
|
||
| `is_edit` | Boolean | NOT NULL, default=True | 是否编辑字段 |
|
||
| `is_list` | Boolean | NOT NULL, default=True | 是否列表字段 |
|
||
| `is_query` | Boolean | NOT NULL, default=False | 是否查询字段 |
|
||
| `query_type` | String(50) | nullable | 查询方式 |
|
||
| `html_type` | String(100) | nullable, default="input" | 显示类型 |
|
||
| `dict_type` | String(200) | nullable, default="" | 字典类型 |
|
||
| `sort` | Integer | NOT NULL, default=0 | 排序 |
|
||
|
||
### 34.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **表名校验** | table_name/class_name 非空去空白 |
|
||
| **包名规范** | package_name 必须以 module_ 开头 |
|
||
| **业务名规范** | business_name 支持斜杠多段(如 demo/demo01) |
|
||
| **同步预览** | 支持 DB→Gen 差异预览(新增/删除/变更字段) |
|
||
| **建表SQL** | 支持从 CREATE TABLE SQL 导入表结构 |
|
||
| **模板生成** | 支持 Python/TS/Vue 三端代码模板(Jinja2) |
|
||
| **主子表** | 通过 sub_table_name/sub_table_fk_name 配置主子表关联 |
|
||
|
||
### 34.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/gencode/detail/{id}` | module_generator:gencode:query | 业务表详情 |
|
||
| GET | `/gencode/list` | module_generator:gencode:query | 业务表列表 |
|
||
| POST | `/gencode/create` | module_generator:gencode:create | 创建业务表 |
|
||
| PUT | `/gencode/update/{id}` | module_generator:gencode:update | 更新业务表 |
|
||
| DELETE | `/gencode/delete` | module_generator:gencode:delete | 删除业务表 |
|
||
| PATCH | `/gencode/status/batch` | module_generator:gencode:patch | 批量设置状态 |
|
||
| GET | `/gencode/db/list` | module_generator:gencode:query | 数据库表列表 |
|
||
| POST | `/gencode/import` | module_generator:gencode:create | 导入表结构 |
|
||
| POST | `/gencode/sync/preview/{id}` | module_generator:gencode:query | 同步预览 |
|
||
| POST | `/gencode/sync/{id}` | module_generator:gencode:update | 同步表结构 |
|
||
| POST | `/gencode/create/table` | module_generator:gencode:create | 从SQL建表 |
|
||
| POST | `/gencode/preview/{id}` | module_generator:gencode:query | 预览代码 |
|
||
| POST | `/gencode/zip/{id}` | module_generator:gencode:query | 下载代码ZIP |
|
||
| POST | `/gencode/gen/{id}` | module_generator:gencode:update | 生成代码到本地 |
|
||
| POST | `/gencode/current/select` | module_generator:gencode:query | 切换当前业务表 |
|
||
|
||
---
|
||
|
||
## 35. Demo 示例模块(module_example/demo)
|
||
|
||
### 35.1 业务描述
|
||
|
||
示例模块,演示 CRUD 标准开发模式和多种数据类型的用法。数据按租户隔离。
|
||
|
||
### 35.2 数据模型
|
||
|
||
#### DemoModel(example_demo,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(64) | NOT NULL | 名称 |
|
||
| `a` | Integer | nullable | 整数 |
|
||
| `b` | BIGINT | nullable | 大整数 |
|
||
| `c` | Float | nullable | 浮点数 |
|
||
| `d` | Boolean | NOT NULL, default=True | 布尔型 |
|
||
| `e` | Date | nullable | 日期 |
|
||
| `f` | Time | nullable | 时间 |
|
||
| `g` | DateTime | nullable | 日期时间 |
|
||
| `h` | Text | nullable | 长文本 |
|
||
| `i` | JSON | nullable | 元数据 JSON |
|
||
|
||
#### Demo01Model(example_demo01,TenantMixin, UserMixin)
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | String(64) | NOT NULL | 名称 |
|
||
|
||
### 35.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **名称校验** | 2-50 位,仅含字母/数字/下划线/中划线 |
|
||
| **状态校验** | 仅支持 0(正常)、1(禁用) |
|
||
|
||
### 35.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/example/demo/detail/{id}` | module_example:demo:query | 详情 |
|
||
| GET | `/example/demo/list` | module_example:demo:query | 列表 |
|
||
| POST | `/example/demo/create` | module_example:demo:create | 创建 |
|
||
| PUT | `/example/demo/update/{id}` | module_example:demo:update | 更新 |
|
||
| DELETE | `/example/demo/delete` | module_example:demo:delete | 删除 |
|
||
| PATCH | `/example/demo/status/batch` | module_example:demo:patch | 批量设置状态 |
|
||
|
||
#### Demo01
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/example/demo01/detail/{id}` | module_example:demo01:query | 详情 |
|
||
| GET | `/example/demo01/list` | module_example:demo01:query | 列表 |
|
||
| POST | `/example/demo01/create` | module_example:demo01:create | 创建 |
|
||
| PUT | `/example/demo01/update/{id}` | module_example:demo01:update | 更新 |
|
||
| DELETE | `/example/demo01/delete` | module_example:demo01:delete | 删除 |
|
||
| PATCH | `/example/demo01/status/batch` | module_example:demo01:patch | 批量设置状态 |
|
||
|
||
---
|
||
|
||
## 36. Monitor 监控模块(module_monitor)
|
||
|
||
### 36.1 业务描述
|
||
|
||
监控模块提供系统运行状态的实时监控能力,包括在线用户追踪、Redis 缓存监控、服务器资源监控和文件系统管理。该模块属于平台级功能,不受租户隔离限制,超级管理员可查看所有数据。
|
||
|
||
### 36.2 在线用户(online)
|
||
|
||
#### 36.2.1 业务描述
|
||
|
||
在线用户监控来自 Redis 存储的会话数据,实时追踪当前登录用户。数据不按租户隔离,超级管理员可查看所有在线用户。
|
||
|
||
#### 36.2.2 数据模型
|
||
|
||
**OnlineOutSchema(Redis 数据结构)**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `user_id` | int | NOT NULL | 用户ID |
|
||
| `tenant_id` | int | NOT NULL | 租户ID |
|
||
| `user_name` | str | NOT NULL | 用户名 |
|
||
| `name` | str | NOT NULL | 用户名称 |
|
||
| `session_id` | str | NOT NULL | 会话编号 |
|
||
| `is_super_admin` | bool | NOT NULL, default=False | 是否超管 |
|
||
| `ipaddr` | str | nullable | 登录IP |
|
||
| `login_location` | str | nullable | 登录地 |
|
||
| `os` | str | nullable | 操作系统 |
|
||
| `browser` | str | nullable | 浏览器 |
|
||
| `login_time` | DateTime | nullable | 登录时间 |
|
||
| `login_type` | str | nullable | 登录类型(PC/移动) |
|
||
|
||
#### 36.2.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **数据来源** | 数据存储在 Redis,会话过期自动移除 |
|
||
| **强制下线** | 超级管理员可强制指定用户下线 |
|
||
| **清空全部** | 超级管理员可清空所有在线用户会话 |
|
||
|
||
#### 36.2.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/monitor/online/list` | module_monitor:online:query | 在线用户列表 |
|
||
| DELETE | `/monitor/online/delete` | module_monitor:online:delete | 强制下线 |
|
||
| DELETE | `/monitor/online/clear` | module_monitor:online:delete | 清空所有在线用户 |
|
||
|
||
---
|
||
|
||
### 36.3 缓存监控(cache)
|
||
|
||
#### 36.3.1 业务描述
|
||
|
||
Redis 缓存监控,提供缓存统计信息、缓存名称列表、键值查看和清除功能。数据不按租户隔离,属于平台级功能。
|
||
|
||
#### 36.3.2 数据模型
|
||
|
||
**CacheMonitorSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `command_stats` | list[dict] | NOT NULL, default=[] | Redis 命令统计 |
|
||
| `db_size` | int | NOT NULL, default=0 | Key 总数 |
|
||
| `info` | dict | NOT NULL, default={} | Redis 服务器信息 |
|
||
|
||
**CacheInfoSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `cache_key` | str | NOT NULL | 缓存键名 |
|
||
| `cache_name` | str | NOT NULL | 缓存名称 |
|
||
| `cache_value` | Any | nullable | 缓存值 |
|
||
| `remark` | str | nullable | 备注说明 |
|
||
|
||
#### 36.3.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **统计信息** | 获取 Redis 命令统计和服务器信息 |
|
||
| **键值管理** | 支持查看和清除指定缓存 |
|
||
| **批量清除** | 支持按名称清除和清空所有缓存 |
|
||
|
||
#### 36.3.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/monitor/cache/info` | module_monitor:cache:query | 获取缓存监控统计 |
|
||
| GET | `/monitor/cache/get/names` | module_monitor:cache:query | 获取缓存名称列表 |
|
||
| GET | `/monitor/cache/get/keys/{cache_name}` | module_monitor:cache:query | 获取缓存键名列表 |
|
||
| GET | `/monitor/cache/get/value/{cache_name}/{cache_key}` | module_monitor:cache:query | 获取缓存值 |
|
||
| DELETE | `/monitor/cache/delete/name/{cache_name}` | module_monitor:cache:delete | 清除指定缓存名称 |
|
||
| DELETE | `/monitor/cache/delete/key/{cache_key}` | module_monitor:cache:delete | 清除指定缓存键 |
|
||
| DELETE | `/monitor/cache/clear` | module_monitor:cache:delete | 清除所有缓存 |
|
||
|
||
---
|
||
|
||
### 36.4 资源管理(resource)
|
||
|
||
#### 36.4.1 业务描述
|
||
|
||
资源文件管理,提供服务器文件系统的浏览、上传、下载、删除、移动、复制、重命名、创建目录等操作。支持文件列表分页、关键词搜索和 Excel 导出。
|
||
|
||
#### 36.4.2 数据模型
|
||
|
||
**ResourceItemSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | str | NOT NULL | 文件名 |
|
||
| `file_url` | str | NOT NULL | 文件URL路径 |
|
||
| `relative_path` | str | NOT NULL | 相对路径 |
|
||
| `is_file` | bool | NOT NULL | 是否为文件 |
|
||
| `is_dir` | bool | NOT NULL | 是否为目录 |
|
||
| `size` | int | nullable | 文件大小(字节) |
|
||
| `created_time` | DateTime | nullable | 创建时间 |
|
||
| `modified_time` | DateTime | nullable | 修改时间 |
|
||
| `is_hidden` | bool | NOT NULL, default=False | 是否隐藏文件 |
|
||
|
||
**ResourceUploadSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `filename` | str | NOT NULL | 文件名 |
|
||
| `file_url` | str | NOT NULL | 访问URL |
|
||
| `file_size` | int | NOT NULL | 文件大小 |
|
||
| `upload_time` | DateTime | NOT NULL | 上传时间 |
|
||
|
||
**ResourceMoveSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `source_path` | str | NOT NULL | 源路径 |
|
||
| `target_path` | str | NOT NULL | 目标路径 |
|
||
| `overwrite` | bool | NOT NULL, default=False | 是否覆盖 |
|
||
|
||
**ResourceRenameSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `old_path` | str | NOT NULL | 原路径 |
|
||
| `new_name` | str | NOT NULL, max_length=255 | 新名称 |
|
||
|
||
**ResourceCreateDirSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `parent_path` | str | NOT NULL | 父目录路径 |
|
||
| `dir_name` | str | NOT NULL, max_length=255 | 目录名称 |
|
||
|
||
#### 36.4.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **路径安全** | 禁止路径遍历(`..`),防止越权访问 |
|
||
| **文件/目录互斥** | 不能同时为文件和目录 |
|
||
| **隐藏文件** | 以 `.` 开头的文件自动标记为隐藏 |
|
||
| **分页查询** | 目录列表支持分页和关键词搜索 |
|
||
| **上传限制** | 仅 resource 类型支持指定目标目录 |
|
||
| **导出功能** | 支持将资源列表导出为 Excel |
|
||
|
||
#### 36.4.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/monitor/resource/list` | module_monitor:resource:query | 目录列表(分页) |
|
||
| POST | `/monitor/resource/upload` | module_monitor:resource:upload | 上传文件 |
|
||
| GET | `/monitor/resource/download` | module_monitor:resource:download | 下载文件 |
|
||
| DELETE | `/monitor/resource/delete` | module_monitor:resource:delete | 删除文件 |
|
||
| POST | `/monitor/resource/move` | module_monitor:resource:move | 移动文件 |
|
||
| POST | `/monitor/resource/copy` | module_monitor:resource:copy | 复制文件 |
|
||
| POST | `/monitor/resource/rename` | module_monitor:resource:rename | 重命名文件 |
|
||
| POST | `/monitor/resource/mkdir` | module_monitor:resource:mkdir | 创建目录 |
|
||
| POST | `/monitor/resource/export` | module_monitor:resource:export | 导出资源列表 |
|
||
|
||
---
|
||
|
||
### 36.5 服务器监控(server)
|
||
|
||
#### 36.5.1 业务描述
|
||
|
||
服务器监控,采集服务器运行时的 CPU、内存、磁盘、Python 进程等信息,供运维人员了解系统资源使用情况。
|
||
|
||
#### 36.5.2 数据模型
|
||
|
||
**CpuInfoSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `cpu_num` | int | NOT NULL | CPU 核心数 |
|
||
| `used` | float | NOT NULL, 0-100 | 用户使用率(%) |
|
||
| `sys` | float | NOT NULL, 0-100 | 系统使用率(%) |
|
||
| `free` | float | NOT NULL, 0-100 | 空闲率(%) |
|
||
|
||
**MemoryInfoSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `total` | str | NOT NULL | 内存总量 |
|
||
| `used` | str | NOT NULL | 已用内存 |
|
||
| `free` | str | NOT NULL | 剩余内存 |
|
||
| `usage` | float | NOT NULL, 0-100 | 使用率(%) |
|
||
|
||
**SysInfoSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `computer_ip` | str | NOT NULL | 服务器IP |
|
||
| `computer_name` | str | NOT NULL | 服务器名称 |
|
||
| `os_arch` | str | NOT NULL | 系统架构 |
|
||
| `os_name` | str | NOT NULL | 操作系统 |
|
||
| `user_dir` | str | NOT NULL | 项目路径 |
|
||
|
||
**PyInfoSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `name` | str | NOT NULL | Python 名称 |
|
||
| `version` | str | NOT NULL | Python 版本 |
|
||
| `start_time` | str | NOT NULL | 启动时间 |
|
||
| `run_time` | str | NOT NULL | 运行时长 |
|
||
| `home` | str | NOT NULL | 安装路径 |
|
||
| `memory_used` | str | NOT NULL | 内存占用 |
|
||
| `memory_usage` | float | NOT NULL, 0-100 | 内存使用率(%) |
|
||
| `memory_total` | str | NOT NULL | 总内存 |
|
||
| `memory_free` | str | NOT NULL | 剩余内存 |
|
||
|
||
**DiskInfoSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `dir_name` | str | NOT NULL | 磁盘路径 |
|
||
| `sys_type_name` | str | NOT NULL | 文件系统类型 |
|
||
| `type_name` | str | NOT NULL | 磁盘类型 |
|
||
| `total` | str | NOT NULL | 总容量 |
|
||
| `used` | str | NOT NULL | 已用容量 |
|
||
| `free` | str | NOT NULL | 可用容量 |
|
||
| `usage` | float | NOT NULL, 0-100 | 使用率(%) |
|
||
|
||
**ServerMonitorSchema**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `cpu` | CpuInfoSchema | NOT NULL | CPU 信息 |
|
||
| `mem` | MemoryInfoSchema | NOT NULL | 内存信息 |
|
||
| `py` | PyInfoSchema | NOT NULL | Python 信息 |
|
||
| `sys` | SysInfoSchema | NOT NULL | 系统信息 |
|
||
| `disks` | list[DiskInfoSchema] | NOT NULL | 磁盘信息列表 |
|
||
|
||
#### 36.5.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **实时采集** | 每次请求实时采集系统信息 |
|
||
| **百分比范围** | 使用率字段限制在 0-100 范围 |
|
||
|
||
#### 36.5.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/monitor/server/info` | module_monitor:server:query | 服务器监控信息 |
|
||
|
||
---
|
||
|
||
## 37. Common 公共模块(module_common)
|
||
|
||
### 37.1 业务描述
|
||
|
||
公共模块提供跨模块复用的基础服务,包括统一文件上传下载、健康检查和指标监控。该模块属于平台级基础设施,不受租户隔离限制。
|
||
|
||
### 37.2 文件管理(file)
|
||
|
||
#### 37.2.1 业务描述
|
||
|
||
统一文件上传下载服务,支持多种上传类型(通用文件、头像、参数配置、监控资源),支持指定目标目录。预留 Excel 导入功能,待后续实现。
|
||
|
||
#### 37.2.2 数据模型
|
||
|
||
**上传响应数据**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `file_name` | str | NOT NULL | 文件名 |
|
||
| `file_url` | str | NOT NULL | 访问URL |
|
||
| `file_size` | int | NOT NULL | 文件大小 |
|
||
| `upload_time` | DateTime | NOT NULL | 上传时间 |
|
||
|
||
**预留:Excel导入字段映射模型(ImportFieldModel)**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `base_column` | str | nullable | 数据库字段名 |
|
||
| `excel_column` | str | nullable | Excel 字段名 |
|
||
| `default_value` | str | nullable | 默认值 |
|
||
| `is_required` | bool | nullable | 是否必传 |
|
||
| `selected` | bool | nullable | 是否勾选 |
|
||
|
||
**预留:Excel导入请求模型(ImportModel)**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `table_name` | str | nullable | 目标表名 |
|
||
| `sheet_name` | str | nullable | Sheet 名 |
|
||
| `filed_info` | list[ImportFieldModel] | nullable | 字段映射列表 |
|
||
| `file_name` | str | nullable | 文件名 |
|
||
|
||
#### 37.2.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **上传类型** | file=通用, avatar=头像, param=参数配置, resource=监控资源 |
|
||
| **目标目录** | 仅 resource 类型支持指定 target_path |
|
||
| **下载选项** | 支持下载后自动删除源文件 |
|
||
| **Excel导入预留** | ImportFieldModel 和 ImportModel 为预留功能,当前未实现对应接口 |
|
||
|
||
#### 37.2.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| POST | `/common/file/upload` | module_common:file:upload | 上传文件 |
|
||
| POST | `/common/file/download` | module_common:file:download | 下载文件 |
|
||
|
||
---
|
||
|
||
### 37.3 健康检查(health)
|
||
|
||
#### 37.3.1 业务描述
|
||
|
||
三级健康检查体系,用于不同场景的健康探测:
|
||
- `/health`: 基础健康检查(负载均衡器探测)
|
||
- `/health/live`: 存活探针(K8s livenessProbe)
|
||
- `/health/ready`: 就绪探针(K8s readinessProbe,检测数据库和 Redis)
|
||
|
||
#### 37.3.2 数据模型
|
||
|
||
**健康检查响应**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `status` | str | NOT NULL | healthy/alive/ready/not_ready |
|
||
| `timestamp` | DateTime | NOT NULL | 检查时间戳 |
|
||
| `version` | str | NOT NULL | 系统版本 |
|
||
| `uptime_seconds` | float | NOT NULL | 运行时间(秒) |
|
||
| `dependencies` | dict | nullable | 依赖检查结果 |
|
||
| `disk_usage` | float | nullable | 磁盘使用率(%) |
|
||
|
||
**依赖检查结果**
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `database` | dict | NOT NULL | 数据库状态 {status, latency_ms} |
|
||
| `redis` | dict | NOT NULL | Redis 状态 {status, latency_ms} |
|
||
|
||
#### 37.3.3 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **基础检查** | 仅检查进程是否存活,返回 healthy |
|
||
| **存活探针** | 进程已启动即可返回 200 |
|
||
| **就绪探针** | 检测数据库和 Redis 连接,失败返回 503 |
|
||
| **依赖状态** | up=正常, down=异常, disabled=已禁用 |
|
||
|
||
#### 37.3.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/health` | — | 基础健康检查 |
|
||
| GET | `/health/live` | — | 存活探针 |
|
||
| GET | `/health/ready` | — | 就绪探针 |
|
||
|
||
---
|
||
|
||
### 37.4 指标监控(metrics)
|
||
|
||
#### 37.4.1 业务描述
|
||
|
||
Prometheus 指标监控,集成 prometheus-fastapi-instrumentator 自动采集 HTTP 请求指标,暴露 `/metrics` 端点供 Prometheus 抓取。
|
||
|
||
#### 37.4.2 采集指标
|
||
|
||
| 指标名称 | 类型 | 说明 |
|
||
|---------|------|------|
|
||
| `http_requests_total` | Counter | HTTP 请求总数(按 method/endpoint/status 分组) |
|
||
| `http_request_duration_seconds` | Histogram | 请求延迟直方图 |
|
||
| `http_requests_in_progress` | Gauge | 当前处理中的请求数 |
|
||
| `http_request_size_bytes` | Histogram | 请求体大小 |
|
||
| `http_response_size_bytes` | Histogram | 响应体大小 |
|
||
|
||
#### 37.4.3 排除端点
|
||
|
||
以下端点不纳入指标采集:
|
||
- `/metrics`: Prometheus 抓取端点
|
||
- `/health`, `/health/live`, `/health/ready`: 健康检查端点
|
||
- `/docs`, `/redoc`, `/openapi.json`: API 文档
|
||
- `/static/*`, `/favicon.ico`: 静态资源
|
||
|
||
#### 37.4.4 API 端点
|
||
|
||
| 方法 | 路径 | 权限标识 | 说明 |
|
||
|------|------|---------|------|
|
||
| GET | `/metrics` | — | Prometheus 指标端点 |
|
||
|
||
---
|
||
|
||
# Part 5:商业运营模块
|
||
|
||
---
|
||
|
||
## 38. Invoice 发票管理模块
|
||
|
||
### 38.1 业务描述
|
||
|
||
发票管理是中国 B2B SaaS 的法律合规要求。租户在完成订单支付后可申请开具电子发票(增值税普通发票/增值税专用发票),平台审核后对接第三方开票 API(如百望云/票通)生成电子发票,支持下载 PDF。
|
||
|
||
### 38.2 发票类型
|
||
|
||
| 类型 | 编码 | 适用场景 | 税率 |
|
||
|------|------|---------|------|
|
||
| **增值税普通发票** | `vat_normal` | 个人/小规模纳税人,不可抵扣 | 1%/3%/6% |
|
||
| **增值税专用发票** | `vat_special` | 一般纳税人,可抵扣进项税额 | 6%/13% |
|
||
|
||
### 38.3 数据模型
|
||
|
||
#### platform_invoice
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `invoice_no` | String(32) | NOT NULL, UNIQUE | 发票号码(平台自增号) |
|
||
| `order_id` | FK→platform_order.id | NOT NULL, UNIQUE | 关联订单(一单一票) |
|
||
| `tenant_id` | FK→platform_tenant.id | NOT NULL | 开票租户 |
|
||
| `invoice_type` | String(20) | NOT NULL | 类型:`vat_normal`(普票) `vat_special`(专票) |
|
||
| `title` | String(200) | NOT NULL | 发票抬头(公司全称/个人姓名) |
|
||
| `tax_no` | String(50) | nullable | 纳税人识别号(普票可选,专票必填) |
|
||
| `bank_info` | Text | nullable | 开户行及账号(专票必填) |
|
||
| `address_info` | Text | nullable | 注册地址及电话(专票必填) |
|
||
| `amount` | Integer | NOT NULL | 发票金额(分) |
|
||
| `tax_amount` | Integer | NOT NULL, default=0 | 税额(分) |
|
||
| `status` | Integer | NOT NULL, default=0 | 0=待开票 1=已开票 2=开票失败 3=已作废 |
|
||
| `pdf_url` | String(500) | nullable | 电子发票 PDF 下载地址 |
|
||
| `api_response` | Text | nullable | 第三方开票 API 原始响应 |
|
||
| `remark` | Text | nullable | 备注 |
|
||
|
||
### 38.4 业务流程
|
||
|
||
```
|
||
租户申请开票
|
||
├── POST /tenant/invoice/apply
|
||
│ body: {order_id, invoice_type, title, tax_no?, bank_info?, address_info?}
|
||
├── 校验:订单已支付(status=1)、未开过票(order_id UNIQUE)
|
||
├── 专票额外校验:tax_no/bank_info/address_info 必填
|
||
├── 创建 platform_invoice 记录(status=0 待开票)
|
||
└── 返回申请成功
|
||
|
||
超管审核开票
|
||
├── GET /platform/invoice/list(待开票列表)
|
||
├── PUT /platform/invoice/issue/{id}
|
||
│ ├── 调用第三方开票 API(百望云等)
|
||
│ ├── 成功 → 更新 status=1、pdf_url、api_response
|
||
│ ├── 失败 → 更新 status=2、记录错误信息
|
||
│ └── 通知租户(站内信 + 邮件,含下载链接)
|
||
└── PUT /platform/invoice/void/{id}(发票作废,仅已开票可作废)
|
||
```
|
||
|
||
### 38.5 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **一单一票** | 每个订单仅可开具一张发票(order_id UNIQUE),杜绝重复开票 |
|
||
| **开票时限** | 订单支付后 30 天内可申请,超期不再支持(税务合规) |
|
||
| **金额匹配** | 发票金额必须等于订单实付金额 |
|
||
| **专票校验** | 增值税专用发票必须填写税号+开户行+地址,缺一不可 |
|
||
| **第三方对接** | 对接百望云/票通等电子发票平台,API 调用失败时自动重试 3 次后标记失败 |
|
||
| **PDF 存储** | 电子发票 PDF 上传至文件服务(§37.2),按 `invoice/{tenant_id}/{invoice_no}.pdf` 路径存储 |
|
||
| **作废规则** | 当月开具的发票可作废,跨月发票需冲红(暂不支持,预留扩展) |
|
||
|
||
### 38.6 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| POST | `/tenant/invoice/apply` | 申请开票 | 租户管理员 |
|
||
| GET | `/tenant/invoice/list` | 我的发票列表 | 租户管理员 |
|
||
| GET | `/tenant/invoice/{id}/download` | 下载发票 PDF | 租户管理员 |
|
||
| GET | `/platform/invoice/list` | 全部发票列表(支持筛选) | 超管 |
|
||
| PUT | `/platform/invoice/issue/{id}` | 开具发票(调用第三方 API) | 超管 |
|
||
| PUT | `/platform/invoice/void/{id}` | 作废发票 | 超管 |
|
||
|
||
---
|
||
|
||
## 39. AuditLog 租户审计日志模块
|
||
|
||
### 39.1 业务描述
|
||
|
||
记录平台级和租户级的关键管理操作,形成不可篡改的审计轨迹。满足企业内部合规审查、SOC2/ISO27001 认证中的数据追溯要求。审计日志与操作日志(§14)的区别在于:操作日志面向业务操作的查询追踪,审计日志面向合规要求的不可否认性记录。
|
||
|
||
### 39.2 操作分类
|
||
|
||
| 分类 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| **租户管理** | 租户生命周期操作 | 创建/启禁用/冻结/删除/变更套餐 |
|
||
| **权限变更** | 角色/菜单/授权操作 | 角色创建/删除、菜单分配/回收 |
|
||
| **套餐变更** | 套餐相关操作 | 套餐价格修改、套餐菜单变更 |
|
||
| **支付与退款** | 财务相关操作 | 订单创建、退款批准/驳回 |
|
||
| **发票管理** | 开票相关操作 | 开具发票、作废发票 |
|
||
| **用户邀请** | 团队管理操作 | 发送邀请、取消邀请 |
|
||
|
||
### 39.3 数据模型
|
||
|
||
#### platform_audit_log
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|------|------|------|------|
|
||
| `action` | String(50) | NOT NULL | 操作类型:`tenant.create`/`tenant.package_change`/`role.delete` 等 |
|
||
| `target_type` | String(50) | NOT NULL | 操作对象类型:`tenant`/`package`/`role`/`order`/`invoice` |
|
||
| `target_id` | Integer | NOT NULL | 操作对象 ID |
|
||
| `target_name` | String(200) | nullable | 操作对象名称(冗余存储,防删除后无法追溯) |
|
||
| `tenant_id` | FK→platform_tenant.id | nullable | 关联租户(平台级操作可为 null) |
|
||
| `operator_id` | FK→sys_user.id | NOT NULL | 操作人 |
|
||
| `operator_name` | String(50) | NOT NULL | 操作人名称(冗余) |
|
||
| `detail` | JSON | NOT NULL | 操作详情(变更前/后的关键字段) |
|
||
| `ip_address` | String(45) | nullable | 操作 IP |
|
||
| `user_agent` | String(500) | nullable | 浏览器 UA |
|
||
|
||
| **设计要点** | 说明 |
|
||
|------|------|
|
||
| **不可篡改** | 无 Update/Delete API,仅支持 Insert 和 Read |
|
||
| **变更对比** | `detail` JSON 字段存储 `{"before": {...}, "after": {...}}` 格式的变更对比 |
|
||
| **冗余存储** | target_name/operator_name 冗余存储,确保删除关联数据后仍可追溯 |
|
||
| **保留策略** | 默认保留 3 年,超期归档至冷存储(S3/OSS),支持按需导出 CSV/JSON |
|
||
|
||
### 39.4 审计事件清单
|
||
|
||
| action | target_type | 触发场景 | detail 示例 |
|
||
|--------|-------------|---------|------------|
|
||
| `tenant.create` | tenant | 创建租户 | `{after: {code, name, package_id}}` |
|
||
| `tenant.status_change` | tenant | 启禁/冻结/归档 | `{before: {status}, after: {status}}` |
|
||
| `tenant.package_change` | tenant | 变更套餐 | `{before: {package_id, name}, after: {package_id, name}}` |
|
||
| `tenant.quota_change` | tenant | 调整配额 | `{before: {max_users}, after: {max_users}}` |
|
||
| `tenant.delete` | tenant | 删除租户 | `{before: {code, name, deleted_at}}` |
|
||
| `package.price_change` | package | 修改套餐价格 | `{before: {price}, after: {price}}` |
|
||
| `package.menu_change` | package | 变更套餐菜单 | `{added: [...], removed: [...]}` |
|
||
| `role.delete` | role | 删除角色 | `{before: {name, user_count}}` |
|
||
| `order.refund_approve` | order | 批准退款 | `{order_no, amount, reason}` |
|
||
| `order.refund_reject` | order | 驳回退款 | `{order_no, amount, reject_reason}` |
|
||
| `invoice.issue` | invoice | 开具发票 | `{invoice_no, amount, type}` |
|
||
| `invoice.void` | invoice | 作废发票 | `{invoice_no, reason}` |
|
||
| `invite.send` | invite | 发送邀请 | `{invitee_email, target_role}` |
|
||
|
||
### 39.5 业务规则
|
||
|
||
| 规则 | 说明 |
|
||
|------|------|
|
||
| **全量记录** | 所有审计事件在业务操作的事务中同步写入,不依赖异步任务(防止丢失) |
|
||
| **不可删除** | 审计日志无 DELETE API,管理员不可手动删除(如需清理需走冷存储归档流程) |
|
||
| **权限** | 仅超管可查阅审计日志,租户端不可见 |
|
||
| **分页与筛选** | 支持按 action/target_type/tenant_id/operator_id/时间范围 多条件筛选分页查询 |
|
||
| **保留策略** | 定时任务 `archive_audit_logs` 每月扫描,将 3 年前的日志导出至 OSS 后从主表删除 |
|
||
|
||
### 39.6 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/platform/audit/list` | 审计日志列表(支持筛选/分页) | 超管 |
|
||
| GET | `/platform/audit/detail/{id}` | 审计日志详情 | 超管 |
|
||
| GET | `/platform/audit/export` | 导出审计日志(CSV/JSON) | 超管 |
|
||
|
||
---
|
||
|
||
## 40. Dashboard 运营大盘
|
||
|
||
### 40.1 业务描述
|
||
|
||
平台运营数据可视化看板,基于已有数据(订单/支付/API用量/租户/工单)聚合展示核心运营指标,帮助超管快速掌握平台健康状况。
|
||
|
||
### 40.2 核心指标
|
||
|
||
| 指标 | 数据源 | 说明 |
|
||
|------|--------|------|
|
||
| **租户总数** | platform_tenant | 按状态分布(active/suspended/expired) |
|
||
| **本月新增租户** | platform_tenant | 按月统计新建租户数 |
|
||
| **今日活跃租户** | platform_api_usage_daily | 当日有 API 调用的租户数 |
|
||
| **月收入(MRR)** | platform_order | status=1 订单按月汇总金额 |
|
||
| **退款率** | platform_refund | 退款金额/总收入 × 100% |
|
||
| **API 调用总量** | platform_api_usage_daily | 按天/月聚合调用次数 |
|
||
| **待处理工单数** | platform_ticket | status=0/1 的工单数量 |
|
||
| **套餐分布** | platform_tenant JOIN platform_package | 各套餐租户数量(饼图) |
|
||
| **收入趋势** | platform_order | 近 12 个月收入折线图 |
|
||
|
||
### 40.3 API 端点
|
||
|
||
| 方法 | 路径 | 说明 | 权限 |
|
||
|------|------|------|------|
|
||
| GET | `/platform/dashboard/overview` | 运营概览(总览数据) | 超管 |
|
||
| GET | `/platform/dashboard/revenue` | 收入趋势(按月) | 超管 |
|
||
| GET | `/platform/dashboard/tenants` | 租户统计 | 超管 |
|
||
| GET | `/platform/dashboard/api-usage` | API 用量趋势 | 超管 |
|
||
|
||
--- |