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到全局路由列表
175 lines
7.4 KiB
Python
175 lines
7.4 KiB
Python
"""Dashboard 聚合视图域 Router(DSB-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)。非法格式抛 ValidationError(400)。
|
||
"""
|
||
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)}
|