forked from xiaohei/taiji-AI-PAD
更新计费
This commit is contained in:
@@ -2853,6 +2853,11 @@ async def get_billing_overview(
|
||||
):
|
||||
"""
|
||||
获取三维度计费统计(所有管理员可查看)
|
||||
|
||||
从 AgentBillingRecord 和 ModelBillingRecord 表查询计费数据,
|
||||
返回渠道维度、租户维度和调用记录三个维度的统计。
|
||||
|
||||
EU 计算规则:1 EU = 10 秒运行时间(向上取整)
|
||||
"""
|
||||
_verify_read_permission(principal)
|
||||
|
||||
@@ -2866,99 +2871,227 @@ async def get_billing_overview(
|
||||
if end_dt.tzinfo is not None:
|
||||
end_dt = end_dt.replace(tzinfo=None)
|
||||
|
||||
# 渠道统计
|
||||
channel_stats_result = await db.execute(
|
||||
# ========== 渠道统计(从 AgentBillingRecord 和 ModelBillingRecord 聚合) ==========
|
||||
|
||||
# 1. 从 AgentBillingRecord 统计 Agent 使用
|
||||
agent_channel_stats = await db.execute(
|
||||
select(
|
||||
Channel.id,
|
||||
Channel.name,
|
||||
func.count(BillingRecord.id).label("calls"),
|
||||
func.sum(BillingRecord.eu).label("total_eu"),
|
||||
func.sum(BillingRecord.cost).label("total_cost"),
|
||||
func.count(AgentBillingRecord.id).label("calls"),
|
||||
func.sum(AgentBillingRecord.eu_consumed).label("total_eu"),
|
||||
func.sum(AgentBillingRecord.cost).label("total_cost"),
|
||||
)
|
||||
.select_from(BillingRecord)
|
||||
.join(Channel, BillingRecord.channel_id == Channel.id)
|
||||
.select_from(AgentBillingRecord)
|
||||
.join(Channel, AgentBillingRecord.channel_id == Channel.id)
|
||||
.where(
|
||||
and_(
|
||||
BillingRecord.timestamp >= start_dt,
|
||||
BillingRecord.timestamp <= end_dt,
|
||||
AgentBillingRecord.start_time >= start_dt,
|
||||
AgentBillingRecord.start_time <= end_dt,
|
||||
)
|
||||
)
|
||||
.group_by(Channel.id, Channel.name)
|
||||
)
|
||||
agent_channel_data = {str(row.id): {"name": row.name, "calls": row.calls or 0, "eu": float(row.total_eu or 0), "cost": float(row.total_cost or 0)} for row in agent_channel_stats.all()}
|
||||
|
||||
channel_stats = [
|
||||
{
|
||||
"channelId": str(row.id),
|
||||
"channelName": row.name,
|
||||
"calls": row.calls,
|
||||
"totalEU": float(row.total_eu or 0),
|
||||
"totalCost": float(row.total_cost or 0),
|
||||
}
|
||||
for row in channel_stats_result.all()
|
||||
]
|
||||
# 2. 从 ModelBillingRecord 统计模型调用
|
||||
model_channel_stats = await db.execute(
|
||||
select(
|
||||
Channel.id,
|
||||
Channel.name,
|
||||
func.count(ModelBillingRecord.id).label("calls"),
|
||||
func.sum(ModelBillingRecord.eu_consumed).label("total_eu"),
|
||||
func.sum(ModelBillingRecord.total_cost).label("total_cost"),
|
||||
)
|
||||
.select_from(ModelBillingRecord)
|
||||
.join(Channel, ModelBillingRecord.channel_id == Channel.id)
|
||||
.where(
|
||||
and_(
|
||||
ModelBillingRecord.start_time >= start_dt,
|
||||
ModelBillingRecord.start_time <= end_dt,
|
||||
)
|
||||
)
|
||||
.group_by(Channel.id, Channel.name)
|
||||
)
|
||||
model_channel_data = {str(row.id): {"name": row.name, "calls": row.calls or 0, "eu": float(row.total_eu or 0), "cost": float(row.total_cost or 0)} for row in model_channel_stats.all()}
|
||||
|
||||
# 租户统计
|
||||
tenant_stats_result = await db.execute(
|
||||
# 3. 合并渠道统计
|
||||
all_channel_ids = set(agent_channel_data.keys()) | set(model_channel_data.keys())
|
||||
channel_stats = []
|
||||
for channel_id in all_channel_ids:
|
||||
agent_data = agent_channel_data.get(channel_id, {"name": "", "calls": 0, "eu": 0, "cost": 0})
|
||||
model_data = model_channel_data.get(channel_id, {"name": "", "calls": 0, "eu": 0, "cost": 0})
|
||||
channel_name = agent_data["name"] or model_data["name"]
|
||||
total_calls = agent_data["calls"] + model_data["calls"]
|
||||
total_eu = agent_data["eu"] + model_data["eu"]
|
||||
total_cost = agent_data["cost"] + model_data["cost"]
|
||||
|
||||
# 应用筛选条件
|
||||
if channelName and channelName.lower() not in channel_name.lower():
|
||||
continue
|
||||
if minCalls is not None and total_calls < minCalls:
|
||||
continue
|
||||
if maxCalls is not None and total_calls > maxCalls:
|
||||
continue
|
||||
|
||||
channel_stats.append({
|
||||
"channelId": channel_id,
|
||||
"channelName": channel_name,
|
||||
"calls": total_calls,
|
||||
"totalEU": round(total_eu, 2),
|
||||
"totalCost": round(total_cost, 4),
|
||||
})
|
||||
|
||||
# ========== 租户统计(从 AgentBillingRecord 和 ModelBillingRecord 聚合) ==========
|
||||
|
||||
# 1. 从 AgentBillingRecord 统计
|
||||
agent_tenant_stats = await db.execute(
|
||||
select(
|
||||
User.id,
|
||||
User.name,
|
||||
Channel.name.label("channel_name"),
|
||||
func.count(BillingRecord.id).label("calls"),
|
||||
func.sum(BillingRecord.eu).label("total_eu"),
|
||||
func.sum(BillingRecord.cost).label("total_cost"),
|
||||
func.count(AgentBillingRecord.id).label("calls"),
|
||||
func.sum(AgentBillingRecord.eu_consumed).label("total_eu"),
|
||||
func.sum(AgentBillingRecord.cost).label("total_cost"),
|
||||
)
|
||||
.select_from(BillingRecord)
|
||||
.join(User, BillingRecord.tenant_id == User.id)
|
||||
.join(Channel, User.channel_id == Channel.id)
|
||||
.select_from(AgentBillingRecord)
|
||||
.join(User, AgentBillingRecord.user_id == User.id)
|
||||
.outerjoin(Channel, User.channel_id == Channel.id)
|
||||
.where(
|
||||
and_(
|
||||
BillingRecord.timestamp >= start_dt,
|
||||
BillingRecord.timestamp <= end_dt,
|
||||
AgentBillingRecord.start_time >= start_dt,
|
||||
AgentBillingRecord.start_time <= end_dt,
|
||||
)
|
||||
)
|
||||
.group_by(User.id, User.name, Channel.name)
|
||||
)
|
||||
agent_tenant_data = {str(row.id): {"name": row.name, "channel_name": row.channel_name or "无渠道", "calls": row.calls or 0, "eu": float(row.total_eu or 0), "cost": float(row.total_cost or 0)} for row in agent_tenant_stats.all()}
|
||||
|
||||
tenant_stats = [
|
||||
{
|
||||
"tenantId": str(row.id),
|
||||
"tenantName": row.name,
|
||||
"channelName": row.channel_name,
|
||||
"calls": row.calls,
|
||||
"totalEU": float(row.total_eu or 0),
|
||||
"totalCost": float(row.total_cost or 0),
|
||||
}
|
||||
for row in tenant_stats_result.all()
|
||||
]
|
||||
|
||||
# 调用记录
|
||||
records_result = await db.execute(
|
||||
select(BillingRecord, Channel.name, User.name)
|
||||
.join(Channel, BillingRecord.channel_id == Channel.id)
|
||||
.join(User, BillingRecord.tenant_id == User.id)
|
||||
# 2. 从 ModelBillingRecord 统计
|
||||
model_tenant_stats = await db.execute(
|
||||
select(
|
||||
User.id,
|
||||
User.name,
|
||||
Channel.name.label("channel_name"),
|
||||
func.count(ModelBillingRecord.id).label("calls"),
|
||||
func.sum(ModelBillingRecord.eu_consumed).label("total_eu"),
|
||||
func.sum(ModelBillingRecord.total_cost).label("total_cost"),
|
||||
)
|
||||
.select_from(ModelBillingRecord)
|
||||
.join(User, ModelBillingRecord.tenant_id == User.id)
|
||||
.outerjoin(Channel, User.channel_id == Channel.id)
|
||||
.where(
|
||||
and_(
|
||||
BillingRecord.timestamp >= start_dt,
|
||||
BillingRecord.timestamp <= end_dt,
|
||||
ModelBillingRecord.start_time >= start_dt,
|
||||
ModelBillingRecord.start_time <= end_dt,
|
||||
)
|
||||
)
|
||||
.order_by(desc(BillingRecord.timestamp))
|
||||
.limit(100)
|
||||
.group_by(User.id, User.name, Channel.name)
|
||||
)
|
||||
model_tenant_data = {str(row.id): {"name": row.name, "channel_name": row.channel_name or "无渠道", "calls": row.calls or 0, "eu": float(row.total_eu or 0), "cost": float(row.total_cost or 0)} for row in model_tenant_stats.all()}
|
||||
|
||||
# 3. 合并租户统计
|
||||
all_tenant_ids = set(agent_tenant_data.keys()) | set(model_tenant_data.keys())
|
||||
tenant_stats = []
|
||||
for tenant_id in all_tenant_ids:
|
||||
agent_data = agent_tenant_data.get(tenant_id, {"name": "", "channel_name": "无渠道", "calls": 0, "eu": 0, "cost": 0})
|
||||
model_data = model_tenant_data.get(tenant_id, {"name": "", "channel_name": "无渠道", "calls": 0, "eu": 0, "cost": 0})
|
||||
tenant_name_val = agent_data["name"] or model_data["name"]
|
||||
channel_name_val = agent_data["channel_name"] or model_data["channel_name"]
|
||||
total_calls = agent_data["calls"] + model_data["calls"]
|
||||
total_eu = agent_data["eu"] + model_data["eu"]
|
||||
total_cost = agent_data["cost"] + model_data["cost"]
|
||||
|
||||
# 应用筛选条件
|
||||
if tenantName and tenantName.lower() not in tenant_name_val.lower():
|
||||
continue
|
||||
if minCalls is not None and total_calls < minCalls:
|
||||
continue
|
||||
if maxCalls is not None and total_calls > maxCalls:
|
||||
continue
|
||||
|
||||
# 计算平均消费
|
||||
avg_cost = total_cost / total_calls if total_calls > 0 else 0
|
||||
|
||||
tenant_stats.append({
|
||||
"tenantId": tenant_id,
|
||||
"tenantName": tenant_name_val,
|
||||
"channelName": channel_name_val,
|
||||
"calls": total_calls,
|
||||
"totalEU": round(total_eu, 2),
|
||||
"totalCost": round(total_cost, 4),
|
||||
"avgCost": round(avg_cost, 4),
|
||||
})
|
||||
|
||||
# ========== 调用记录(合并 AgentBillingRecord 和 ModelBillingRecord) ==========
|
||||
call_records = []
|
||||
|
||||
# 1. 从 AgentBillingRecord 获取记录
|
||||
agent_records_result = await db.execute(
|
||||
select(AgentBillingRecord, Channel.name.label("channel_name"), User.name.label("user_name"))
|
||||
.outerjoin(Channel, AgentBillingRecord.channel_id == Channel.id)
|
||||
.join(User, AgentBillingRecord.user_id == User.id)
|
||||
.where(
|
||||
and_(
|
||||
AgentBillingRecord.start_time >= start_dt,
|
||||
AgentBillingRecord.start_time <= end_dt,
|
||||
)
|
||||
)
|
||||
.order_by(desc(AgentBillingRecord.start_time))
|
||||
.limit(50)
|
||||
)
|
||||
|
||||
call_records = [
|
||||
{
|
||||
for record, channel_name, user_name in agent_records_result.all():
|
||||
call_records.append({
|
||||
"id": str(record.id),
|
||||
"timestamp": record.timestamp.isoformat(),
|
||||
"channelName": channel_name,
|
||||
"tenantName": tenant_name,
|
||||
"type": "agent",
|
||||
"timestamp": record.start_time.isoformat() if record.start_time else None,
|
||||
"channelName": channel_name or "无渠道",
|
||||
"tenantName": user_name,
|
||||
"agentName": record.agent_name,
|
||||
"duration": record.duration,
|
||||
"eu": record.eu,
|
||||
"cost": float(record.cost),
|
||||
}
|
||||
for record, channel_name, tenant_name in records_result.all()
|
||||
]
|
||||
"modelName": record.model_name,
|
||||
"duration": record.duration_seconds or 0,
|
||||
"eu": record.eu_consumed or 0,
|
||||
"cost": float(record.cost or 0),
|
||||
})
|
||||
|
||||
# 2. 从 ModelBillingRecord 获取记录
|
||||
model_records_result = await db.execute(
|
||||
select(ModelBillingRecord, Channel.name.label("channel_name"), User.name.label("user_name"))
|
||||
.outerjoin(Channel, ModelBillingRecord.channel_id == Channel.id)
|
||||
.join(User, ModelBillingRecord.tenant_id == User.id)
|
||||
.where(
|
||||
and_(
|
||||
ModelBillingRecord.start_time >= start_dt,
|
||||
ModelBillingRecord.start_time <= end_dt,
|
||||
)
|
||||
)
|
||||
.order_by(desc(ModelBillingRecord.start_time))
|
||||
.limit(50)
|
||||
)
|
||||
|
||||
for record, channel_name, user_name in model_records_result.all():
|
||||
# 计算 duration(从 response_time_ms 转换为秒)
|
||||
duration = (record.response_time_ms or 0) / 1000
|
||||
call_records.append({
|
||||
"id": str(record.id),
|
||||
"type": "model",
|
||||
"timestamp": record.start_time.isoformat() if record.start_time else record.created_at.isoformat(),
|
||||
"channelName": channel_name or "无渠道",
|
||||
"tenantName": user_name,
|
||||
"agentName": None,
|
||||
"modelName": record.model_name,
|
||||
"duration": round(duration, 2),
|
||||
"eu": float(record.eu_consumed or 0),
|
||||
"cost": float(record.total_cost or 0),
|
||||
"inputTokens": record.input_tokens,
|
||||
"outputTokens": record.output_tokens,
|
||||
"totalTokens": record.total_tokens,
|
||||
})
|
||||
|
||||
# 3. 按时间排序并限制数量
|
||||
call_records.sort(key=lambda x: x["timestamp"] or "", reverse=True)
|
||||
call_records = call_records[:100]
|
||||
|
||||
# 如果是导出请求
|
||||
if export:
|
||||
@@ -3497,45 +3630,6 @@ async def get_admin_roles(
|
||||
|
||||
# ============= 平台 Agent 资源申请审批 =============
|
||||
|
||||
# 模板显示信息(用于在 Agent Manager 返回数据不包含显示名称时提供默认值)
|
||||
TEMPLATE_DISPLAY_INFO: Dict[str, Dict[str, str]] = {
|
||||
"echo_agent": {
|
||||
"displayName": "Echo 测试服务",
|
||||
"description": "简单的 Echo 服务,用于测试和调试",
|
||||
"category": "testing",
|
||||
},
|
||||
"chat_agent": {
|
||||
"displayName": "聊天对话服务",
|
||||
"description": "通用聊天对话 Agent,支持多轮对话",
|
||||
"category": "assistant",
|
||||
},
|
||||
"code_agent": {
|
||||
"displayName": "代码执行服务",
|
||||
"description": "代码生成和执行 Agent,支持多种编程语言",
|
||||
"category": "development",
|
||||
},
|
||||
"search_agent": {
|
||||
"displayName": "通用搜索服务",
|
||||
"description": "通用搜索 Agent,支持多种搜索引擎",
|
||||
"category": "search",
|
||||
},
|
||||
"jina_search_agent": {
|
||||
"displayName": "Jina 搜索服务",
|
||||
"description": "基于 Jina AI 的语义搜索 Agent",
|
||||
"category": "search",
|
||||
},
|
||||
"mysql_agent": {
|
||||
"displayName": "MySQL 数据库客户端",
|
||||
"description": "MySQL 数据库查询和管理 Agent",
|
||||
"category": "database",
|
||||
},
|
||||
"postgresql_agent": {
|
||||
"displayName": "PostgreSQL 数据库客户端",
|
||||
"description": "PostgreSQL 数据库查询和管理 Agent",
|
||||
"category": "database",
|
||||
},
|
||||
}
|
||||
|
||||
# 模板资源配置建议
|
||||
TEMPLATE_RESOURCE_CONFIG: Dict[str, Dict[str, str]] = {
|
||||
"echo_agent": {
|
||||
@@ -3607,18 +3701,22 @@ async def _get_platform_templates_from_agent_manager(db: Optional[AsyncSession]
|
||||
result = []
|
||||
for template in templates:
|
||||
template_name = template.template
|
||||
display_info = TEMPLATE_DISPLAY_INFO.get(template_name, {})
|
||||
default_resource_config = TEMPLATE_RESOURCE_CONFIG.get(template_name, {})
|
||||
|
||||
# 优先使用数据库中的管理员配置,否则使用默认值
|
||||
# 优先使用 Agent Manager 返回的 displayName 和 description
|
||||
agent_manager_display_name = template.display_name
|
||||
agent_manager_description = template.description
|
||||
agent_manager_category = template.category
|
||||
|
||||
# 优先使用数据库中的管理员配置,否则使用 Agent Manager 返回值
|
||||
db_config = db_configs.get(template_name)
|
||||
if db_config:
|
||||
# 使用数据库配置覆盖默认值
|
||||
result.append({
|
||||
"name": template_name,
|
||||
"displayName": db_config.display_name or display_info.get("displayName", template_name),
|
||||
"description": db_config.description or display_info.get("description", f"{template_name} Agent"),
|
||||
"category": display_info.get("category", "general"),
|
||||
"displayName": db_config.display_name or agent_manager_display_name or template_name,
|
||||
"description": db_config.description or agent_manager_description or f"{template_name} Agent",
|
||||
"category": agent_manager_category or "general",
|
||||
"version": "1.0.0",
|
||||
"port": template.port,
|
||||
"envInfo": template.env_info,
|
||||
@@ -3631,12 +3729,12 @@ async def _get_platform_templates_from_agent_manager(db: Optional[AsyncSession]
|
||||
"status": "available" if (db_config.is_enabled is None or db_config.is_enabled) else "disabled",
|
||||
})
|
||||
else:
|
||||
# 使用默认配置
|
||||
# 使用 Agent Manager 返回值和默认资源配置
|
||||
result.append({
|
||||
"name": template_name,
|
||||
"displayName": display_info.get("displayName", template_name),
|
||||
"description": display_info.get("description", f"{template_name} Agent"),
|
||||
"category": display_info.get("category", "general"),
|
||||
"displayName": agent_manager_display_name or template_name,
|
||||
"description": agent_manager_description or f"{template_name} Agent",
|
||||
"category": agent_manager_category or "general",
|
||||
"version": "1.0.0",
|
||||
"port": template.port,
|
||||
"envInfo": template.env_info,
|
||||
@@ -3653,45 +3751,9 @@ async def _get_platform_templates_from_agent_manager(db: Optional[AsyncSession]
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.warning("admin: 从 Agent Manager 获取平台模板失败,使用默认模板", error=str(e))
|
||||
# 返回基于 TEMPLATE_DISPLAY_INFO 的默认模板
|
||||
result = []
|
||||
for name, info in TEMPLATE_DISPLAY_INFO.items():
|
||||
default_resource_config = TEMPLATE_RESOURCE_CONFIG.get(name, {})
|
||||
|
||||
# 优先使用数据库中的管理员配置
|
||||
db_config = db_configs.get(name)
|
||||
if db_config:
|
||||
result.append({
|
||||
"name": name,
|
||||
"displayName": db_config.display_name or info.get("displayName", name),
|
||||
"description": db_config.description or info.get("description", f"{name} Agent"),
|
||||
"category": info.get("category", "general"),
|
||||
"version": "1.0.0",
|
||||
"cpuRequest": db_config.cpu_request or default_resource_config.get("cpuRequest", "100m"),
|
||||
"cpuLimit": db_config.cpu_limit or default_resource_config.get("cpuLimit", "500m"),
|
||||
"memoryRequest": db_config.memory_request or default_resource_config.get("memoryRequest", "128Mi"),
|
||||
"memoryLimit": db_config.memory_limit or default_resource_config.get("memoryLimit", "512Mi"),
|
||||
"maxPods": db_config.max_pods if db_config.max_pods is not None else 10,
|
||||
"isEnabled": db_config.is_enabled if db_config.is_enabled is not None else True,
|
||||
"status": "available" if (db_config.is_enabled is None or db_config.is_enabled) else "disabled",
|
||||
})
|
||||
else:
|
||||
result.append({
|
||||
"name": name,
|
||||
"displayName": info.get("displayName", name),
|
||||
"description": info.get("description", f"{name} Agent"),
|
||||
"category": info.get("category", "general"),
|
||||
"version": "1.0.0",
|
||||
"cpuRequest": default_resource_config.get("cpuRequest", "100m"),
|
||||
"cpuLimit": default_resource_config.get("cpuLimit", "500m"),
|
||||
"memoryRequest": default_resource_config.get("memoryRequest", "128Mi"),
|
||||
"memoryLimit": default_resource_config.get("memoryLimit", "512Mi"),
|
||||
"maxPods": 10,
|
||||
"isEnabled": True,
|
||||
"status": "available",
|
||||
})
|
||||
return result
|
||||
logger.error("admin: 从 Agent Manager 获取平台模板失败", error=str(e))
|
||||
# Agent Manager 不可用时,返回空列表
|
||||
return []
|
||||
|
||||
|
||||
async def _validate_template_exists(template_name: str) -> bool:
|
||||
@@ -3702,8 +3764,8 @@ async def _validate_template_exists(template_name: str) -> bool:
|
||||
templates = await client.list_platform_templates()
|
||||
return any(t.template == template_name for t in templates)
|
||||
except Exception as e:
|
||||
logger.warning("admin: 验证模板失败,使用本地验证", error=str(e))
|
||||
return template_name in TEMPLATE_DISPLAY_INFO
|
||||
logger.error("admin: 验证模板失败", error=str(e))
|
||||
return False
|
||||
|
||||
|
||||
@router.get("/platform-agents/templates", response_model=SuccessResponse)
|
||||
@@ -3731,51 +3793,128 @@ async def list_platform_agent_templates(
|
||||
async def list_platform_agent_applications(
|
||||
status_filter: Optional[str] = Query(None, alias="status", pattern="^(pending|approved|rejected)$"),
|
||||
channel_id: Optional[str] = Query(None),
|
||||
limit: int = Query(10, ge=1, le=50, description="返回数量,默认10条,最多50条"),
|
||||
principal: dict = Depends(require_auth),
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
获取平台 Agent 申请列表(管理员视图)
|
||||
|
||||
默认优先返回未审批(pending)的申请,如果未审批数量不足则用已审批的填充。
|
||||
如果指定了 status 参数,则只返回该状态的申请。
|
||||
|
||||
权限:view:applications (所有管理员)
|
||||
"""
|
||||
_verify_read_permission(principal)
|
||||
|
||||
# 构建查询
|
||||
query = select(ResourceApplication, Channel).join(
|
||||
Channel, ResourceApplication.channel_id == Channel.id
|
||||
).where(
|
||||
ResourceApplication.resource_type == "platform_agent"
|
||||
)
|
||||
|
||||
if status_filter:
|
||||
query = query.where(ResourceApplication.status == status_filter)
|
||||
|
||||
if channel_id:
|
||||
query = query.where(ResourceApplication.channel_id == channel_id)
|
||||
|
||||
query = query.order_by(desc(ResourceApplication.created_at))
|
||||
|
||||
result = await db.execute(query)
|
||||
|
||||
data = []
|
||||
for app, channel in result.all():
|
||||
display_info = TEMPLATE_DISPLAY_INFO.get(app.template_name, {})
|
||||
data.append({
|
||||
"id": str(app.id),
|
||||
"channelId": str(app.channel_id),
|
||||
"channelName": channel.name,
|
||||
"resourceType": app.resource_type,
|
||||
"templateName": app.template_name,
|
||||
"templateDisplayName": display_info.get("displayName", app.template_name),
|
||||
"requestedPodQuota": app.requested_pod_quota,
|
||||
"approvedPodQuota": app.approved_pod_quota,
|
||||
"reason": app.reason,
|
||||
"status": app.status,
|
||||
"reviewReason": app.review_reason,
|
||||
"reviewedAt": app.reviewed_at.isoformat() if app.reviewed_at else None,
|
||||
"createdAt": app.created_at.isoformat(),
|
||||
})
|
||||
|
||||
# 如果指定了状态筛选,直接按该状态查询
|
||||
if status_filter:
|
||||
query = select(ResourceApplication, Channel).join(
|
||||
Channel, ResourceApplication.channel_id == Channel.id
|
||||
).where(
|
||||
and_(
|
||||
ResourceApplication.resource_type == "platform_agent",
|
||||
ResourceApplication.status == status_filter
|
||||
)
|
||||
)
|
||||
|
||||
if channel_id:
|
||||
query = query.where(ResourceApplication.channel_id == channel_id)
|
||||
|
||||
query = query.order_by(desc(ResourceApplication.created_at)).limit(limit)
|
||||
|
||||
result = await db.execute(query)
|
||||
|
||||
for app, channel in result.all():
|
||||
data.append({
|
||||
"id": str(app.id),
|
||||
"channelId": str(app.channel_id),
|
||||
"channelName": channel.name,
|
||||
"resourceType": app.resource_type,
|
||||
"templateName": app.template_name,
|
||||
"templateDisplayName": app.template_name,
|
||||
"requestedPodQuota": app.requested_pod_quota,
|
||||
"approvedPodQuota": app.approved_pod_quota,
|
||||
"reason": app.reason,
|
||||
"status": app.status,
|
||||
"reviewReason": app.review_reason,
|
||||
"reviewedAt": app.reviewed_at.isoformat() if app.reviewed_at else None,
|
||||
"createdAt": app.created_at.isoformat(),
|
||||
})
|
||||
else:
|
||||
# 未指定状态筛选时,优先返回 pending 状态的申请
|
||||
# 1. 先查询 pending 状态的申请(最多 limit 条)
|
||||
pending_query = select(ResourceApplication, Channel).join(
|
||||
Channel, ResourceApplication.channel_id == Channel.id
|
||||
).where(
|
||||
and_(
|
||||
ResourceApplication.resource_type == "platform_agent",
|
||||
ResourceApplication.status == "pending"
|
||||
)
|
||||
)
|
||||
|
||||
if channel_id:
|
||||
pending_query = pending_query.where(ResourceApplication.channel_id == channel_id)
|
||||
|
||||
pending_query = pending_query.order_by(desc(ResourceApplication.created_at)).limit(limit)
|
||||
|
||||
pending_result = await db.execute(pending_query)
|
||||
pending_apps = pending_result.all()
|
||||
|
||||
for app, channel in pending_apps:
|
||||
data.append({
|
||||
"id": str(app.id),
|
||||
"channelId": str(app.channel_id),
|
||||
"channelName": channel.name,
|
||||
"resourceType": app.resource_type,
|
||||
"templateName": app.template_name,
|
||||
"templateDisplayName": app.template_name,
|
||||
"requestedPodQuota": app.requested_pod_quota,
|
||||
"approvedPodQuota": app.approved_pod_quota,
|
||||
"reason": app.reason,
|
||||
"status": app.status,
|
||||
"reviewReason": app.review_reason,
|
||||
"reviewedAt": app.reviewed_at.isoformat() if app.reviewed_at else None,
|
||||
"createdAt": app.created_at.isoformat(),
|
||||
})
|
||||
|
||||
# 2. 如果 pending 数量不足 limit,用已审批的(approved/rejected)填充
|
||||
remaining = limit - len(data)
|
||||
if remaining > 0:
|
||||
reviewed_query = select(ResourceApplication, Channel).join(
|
||||
Channel, ResourceApplication.channel_id == Channel.id
|
||||
).where(
|
||||
and_(
|
||||
ResourceApplication.resource_type == "platform_agent",
|
||||
ResourceApplication.status.in_(["approved", "rejected"])
|
||||
)
|
||||
)
|
||||
|
||||
if channel_id:
|
||||
reviewed_query = reviewed_query.where(ResourceApplication.channel_id == channel_id)
|
||||
|
||||
reviewed_query = reviewed_query.order_by(desc(ResourceApplication.created_at)).limit(remaining)
|
||||
|
||||
reviewed_result = await db.execute(reviewed_query)
|
||||
|
||||
for app, channel in reviewed_result.all():
|
||||
data.append({
|
||||
"id": str(app.id),
|
||||
"channelId": str(app.channel_id),
|
||||
"channelName": channel.name,
|
||||
"resourceType": app.resource_type,
|
||||
"templateName": app.template_name,
|
||||
"templateDisplayName": app.template_name,
|
||||
"requestedPodQuota": app.requested_pod_quota,
|
||||
"approvedPodQuota": app.approved_pod_quota,
|
||||
"reason": app.reason,
|
||||
"status": app.status,
|
||||
"reviewReason": app.review_reason,
|
||||
"reviewedAt": app.reviewed_at.isoformat() if app.reviewed_at else None,
|
||||
"createdAt": app.created_at.isoformat(),
|
||||
})
|
||||
|
||||
return SuccessResponse(data={"applications": data})
|
||||
|
||||
@@ -3918,8 +4057,6 @@ async def list_platform_agent_allocations(
|
||||
|
||||
data = []
|
||||
for quota, channel in result.all():
|
||||
display_info = TEMPLATE_DISPLAY_INFO.get(quota.template_name, {})
|
||||
|
||||
# 从模板配置中获取管理员设置的CPU和内存限制
|
||||
template_config = template_configs.get(quota.template_name)
|
||||
cpu_limit = template_config.cpu_limit if template_config and template_config.cpu_limit else "100m"
|
||||
@@ -3930,7 +4067,7 @@ async def list_platform_agent_allocations(
|
||||
"channelId": str(quota.target_id),
|
||||
"channelName": channel.name if channel else "未知",
|
||||
"templateName": quota.template_name,
|
||||
"templateDisplayName": display_info.get("displayName", quota.template_name),
|
||||
"templateDisplayName": quota.template_name,
|
||||
"podQuota": quota.pod_quota,
|
||||
"podUsed": quota.pod_used,
|
||||
"podRemaining": quota.pod_quota - quota.pod_used,
|
||||
@@ -4024,14 +4161,12 @@ async def allocate_platform_agent_to_channel(
|
||||
|
||||
await db.commit()
|
||||
|
||||
display_info = TEMPLATE_DISPLAY_INFO.get(template_name, {})
|
||||
|
||||
return SuccessResponse(
|
||||
data={
|
||||
"channelId": str(channel_uuid),
|
||||
"channelName": channel.name,
|
||||
"templateName": template_name,
|
||||
"templateDisplayName": display_info.get("displayName", template_name),
|
||||
"templateDisplayName": template_name,
|
||||
"podQuota": pod_quota,
|
||||
},
|
||||
message=message
|
||||
|
||||
Reference in New Issue
Block a user