chore: 提交所有工作进度 — SaaS 后端增强、Admin UI、桌面端集成

包含大量 SaaS 平台改进、Admin 管理后台更新、桌面端集成完善、
文档同步、测试文件重构等内容。为 QA 测试准备干净工作树。
This commit is contained in:
iven
2026-03-29 10:46:26 +08:00
parent 9a5fad2b59
commit 5fdf96c3f5
268 changed files with 22011 additions and 3886 deletions

View File

@@ -0,0 +1,385 @@
# ZCLAW SaaS 后端优化计划
> 生成时间: 2026-03-28
> 分析范围: crates/zclaw-saas
## 一、架构概览
```
┌─────────────────────────────────────────────────────────────────┐
│ ZCLAW SaaS Backend │
│ (Rust + Axum + PostgreSQL) │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ auth │ │ account │ │model_cfg │ │ relay │ │
│ │ 认证 │ │ 账号管理 │ │ 模型配置 │ │ 中转服务 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └─────────────┴─────────────┴─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ middleware │ │
│ │ - auth │ │
│ │ - rate_limit│ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ PostgreSQL │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## 二、API 接口清单 (共 42 个端点)
### 2.1 认证模块 `/api/v1/auth` (5 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| POST | `/auth/register` | 公开 | 用户注册 |
| POST | `/auth/login` | 公开 | 用户登录 |
| POST | `/auth/refresh` | 认证 | 刷新 Token |
| GET | `/auth/me` | 认证 | 获取当前用户 |
| PUT | `/auth/password` | 认证 | 修改密码 |
### 2.2 账号管理 `/api/v1` (12 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| GET | `/accounts` | admin | 列出账号 |
| GET | `/accounts/:id` | 自己/admin | 账号详情 |
| PUT | `/accounts/:id` | 自己/admin | 更新账号 |
| PATCH | `/accounts/:id/status` | admin | 更新状态 |
| GET | `/tokens` | 认证 | 列出 Token |
| POST | `/tokens` | 认证 | 创建 Token |
| DELETE | `/tokens/:id` | 认证 | 撤销 Token |
| GET | `/logs/operations` | admin | 操作日志 |
| GET | `/stats/dashboard` | admin | 仪表盘 |
| POST | `/devices/register` | 认证 | 注册设备 |
| POST | `/devices/heartbeat` | 认证 | 设备心跳 |
| GET | `/devices` | 认证 | 设备列表 |
### 2.3 模型配置 `/api/v1` (15 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| GET | `/providers` | 认证 | 服务商列表 |
| GET | `/providers/:id` | 认证 | 服务商详情 |
| POST | `/providers` | provider:manage | 创建服务商 |
| PUT | `/providers/:id` | provider:manage | 更新服务商 |
| DELETE | `/providers/:id` | provider:manage | 删除服务商 |
| GET | `/models` | 认证 | 模型列表 |
| GET | `/models/:id` | 认证 | 模型详情 |
| POST | `/models` | model:manage | 创建模型 |
| PUT | `/models/:id` | model:manage | 更新模型 |
| DELETE | `/models/:id` | model:manage | 删除模型 |
| GET | `/keys` | 认证 | API Key 列表 |
| POST | `/keys` | 认证 | 创建 Key |
| POST | `/keys/:id/rotate` | 认证 | 轮换 Key |
| DELETE | `/keys/:id` | 认证 | 撤销 Key |
| GET | `/usage` | 认证 | 用量统计 |
### 2.4 中转服务 `/api/v1/relay` (5 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| POST | `/relay/chat/completions` | relay:use | 聊天补全 |
| GET | `/relay/tasks` | 认证 | 任务列表 |
| GET | `/relay/tasks/:id` | 认证 | 任务详情 |
| GET | `/relay/models` | 认证 | 可用模型 |
| POST | `/relay/tasks/:id/retry` | relay:admin | 重试任务 |
### 2.5 配置迁移 `/api/v1/config` (10 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| GET | `/config/items` | 认证 | 配置列表 |
| GET | `/config/items/:id` | 认证 | 配置详情 |
| POST | `/config/items` | config:write | 创建配置 |
| PUT | `/config/items/:id` | config:write | 更新配置 |
| DELETE | `/config/items/:id` | config:write | 删除配置 |
| GET | `/config/analysis` | 认证 | 配置分析 |
| POST | `/config/seed` | config:write | 种子配置 |
| POST | `/config/sync` | 认证 | 同步配置 |
| POST | `/config/diff` | 认证 | 配置差异 |
| GET | `/config/sync-logs` | 认证 | 同步日志 |
---
## 三、问题清单
### 🔴 高优先级 (影响功能/性能)
#### P1-001: 登录接口 N+1 查询
**位置:** `auth/handlers.rs:login()`
**现状:**
```rust
// 查询 1: 获取用户信息
let row = sqlx::query_as("SELECT id, username, ... FROM accounts WHERE username = $1")...
// 查询 2: 获取密码哈希
let (password_hash,) = sqlx::query_as("SELECT password_hash FROM accounts WHERE id = $1")...
// 查询 3: 获取权限
let permissions = get_role_permissions(&state.db, &role).await?;
```
**影响:** 每次登录触发 3 次数据库查询
**修复方案:**
```sql
SELECT a.id, a.username, a.email, a.display_name, a.role, a.status,
a.totp_enabled, a.created_at, a.password_hash,
r.permissions
FROM accounts a
LEFT JOIN roles r ON a.role = r.id
WHERE a.username = $1 OR a.email = $1
```
**工作量:** 小 (1-2 小时)
---
#### P1-002: 流式响应 Token 统计缺失
**位置:** `relay/handlers.rs:chat_completions()`
**现状:**
```rust
Ok(service::RelayResponse::Sse(body)) => {
model_service::record_usage(..., 0, 0, ...); // 流式记录 0 tokens
}
```
**影响:** 流式请求的 token 使用量无法统计,影响计费和监控
**修复方案:**
1. 解析 SSE 流中的 `usage` 字段
2. 在流结束后更新统计
**工作量:** 中 (4-6 小时)
---
#### P1-003: 健康检查端点缺失
**位置:** `main.rs`
**现状:**`/health``/ready` 端点
**影响:**
- K8s/Docker 无法进行健康检查
- 负载均衡器无法判断服务状态
**修复方案:**
```rust
.route("/health", get(|| async {
Json(json!({"status": "ok"}))
}))
.route("/ready", get(|State(state): State<AppState>| async move {
// 检查数据库连接
let db_ok = sqlx::query("SELECT 1").fetch_one(&state.db).await.is_ok();
Json(json!({"ready": db_ok, "db": if db_ok { "connected" } else { "disconnected" }}))
}))
```
**工作量:** 小 (1 小时)
---
### 🟡 中优先级 (影响可维护性)
#### P2-001: 权限系统无缓存
**位置:** `auth/handlers.rs:get_role_permissions()`
**现状:** 每次请求都查询数据库获取权限
**影响:**
- 数据库压力增加
- 响应延迟增加
**修复方案:**
1. 方案 A: 在 JWT 中嵌入权限 (无需查询,但权限变更需重新登录)
2. 方案 B: 添加内存缓存 (LRU Cache权限变更即时生效)
**推荐:** 方案 B使用 `moka``dashmap` 缓存
**工作量:** 中 (4-8 小时)
---
#### P2-002: 错误响应格式不统一
**位置:** 所有 handlers
**现状:**
```json
// 格式 1
{"error": "AUTH_ERROR", "message": "认证失败"}
// 格式 2
{"ok": true}
// 格式 3
{"ok": true, "message": "密码修改成功"}
```
**影响:** 前端需要处理多种格式,增加复杂度
**修复方案:** 统一为 RFC 7807 Problem Details 格式:
```json
{
"type": "https://zclaw.ai/errors/auth-error",
"title": "认证失败",
"status": 401,
"detail": "用户名或密码错误",
"code": "AUTH_ERROR"
}
```
**工作量:** 中 (4-6 小时)
---
#### P2-003: 分页响应缺少元数据
**位置:** `account/handlers.rs:list_accounts()`
**现状:**
```rust
pub struct PaginatedResponse<T> {
pub items: Vec<T>,
// 缺少 total, page, total_pages
}
```
**影响:** 前端无法显示总页数和分页导航
**修复方案:**
```rust
pub struct PaginatedResponse<T> {
pub items: Vec<T>,
pub total: i64,
pub page: i64,
pub page_size: i64,
pub total_pages: i64,
}
```
**工作量:** 小 (2-3 小时)
---
### 🟢 低优先级 (技术债务)
#### P3-001: 数据库 Schema 使用 TEXT 类型
**位置:** `db.rs`
**现状:**
```sql
created_at TEXT NOT NULL, -- 应该用 TIMESTAMPTZ
role TEXT NOT NULL DEFAULT 'user' -- 应该用外键
```
**影响:**
- 无法使用 PostgreSQL 时间函数
- 角色无外键约束,可能导致数据不一致
**修复方案:** 编写迁移脚本,逐步更新 Schema
**工作量:** 大 (需要数据迁移)
---
#### P3-002: 缺少请求追踪
**现状:** 操作日志只记录业务操作,不记录 API 请求详情
**影响:**
- 无法追踪请求链路
- 问题排查困难
**修复方案:** 添加请求追踪中间件:
- 生成 `request_id`
- 记录请求耗时
- 关联日志与请求
**工作量:** 中 (4-6 小时)
---
#### P3-003: API 版本控制策略缺失
**现状:** 只有 `v1`,无版本升级策略
**影响:** 未来 API 变更可能导致兼容性问题
**修复方案:**
1. 在响应头添加 `X-API-Version`
2. 支持 `Accept: application/vnd.zclaw.v1+json`
3. 添加版本废弃机制
**工作量:** 小 (2-3 小时)
---
## 四、优化实施计划
### Phase 1: 高优先级修复 (1-2 天)
| 任务 | 工作量 | 负责人 | 状态 |
|------|--------|--------|------|
| P1-001 登录 N+1 查询优化 | 2h | - | 待开始 |
| P1-003 健康检查端点 | 1h | - | 待开始 |
| P1-002 流式 Token 统计 | 6h | - | 待开始 |
### Phase 2: 中优先级优化 (2-3 天)
| 任务 | 工作量 | 负责人 | 状态 |
|------|--------|--------|------|
| P2-001 权限缓存 | 8h | - | 待开始 |
| P2-002 错误格式统一 | 6h | - | 待开始 |
| P2-003 分页元数据 | 3h | - | 待开始 |
### Phase 3: 技术债务清理 (按需)
| 任务 | 工作量 | 负责人 | 状态 |
|------|--------|--------|------|
| P3-001 Schema 迁移 | 2-3 天 | - | 待评估 |
| P3-002 请求追踪 | 6h | - | 待开始 |
| P3-003 API 版本控制 | 3h | - | 待开始 |
---
## 五、NOT in Scope
以下内容在本次优化范围之外:
1. **前端 Admin UI 优化** - 仅关注后端 API
2. **数据库分库分表** - 当前数据量不需要
3. **微服务拆分** - 架构已足够清晰
4. **GraphQL 支持** - REST API 已满足需求
5. **WebSocket 支持** - 当前无实时推送需求
---
## 六、风险评估
| 风险 | 可能性 | 影响 | 缓解措施 |
|------|--------|------|----------|
| Schema 迁移数据丢失 | 低 | 高 | 先备份,分批迁移 |
| 权限缓存不一致 | 中 | 中 | 设置 TTL主动失效 |
| 流式解析兼容性 | 中 | 低 | 多模型测试 |
---
## 七、验收标准
- [ ] 所有 API 端点有健康检查
- [ ] 登录接口响应时间 < 100ms (P99)
- [ ] 流式请求 Token 统计准确率 > 95%
- [ ] 错误响应格式统一
- [ ] 分页接口包含完整元数据