152 lines
5.1 KiB
Python
152 lines
5.1 KiB
Python
"""统计分析模块出入参(需求 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 班级")
|