add backend source code
This commit is contained in:
241
backend/app/api/v1/stats.py
Normal file
241
backend/app/api/v1/stats.py
Normal file
@@ -0,0 +1,241 @@
|
||||
"""
|
||||
统计报表 API
|
||||
"""
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.security import get_current_active_user
|
||||
from app.models.models import User
|
||||
from app.services.stats_service import StatsService
|
||||
|
||||
router = APIRouter(prefix="/stats", tags=["统计报表"])
|
||||
|
||||
|
||||
@router.get("/bsc-dimension", summary="BSC 维度分析")
|
||||
async def get_bsc_dimension_stats(
|
||||
department_id: Optional[int] = Query(None, description="科室 ID"),
|
||||
period_year: int = Query(..., description="年度"),
|
||||
period_month: int = Query(..., description="月份"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取 BSC 四个维度的统计分析"""
|
||||
result = await StatsService.get_bsc_dimension_stats(
|
||||
db, department_id, period_year, period_month
|
||||
)
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": result
|
||||
}
|
||||
|
||||
|
||||
@router.get("/department", summary="科室绩效统计")
|
||||
async def get_department_stats(
|
||||
period_year: int = Query(..., description="年度"),
|
||||
period_month: int = Query(..., description="月份"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取各科室绩效统计"""
|
||||
result = await StatsService.get_department_stats(db, period_year, period_month)
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": result
|
||||
}
|
||||
|
||||
|
||||
@router.get("/trend", summary="趋势分析")
|
||||
async def get_trend_stats(
|
||||
department_id: Optional[int] = Query(None, description="科室 ID"),
|
||||
period_year: Optional[int] = Query(None, description="年度"),
|
||||
months: Optional[int] = Query(6, ge=1, le=24, description="最近几个月"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取绩效趋势分析(月度)"""
|
||||
# 如果没有指定年份,使用当前年份
|
||||
if not period_year:
|
||||
period_year = datetime.now().year
|
||||
|
||||
result = await StatsService.get_trend_stats(db, department_id, period_year, months)
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": result
|
||||
}
|
||||
|
||||
|
||||
@router.get("/alerts", summary="预警数据")
|
||||
async def get_alerts(
|
||||
limit: Optional[int] = Query(10, ge=1, le=100, description="返回数量"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取预警数据(考核到期、工资未发等)"""
|
||||
# TODO: 从数据库实际查询预警数据
|
||||
# 目前返回模拟数据用于演示
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"lowScoreStaff": [], # 低分员工
|
||||
"incompleteDepartments": [], # 未完成考核科室
|
||||
"anomalyData": [] # 异常数据
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@router.get("/period", summary="周期统计")
|
||||
async def get_period_stats(
|
||||
period_year: Optional[int] = Query(None, description="年度"),
|
||||
period_month: Optional[int] = Query(None, description="月份"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取周期统计数据"""
|
||||
# 如果没有指定年月,使用当前年月
|
||||
if not period_year:
|
||||
period_year = datetime.now().year
|
||||
if not period_month:
|
||||
period_month = datetime.now().month
|
||||
|
||||
# 获取该周期的考核统计
|
||||
result = await StatsService.get_department_stats(db, period_year, period_month)
|
||||
|
||||
# 计算汇总数据
|
||||
total_departments = len(result)
|
||||
total_staff = sum(dept.get('staff_count', 0) for dept in result)
|
||||
avg_score = sum(dept.get('avg_score', 0) for dept in result) / total_departments if total_departments > 0 else 0
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"period": f"{period_year}年{period_month}月",
|
||||
"total_departments": total_departments,
|
||||
"total_staff": total_staff,
|
||||
"avg_score": round(avg_score, 2),
|
||||
"departments": result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@router.get("/kpi-gauges", summary="关键指标仪表盘")
|
||||
async def get_kpi_gauges(
|
||||
period_year: Optional[int] = Query(None, description="年度"),
|
||||
period_month: Optional[int] = Query(None, description="月份"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取关键指标仪表盘数据"""
|
||||
# 如果没有指定年月,使用当前年月
|
||||
if not period_year:
|
||||
period_year = datetime.now().year
|
||||
if not period_month:
|
||||
period_month = datetime.now().month
|
||||
|
||||
# TODO: 从数据库实际计算这些指标
|
||||
# 目前返回模拟数据用于演示
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"bed_usage_rate": 85.5, # 床位使用率 (%)
|
||||
"drug_ratio": 32.8, # 药占比 (%)
|
||||
"material_ratio": 18.5, # 材料占比 (%)
|
||||
"satisfaction_rate": 92.3 # 患者满意度 (%)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@router.get("/finance-trend", summary="收支趋势")
|
||||
async def get_finance_trend(
|
||||
months: Optional[int] = Query(6, ge=1, le=24, description="最近几个月"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取收支趋势数据"""
|
||||
# TODO: 从数据库实际查询收支数据
|
||||
# 目前返回模拟数据用于演示
|
||||
from datetime import datetime
|
||||
current_month = datetime.now().month
|
||||
data = []
|
||||
for i in range(months, 0, -1):
|
||||
month = current_month - i + 1
|
||||
if month < 1:
|
||||
month += 12
|
||||
data.append({
|
||||
"period": f"{month}月",
|
||||
"income": 1000000 + (months - i) * 50000,
|
||||
"expense": 800000 + (months - i) * 30000,
|
||||
"profit": 200000 + (months - i) * 20000
|
||||
})
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": data
|
||||
}
|
||||
|
||||
|
||||
@router.get("/department-ranking", summary="科室绩效排名")
|
||||
async def get_department_ranking(
|
||||
period_year: Optional[int] = Query(None, description="年度"),
|
||||
period_month: Optional[int] = Query(None, description="月份"),
|
||||
limit: Optional[int] = Query(10, ge=1, le=100, description="返回数量"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取科室绩效排名"""
|
||||
# 如果没有指定年月,使用当前年月
|
||||
if not period_year:
|
||||
period_year = datetime.now().year
|
||||
if not period_month:
|
||||
period_month = datetime.now().month
|
||||
|
||||
result = await StatsService.get_department_stats(db, period_year, period_month)
|
||||
# 返回前 limit 个
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": result[:limit] if limit else result
|
||||
}
|
||||
|
||||
|
||||
@router.get("/ranking", summary="绩效排名")
|
||||
async def get_ranking_stats(
|
||||
period_year: int = Query(..., description="年度"),
|
||||
period_month: int = Query(..., description="月份"),
|
||||
limit: int = Query(10, ge=1, le=100, description="返回数量"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取绩效排名前 N 名"""
|
||||
result = await StatsService.get_ranking_stats(db, period_year, period_month, limit)
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": result
|
||||
}
|
||||
|
||||
|
||||
@router.get("/completion", summary="指标完成度")
|
||||
async def get_completion_stats(
|
||||
indicator_id: Optional[int] = Query(None, description="指标 ID"),
|
||||
period_year: int = Query(..., description="年度"),
|
||||
period_month: int = Query(..., description="月份"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
"""获取指标完成度统计"""
|
||||
result = await StatsService.get_completion_stats(db, indicator_id, period_year, period_month)
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": result
|
||||
}
|
||||
Reference in New Issue
Block a user