Files
test/app/schema/statistics_schema.py
T

152 lines
5.1 KiB
Python
Raw Normal View History

2026-09-21 19:03:31 +08:00
"""统计分析模块出入参(需求 2.6)。"""
from __future__ import annotations
from datetime import date
from typing import Any
from pydantic import BaseModel, Field
class ClassOverviewItem(BaseModel):
"""2.6.1 多维度班级统计:每班总人数 + 男女分布。"""
class_id: int
class_no: str
class_name: str
status_text: str | None = None
head_teacher_name: str | None = None
total: int = Field(0, description="总人数")
male: int = Field(0, description="男生数")
female: int = Field(0, description="女生数")
other: int = Field(0, description="未标注性别人数")
class AllAboveItem(BaseModel):
"""2.6.2 每次考试都过线的学生。"""
stu_id: int
stu_no: str
name: str
class_name: str | None = None
exam_count: int = Field(0, description="参加考核次数")
min_score: float = Field(0, description="最低分(就是它决定了过线)")
avg_score: float = Field(0, description="平均分")
scores: list[dict[str, Any]] = Field(default_factory=list, description="各次成绩明细")
class FailDetailItem(BaseModel):
"""2.6.2 不及格明细。"""
stu_id: int
stu_no: str
name: str
class_name: str | None = None
fail_times: int = Field(0, description="不及格次数")
fail_details: list[dict[str, Any]] = Field(default_factory=list, description="不及格场次明细")
class ClassAvgScoreItem(BaseModel):
"""2.6.2 每场考试每个班级的平均分。"""
exam_seq: int
class_id: int | None = None
class_name: str | None = None
student_count: int = Field(0, description="参考人数")
avg_score: float = Field(0, description="平均分")
max_score: float = 0
min_score: float = 0
pass_rate: float = Field(0, description="及格率 %")
class SalaryTopItem(BaseModel):
"""2.6.3 就业薪资 Top N。"""
rank: int
stu_id: int
stu_no: str
name: str
class_name: str | None = None
company: str | None = None
salary: float = 0
salary_wan: float = 0
offer_date: date | None = None
duration_days: int | None = None
class StudentDurationItem(BaseModel):
"""2.6.3 每个学生的就业时长。"""
stu_id: int
stu_no: str
name: str
class_name: str | None = None
company: str | None = None
open_date: date | None = None
offer_date: date | None = None
duration_days: int | None = Field(None, description="offer 时间 - 开放时间(天)")
state: str = Field("", description="就业中 / 已拿到 offer")
class ClassAvgDurationItem(BaseModel):
"""2.6.3 每个班级的平均就业时长。"""
class_id: int | None = None
class_name: str | None = None
student_count: int = Field(0, description="班级总人数")
open_count: int = Field(0, description="已开放就业的人数(统计基数)")
offer_count: int = Field(0, description="已下发 offer 的人数")
avg_duration_days: float | None = Field(None, description="平均就业时长(天)")
min_duration_days: int | None = None
max_duration_days: int | None = None
class VolatilityItem(BaseModel):
"""2.7.2 成绩波动分析。"""
rank: int
stu_id: int
stu_no: str
name: str
class_name: str | None = None
exam_count: int = 0
avg_score: float = 0
stddev: float = Field(0, description="成绩标准差")
score_range: float = Field(0, description="最大分差 max-min")
trend: str = Field("", description="上升 / 下降 / 基本持平(按最小二乘斜率,阈值 ±1 分/场)")
trend_slope: float = Field(0, description="成绩趋势斜率,单位:分/场(对考核序次做最小二乘拟合)")
scores: list[float] = Field(default_factory=list, description="按序次排列的成绩")
class FunnelItem(BaseModel):
"""2.7.2 班级就业漏斗。"""
class_id: int
class_no: str
class_name: str
total: int = Field(0, description="总人数")
employed: int = Field(0, description="已就业人数(拿到 offer)")
high_salary: int = Field(0, description="高薪人数(>= 高薪线)")
employment_rate: float = Field(0, description="就业率 %")
high_salary_rate: float = Field(0, description="高薪占已就业比例 %")
avg_salary: float | None = Field(None, description="已就业学生平均薪资")
avg_duration_days: float | None = Field(None, description="平均就业时长(天)")
class OverviewOut(BaseModel):
"""仪表盘概览。"""
student_total: int = 0
student_by_status: dict[str, int] = Field(default_factory=dict, description="各状态人数")
class_total: int = 0
teacher_total: int = 0
advisor_total: int = 0
employment_total: int = 0
employment_rate: float = Field(0, description="整体就业率 %")
avg_salary: float | None = None
high_salary_count: int = 0
score_record_total: int = 0
score_avg: float | None = None
warning_student_count: int = Field(0, description="存在红线预警的学生数")
top_classes: list[dict[str, Any]] = Field(default_factory=list, description="就业率前 5 班级")