bd7635986a
Vue 前端 + FastAPI 后端,含部署脚本与词典数据。 Co-authored-by: Cursor <cursoragent@cursor.com>
143 lines
2.8 KiB
Python
143 lines
2.8 KiB
Python
from typing import Optional
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# Auth
|
|
class UserRegister(BaseModel):
|
|
username: str = Field(min_length=2, max_length=50)
|
|
password: str = Field(min_length=6, max_length=100)
|
|
|
|
|
|
class UserLogin(BaseModel):
|
|
username: str
|
|
password: str
|
|
|
|
|
|
class TokenResponse(BaseModel):
|
|
access_token: str
|
|
token_type: str = "bearer"
|
|
|
|
|
|
class UserOut(BaseModel):
|
|
id: int
|
|
username: str
|
|
created_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Translate
|
|
class TranslateRequest(BaseModel):
|
|
text: str = Field(min_length=1)
|
|
|
|
|
|
class TranslateResponse(BaseModel):
|
|
source_text: str
|
|
target_text: str
|
|
source_lang: str
|
|
target_lang: str
|
|
phonetic: Optional[str] = None
|
|
example_en: Optional[str] = None
|
|
example_cn: Optional[str] = None
|
|
|
|
|
|
# Words
|
|
class WordCreate(BaseModel):
|
|
source_text: str
|
|
target_text: str
|
|
source_lang: str
|
|
target_lang: str
|
|
phonetic: Optional[str] = None
|
|
example_en: Optional[str] = None
|
|
example_cn: Optional[str] = None
|
|
|
|
|
|
class WordUpdate(BaseModel):
|
|
status: Optional[str] = None
|
|
|
|
|
|
class WordOut(BaseModel):
|
|
id: int
|
|
user_id: int
|
|
source_text: str
|
|
target_text: str
|
|
source_lang: str
|
|
target_lang: str
|
|
phonetic: Optional[str] = None
|
|
example_en: Optional[str] = None
|
|
example_cn: Optional[str] = None
|
|
status: str
|
|
correct_count: int
|
|
wrong_count: int
|
|
consecutive_correct_count: int
|
|
mastery_score: int
|
|
review_due_date: Optional[str] = None
|
|
last_reviewed_at: Optional[str] = None
|
|
created_at: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# Quiz
|
|
class QuizOption(BaseModel):
|
|
label: str
|
|
text: str
|
|
|
|
|
|
class QuizQuestion(BaseModel):
|
|
word_id: int
|
|
question_type: str
|
|
prompt: str
|
|
options: list[QuizOption]
|
|
correct_answer: str
|
|
|
|
|
|
class DailyQuizResponse(BaseModel):
|
|
questions: list[QuizQuestion]
|
|
total: int
|
|
|
|
|
|
class QuizAnswerRequest(BaseModel):
|
|
word_id: int
|
|
question_type: str
|
|
user_answer: str
|
|
correct_answer: str
|
|
|
|
|
|
class QuizAnswerResponse(BaseModel):
|
|
is_correct: bool
|
|
correct_answer: str
|
|
word: WordOut
|
|
|
|
|
|
class QuizStatsResponse(BaseModel):
|
|
total_words: int
|
|
new_count: int
|
|
learning_count: int
|
|
mastered_count: int
|
|
weak_count: int
|
|
today_quiz_count: int
|
|
today_correct_count: int
|
|
today_accuracy: float
|
|
daily_target: int
|
|
today_completed: int
|
|
streak_days: int
|
|
|
|
|
|
# Settings
|
|
class SettingsOut(BaseModel):
|
|
daily_target: int
|
|
master_required_count: int
|
|
weak_wrong_threshold: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class SettingsUpdate(BaseModel):
|
|
daily_target: Optional[int] = Field(None, ge=1, le=100)
|
|
master_required_count: Optional[int] = Field(None, ge=1, le=20)
|
|
weak_wrong_threshold: Optional[int] = Field(None, ge=1, le=20)
|