feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

View File

@@ -0,0 +1,187 @@
"""
能力评估API接口
用于智能工牌数据分析、能力评估报告生成等
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List
from app.core.deps import get_current_user, get_db
from app.models.user import User
from app.schemas.base import ResponseModel
from app.schemas.ability import AbilityAssessmentResponse, AbilityAssessmentHistory
from app.services.yanji_service import YanjiService
from app.services.ability_assessment_service import get_ability_assessment_service
import logging
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/analyze-yanji", response_model=ResponseModel)
async def analyze_yanji_badge_data(
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""
分析智能工牌数据生成能力评估和课程推荐
使用 Python 原生 AI 服务实现。
功能说明:
1. 从言迹智能工牌获取员工的最近10条录音记录
2. 分析对话数据进行能力评估6个维度
3. 基于能力短板生成课程推荐3-5门
4. 保存评估记录到数据库
要求:
- 用户必须已绑定手机号(用于匹配言迹数据)
返回:
- assessment_id: 评估记录ID
- total_score: 综合评分0-100
- dimensions: 能力维度列表6个维度
- recommended_courses: 推荐课程列表3-5门
- conversation_count: 分析的对话数量
"""
# 检查用户是否绑定手机号
if not current_user.phone:
logger.warning(f"用户未绑定手机号: user_id={current_user.id}")
raise HTTPException(
status_code=400,
detail="用户未绑定手机号,无法匹配言迹数据"
)
# 获取服务实例
yanji_service = YanjiService()
assessment_service = get_ability_assessment_service()
try:
logger.info(
f"开始分析智能工牌数据: user_id={current_user.id}, "
f"phone={current_user.phone}"
)
# 调用能力评估服务(使用 Python 原生实现)
result = await assessment_service.analyze_yanji_conversations(
user_id=current_user.id,
phone=current_user.phone,
db=db,
yanji_service=yanji_service,
engine="v2" # 固定使用 V2
)
logger.info(
f"智能工牌数据分析完成: user_id={current_user.id}, "
f"assessment_id={result['assessment_id']}, "
f"total_score={result['total_score']}"
)
return ResponseModel(
code=200,
message="智能工牌数据分析完成",
data=result
)
except ValueError as e:
# 业务逻辑错误(如未找到录音记录)
logger.warning(f"智能工牌数据分析失败: {e}")
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
# 系统错误
logger.error(f"分析智能工牌数据失败: {e}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"分析失败: {str(e)}"
)
@router.get("/history", response_model=ResponseModel)
async def get_assessment_history(
limit: int = Query(default=10, ge=1, le=50, description="返回记录数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""
获取用户的能力评估历史记录
参数:
- limit: 返回记录数量默认10最大50
返回:
- 评估历史记录列表
"""
assessment_service = get_ability_assessment_service()
try:
history = await assessment_service.get_user_assessment_history(
user_id=current_user.id,
db=db,
limit=limit
)
return ResponseModel(
code=200,
message=f"获取评估历史成功,共{len(history)}",
data={"history": history, "total": len(history)}
)
except Exception as e:
logger.error(f"获取评估历史失败: {e}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"获取评估历史失败: {str(e)}"
)
@router.get("/{assessment_id}", response_model=ResponseModel)
async def get_assessment_detail(
assessment_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""
获取单个评估记录的详细信息
参数:
- assessment_id: 评估记录ID
返回:
- 评估详细信息
"""
assessment_service = get_ability_assessment_service()
try:
detail = await assessment_service.get_assessment_detail(
assessment_id=assessment_id,
db=db
)
# 权限检查:只能查看自己的评估记录
if detail['user_id'] != current_user.id:
raise HTTPException(
status_code=403,
detail="无权访问该评估记录"
)
return ResponseModel(
code=200,
message="获取评估详情成功",
data=detail
)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except HTTPException:
raise
except Exception as e:
logger.error(f"获取评估详情失败: {e}", exc_info=True)
raise HTTPException(
status_code=500,
detail=f"获取评估详情失败: {str(e)}"
)