""" 知识仪表盘 API — 瓶颈分析、知识条目查询、趋势统计 """ from __future__ import annotations import logging from datetime import datetime, timedelta from typing import Optional from fastapi import APIRouter, Depends, Query from sqlalchemy import func from sqlalchemy.orm import Session from app.core.database import get_db from app.api.auth import get_current_user from app.models.user import User from app.models.knowledge_entry import KnowledgeEntry from app.services.bottleneck_detector import bottleneck_detector from app.services.optimization_engine import optimization_engine logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/v1/knowledge-dashboard", tags=["knowledge-dashboard"]) @router.get("/bottlenecks") def get_bottlenecks( hours: int = Query(168, ge=1, le=2160, description="分析时长(小时)"), current_user: User = Depends(get_current_user), ): """瓶颈分析 — 检测工作流性能瓶颈并生成优化建议。""" analysis = bottleneck_detector.run_full_analysis(hours=hours) optimizations = optimization_engine.generate_optimizations(analysis.get("bottlenecks", [])) # Build recommendations dict keyed by node_type for frontend lookup recommendations_map = {} for opt in optimizations: recommendations_map[opt["node_type"]] = { "node_type": opt["node_type"], "severity": opt["severity"], "current_state": opt.get("current_metrics", {}), "changes": opt.get("changes", []), } return { **analysis, "recommendations": list(optimizations), "optimizations": recommendations_map, } @router.get("/entries") def get_knowledge_entries( days: int = Query(7, ge=1, le=365, description="统计天数"), limit: int = Query(50, ge=1, le=200, description="返回条数"), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """获取知识条目列表,按创建时间倒序。""" since = datetime.now() - timedelta(days=days) entries = ( db.query(KnowledgeEntry) .filter( KnowledgeEntry.created_at >= since, KnowledgeEntry.is_active == True, ) .order_by(KnowledgeEntry.created_at.desc()) .limit(limit) .all() ) return [e.to_dict() for e in entries] @router.get("/trend") def get_knowledge_trend( days: int = Query(7, ge=1, le=365, description="统计天数"), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """知识条目增长趋势 — 按天统计新增数量。""" since = datetime.now() - timedelta(days=days) # GROUP BY date(created_at) rows = ( db.query( func.date(KnowledgeEntry.created_at).label("date"), func.count(KnowledgeEntry.id).label("count"), ) .filter( KnowledgeEntry.created_at >= since, KnowledgeEntry.is_active == True, ) .group_by(func.date(KnowledgeEntry.created_at)) .order_by(func.date(KnowledgeEntry.created_at).asc()) .all() ) # Fill in missing dates with 0 count trend = [] current_date = since.date() end_date = datetime.now().date() date_counts = {row.date: row.count for row in rows} while current_date <= end_date: trend.append({ "date": current_date.isoformat(), "count": date_counts.get(current_date, 0), }) current_date += timedelta(days=1) return trend