Files

142 lines
4.7 KiB
Python
Raw Permalink Normal View History

# =============================================================================
# 企微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)