更新超级管理查看资源分配

This commit is contained in:
zhanggangyong
2026-01-12 17:16:55 +00:00
parent c6bab43f12
commit 0ddc548d0f
4 changed files with 1092 additions and 3 deletions
@@ -0,0 +1,676 @@
# 超级管理员查看渠道资源分配接口文档
> **版本**: v1.0.0
> **更新时间**: 2026-01-13
> **说明**: 超级管理员查看渠道已分配的资源详情,包括自定义Agent、平台Agent、模型供应商、模型等
---
## 目录
1. [接口概述](#接口概述)
2. [接口详情](#接口详情)
3. [数据结构说明](#数据结构说明)
4. [使用场景](#使用场景)
5. [前端调用示例](#前端调用示例)
---
## 接口概述
| 接口 | 路径 | 方法 | 权限 | 说明 |
|------|------|------|------|------|
| 查看渠道资源分配详情 | `/api/admin/channels/{channel_id}/allocated-resources` | GET | super_admin, billing_admin, operations_admin | 查看指定渠道被分配的所有资源详情 |
### 权限说明
- **super_admin**: 可查看所有渠道的资源分配
- **billing_admin / operations_admin**: 可查看所有渠道的资源分配
---
## 接口详情
### 基本信息
| 属性 | 值 |
|------|-----|
| **接口路径** | `GET /api/admin/channels/{channel_id}/allocated-resources` |
| **后端文件** | `services/mcp-server/app/routes/admin.py` |
| **后端状态** | ✅ 已实现 |
| **权限要求** | super_admin, billing_admin, operations_admin |
### 请求参数
#### 路径参数 (Path Parameters)
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| channel_id | string (UUID) | 是 | 渠道ID | `6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6` |
#### 请求头 (Headers)
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| Authorization | string | 是 | Bearer Token | `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...` |
### 请求示例
```bash
curl -X GET "http://localhost:8002/api/admin/channels/6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6/allocated-resources" \
-H "Authorization: Bearer $SUPER_ADMIN_TOKEN"
```
### 响应参数
#### 成功响应 (200 OK)
```json
{
"success": true,
"data": {
"channelId": "string (UUID)",
"channelName": "string",
"channelEmail": "string",
"channelStatus": "string",
"createdAt": "string (ISO 8601)",
"channelCredit": "number",
"commissionRate": "number",
"customAgentQuota": {
"cpuQuota": "number",
"memoryQuota": "number",
"cpuAllocatedToTenants": "number",
"memoryAllocatedToTenants": "number",
"cpuAvailable": "number",
"memoryAvailable": "number"
} | null,
"platformAgents": [
{
"templateName": "string",
"templateDisplayName": "string",
"podQuota": "integer",
"podUsed": "integer",
"podAllocatedToTenants": "integer",
"podAvailable": "integer",
"cpuPerPod": "string",
"memoryPerPod": "string",
"allocatedAt": "string (ISO 8601)"
}
],
"modelProviders": [
{
"providerId": "string (UUID)",
"providerName": "string",
"providerType": "string",
"status": "string",
"models": [
{
"modelName": "string",
"rpmLimit": "integer",
"tpmLimit": "integer",
"maxBudget": "number | null",
"budgetDuration": "string"
}
]
}
],
"models": [
{
"modelName": "string",
"providerName": "string | null",
"rpmLimit": "integer",
"tpmLimit": "integer",
"maxBudget": "number | null",
"budgetDuration": "string",
"allocatedToTenants": "integer"
}
],
"summary": {
"totalCustomAgentCpuQuota": "number",
"totalCustomAgentMemoryQuota": "number",
"totalPlatformAgentPodQuota": "integer",
"totalPlatformAgentPodUsed": "integer",
"totalModelProviders": "integer",
"totalModels": "integer",
"totalTenantsWithResources": "integer"
}
},
"message": "获取渠道资源分配详情成功"
}
```
#### 响应字段说明
| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `data.channelId` | string | 渠道ID |
| `data.channelName` | string | 渠道名称 |
| `data.channelEmail` | string | 渠道邮箱 |
| `data.channelStatus` | string | 渠道状态 (active/inactive/suspended) |
| `data.createdAt` | string | 渠道创建时间 (ISO 8601格式) |
| `data.channelCredit` | number | 渠道信用额度 |
| `data.commissionRate` | number | 渠道佣金比例 |
**自定义Agent配额 (customAgentQuota)**
| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `cpuQuota` | number | CPU配额上限(核心数) |
| `memoryQuota` | number | 内存配额上限(GB) |
| `cpuAllocatedToTenants` | number | 已分配给租户的CPU(核心数) |
| `memoryAllocatedToTenants` | number | 已分配给租户的内存(GB) |
| `cpuAvailable` | number | 剩余可分配CPU(核心数) |
| `memoryAvailable` | number | 剩余可分配内存(GB) |
**平台Agent配额 (platformAgents)**
| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `templateName` | string | 模板技术名称 (如 echo_agent) |
| `templateDisplayName` | string | 模板显示名称 (如 Echo测试服务) |
| `podQuota` | integer | 该模板的Pod配额数量 |
| `podUsed` | integer | 已使用的Pod数量(运行中) |
| `podAllocatedToTenants` | integer | 已分配给租户的Pod数量 |
| `podAvailable` | integer | 剩余可分配Pod数量 |
| `cpuPerPod` | string | 每个Pod的CPU配置 (如 100m) |
| `memoryPerPod` | string | 每个Pod的内存配置 (如 256Mi) |
| `allocatedAt` | string | 分配时间 (ISO 8601格式) |
**模型供应商 (modelProviders)**
| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `providerId` | string | 供应商ID |
| `providerName` | string | 供应商名称 (如 OpenAI、Anthropic) |
| `providerType` | string | 供应商类型 (如 openai、anthropic) |
| `status` | string | 供应商状态 (active/inactive) |
| `models` | array | 该供应商下的模型列表 |
**模型配额 (models)**
| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `modelName` | string | 模型全名 (如 taiji/gpt-4o) |
| `providerName` | string/null | 所属供应商名称 |
| `rpmLimit` | integer | RPM限制(每分钟请求数) |
| `tpmLimit` | integer | TPM限制(每分钟Token数) |
| `maxBudget` | number/null | 最大预算限额 |
| `budgetDuration` | string | 预算周期 (monthly/daily) |
| `allocatedToTenants` | integer | 已分配给租户的数量 |
**汇总统计 (summary)**
| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `totalCustomAgentCpuQuota` | number | 自定义Agent总CPU配额 |
| `totalCustomAgentMemoryQuota` | number | 自定义Agent总内存配额 |
| `totalPlatformAgentPodQuota` | integer | 平台Agent总Pod配额 |
| `totalPlatformAgentPodUsed` | integer | 平台Agent已使用Pod数 |
| `totalModelProviders` | integer | 模型供应商数量 |
| `totalModels` | integer | 模型总数 |
| `totalTenantsWithResources` | integer | 有资源分配的租户数 |
### 实际响应示例
```json
{
"success": true,
"data": {
"channelId": "6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6",
"channelName": "示例渠道",
"channelEmail": "channel@example.com",
"channelStatus": "active",
"createdAt": "2026-01-01T00:00:00.000000",
"channelCredit": 100000.0,
"commissionRate": 0.15,
"customAgentQuota": {
"cpuQuota": 20.0,
"memoryQuota": 40.0,
"cpuAllocatedToTenants": 12.0,
"memoryAllocatedToTenants": 24.0,
"cpuAvailable": 8.0,
"memoryAvailable": 16.0
},
"platformAgents": [
{
"templateName": "echo_agent",
"templateDisplayName": "Echo 测试服务",
"podQuota": 10,
"podUsed": 3,
"podAllocatedToTenants": 6,
"podAvailable": 4,
"cpuPerPod": "100m",
"memoryPerPod": "256Mi",
"allocatedAt": "2026-01-05T10:30:00.000000"
},
{
"templateName": "code_agent",
"templateDisplayName": "代码执行服务",
"podQuota": 5,
"podUsed": 2,
"podAllocatedToTenants": 3,
"podAvailable": 2,
"cpuPerPod": "200m",
"memoryPerPod": "512Mi",
"allocatedAt": "2026-01-06T14:20:00.000000"
}
],
"modelProviders": [
{
"providerId": "550e8400-e29b-41d4-a716-446655440000",
"providerName": "OpenAI",
"providerType": "openai",
"status": "active",
"models": [
{
"modelName": "taiji/gpt-4o",
"rpmLimit": 1000,
"tpmLimit": 100000,
"maxBudget": 5000.0,
"budgetDuration": "monthly"
},
{
"modelName": "taiji/gpt-4o-mini",
"rpmLimit": 2000,
"tpmLimit": 200000,
"maxBudget": 2000.0,
"budgetDuration": "monthly"
}
]
},
{
"providerId": "660e8400-e29b-41d4-a716-446655440001",
"providerName": "Anthropic",
"providerType": "anthropic",
"status": "active",
"models": [
{
"modelName": "taiji/claude-3-opus",
"rpmLimit": 500,
"tpmLimit": 50000,
"maxBudget": 10000.0,
"budgetDuration": "monthly"
}
]
}
],
"models": [
{
"modelName": "taiji/gpt-4o",
"providerName": "OpenAI",
"rpmLimit": 1000,
"tpmLimit": 100000,
"maxBudget": 5000.0,
"budgetDuration": "monthly",
"allocatedToTenants": 3
},
{
"modelName": "taiji/gpt-4o-mini",
"providerName": "OpenAI",
"rpmLimit": 2000,
"tpmLimit": 200000,
"maxBudget": 2000.0,
"budgetDuration": "monthly",
"allocatedToTenants": 5
},
{
"modelName": "taiji/claude-3-opus",
"providerName": "Anthropic",
"rpmLimit": 500,
"tpmLimit": 50000,
"maxBudget": 10000.0,
"budgetDuration": "monthly",
"allocatedToTenants": 2
}
],
"summary": {
"totalCustomAgentCpuQuota": 20.0,
"totalCustomAgentMemoryQuota": 40.0,
"totalPlatformAgentPodQuota": 15,
"totalPlatformAgentPodUsed": 5,
"totalModelProviders": 2,
"totalModels": 3,
"totalTenantsWithResources": 5
}
},
"message": "获取渠道资源分配详情成功"
}
```
### 错误响应
| HTTP状态码 | 错误说明 | 响应示例 |
|------------|----------|----------|
| 400 | 无效的渠道ID格式 | `{"success": false, "detail": "无效的渠道ID格式"}` |
| 403 | 权限不足 | `{"success": false, "detail": "权限不足,无法查看渠道资源"}` |
| 404 | 渠道不存在 | `{"success": false, "detail": "渠道不存在"}` |
---
## 数据结构说明
### 渠道状态 (channelStatus)
| 值 | 说明 |
|----|------|
| `active` | 活跃状态 |
| `inactive` | 已停用 |
| `suspended` | 已暂停 |
### 供应商状态 (status)
| 值 | 说明 |
|----|------|
| `active` | 正常可用 |
| `inactive` | 已停用 |
| `error` | 连接异常 |
### 预算周期 (budgetDuration)
| 值 | 说明 |
|----|------|
| `monthly` | 月度预算 |
| `daily` | 每日预算 |
### CPU/内存格式
| 格式 | 说明 | 示例 |
|------|------|------|
| CPU (millicores) | Kubernetes CPU格式 | `100m` = 0.1核, `500m` = 0.5核 |
| Memory (MiB/GiB) | Kubernetes 内存格式 | `256Mi` = 256MB, `2Gi` = 2GB |
---
## 使用场景
### 场景1: 超级管理员审查渠道资源配置
超级管理员需要全面了解某个渠道被分配了哪些资源,以及这些资源的使用情况。
```bash
# 查看渠道 "示例渠道" 的所有资源分配
curl -X GET "http://localhost:8002/api/admin/channels/6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6/allocated-resources" \
-H "Authorization: Bearer $SUPER_ADMIN_TOKEN"
```
### 场景2: 资源规划与调配
通过查看各渠道的资源分配和使用情况,进行合理的资源规划:
- **查看自定义Agent配额使用率**: `cpuAllocatedToTenants / cpuQuota`
- **查看平台Agent使用率**: `podUsed / podQuota`
- **了解模型分配情况**: 通过 `allocatedToTenants` 了解每个模型被多少租户使用
### 场景3: 计费审计
计费管理员可以通过此接口了解渠道的资源配置和信用额度,辅助计费审计工作。
---
## 前端调用示例
### JavaScript/TypeScript
```typescript
interface CustomAgentQuota {
cpuQuota: number;
memoryQuota: number;
cpuAllocatedToTenants: number;
memoryAllocatedToTenants: number;
cpuAvailable: number;
memoryAvailable: number;
}
interface PlatformAgentQuota {
templateName: string;
templateDisplayName: string;
podQuota: number;
podUsed: number;
podAllocatedToTenants: number;
podAvailable: number;
cpuPerPod: string;
memoryPerPod: string;
allocatedAt: string;
}
interface ModelInfo {
modelName: string;
rpmLimit: number;
tpmLimit: number;
maxBudget: number | null;
budgetDuration: string;
}
interface ModelProviderInfo {
providerId: string;
providerName: string;
providerType: string;
status: string;
models: ModelInfo[];
}
interface ChannelModelInfo extends ModelInfo {
providerName: string | null;
allocatedToTenants: number;
}
interface ResourceSummary {
totalCustomAgentCpuQuota: number;
totalCustomAgentMemoryQuota: number;
totalPlatformAgentPodQuota: number;
totalPlatformAgentPodUsed: number;
totalModelProviders: number;
totalModels: number;
totalTenantsWithResources: number;
}
interface ChannelAllocatedResources {
channelId: string;
channelName: string;
channelEmail: string;
channelStatus: string;
createdAt: string;
channelCredit: number;
commissionRate: number;
customAgentQuota: CustomAgentQuota | null;
platformAgents: PlatformAgentQuota[];
modelProviders: ModelProviderInfo[];
models: ChannelModelInfo[];
summary: ResourceSummary;
}
interface ChannelAllocatedResourcesResponse {
success: boolean;
data: ChannelAllocatedResources;
message: string;
}
// API 调用函数
async function getChannelAllocatedResources(channelId: string): Promise<ChannelAllocatedResourcesResponse> {
const response = await fetch(
`${API_BASE_URL}/api/admin/channels/${channelId}/allocated-resources`,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
// 使用示例
async function displayChannelResources(channelId: string) {
try {
const result = await getChannelAllocatedResources(channelId);
if (result.success) {
const { data } = result;
console.log(`渠道: ${data.channelName}`);
console.log(`状态: ${data.channelStatus}`);
console.log(`信用额度: ¥${data.channelCredit}`);
// 自定义Agent配额
if (data.customAgentQuota) {
const { cpuQuota, cpuAllocatedToTenants, memoryQuota, memoryAllocatedToTenants } = data.customAgentQuota;
console.log(`自定义Agent CPU: ${cpuAllocatedToTenants}/${cpuQuota} 核`);
console.log(`自定义Agent 内存: ${memoryAllocatedToTenants}/${memoryQuota} GB`);
}
// 平台Agent配额
console.log(`平台Agent模板数: ${data.platformAgents.length}`);
data.platformAgents.forEach(agent => {
console.log(` - ${agent.templateDisplayName}: ${agent.podUsed}/${agent.podQuota} Pods`);
});
// 模型统计
console.log(`模型供应商数: ${data.summary.totalModelProviders}`);
console.log(`模型总数: ${data.summary.totalModels}`);
}
} catch (error) {
console.error('获取渠道资源失败:', error);
}
}
```
### React Hook 示例
```typescript
import { useState, useEffect } from 'react';
function useChannelAllocatedResources(channelId: string | null) {
const [data, setData] = useState<ChannelAllocatedResources | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
if (!channelId) return;
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const result = await getChannelAllocatedResources(channelId);
if (result.success) {
setData(result.data);
} else {
throw new Error(result.message);
}
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
};
fetchData();
}, [channelId]);
return { data, loading, error };
}
// 组件使用
function ChannelResourcesPanel({ channelId }: { channelId: string }) {
const { data, loading, error } = useChannelAllocatedResources(channelId);
if (loading) return <div>加载中...</div>;
if (error) return <div>错误: {error.message}</div>;
if (!data) return null;
return (
<div className="channel-resources">
<h2>{data.channelName} - 资源分配详情</h2>
{/* 自定义Agent配额卡片 */}
{data.customAgentQuota && (
<ResourceCard title="自定义Agent配额">
<ProgressBar
label="CPU"
used={data.customAgentQuota.cpuAllocatedToTenants}
total={data.customAgentQuota.cpuQuota}
unit="核"
/>
<ProgressBar
label="内存"
used={data.customAgentQuota.memoryAllocatedToTenants}
total={data.customAgentQuota.memoryQuota}
unit="GB"
/>
</ResourceCard>
)}
{/* 平台Agent配额列表 */}
<ResourceCard title="平台Agent配额">
{data.platformAgents.map(agent => (
<div key={agent.templateName}>
<span>{agent.templateDisplayName}</span>
<ProgressBar
label="Pods"
used={agent.podUsed}
total={agent.podQuota}
/>
</div>
))}
</ResourceCard>
{/* 模型列表 */}
<ResourceCard title="模型配额">
<table>
<thead>
<tr>
<th>模型</th>
<th>供应商</th>
<th>RPM</th>
<th>TPM</th>
<th>已分配租户</th>
</tr>
</thead>
<tbody>
{data.models.map(model => (
<tr key={model.modelName}>
<td>{model.modelName}</td>
<td>{model.providerName || '-'}</td>
<td>{model.rpmLimit}</td>
<td>{model.tpmLimit}</td>
<td>{model.allocatedToTenants}</td>
</tr>
))}
</tbody>
</table>
</ResourceCard>
</div>
);
}
```
---
## 与现有接口的对比
| 特性 | 现有接口 `/api/admin/channels/{channel_id}/resources` | 新接口 `/api/admin/channels/{channel_id}/allocated-resources` |
|------|------------------------------------------------------|---------------------------------------------------------------|
| 自定义Agent配额 | 只有配额总量 | 配额+已分配+可用量 |
| 平台Agent | 只有Agent列表 | 每个模板的配额详情+使用情况 |
| 模型信息 | 只有模型名称列表 | 供应商+模型+RPM/TPM限制+分配情况 |
| 渠道信息 | 无 | 包含渠道基本信息 |
| 汇总统计 | 无 | 完整的资源汇总统计 |
---
## 更新日志
### v1.0.0 (2026-01-13)
- 初始版本
- 实现超级管理员查看渠道资源分配详情接口
- 支持自定义Agent、平台Agent、模型供应商、模型的完整资源查看
- 包含资源使用率和分配统计