Files
012-kaopeilian/backend/app/api/v1/endpoints/growth_path.py
yuliang_guo 0b7c07eb7f
All checks were successful
continuous-integration/drone/push Build is passing
feat: 添加请求验证错误详细日志
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-31 10:03:54 +08:00

235 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
成长路径 API 端点
"""
import logging
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.deps import get_db, get_current_user
from app.models.user import User
from app.services.growth_path_service import growth_path_service
from app.schemas.growth_path import (
GrowthPathCreate,
GrowthPathUpdate,
GrowthPathResponse,
GrowthPathListResponse,
TraineeGrowthPathResponse,
UserGrowthPathProgressResponse,
StartGrowthPathRequest,
CompleteNodeRequest,
)
logger = logging.getLogger(__name__)
router = APIRouter()
# =====================================================
# 学员端 API
# =====================================================
@router.get("/trainee/growth-path", response_model=Optional[TraineeGrowthPathResponse])
async def get_trainee_growth_path(
position_id: Optional[int] = Query(None, description="岗位ID不传则自动匹配"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
获取学员的成长路径(含进度)
返回数据包含:
- 成长路径基本信息
- 各阶段及节点信息
- 每个节点的学习状态locked/unlocked/in_progress/completed
- 每个节点的课程学习进度
"""
try:
result = await growth_path_service.get_trainee_growth_path(
db=db,
user_id=current_user.id,
position_id=position_id
)
return result
except Exception as e:
logger.error(f"获取成长路径失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/trainee/growth-path/start")
async def start_growth_path(
request: StartGrowthPathRequest,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
开始学习成长路径
"""
try:
progress = await growth_path_service.start_growth_path(
db=db,
user_id=current_user.id,
growth_path_id=request.growth_path_id
)
return {
"success": True,
"message": "已开始学习成长路径",
"progress_id": progress.id,
}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"开始成长路径失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/trainee/growth-path/node/complete")
async def complete_growth_path_node(
request: CompleteNodeRequest,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
完成成长路径节点
"""
try:
result = await growth_path_service.complete_node(
db=db,
user_id=current_user.id,
node_id=request.node_id
)
return result
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"完成节点失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
# =====================================================
# 管理端 API
# =====================================================
@router.get("/manager/growth-paths")
async def list_growth_paths(
position_id: Optional[int] = Query(None, description="岗位ID筛选"),
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_user),
):
"""
获取成长路径列表(管理端)
"""
try:
result = await growth_path_service.list_growth_paths(
db=db,
position_id=position_id,
is_active=is_active,
page=page,
page_size=page_size
)
return result
except Exception as e:
logger.error(f"获取成长路径列表失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/manager/growth-paths")
async def create_growth_path(
data: GrowthPathCreate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
创建成长路径(管理端)
"""
try:
growth_path = await growth_path_service.create_growth_path(
db=db,
data=data,
created_by=current_user.id
)
return {
"success": True,
"message": "创建成功",
"id": growth_path.id,
}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"创建成长路径失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/manager/growth-paths/{path_id}")
async def get_growth_path(
path_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
获取成长路径详情(管理端)
"""
try:
result = await growth_path_service.get_growth_path(db=db, path_id=path_id)
if not result:
raise HTTPException(status_code=404, detail="成长路径不存在")
return result
except HTTPException:
raise
except Exception as e:
logger.error(f"获取成长路径详情失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/manager/growth-paths/{path_id}")
async def update_growth_path(
path_id: int,
data: GrowthPathUpdate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
更新成长路径(管理端)
"""
try:
await growth_path_service.update_growth_path(
db=db,
path_id=path_id,
data=data
)
return {
"success": True,
"message": "更新成功",
}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"更新成长路径失败: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/manager/growth-paths/{path_id}")
async def delete_growth_path(
path_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""
删除成长路径(管理端)
"""
try:
await growth_path_service.delete_growth_path(db=db, path_id=path_id)
return {
"success": True,
"message": "删除成功",
}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"删除成长路径失败: {e}")
raise HTTPException(status_code=500, detail=str(e))