Files
hospital_performance/backend/app/api/v1/templates.py
2026-02-28 15:06:52 +08:00

272 lines
10 KiB
Python

"""
API路由 - 指标模板管理
"""
from typing import Annotated, Optional, List
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.core.security import get_current_active_user, get_current_manager_user
from app.schemas.schemas import (
IndicatorTemplateCreate, IndicatorTemplateUpdate,
IndicatorTemplateResponse, IndicatorTemplateListResponse,
TemplateIndicatorCreate, TemplateIndicatorUpdate, TemplateIndicatorResponse,
ResponseBase
)
from app.services.template_service import TemplateService
from app.models.models import User
router = APIRouter(prefix="/templates", tags=["指标模板"])
@router.get("", summary="获取模板列表")
async def get_templates(
template_type: Optional[str] = Query(None, description="模板类型"),
is_active: Optional[bool] = Query(None, description="是否启用"),
page: int = Query(1, ge=1, description="页码"),
page_size: int = Query(20, ge=1, le=100, description="每页数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取模板列表"""
templates, total = await TemplateService.get_list(
db, template_type, is_active, page, page_size
)
return {
"code": 200,
"message": "success",
"data": templates,
"total": total,
"page": page,
"page_size": page_size
}
@router.get("/types", summary="获取模板类型列表")
async def get_template_types(
current_user: User = Depends(get_current_active_user)
):
"""获取模板类型列表"""
types = [
{"value": "general", "label": "通用模板"},
{"value": "surgical", "label": "手术临床科室"},
{"value": "nonsurgical_ward", "label": "非手术有病房科室"},
{"value": "nonsurgical_noward", "label": "非手术无病房科室"},
{"value": "medical_tech", "label": "医技科室"},
{"value": "nursing", "label": "护理单元"},
{"value": "admin", "label": "行政科室"},
{"value": "logistics", "label": "后勤科室"}
]
return {"code": 200, "message": "success", "data": types}
@router.get("/dimensions", summary="获取BSC维度列表")
async def get_dimensions(
current_user: User = Depends(get_current_active_user)
):
"""获取BSC维度列表"""
dimensions = [
{"value": "financial", "label": "财务管理", "weight_range": "30%-40%"},
{"value": "customer", "label": "顾客服务", "weight_range": "25%-35%"},
{"value": "internal_process", "label": "内部流程", "weight_range": "20%-30%"},
{"value": "learning_growth", "label": "学习与成长", "weight_range": "5%-15%"}
]
return {"code": 200, "message": "success", "data": dimensions}
@router.get("/{template_id}", summary="获取模板详情")
async def get_template(
template_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取模板详情"""
template = await TemplateService.get_by_id(db, template_id)
if not template:
raise HTTPException(status_code=404, detail="模板不存在")
# 构建响应数据
indicators = []
for ti in template.indicators:
ind_dict = {
"id": ti.id,
"template_id": ti.template_id,
"indicator_id": ti.indicator_id,
"indicator_name": ti.indicator.name if ti.indicator else None,
"indicator_code": ti.indicator.code if ti.indicator else None,
"indicator_type": ti.indicator.indicator_type.value if ti.indicator else None,
"bs_dimension": ti.indicator.bs_dimension.value if ti.indicator else None,
"category": ti.category,
"target_value": float(ti.target_value) if ti.target_value else None,
"target_unit": ti.target_unit,
"weight": float(ti.weight),
"scoring_method": ti.scoring_method,
"scoring_params": ti.scoring_params,
"sort_order": ti.sort_order,
"remark": ti.remark,
"created_at": ti.created_at,
"updated_at": ti.updated_at
}
indicators.append(ind_dict)
response_data = {
"id": template.id,
"template_name": template.template_name,
"template_code": template.template_code,
"template_type": template.template_type.value,
"description": template.description,
"dimension_weights": template.dimension_weights,
"assessment_cycle": template.assessment_cycle,
"is_active": template.is_active,
"created_at": template.created_at,
"updated_at": template.updated_at,
"indicators": indicators
}
return {"code": 200, "message": "success", "data": response_data}
@router.post("", summary="创建模板")
async def create_template(
template_data: IndicatorTemplateCreate,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""创建模板(需要管理员或经理权限)"""
# 检查编码是否已存在
existing = await TemplateService.get_by_code(db, template_data.template_code)
if existing:
raise HTTPException(status_code=400, detail="模板编码已存在")
template = await TemplateService.create(db, template_data)
return {"code": 200, "message": "创建成功", "data": {"id": template.id}}
@router.put("/{template_id}", summary="更新模板")
async def update_template(
template_id: int,
template_data: IndicatorTemplateUpdate,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""更新模板(需要管理员或经理权限)"""
template = await TemplateService.update(db, template_id, template_data)
if not template:
raise HTTPException(status_code=404, detail="模板不存在")
return {"code": 200, "message": "更新成功"}
@router.delete("/{template_id}", summary="删除模板")
async def delete_template(
template_id: int,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""删除模板(需要管理员或经理权限)"""
success = await TemplateService.delete(db, template_id)
if not success:
raise HTTPException(status_code=404, detail="模板不存在")
return {"code": 200, "message": "删除成功"}
# ==================== 模板指标管理 ====================
@router.get("/{template_id}/indicators", summary="获取模板指标列表")
async def get_template_indicators(
template_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_active_user)
):
"""获取模板指标列表"""
indicators = await TemplateService.get_template_indicators(db, template_id)
result = []
for ti in indicators:
ind_dict = {
"id": ti.id,
"template_id": ti.template_id,
"indicator_id": ti.indicator_id,
"indicator_name": ti.indicator.name if ti.indicator else None,
"indicator_code": ti.indicator.code if ti.indicator else None,
"indicator_type": ti.indicator.indicator_type.value if ti.indicator else None,
"bs_dimension": ti.indicator.bs_dimension.value if ti.indicator else None,
"category": ti.category,
"target_value": float(ti.target_value) if ti.target_value else None,
"target_unit": ti.target_unit,
"weight": float(ti.weight),
"scoring_method": ti.scoring_method,
"scoring_params": ti.scoring_params,
"sort_order": ti.sort_order,
"remark": ti.remark,
"created_at": ti.created_at,
"updated_at": ti.updated_at
}
result.append(ind_dict)
return {"code": 200, "message": "success", "data": result}
@router.post("/{template_id}/indicators", summary="添加模板指标")
async def add_template_indicator(
template_id: int,
indicator_data: TemplateIndicatorCreate,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""添加模板指标"""
ti = await TemplateService.add_indicator(db, template_id, indicator_data)
if not ti:
raise HTTPException(status_code=400, detail="添加失败,模板不存在或指标已存在")
return {"code": 200, "message": "添加成功", "data": {"id": ti.id}}
@router.put("/{template_id}/indicators/{indicator_id}", summary="更新模板指标")
async def update_template_indicator(
template_id: int,
indicator_id: int,
indicator_data: TemplateIndicatorUpdate,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""更新模板指标"""
ti = await TemplateService.update_indicator(db, template_id, indicator_id, indicator_data)
if not ti:
raise HTTPException(status_code=404, detail="模板指标不存在")
return {"code": 200, "message": "更新成功"}
@router.delete("/{template_id}/indicators/{indicator_id}", summary="移除模板指标")
async def remove_template_indicator(
template_id: int,
indicator_id: int,
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""移除模板指标"""
success = await TemplateService.remove_indicator(db, template_id, indicator_id)
if not success:
raise HTTPException(status_code=404, detail="模板指标不存在")
return {"code": 200, "message": "移除成功"}
@router.post("/{template_id}/indicators/batch", summary="批量添加模板指标")
async def batch_add_template_indicators(
template_id: int,
indicators_data: List[TemplateIndicatorCreate],
db: AsyncSession = Depends(get_db),
current_user: Annotated[User, Depends(get_current_manager_user)] = None
):
"""批量添加模板指标"""
added_count = 0
for idx, ind_data in enumerate(indicators_data):
ind_data.sort_order = ind_data.sort_order or idx
ti = await TemplateService.add_indicator(db, template_id, ind_data)
if ti:
added_count += 1
return {
"code": 200,
"message": f"成功添加 {added_count} 个指标",
"data": {"added_count": added_count}
}