mirror of
https://github.com/handsomezhuzhu/QQuiz.git
synced 2026-02-20 20:10:14 +00:00
🎉 Initial commit: QQuiz - 智能刷题与题库管理平台
## 功能特性 ✅ **核心功能** - 多文件上传与智能去重(基于 content_hash) - 异步文档解析(支持 TXT/PDF/DOCX/XLSX) - AI 智能题目提取与评分(OpenAI/Anthropic/Qwen) - 断点续做与进度管理 - 自动错题本收集 ✅ **技术栈** - Backend: FastAPI + SQLAlchemy 2.0 + PostgreSQL - Frontend: React 18 + Vite + Tailwind CSS - Deployment: Docker Compose ✅ **项目结构** - 53 个文件 - 完整的前后端分离架构 - Docker/源码双模部署支持 🚀 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
160
backend/schemas.py
Normal file
160
backend/schemas.py
Normal file
@@ -0,0 +1,160 @@
|
||||
"""
|
||||
Pydantic Schemas for Request/Response Validation
|
||||
"""
|
||||
from pydantic import BaseModel, Field, validator
|
||||
from typing import Optional, List
|
||||
from datetime import datetime
|
||||
from models import ExamStatus, QuestionType
|
||||
|
||||
|
||||
# ============ Auth Schemas ============
|
||||
class UserCreate(BaseModel):
|
||||
username: str = Field(..., min_length=3, max_length=50)
|
||||
password: str = Field(..., min_length=6)
|
||||
|
||||
@validator('username')
|
||||
def username_alphanumeric(cls, v):
|
||||
if not v.replace('_', '').replace('-', '').isalnum():
|
||||
raise ValueError('Username must be alphanumeric (allows _ and -)')
|
||||
return v
|
||||
|
||||
|
||||
class UserLogin(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
|
||||
|
||||
class Token(BaseModel):
|
||||
access_token: str
|
||||
token_type: str = "bearer"
|
||||
|
||||
|
||||
class UserResponse(BaseModel):
|
||||
id: int
|
||||
username: str
|
||||
is_admin: bool
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ============ System Config Schemas ============
|
||||
class SystemConfigUpdate(BaseModel):
|
||||
allow_registration: Optional[bool] = None
|
||||
max_upload_size_mb: Optional[int] = None
|
||||
max_daily_uploads: Optional[int] = None
|
||||
ai_provider: Optional[str] = None
|
||||
|
||||
|
||||
class SystemConfigResponse(BaseModel):
|
||||
allow_registration: bool
|
||||
max_upload_size_mb: int
|
||||
max_daily_uploads: int
|
||||
ai_provider: str
|
||||
|
||||
|
||||
# ============ Exam Schemas ============
|
||||
class ExamCreate(BaseModel):
|
||||
title: str = Field(..., min_length=1, max_length=200)
|
||||
|
||||
|
||||
class ExamResponse(BaseModel):
|
||||
id: int
|
||||
user_id: int
|
||||
title: str
|
||||
status: ExamStatus
|
||||
current_index: int
|
||||
total_questions: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ExamListResponse(BaseModel):
|
||||
exams: List[ExamResponse]
|
||||
total: int
|
||||
|
||||
|
||||
class ExamUploadResponse(BaseModel):
|
||||
exam_id: int
|
||||
title: str
|
||||
status: str
|
||||
message: str
|
||||
|
||||
|
||||
class ParseResult(BaseModel):
|
||||
"""Result from file parsing"""
|
||||
total_parsed: int
|
||||
duplicates_removed: int
|
||||
new_added: int
|
||||
message: str
|
||||
|
||||
|
||||
# ============ Question Schemas ============
|
||||
class QuestionBase(BaseModel):
|
||||
content: str
|
||||
type: QuestionType
|
||||
options: Optional[List[str]] = None
|
||||
answer: str
|
||||
analysis: Optional[str] = None
|
||||
|
||||
|
||||
class QuestionCreate(QuestionBase):
|
||||
exam_id: int
|
||||
|
||||
|
||||
class QuestionResponse(QuestionBase):
|
||||
id: int
|
||||
exam_id: int
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class QuestionListResponse(BaseModel):
|
||||
questions: List[QuestionResponse]
|
||||
total: int
|
||||
|
||||
|
||||
# ============ Quiz Schemas ============
|
||||
class AnswerSubmit(BaseModel):
|
||||
question_id: int
|
||||
user_answer: str
|
||||
|
||||
|
||||
class AnswerCheckResponse(BaseModel):
|
||||
correct: bool
|
||||
user_answer: str
|
||||
correct_answer: str
|
||||
analysis: Optional[str] = None
|
||||
ai_score: Optional[float] = None # For short answer questions
|
||||
ai_feedback: Optional[str] = None # For short answer questions
|
||||
|
||||
|
||||
class QuizProgressUpdate(BaseModel):
|
||||
current_index: int
|
||||
|
||||
|
||||
# ============ Mistake Schemas ============
|
||||
class MistakeAdd(BaseModel):
|
||||
question_id: int
|
||||
|
||||
|
||||
class MistakeResponse(BaseModel):
|
||||
id: int
|
||||
user_id: int
|
||||
question_id: int
|
||||
question: QuestionResponse
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class MistakeListResponse(BaseModel):
|
||||
mistakes: List[MistakeResponse]
|
||||
total: int
|
||||
Reference in New Issue
Block a user