add backend source code

This commit is contained in:
2026-02-28 15:06:52 +08:00
parent 1bc330e20c
commit 2c37aa9064
67 changed files with 11654 additions and 0 deletions

241
backend/app/api/v1/stats.py Normal file
View 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
}