ForcePilot/backend/server/routers/channels/dashboard_router.py
Kris ddafd95ff0 refactor(routers): 整理并新增多组渠道相关路由功能
1.  移除多个导出接口的显式response_model声明
2.  调整access_rule和test_case的创建接口位置,修复静态路径冲突
3.  优化适配器配置校验的异常处理逻辑
4.  重构集成路由的查询逻辑,统一使用get_integration_or_raise
5.  新增channels路由组下的capability、reports、dashboard、webhook、wizard、doctor、directory、session共8个子路由模块
6.  注册channels_router到全局路由列表
2026-07-02 03:29:06 +08:00

175 lines
7.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Dashboard 聚合视图域 RouterDSB-01~DSB-04
统一采用模板 A控制面端口路由鉴权依赖 get_admin_user调用
use_cases.dashboard_view.<method>raiseOnControlFailure 转译失败,
serialize_control_data 序列化响应。
路径设计4 个端点均为静态路径(/dashboard/overview / /dashboard/accounts
/ /dashboard/messages / /dashboard/sessions。子 router 自身不设置
prefix根前缀 ``/channels`` 由 ``channels_router`` 聚合 router 统一追加。
端点清单对应《16-聚合视图域-dashboard-router-设计方案》):
- GET /dashboard/overview DSB-01 getDashboardOverview
- GET /dashboard/accounts DSB-02 getAccountStats
- GET /dashboard/messages DSB-03 getMessageStats
- GET /dashboard/sessions DSB-04 getDashboardSessionStats
- GET /dashboard/delivery DSB-DELIVERY getDashboardDelivery
- GET /dashboard/realtime DSB-REALTIME getRealtimeMetrics
"""
from __future__ import annotations
from typing import Any
from fastapi import APIRouter, Depends, Query, Request
from yuxi.channels.contract.dtos.channel import ChannelType
from yuxi.channels.contract.dtos.dashboard import (
DashboardDeliveryQuery,
RealtimeQuery,
)
from yuxi.storage.postgres.models_business import User
from server.routers.channels import (
build_operator,
get_channel_use_cases,
parse_datetime,
raiseOnControlFailure,
serialize_control_data,
)
from server.utils.auth_middleware import get_admin_user
dashboard_router = APIRouter(tags=["channels-dashboard"])
@dashboard_router.get("/dashboard/overview", response_model=dict)
async def get_dashboard_overview(
request: Request,
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""查询全局总览DSB-01。对应控制面操作 dashboard/overview。
聚合账户 / 消息 / 会话 / 投递四类子域 KPI 计数。
"""
operator = build_operator(current_user, request)
result = await use_cases.dashboard_view.getDashboardOverview(operator=operator)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@dashboard_router.get("/dashboard/accounts", response_model=dict)
async def get_dashboard_accounts(
request: Request,
channel_type: ChannelType | None = Query(default=None, description="按渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""查询账户总览DSB-02。对应控制面操作 dashboard/accounts。
返回账户按渠道 / 状态分组的计数快照。
"""
operator = build_operator(current_user, request)
result = await use_cases.dashboard_view.getAccountStats(
channel_type=channel_type,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@dashboard_router.get("/dashboard/messages", response_model=dict)
async def get_dashboard_messages(
request: Request,
channel_type: ChannelType | None = Query(default=None, description="按渠道类型过滤"),
start_time: str | None = Query(default=None, description="起始时间ISO 8601"),
end_time: str | None = Query(default=None, description="截止时间ISO 8601"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""查询消息总览DSB-03。对应控制面操作 dashboard/messages。
返回指定时间范围内的消息按渠道 / 角色 / 投递状态分组的计数快照。
时间参数由 parse_datetime 在 Router 层翻译为 UTC datetime再转回 ISO 8601 字符串传给端口(端口签名为 str。非法格式抛 ValidationError400
"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.dashboard_view.getMessageStats(
channel_type=channel_type,
start_time=start_time_dt.isoformat() if start_time_dt else None,
end_time=end_time_dt.isoformat() if end_time_dt else None,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@dashboard_router.get("/dashboard/sessions", response_model=dict)
async def get_dashboard_sessions(
request: Request,
channel_type: ChannelType | None = Query(default=None, description="按渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""查询会话总览DSB-04。对应控制面操作 dashboard/sessions。
返回未软删除会话按渠道 / 是否临时会话分组的计数快照。
"""
operator = build_operator(current_user, request)
result = await use_cases.dashboard_view.getDashboardSessionStats(
channel_type=channel_type,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@dashboard_router.get("/dashboard/delivery", response_model=dict)
async def get_dashboard_delivery(
request: Request,
channel_type: ChannelType | None = Query(default=None, description="按渠道类型过滤"),
start_time: str | None = Query(default=None, description="起始时间ISO 8601"),
end_time: str | None = Query(default=None, description="截止时间ISO 8601"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""查询投递总览DSB-DELIVERY。对应控制面操作 dashboard/delivery。
聚合投递 KPI 指标(总数、成功率、延迟分位数、死信数、按渠道切片)。
时间参数由 ``parse_datetime`` 在 Router 层翻译为 UTC datetime非法格式
抛 ``ValidationError``400由全局异常处理器映射。
"""
operator = build_operator(current_user, request)
query = DashboardDeliveryQuery(
channel_type=channel_type,
start_time=parse_datetime("start_time", start_time),
end_time=parse_datetime("end_time", end_time),
)
result = await use_cases.dashboard_view.getDashboardDelivery(query, operator=operator)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@dashboard_router.get("/dashboard/realtime", response_model=dict)
async def get_dashboard_realtime(
request: Request,
channel_type: ChannelType | None = Query(default=None, description="按渠道类型过滤"),
window_seconds: int = Query(default=60, ge=10, le=300, description="滑动窗口秒数10-300默认 60"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""查询实时监控指标DSB-REALTIME。对应控制面操作 dashboard/realtime。
纯内存态聚合(不开启 DB 事务),高频查询场景使用。
"""
operator = build_operator(current_user, request)
query = RealtimeQuery(
channel_type=channel_type,
window_seconds=window_seconds,
)
result = await use_cases.dashboard_view.getRealtimeMetrics(query, operator=operator)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}