forked from xiaohei/taiji-AI-PAD
10 KiB
10 KiB
计费仪表板概览接口文档
接口信息
接口路径: GET /api/user/dashboard/billing-overview
功能: 获取用户计费和资源使用的完整仪表板数据
认证: 需要 Bearer Token
权限: 租户用户(user角色)
响应数据结构
完整示例
{
"success": true,
"message": "成功获取仪表板数据",
"data": {
"currentMonth": {
"spent": 1250.50,
"euConsumed": 12505.0,
"avgDailySpent": 125.05,
"predictedTotal": 3876.55,
"daysElapsed": 10,
"totalDays": 31,
"currency": "CNY"
},
"lastMonth": {
"spent": 1000.00,
"euConsumed": 10000.0
},
"comparison": {
"percentage": 25.1,
"direction": "up"
},
"balance": {
"eu": 50000.0,
"cash": 50000.0
},
"euHistory": [
{
"date": "2026-01-01",
"euConsumed": 1200.5,
"cost": 120.05,
"calls": 150
},
{
"date": "2026-01-02",
"euConsumed": 1350.0,
"cost": 135.00,
"calls": 180
}
],
"costBreakdown": {
"categories": [
{
"category": "platform_agent",
"name": "平台Agent",
"cost": 450.50,
"percentage": 36.0
},
{
"category": "custom_agent",
"name": "自定义Agent",
"cost": 350.00,
"percentage": 28.0
},
{
"category": "model_api",
"name": "模型API",
"cost": 400.00,
"percentage": 32.0
},
{
"category": "other",
"name": "其他",
"cost": 50.00,
"percentage": 4.0
}
],
"total": 1250.50
},
"resourceUsage": {
"resources": [
{
"type": "cpu",
"name": "CPU",
"used": 2.5,
"limit": 10.0,
"unit": "核",
"percentage": 25.0
},
{
"type": "memory",
"name": "内存",
"used": 5.0,
"limit": 20.0,
"unit": "GB",
"percentage": 25.0
},
{
"type": "storage",
"name": "存储",
"used": 0,
"limit": 1000,
"unit": "GB",
"percentage": 0.0
},
{
"type": "api_calls",
"name": "API调用",
"used": 15000,
"limit": 100000,
"unit": "次",
"percentage": 15.0
}
]
},
"metadata": {
"timestamp": "2026-01-10T12:30:45.123456",
"userId": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
数据字段说明
currentMonth (当前月份统计)
| 字段 | 类型 | 说明 |
|---|---|---|
| spent | float | 本月已消费金额(CNY) |
| euConsumed | float | 本月已消费EU(执行单位) |
| avgDailySpent | float | 平均每日消费金额 |
| predictedTotal | float | 预计月底总消费(基于日均值) |
| daysElapsed | int | 本月已过天数 |
| totalDays | int | 本月总天数 |
| currency | string | 货币类型(CNY) |
lastMonth (上月统计)
| 字段 | 类型 | 说明 |
|---|---|---|
| spent | float | 上月总消费金额 |
| euConsumed | float | 上月总消费EU |
comparison (对比数据)
| 字段 | 类型 | 说明 |
|---|---|---|
| percentage | float | 与上月对比的百分比变化 |
| direction | string | 趋势方向:up(上升)、down(下降)、stable(持平) |
balance (余额信息)
| 字段 | 类型 | 说明 |
|---|---|---|
| eu | float | 当前EU余额(1 EU = 1 美元) |
| cash | float | 当前现金余额(美元),与 eu 相等(1 美元 = 1 EU) |
euHistory (EU消费历史)
数组,每个元素包含:
| 字段 | 类型 | 说明 |
|---|---|---|
| date | string | 日期(ISO格式:YYYY-MM-DD) |
| euConsumed | float | 当日消费的EU |
| cost | float | 当日费用 |
| calls | int | 当日调用次数 |
时间范围: 最近30天的数据
costBreakdown (费用明细)
| 字段 | 类型 | 说明 |
|---|---|---|
| categories | array | 费用分类数组 |
| total | float | 总费用 |
categories数组元素:
| 字段 | 类型 | 说明 |
|---|---|---|
| category | string | 分类标识:platform_agent、custom_agent、model_api、other |
| name | string | 分类名称 |
| cost | float | 该分类的费用 |
| percentage | float | 占总费用的百分比 |
resourceUsage (资源使用)
| 字段 | 类型 | 说明 |
|---|---|---|
| resources | array | 资源使用数组 |
resources数组元素:
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 资源类型:cpu、memory、storage、api_calls |
| name | string | 资源名称 |
| used | float/int | 已使用量 |
| limit | float/int | 配额上限 |
| unit | string | 单位:核、GB、次 |
| percentage | float | 使用百分比 |
metadata (元数据)
| 字段 | 类型 | 说明 |
|---|---|---|
| timestamp | string | 数据生成时间(ISO 8601格式) |
| userId | string | 用户ID(UUID格式) |
前端调用示例
JavaScript/TypeScript
// 使用fetch
async function getBillingOverview() {
try {
const response = await fetch('/api/user/dashboard/billing-overview', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
if (data.success) {
return data.data;
} else {
throw new Error(data.message || '获取数据失败');
}
} catch (error) {
console.error('获取计费概览失败:', error);
throw error;
}
}
// 使用axios
import axios from 'axios';
async function getBillingOverviewAxios() {
try {
const response = await axios.get('/api/user/dashboard/billing-overview', {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.data.data;
} catch (error) {
console.error('获取计费概览失败:', error);
throw error;
}
}
React示例
import { useState, useEffect } from 'react';
import axios from 'axios';
interface BillingOverview {
currentMonth: {
spent: number;
euConsumed: number;
avgDailySpent: number;
predictedTotal: number;
daysElapsed: number;
totalDays: number;
currency: string;
};
lastMonth: {
spent: number;
euConsumed: number;
};
comparison: {
percentage: number;
direction: 'up' | 'down' | 'stable';
};
balance: {
eu: number;
cash: number;
};
euHistory: Array<{
date: string;
euConsumed: number;
cost: number;
calls: number;
}>;
costBreakdown: {
categories: Array<{
category: string;
name: string;
cost: number;
percentage: number;
}>;
total: number;
};
resourceUsage: {
resources: Array<{
type: string;
name: string;
used: number;
limit: number;
unit: string;
percentage: number;
}>;
};
}
function BillingDashboard() {
const [overview, setOverview] = useState<BillingOverview | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
async function fetchData() {
try {
setLoading(true);
const response = await axios.get('/api/user/dashboard/billing-overview', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
});
if (response.data.success) {
setOverview(response.data.data);
} else {
setError(response.data.message || '获取数据失败');
}
} catch (err) {
setError('网络请求失败');
console.error(err);
} finally {
setLoading(false);
}
}
fetchData();
}, []);
if (loading) return <div>加载中...</div>;
if (error) return <div>错误: {error}</div>;
if (!overview) return <div>暂无数据</div>;
return (
<div className="billing-dashboard">
{/* 本月费用 */}
<div className="current-month">
<h2>本月费用</h2>
<p>已消费: ¥{overview.currentMonth.spent.toFixed(2)}</p>
<p>平均每日: ¥{overview.currentMonth.avgDailySpent.toFixed(2)}</p>
<p>预计月底: ¥{overview.currentMonth.predictedTotal.toFixed(2)}</p>
</div>
{/* EU消费历史图表 */}
<div className="eu-history">
<h2>EU消费历史</h2>
{/* 这里可以使用图表库如Chart.js、ECharts等 */}
{overview.euHistory.map(item => (
<div key={item.date}>
{item.date}: {item.euConsumed} EU
</div>
))}
</div>
{/* 费用明细 */}
<div className="cost-breakdown">
<h2>费用明细</h2>
{overview.costBreakdown.categories.map(cat => (
<div key={cat.category}>
{cat.name}: ¥{cat.cost.toFixed(2)} ({cat.percentage.toFixed(1)}%)
</div>
))}
</div>
{/* 资源使用 */}
<div className="resource-usage">
<h2>资源使用</h2>
{overview.resourceUsage.resources.map(res => (
<div key={res.type}>
<div>{res.name}</div>
<progress value={res.percentage} max={100}></progress>
<span>{res.used} / {res.limit} {res.unit}</span>
</div>
))}
</div>
</div>
);
}
export default BillingDashboard;
错误响应
401 未授权
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "未提供有效的认证令牌"
}
}
500 服务器错误
{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "服务器内部错误"
}
}
性能优化建议
- 缓存策略: 建议前端缓存数据5分钟,避免频繁请求
- 按需加载: 可以考虑将历史数据单独请求
- 数据轮询: 如需实时更新,建议轮询间隔不少于30秒
更新日志
| 版本 | 日期 | 说明 |
|---|---|---|
| v1.0.0 | 2026-01-10 | 初始版本,实现完整仪表板数据接口 |
相关接口
GET /api/user/dashboard/stats- 基础仪表板统计GET /api/user/billing/balance- 余额查询GET /api/user/billing/history- 计费历史