更新渠道删除

This commit is contained in:
Ubuntu
2025-12-25 10:59:02 +00:00
parent f3e10771ea
commit 658548b61c
8 changed files with 719 additions and 651 deletions
+171 -8
View File
@@ -2040,7 +2040,89 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
---
#### 4. 统一管理渠道资源
#### 4. 更新渠道信息
**PUT** `/api/admin/channels/{channel_id}`
更新渠道的基本信息。
**请求体**:
```json
{
"name": "合作渠道A(更新)",
"email": "new-email@channel-a.com",
"commissionRate": 12.0,
"status": "active"
}
```
**请求参数说明**:
- `name` (string, 可选): 渠道名称
- `email` (string, 可选): 渠道管理员邮箱
- `commissionRate` (float, 可选): 佣金比例,0-100之间
- `status` (string, 可选): 状态,`active` 或 `inactive`
**curl示例**:
```bash
curl -X PUT "http://localhost:8002/api/admin/channels/channel-uuid-1" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{
"name": "合作渠道A(更新)",
"commissionRate": 12.0
}'
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "channel-uuid-1",
"name": "合作渠道A(更新)",
"email": "partner@channel-a.com",
"commissionRate": 12.0,
"status": "active"
},
"message": "渠道信息更新成功"
}
```
---
#### 5. 删除渠道
**DELETE** `/api/admin/channels/{channel_id}`
删除渠道(软删除,仅标记为不活跃)。如果渠道下有活跃租户,将拒绝删除。
**curl示例**:
```bash
curl -X DELETE "http://localhost:8002/api/admin/channels/channel-uuid-1" \
-H "Authorization: Bearer $ADMIN_TOKEN"
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "channel-uuid-1"
},
"message": "渠道已删除"
}
```
**错误响应(有关联租户)**:
```json
{
"detail": "渠道下有 5 个活跃租户,无法删除。请先移除或停用所有租户。"
}
```
---
#### 6. 统一管理渠道资源
**PUT** `/api/admin/channels/{channel_id}/resources`
@@ -2074,7 +2156,7 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
### 申请审批相关
#### 5. 获取所有申请
#### 7. 获取所有申请
**GET** `/api/admin/channels/applications`
@@ -2105,7 +2187,7 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
---
#### 6. 审批申请
#### 8. 审批申请
**PUT** `/api/admin/channels/applications/{application_id}/review`
@@ -2129,7 +2211,7 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
### 资源管理相关
#### 7. 获取所有模型供应商
#### 9. 获取所有模型供应商
**GET** `/api/admin/resources/models`
@@ -2157,7 +2239,7 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
---
#### 8. 获取所有Agent资源
#### 10. 获取所有Agent资源
**GET** `/api/admin/resources/agents`
@@ -2183,9 +2265,84 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
---
#### 11. 删除Agent资源
**DELETE** `/api/admin/resources/agents/{agent_id}`
删除Agent资源(软删除,仅标记为不活跃)。
**curl示例**:
```bash
curl -X DELETE "http://localhost:8002/api/admin/resources/agents/agent-uuid-1" \
-H "Authorization: Bearer $ADMIN_TOKEN"
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "agent-uuid-1",
"name": "weather-agent"
},
"message": "Agent资源已删除"
}
```
---
#### 12. 更新Agent资源配置
**PUT** `/api/admin/resources/agents/{agent_id}/config`
更新Agent的资源配置(CPU、内存、最大实例数)。
**请求体**:
```json
{
"cpu": 4.0,
"memory": 8.0,
"maxInstances": 10
}
```
**请求参数说明**:
- `cpu` (float, 可选): CPU核心数,0.1-64之间
- `memory` (float, 可选): 内存大小(GB),0.5-256之间
- `maxInstances` (int, 可选): 最大实例数,1-1000之间
**curl示例**:
```bash
curl -X PUT "http://localhost:8002/api/admin/resources/agents/agent-uuid-1/config" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{
"cpu": 4.0,
"memory": 8.0,
"maxInstances": 10
}'
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "agent-uuid-1",
"name": "weather-agent",
"cpu": 4.0,
"memory": 8.0,
"maxInstances": 10
},
"message": "Agent资源配置更新成功"
}
```
---
### 监控相关
#### 9. 监控Agent健康状态
#### 13. 监控Agent健康状态
**GET** `/api/admin/monitoring/agents`
@@ -2214,7 +2371,7 @@ curl -s -X POST "http://localhost:8002/api/admin/channels/create" \
### 计费相关(三维度)
#### 10. 获取三维度计费统计
#### 14. 获取三维度计费统计
**GET** `/api/admin/billing/overview`
@@ -2520,7 +2677,7 @@ def get_dashboard(token: str):
---
**文档版本**: v2.2.0
**文档版本**: v2.3.0
**最后更新**: 2025年12月25日
**维护者**: taiji-AI-PAD 项目组
@@ -2647,6 +2804,12 @@ echo "=== API测试完成 ==="
## 更新日志
- **v2.3.0** (2025-12-25): **新增管理接口**
- ✅ 添加 PUT /api/admin/channels/{channel_id} - 更新渠道信息
- ✅ 添加 DELETE /api/admin/channels/{channel_id} - 删除渠道(软删除)
- ✅ 添加 DELETE /api/admin/resources/agents/{agent_id} - 删除Agent资源(软删除)
- ✅ 添加 PUT /api/admin/resources/agents/{agent_id}/config - 更新Agent资源配置
- ✅ 更新超级管理员API接口编号
- **v2.2.0** (2025-12-25): **完整API测试验证**
- ✅ 添加完整API测试流程示例
- ✅ 更新所有curl命令示例
@@ -1,278 +0,0 @@
# Taiji AI-PAD 全面 API 测试报告
**测试日期**: 2025年12月25日
**测试版本**: v2.1.0
**测试环境**: Docker Compose 部署环境
---
## 📊 测试总结
| 指标 | 结果 |
|------|------|
| **总测试数** | 40 |
| **通过测试** | 40 |
| **失败测试** | 0 |
| **成功率** | **100%** ✅ |
---
## 🔧 修复的问题
### 1. Agent创建时数据库约束错误
**问题**: 创建Agent时,测试用户缺少必需的`name`字段,导致数据库NOT NULL约束违反。
**修复**:
- 在`_ensure_test_user`函数中添加`name`、`password_hash`和`role`字段
- 文件: `services/mcp-server/app/routes/agents.py`
```python
test_user = User(
id=TEST_USER_ID,
name="测试用户", # 添加name字段
username="test_user",
email="test@taiji-ai.com",
password_hash="", # 添加password_hash字段
hashed_password="",
full_name="测试用户",
role="user", # 添加role字段
is_active=True,
is_admin=False,
)
```
### 2. 渠道租户列表获取channelId失败
**问题**: 渠道管理员登录时,JWT token中缺少`channelId`字段,导致无法获取租户列表。
**修复**:
- 在渠道登录时自动创建或关联渠道
- 在JWT token中包含`channelId`
- 文件: `services/mcp-server/app/routes/frontend_integration.py`
```python
# 如果用户没有channel_id,查找或创建对应的渠道
channel_id = user.channel_id
if not channel_id:
result = await db.execute(select(Channel).where(Channel.email == email))
channel = result.scalar_one_or_none()
if not channel:
# 创建一个默认渠道
channel = Channel(
name=f"渠道-{email.split('@')[0]}",
email=email,
password_hash=user.password_hash,
commission_rate=10.0,
channel_credit=0.0,
custom_agent_cpu=2.0,
custom_agent_memory=4.0,
status="active"
)
db.add(channel)
await db.flush()
user.channel_id = channel.id
await db.commit()
channel_id = channel.id
token = create_access_token({
"sub": str(user.id),
"email": email,
"role": "channel_admin",
"channelId": str(channel_id) # 包含channelId
})
```
### 3. Agent工具执行时execution_id重复
**问题**: 测试脚本使用固定的request id,导致execution_id重复,违反数据库唯一约束。
**修复**:
- 在测试脚本中使用时间戳生成唯一的request id
- 文件: `scripts/test_all_apis.py`
```python
execution_data = {
"jsonrpc": "2.0",
"id": f"test-{int(time.time()*1000)}", # 使用时间戳生成唯一ID
"method": "tools/call",
...
}
```
### 4. Prometheus指标返回格式
**说明**: Prometheus指标端点返回纯文本格式(不是JSON),这是正常的。
**修复**:
- 在测试脚本中添加`expect_json=False`参数
- 正确处理非JSON响应
---
## 📋 测试覆盖范围
### 1. Data Ingestion 服务 (6项测试)
- ✅ 健康检查
- ✅ 获取统计信息
- ✅ 获取工具列表
- ✅ 获取Prometheus指标
- ✅ 同步RapidAPI端点
- ✅ APILLAMA处理API文档
### 2. MCP Server 基础服务 (3项测试)
- ✅ 健康检查
- ✅ 获取Prometheus指标
- ✅ 获取工具列表
### 3. Agent 管理 (4项测试)
- ✅ 获取Agent列表
- ✅ 创建Agent
- ✅ 获取特定Agent
- ✅ 执行Agent工具
### 4. 认证模块 (4项测试)
- ✅ 管理员登录
- ✅ 渠道管理员登录
- ✅ 供应商登录
- ✅ 标准用户登录(预期失败,用户不存在)
### 5. 用户侧平台 API (7项测试)
- ✅ 获取仪表板统计
- ✅ 获取Agent活动数据
- ✅ 选择网关类型
- ✅ 获取网关API列表
- ✅ 获取网关监控数据
- ✅ 获取平台Agent列表
- ✅ 获取余额信息
### 6. 渠道合作伙伴 API (3项测试)
- ✅ 获取渠道仪表板统计
- ✅ 获取租户列表
- ✅ 获取渠道计费统计
### 7. 超级管理员 API (7项测试)
- ✅ 获取平台统计
- ✅ 获取渠道列表
- ✅ 获取所有申请
- ✅ 获取所有模型供应商
- ✅ 获取所有Agent资源
- ✅ 监控Agent健康状态
- ✅ 获取三维度计费统计
### 8. 供应商管理 API (1项测试)
- ✅ 获取模型供应商列表
### 9. MCP 监控 API (5项测试)
- ✅ 获取系统性能指标
- ✅ 获取服务统计信息
- ✅ 获取性能趋势数据
- ✅ 获取系统告警
- ✅ 获取监控仪表盘聚合
---
## 🎯 测试结果详情
### 系统健康状态
```json
{
"status": "healthy",
"services": {
"data_ingestion": "healthy",
"redis": "healthy",
"nats": "healthy",
"database": "healthy"
}
}
```
### 系统性能指标
```json
{
"system": {
"cpu_usage_percent": 3.8,
"memory_usage_percent": 30.8,
"disk_usage_percent": 13.6
},
"services": {
"active_agents": 3,
"total_executions_24h": 2,
"daily_active_users": 0
}
}
```
### 认证测试
- ✅ 管理员登录成功,获取token
- ✅ 渠道管理员登录成功,获取token(包含channelId)
- ✅ 供应商登录成功,获取token
- ✅ 标准用户登录(预期401,用户不存在)
### Agent管理测试
- ✅ 成功创建3个测试Agent
- ✅ 成功执行Agent工具(math_add)
- ✅ 计费记录正确创建
- ✅ EU消费正确计算
---
## 🚀 部署状态
### Docker容器状态
```
NAME STATUS
taiji-api-gateway Up (healthy)
taiji-data-ingestion Up (healthy)
taiji-grafana Up
taiji-litellm-gateway Up (healthy)
taiji-mcp-server Up (healthy)
taiji-nats Up
taiji-prometheus Up
```
### 端口映射
- Data Ingestion: `http://localhost:8001`
- MCP Server: `http://localhost:8002`
- LiteLLM Gateway: `http://localhost:4000`
- API Gateway: `http://localhost:80`
- Prometheus: `http://localhost:9090`
- Grafana: `http://localhost:3000`
- NATS: `nats://localhost:4222`
---
## 📝 测试脚本
完整的测试脚本位于: `scripts/test_all_apis.py`
### 运行测试
```bash
cd /home/taiji/tools/taiji-AI-PAD
python3 scripts/test_all_apis.py
```
### 测试特点
- 自动化测试所有API端点
- 支持认证token管理
- 详细的错误报告
- 彩色输出和进度显示
- 100%测试覆盖率
---
## ✅ 结论
所有40项API测试全部通过,系统运行稳定,功能完整。主要修复了以下问题:
1. ✅ 数据库约束错误
2. ✅ 认证token缺失字段
3. ✅ 唯一约束冲突
4. ✅ 响应格式处理
系统已经可以正常使用,所有核心功能均已验证。
---
**测试人员**: AI Assistant
**审核人员**: 待定
**下次测试日期**: 根据需要
@@ -1,227 +0,0 @@
# Taiji AI-PAD 普通用户创建和登录功能测试报告
## 测试时间
2025-12-25
## 测试环境
- 服务地址: http://localhost:8002
- 服务状态: ✅ Healthy
- 数据库状态: ✅ Healthy
## 测试结果总结
### ✅ 成功的功能 (7/9) - 通过率: 77.8%
1. **管理员创建** - ✅ 通过
- 端点: `/api/admin/auth/login`
- 功能: 自动创建管理员账号
- 测试账号: admin_test@test.com
2. **普通用户创建** - ✅ 通过
- 端点: `/api/channel/tenants/create`
- 功能: 通过渠道管理员创建租户(普通用户)
- 测试账号: normaluser@test.com
- 关联渠道: test_channel@test.com
3. **普通用户登录** - ✅ 通过
- 端点: `/api/auth/login`
- 角色: user
- JWT Token: ✅ 成功返回
- 用户信息: ✅ 完整返回(包含channelId)
4. **用户仪表板访问** - ✅ 通过
- 端点: `/api/user/dashboard/stats`
- 返回数据: activeAgents, totalRequests, euBalance, systemHealth
- 认证方式: Bearer Token ✅
5. **Agent列表查询** - ✅ 通过
- 端点: `/agents`
- 功能: 查询用户可用的Agent列表
- 认证: ✅ 正常
6. **错误密码拒绝** - ✅ 通过
- 状态码: 401 Unauthorized
- 安全性: ✅ 正确拒绝错误密码
7. **用户登出** - ✅ 通过
- 端点: `/api/auth/logout`
- 功能: 用户登出功能正常
### ⚠️ 问题项 (2/9)
1. **渠道创建失败** - ⚠️
- 端点: `/api/admin/channels/create`
- 原因: 渠道已存在(邮箱重复)
- 影响: 不影响测试,使用已存在的渠道
- 状态: 非关键问题
2. **用户余额查询** - ❌ 404
- 端点: `/api/user/balance`
- 问题: 端点不存在或路径错误
- 影响: 余额查询功能不可用
- 建议: 检查API路由配置
## 测试流程
### 完整的普通用户创建和登录流程
```
1. 管理员账号创建/登录
↓
2. 管理员创建渠道
↓
3. 渠道管理员登录(role=channel)
↓
4. 渠道管理员创建租户(普通用户)
↓
5. 普通用户登录(role=user)
↓
6. 普通用户访问受保护的API
```
### 关键发现
#### 1. 渠道管理员登录方式
- ❌ **不推荐**: `/api/channel/auth/login`
- 问题: 创建的是普通用户,不是真正的渠道记录
- 无channelId,无法创建租户
- ✅ **推荐**: `/api/auth/login` + `role="channel"`
- 正确: 从Channel表查找,有channelId
- 可以正常创建租户
#### 2. 用户数据结构
```json
{
"id": "e2224c57-ed0a-4047-8e3d-204ac8432c19",
"name": "普通用户",
"email": "normaluser@test.com",
"role": "user",
"channelId": "fc9020ac-cdd7-4924-8941-afb2be33bc74"
}
```
#### 3. JWT Token结构
```
Token包含信息:
- sub: 用户ID
- email: 用户邮箱
- role: 用户角色(user)
- channelId: 关联的渠道ID
```
## 功能验证
### ✅ 已验证的功能
1. **账号创建**
- ✅ 管理员可以创建渠道
- ✅ 渠道管理员可以创建租户(普通用户)
- ✅ 用户信息正确保存到数据库
- ✅ 用户与渠道正确关联
2. **登录认证**
- ✅ 普通用户使用邮箱密码登录
- ✅ JWT Token正常生成和返回
- ✅ 错误密码正确拒绝
- ✅ 不存在用户正确拒绝
3. **权限控制**
- ✅ Bearer Token认证机制正常
- ✅ 用户可以访问自己的仪表板
- ✅ 用户可以查询Agent列表
- ✅ 角色权限验证正常
4. **会话管理**
- ✅ 登出功能正常
- ✅ Token有效期控制
## API端点清单
### 成功验证的端点
| 端点 | 方法 | 功能 | 状态 |
|------|------|------|------|
| `/api/admin/auth/login` | POST | 管理员登录 | ✅ |
| `/api/auth/login` | POST | 统一登录(支持channel角色) | ✅ |
| `/api/channel/tenants/create` | POST | 创建租户 | ✅ |
| `/api/user/dashboard/stats` | GET | 用户仪表板 | ✅ |
| `/agents` | GET | Agent列表 | ✅ |
| `/api/auth/logout` | POST | 用户登出 | ✅ |
### 需要修复的端点
| 端点 | 方法 | 问题 | 优先级 |
|------|------|------|--------|
| `/api/user/balance` | GET | 404 Not Found | 中 |
| `/api/admin/channels/create` | POST | 重复创建报错 | 低 |
## 测试账号
### 创建的测试账号
1. **管理员**
- 邮箱: admin_test@test.com
- 密码: admin123
- 角色: admin
2. **渠道**
- 名称: 测试渠道
- 邮箱: test_channel@test.com
- 密码: channel123
- 佣金率: 10%
3. **普通用户(租户)**
- 姓名: 普通用户
- 邮箱: normaluser@test.com
- 密码: user123456
- 角色: user
- 订阅等级: free
- 关联渠道: test_channel@test.com
## 安全特性验证
- ✅ 密码bcrypt加密存储
- ✅ JWT Token认证
- ✅ 错误密码拒绝(401)
- ✅ 角色权限验证
- ✅ Bearer Token访问控制
## 建议
### 1. API路由修复
- 检查并修复 `/api/user/balance` 端点
- 确保所有用户相关API路由正确配置
### 2. 错误处理改进
- 渠道重复创建应返回更明确的错误信息
- 建议返回409 Conflict而不是400
### 3. 文档更新
- 更新API文档,明确说明渠道登录的正确方式
- 添加普通用户创建流程的完整示例
### 4. 测试覆盖
- 添加用户充值功能测试
- 添加用户Agent执行功能测试
- 添加用户账单查询功能测试
## 结论
✅ **普通用户创建和登录核心功能正常运行!**
### 关键成果
- ✅ 普通用户创建流程完整可用
- ✅ 登录认证机制工作正常
- ✅ JWT Token认证成功
- ✅ 用户权限控制有效
- ✅ 基础API访问正常
### 通过率: **77.8% (7/9)**
系统已具备完整的用户注册、登录和基础功能访问能力,可以支持普通用户的正常使用。剩余问题为非关键功能,不影响核心业务流程。
## 测试脚本
- 位置: `/home/taiji/tools/taiji-AI-PAD/scripts/test_normal_user_v2.py`
- 运行命令: `python3 scripts/test_normal_user_v2.py`
@@ -1,138 +0,0 @@
# Taiji AI-PAD 账号注册和登录功能测试报告
## 测试时间
2025-12-25
## 测试环境
- 服务地址: http://localhost:8002
- 服务状态: ✅ Healthy
- 数据库状态: ✅ Healthy
## 测试结果总结
### ✅ 成功的功能 (8/11)
1. **健康检查** - ✅ 通过
- 端点: `/health`
- 状态: 正常
2. **管理员账号自动创建** - ✅ 通过
- 端点: `/api/admin/auth/login`
- 功能: 首次登录自动创建账号
- 测试账号: admin@test.com
3. **渠道管理员账号自动创建** - ✅ 通过
- 端点: `/api/channel/auth/login`
- 功能: 首次登录自动创建账号
- 测试账号: channel@test.com
4. **供应商账号自动创建** - ✅ 通过
- 端点: `/api/providers/auth/login`
- 功能: 首次登录自动创建账号
- 测试账号: provider@test.com
5. **管理员API访问** - ✅ 通过
- 端点: `/api/admin/dashboard/stats`
- 功能: 使用JWT token访问受保护的API
- 认证方式: Bearer Token
6. **渠道管理员API访问** - ✅ 通过
- 端点: `/api/channel/dashboard/stats`
- 功能: 渠道仪表板数据访问
7. **供应商API访问** - ✅ 通过
- 端点: `/api/providers/models`
- 功能: 供应商模型列表访问
8. **错误处理** - ✅ 通过
- 错误密码正确拒绝 (401)
- 不存在用户正确拒绝 (401)
### ⚠️ 需要注意的问题 (3/11)
1. **标准Auth端点登录** - ⚠️ 部分失败
- 端点: `/api/auth/login`
- 问题: 角色验证严格,frontend-integration创建的用户角色为"user",无法以admin/provider角色登录
- 原因: 角色不匹配(用户role="user",但尝试以"admin"/"provider"登录)
- 影响: 需要确保用户创建时设置正确的角色
2. **bcrypt密码哈希** - ⚠️ 已修复
- 问题: bcrypt版本兼容性导致密码哈希失败
- 解决方案: 更新bcrypt到4.0.1版本
- 状态: ✅ 已解决
3. **数据库字段约束** - ⚠️ 已修复
- 问题: User表的name字段NOT NULL约束
- 解决方案: 在ensure_user函数中添加name字段
- 状态: ✅ 已解决
## 功能特性
### 1. 自动账号创建
- ✅ Frontend Integration端点支持首次登录自动创建账号
- ✅ 自动生成用户名、设置默认值
- ✅ 密码使用bcrypt加密存储
### 2. JWT Token认证
- ✅ 登录成功返回JWT token
- ✅ Token包含用户信息(sub, email, role)
- ✅ Token有效期: 3600秒 (1小时)
### 3. 多角色支持
- ✅ 管理员 (admin, super_admin)
- ✅ 渠道管理员 (channel_admin)
- ✅ 供应商 (provider_admin)
- ✅ 普通用户 (user)
- ✅ 计费管理员 (billing_admin)
- ✅ 运营管理员 (operations_admin)
### 4. 安全特性
- ✅ 密码bcrypt加密
- ✅ 错误密码拒绝访问
- ✅ 不存在用户拒绝访问
- ✅ JWT token验证
- ✅ 角色权限验证
## API端点清单
### Frontend Integration端点
1. `/api/admin/auth/login` - 管理员登录(自动创建)
2. `/api/channel/auth/login` - 渠道管理员登录(自动创建)
3. `/api/providers/auth/login` - 供应商登录(自动创建)
### 标准Auth端点
1. `/api/auth/login` - 统一登录端点(需要指定role)
2. `/api/auth/logout` - 登出
### 受保护的API端点
1. `/api/admin/dashboard/stats` - 管理员仪表板
2. `/api/channel/dashboard/stats` - 渠道仪表板
3. `/api/providers/models` - 供应商模型列表
## 建议
1. **角色管理改进**
- 建议在frontend-integration端点创建用户时,根据端点类型设置正确的角色
- admin端点创建的用户应设置role为"admin"或"super_admin"
- provider端点创建的用户应设置role为"provider_admin"
2. **用户注册端点**
- 考虑添加公开的用户注册端点,允许新用户自主注册
3. **密码策略**
- 建议添加密码复杂度验证
- 建议添加密码重置功能
## 结论
✅ **账号注册和登录核心功能正常运行**
- 自动账号创建功能完善
- JWT认证机制工作正常
- 多角色支持完整
- 安全特性到位
- API访问控制有效
通过率: **73% (8/11)**
主要问题已修复,剩余问题为角色匹配逻辑,不影响核心功能使用。
+174
View File
@@ -0,0 +1,174 @@
# 缺失的 API 接口清单
根据前端代码和 API 文档的对比,以下接口在 API 文档中**没有提供**:
## 1. 删除 Agent 接口
**前端使用位置**: `/app/admin/dashboard/page.tsx` (资源管理标签页)
**当前实现**:
- 前端使用 `TaijiAPIClient.deleteTool(agent.id || agent.name)` 来删除 Agent
- 这个接口实际上是删除 Data Ingestion 服务中的工具,而不是删除 Agent 资源
**需要的接口**:
```
DELETE /api/admin/resources/agents/{agent_id}
```
**请求示例**:
```bash
curl -X DELETE "http://localhost:8002/api/admin/resources/agents/agent-uuid-1" \
-H "Authorization: Bearer <admin_token>"
```
**响应示例**:
```json
{
"success": true,
"message": "Agent资源已删除"
}
```
**说明**:
- 当前前端代码错误地使用了 `deleteTool` 接口来删除 Agent
- 应该提供一个专门的删除 Agent 资源的接口
- 删除应该是软删除,仅标记为不活跃
---
## 2. 删除渠道接口
**前端使用位置**: `/app/admin/dashboard/page.tsx` (渠道管理标签页)
**当前状态**:
- 前端UI中有"删除渠道"按钮,但没有实现对应的API调用
**需要的接口**:
```
DELETE /api/admin/channels/{channel_id}
```
**请求示例**:
```bash
curl -X DELETE "http://localhost:8002/api/admin/channels/channel-uuid-1" \
-H "Authorization: Bearer <admin_token>"
```
**响应示例**:
```json
{
"success": true,
"message": "渠道已删除"
}
```
**说明**:
- 删除渠道前应该检查是否有关联的租户
- 如果有租户,应该提示或阻止删除
- 删除应该是软删除,仅标记为不活跃
---
## 3. 更新渠道信息接口
**前端使用位置**: `/app/admin/dashboard/page.tsx` (渠道管理标签页)
**当前状态**:
- 前端可能有编辑渠道信息的功能,但需要确认是否有对应的API
**需要的接口**:
```
PUT /api/admin/channels/{channel_id}
```
**请求体**:
```json
{
"name": "合作渠道A(更新)",
"email": "new-email@channel-a.com",
"commissionRate": 12.0,
"status": "active"
}
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "channel-uuid-1",
"name": "合作渠道A(更新)",
"email": "new-email@channel-a.com"
},
"message": "渠道信息更新成功"
}
```
---
## 4. 更新 Agent 资源配置接口
**前端使用位置**: `/app/admin/dashboard/page.tsx` (资源管理标签页 - Agent资源配置对话框)
**当前状态**:
- 前端有配置 Agent CPU 和内存的对话框,但保存时没有调用API
**需要的接口**:
```
PUT /api/admin/resources/agents/{agent_id}/config
```
**请求体**:
```json
{
"cpu": 4.0,
"memory": 8.0,
"maxInstances": 10
}
```
**响应示例**:
```json
{
"success": true,
"message": "Agent资源配置更新成功"
}
```
---
## 总结
### 已实现的接口(2025-12-25 更新):
1. ✅ **DELETE /api/admin/resources/agents/{agent_id}** - 删除Agent资源(软删除)
2. ✅ **DELETE /api/admin/channels/{channel_id}** - 删除渠道(软删除,检查关联租户)
3. ✅ **PUT /api/admin/channels/{channel_id}** - 更新渠道信息
4. ✅ **PUT /api/admin/resources/agents/{agent_id}/config** - 更新Agent资源配置
### 所有接口状态:
✅ 所有接口都已实现并在API文档中有说明
---
## 实现说明
### 2025-12-25 新增接口
1. **DELETE /api/admin/resources/agents/{agent_id}**
- 软删除Agent资源,将状态标记为 `inactive`
- 需要超级管理员权限
2. **DELETE /api/admin/channels/{channel_id}**
- 软删除渠道,将状态标记为 `inactive`
- 删除前检查是否有活跃租户,如有则拒绝删除
- 需要超级管理员权限
3. **PUT /api/admin/channels/{channel_id}**
- 更新渠道的名称、邮箱、佣金比例、状态
- 更新邮箱时检查是否与其他渠道冲突
- 需要超级管理员权限
4. **PUT /api/admin/resources/agents/{agent_id}/config**
- 更新Agent的CPU、内存、最大实例数配置
- 需要超级管理员权限
+162
View File
@@ -0,0 +1,162 @@
#!/usr/bin/env python3
"""
生成初始用户的SQL插入语句
使用bcrypt加密密码
"""
import uuid
from datetime import datetime
import bcrypt
def hash_password(password: str) -> str:
"""使用bcrypt加密密码"""
# bcrypt需要bytes类型的密码
password_bytes = password.encode('utf-8')
# 生成salt并加密
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password_bytes, salt)
# 返回字符串形式
return hashed.decode('utf-8')
# 定义初始用户
USERS = [
{
"name": "超级管理员",
"username": "admin",
"email": "admin@test.com",
"password": "admin123",
"role": "super_admin",
"full_name": "系统超级管理员",
"is_active": True,
"is_admin": True,
"subscription_tier": "enterprise",
"balance": 100000,
"credit_limit": 500000,
"status": "active"
},
{
"name": "渠道管理员",
"username": "channel",
"email": "channel@test.com",
"password": "channel123",
"role": "channel_admin",
"full_name": "渠道管理员",
"is_active": True,
"is_admin": False,
"subscription_tier": "business",
"balance": 50000,
"credit_limit": 100000,
"status": "active"
},
{
"name": "供应商管理员",
"username": "provider",
"email": "provider@test.com",
"password": "provider123",
"role": "provider_admin",
"full_name": "供应商管理员",
"is_active": True,
"is_admin": False,
"subscription_tier": "business",
"balance": 50000,
"credit_limit": 100000,
"status": "active"
},
{
"name": "测试用户",
"username": "user",
"email": "user@test.com",
"password": "user123",
"role": "user",
"full_name": "普通测试用户",
"is_active": True,
"is_admin": False,
"subscription_tier": "free",
"balance": 100,
"credit_limit": 1000,
"status": "active"
},
{
"name": "计费管理员",
"username": "billing",
"email": "billing@test.com",
"password": "billing123",
"role": "billing_admin",
"full_name": "计费管理员",
"is_active": True,
"is_admin": False,
"subscription_tier": "business",
"balance": 10000,
"credit_limit": 50000,
"status": "active"
},
{
"name": "运维管理员",
"username": "operations",
"email": "operations@test.com",
"password": "operations123",
"role": "operations_admin",
"full_name": "运维管理员",
"is_active": True,
"is_admin": False,
"subscription_tier": "business",
"balance": 10000,
"credit_limit": 50000,
"status": "active"
}
]
def generate_sql():
"""生成SQL插入语句"""
print("-- 初始用户数据")
print("-- 自动生成时间:", datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
print("-- 注意: 此脚本会在用户不存在时插入初始用户\n")
for user in USERS:
user_id = str(uuid.uuid4())
password_hash = hash_password(user["password"])
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"-- 创建用户: {user['name']} ({user['email']})")
print(f"INSERT INTO users (")
print(f" id, created_at, updated_at,")
print(f" name, username, email,")
print(f" password_hash, hashed_password,")
print(f" role, full_name,")
print(f" is_active, is_admin,")
print(f" subscription_tier, balance, credit_limit,")
print(f" status, discount")
print(f") VALUES (")
print(f" '{user_id}', '{now}', '{now}',")
print(f" '{user['name']}', '{user['username']}', '{user['email']}',")
print(f" '{password_hash}', '{password_hash}',")
print(f" '{user['role']}', '{user['full_name']}',")
print(f" {user['is_active']}, {user['is_admin']},")
print(f" '{user['subscription_tier']}', {user['balance']}, {user['credit_limit']},")
print(f" '{user['status']}', 0")
print(f") ON CONFLICT (email) DO NOTHING;")
print()
def main():
print("="*80)
print("Taiji AI-PAD 初始用户SQL生成器")
print("="*80)
print()
generate_sql()
print("\n-- 用户信息汇总:")
print("-- " + "="*76)
for user in USERS:
print(f"-- {user['name']:15} | {user['email']:25} | 密码: {user['password']}")
print("-- " + "="*76)
print("\n-- 提示: 将上述SQL语句添加到 scripts/init.sql 文件末尾")
print("-- 或者创建新的 scripts/init_users.sql 文件")
if __name__ == "__main__":
main()
+197
View File
@@ -18,6 +18,8 @@ from app.auth import require_auth, get_password_hash
from app.schemas import (
SuccessResponse,
CreateChannelRequest,
UpdateChannelRequest,
UpdateAgentConfigRequest,
ChannelInfo,
ChannelResourceAllocation,
ApplicationInfo,
@@ -164,6 +166,121 @@ async def create_channel(
)
@router.put("/channels/{channel_id}", response_model=SuccessResponse)
async def update_channel(
channel_id: str,
req: UpdateChannelRequest,
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""
更新渠道信息
"""
_verify_admin_permission(principal)
# 验证渠道存在
result = await db.execute(
select(Channel).where(Channel.id == channel_id)
)
channel = result.scalar_one_or_none()
if not channel:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="渠道不存在"
)
# 如果更新邮箱,检查邮箱是否已被其他渠道使用
if req.email and req.email != channel.email:
email_check = await db.execute(
select(Channel).where(
and_(
Channel.email == req.email,
Channel.id != channel_id
)
)
)
if email_check.scalar_one_or_none():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="邮箱已被其他渠道使用"
)
channel.email = req.email
# 更新其他字段
if req.name is not None:
channel.name = req.name
if req.commissionRate is not None:
channel.commission_rate = req.commissionRate
if req.status is not None:
channel.status = req.status
await db.commit()
await db.refresh(channel)
return SuccessResponse(
data={
"id": str(channel.id),
"name": channel.name,
"email": channel.email,
"commissionRate": float(channel.commission_rate),
"status": channel.status,
},
message="渠道信息更新成功"
)
@router.delete("/channels/{channel_id}", response_model=SuccessResponse)
async def delete_channel(
channel_id: str,
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""
删除渠道(软删除,标记为不活跃)
"""
_verify_admin_permission(principal)
# 验证渠道存在
result = await db.execute(
select(Channel).where(Channel.id == channel_id)
)
channel = result.scalar_one_or_none()
if not channel:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="渠道不存在"
)
# 检查是否有关联的租户
tenants_result = await db.execute(
select(func.count(User.id)).where(
and_(
User.channel_id == channel_id,
User.role == "user",
User.status == "active"
)
)
)
tenant_count = tenants_result.scalar() or 0
if tenant_count > 0:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"渠道下有 {tenant_count} 个活跃租户,无法删除。请先移除或停用所有租户。"
)
# 软删除:标记为不活跃
channel.status = "inactive"
await db.commit()
return SuccessResponse(
data={"id": str(channel.id)},
message="渠道已删除"
)
@router.put("/channels/{channel_id}/resources", response_model=SuccessResponse)
async def allocate_channel_resources(
channel_id: str,
@@ -421,6 +538,86 @@ async def list_all_agents(
return SuccessResponse(data={"agents": data})
@router.delete("/resources/agents/{agent_id}", response_model=SuccessResponse)
async def delete_agent_resource(
agent_id: str,
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""
删除Agent资源(软删除,标记为不活跃)
"""
_verify_admin_permission(principal)
# 验证Agent存在
result = await db.execute(
select(Agent).where(Agent.id == agent_id)
)
agent = result.scalar_one_or_none()
if not agent:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Agent资源不存在"
)
# 软删除:标记为不活跃
agent.status = "inactive"
await db.commit()
return SuccessResponse(
data={"id": str(agent.id), "name": agent.name},
message="Agent资源已删除"
)
@router.put("/resources/agents/{agent_id}/config", response_model=SuccessResponse)
async def update_agent_config(
agent_id: str,
req: UpdateAgentConfigRequest,
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""
更新Agent资源配置(CPU、内存、最大实例数)
"""
_verify_admin_permission(principal)
# 验证Agent存在
result = await db.execute(
select(Agent).where(Agent.id == agent_id)
)
agent = result.scalar_one_or_none()
if not agent:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Agent资源不存在"
)
# 更新配置
if req.cpu is not None:
agent.cpu = req.cpu
if req.memory is not None:
agent.memory = req.memory
if req.maxInstances is not None:
agent.max_instances = req.maxInstances
await db.commit()
await db.refresh(agent)
return SuccessResponse(
data={
"id": str(agent.id),
"name": agent.name,
"cpu": float(agent.cpu),
"memory": float(agent.memory),
"maxInstances": agent.max_instances,
},
message="Agent资源配置更新成功"
)
# ============= 监控 =============
@router.get("/monitoring/agents", response_model=SuccessResponse)
+15
View File
@@ -462,6 +462,21 @@ class CreateChannelRequest(BaseModel):
commissionRate: float = Field(0, ge=0, le=100)
class UpdateChannelRequest(BaseModel):
"""更新渠道信息请求"""
name: Optional[str] = None
email: Optional[EmailStr] = None
commissionRate: Optional[float] = Field(None, ge=0, le=100)
status: Optional[str] = Field(None, pattern="^(active|inactive)$")
class UpdateAgentConfigRequest(BaseModel):
"""更新Agent资源配置请求"""
cpu: Optional[float] = Field(None, ge=0.1, le=64)
memory: Optional[float] = Field(None, ge=0.5, le=256)
maxInstances: Optional[int] = Field(None, ge=1, le=1000)
class ChannelInfo(BaseModel):
"""渠道信息"""
id: str