yearning
11 小时以前 3f96c9c6502243b06efd4bb34a189e72e3a5557c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from pydantic import BaseModel, Field
 
 
class SystemSettingsOut(BaseModel):
    system_name: str
    logo_url: str | None = None
 
 
class SystemSettingsUpdate(BaseModel):
    system_name: str = Field(min_length=1, max_length=128)
 
 
class LoginRequest(BaseModel):
    username: str
    password: str
 
 
class ChangePasswordRequest(BaseModel):
    old_password: str = Field(min_length=1, max_length=128)
    new_password: str = Field(min_length=6, max_length=128)
 
 
class TokenResponse(BaseModel):
    access_token: str
    token_type: str = "bearer"
 
 
class UserMe(BaseModel):
    id: int
    username: str
    display_name: str
    role: str
 
    class Config:
        from_attributes = True
 
 
class ScoreRow(BaseModel):
    examinee_id: str
    name: str | None
    id_card: str | None
    subject_name: str
    score: float
    attempt_id: str
    room_id: str | None = None
    paper_name: str | None = None
    start_time: str | None = None
    end_time: str | None = None
 
 
class ScoresResponse(BaseModel):
    total: int
    page: int
    page_size: int
    items: list[ScoreRow]
 
 
class QuestionDetail(BaseModel):
    external_item_id: str
    part_name: str | None
    item_type: int | None
    item_order: int | None
    title_html: str | None
    detail_json: str | None
    max_score: float | None
    reference_answer: str | None
    user_answer: str | None
    is_correct: bool
    score: float
 
 
class PartGroup(BaseModel):
    part_name: str
    questions: list[QuestionDetail]
 
 
class AttemptDetail(BaseModel):
    attempt_id: str
    examinee_name: str | None
    id_card: str | None
    score: float
    paper_total_score: float | None
    paper_name: str | None
    subject_name: str | None
    room_id: str | None
    seat_number: str | None
    start_time: str | None
    end_time: str | None
    parts: list[PartGroup]
 
 
class GraderOut(BaseModel):
    id: int
    username: str
    display_name: str
    is_active: bool
    created_at: str
    subjects: list[str] = []
 
 
class GraderCreate(BaseModel):
    username: str = Field(min_length=2, max_length=64)
    password: str = Field(min_length=6, max_length=128)
    display_name: str = Field(default="", max_length=128)
    subjects: list[str] = Field(min_length=1)
 
 
class GraderUpdate(BaseModel):
    username: str | None = Field(default=None, min_length=2, max_length=64)
    password: str | None = Field(default=None, min_length=6, max_length=128)
    display_name: str | None = Field(default=None, max_length=128)
    is_active: bool | None = None
    subjects: list[str] | None = None
 
 
class GradersResponse(BaseModel):
    items: list[GraderOut]
 
 
class ImportBatchOut(BaseModel):
    id: int
    subject_name: str
    exam_id: int | None
    exam_ids: list[int] = []
    zip_filename: str
    imported_at: str
    status: str
    attempt_count: int = 0
    paper_name: str | None = None
 
    class Config:
        from_attributes = True