# ============================================================================= # 企微IT智能服务台 — 答题系统 API # ============================================================================= # 说明:排队等待期间的答题+积分API # # 路由: # GET /api/h5/quiz/question — 获取下一道题(双模式自动选择) # POST /api/h5/quiz/answer — 提交答案(正误+积分+插队+下一题) # GET /api/h5/quiz/history — 答题历史记录和积分 # ============================================================================= import logging from typing import Optional from fastapi import APIRouter, Depends, Query from pydantic import BaseModel from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models.conversation import Conversation from app.services.quiz_service import get_quiz_service from app.utils.response import AppException, success_response logger = logging.getLogger(__name__) router = APIRouter(tags=["quiz"]) # ============================================================================= # 请求体定义 # ============================================================================= class AnswerRequest(BaseModel): """提交答案请求体。""" employee_id: str question_id: str selected_index: int conversation_id: Optional[str] = None # ============================================================================= # GET /api/h5/quiz/question — 获取下一道题 # ============================================================================= @router.get("/h5/quiz/question") async def get_quiz_question( employee_id: str = Query(..., description="员工ID"), conversation_id: Optional[str] = Query(None, description="当前会话ID(排队时传入)"), db: AsyncSession = Depends(get_db), ): """获取下一道题(双模式自动选择)。 模式选择: - 排队中且 info_locked=false → 诊断题(答案附加到会话上下文) - 排队中且 info_locked=true → IT知识题 - 非排队 → IT知识题 Args: employee_id: 员工ID conversation_id: 当前会话ID(可选) Returns: 题目数据 """ quiz_service = get_quiz_service() # 查找当前会话 conversation = None if conversation_id: result = await db.execute( select(Conversation).where(Conversation.id == conversation_id) ) conversation = result.scalar_one_or_none() question = await quiz_service.get_next_question(db, employee_id, conversation) return success_response(data=question) # ============================================================================= # POST /api/h5/quiz/answer — 提交答案 # ============================================================================= @router.post("/h5/quiz/answer") async def submit_quiz_answer( body: AnswerRequest, db: AsyncSession = Depends(get_db), ): """提交答案,返回正误+积分变化+插队效果+下一题。 处理流程: 1. 判定正误 2. 记录答题 3. 更新积分(答对+10分,跨会话累积) 4. 更新 queue_priority(每答3题前移1位,上限2) 5. 如果是诊断题且答对,答案附加到会话上下文 6. 返回下一道题 Args: body: 答案请求体 Returns: 答题结果+下一题 """ quiz_service = get_quiz_service() # 查找当前会话 conversation = None if body.conversation_id: result = await db.execute( select(Conversation).where(Conversation.id == body.conversation_id) ) conversation = result.scalar_one_or_none() result = await quiz_service.submit_answer( db, body.employee_id, body.question_id, body.selected_index, conversation ) return success_response(data=result) # ============================================================================= # GET /api/h5/quiz/history — 答题历史记录和积分 # ============================================================================= @router.get("/h5/quiz/history") async def get_quiz_history( employee_id: str = Query(..., description="员工ID"), page: int = Query(1, ge=1, description="页码"), page_size: int = Query(20, ge=1, le=100, description="每页数量"), db: AsyncSession = Depends(get_db), ): """获取答题历史记录和积分信息。 Args: employee_id: 员工ID page: 页码 page_size: 每页数量 Returns: 答题历史+积分信息 """ quiz_service = get_quiz_service() history = await quiz_service.get_quiz_history(db, employee_id, page, page_size) return success_response(data=history)