commit
build / build-push (push) Successful in 1m29s

This commit is contained in:
wanghu
2026-10-21 15:00:26 +08:00
parent b857575710
commit 9e83208f35
117 changed files with 13358 additions and 0 deletions
@@ -0,0 +1,24 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 手动调班请求。
*/
@Data
public class AdjustRequest {
private Integer stage;
private String year;
private Integer term;
private Integer studentId;
/** 目标班级id */
private Integer toClassId;
/** 约束冲突时是否人工确认强行执行(审计记录) */
private Boolean force;
}
@@ -0,0 +1,19 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 手动调班结果:冲突未强制时返回 conflicts,applied=true 表示已执行。
*/
@Data
public class AdjustResultVo {
/** 是否已执行 */
private boolean applied;
/** 约束冲突提示(applied=false 时返回,供前端人工确认) */
private List<String> conflicts = new ArrayList<>();
}
@@ -0,0 +1,52 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 数据提交页:摘要 + 提交前检查清单。
*/
@Data
public class AssignSubmitCheckVo {
private Integer status;
private LocalDateTime submitTime;
private String year;
private Integer term;
private int classCount;
private long studentCount;
/** 班主任已指定数 */
private int teacherSetCount;
/** 是否已完成分班 */
private boolean assigned;
/** 人数极差 */
private int countSpread;
/** 校验警告条数 */
private int warnCount;
/** 检查清单:{name, level(ok/warn/bad), msg} */
private List<CheckItem> checks = new ArrayList<>();
@Data
public static class CheckItem {
private String name;
/** ok / warn / bad */
private String level;
private String msg;
}
}
@@ -0,0 +1,33 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.List;
/**
* 均衡维度勾选(人数维度恒开不入库)。
*/
@Data
public class BalanceVo {
/** 总分均分(小学版恒 false) */
private Boolean total;
/** 三科平均分(语文+数学+英语;三科齐全时可用) */
private Boolean core3;
/** 男女生比例 */
private Boolean gender;
/** 各分数段人数 */
private Boolean bands;
/** 参与均衡的单科列表 */
private List<String> subjects;
/** 参与均衡的数值型字段列表 */
private List<String> nums;
/** 参与均衡的是否型字段列表 */
private List<String> tags;
}
@@ -0,0 +1,44 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 分数段报表(学科 × 区间人数,全部 + 各班)。
*/
@Data
public class BandReportVo {
/** 学科名("总分" 或单科名) */
private String subject;
private double minScore;
private double maxScore;
private double step;
/** 区间标签(左闭右开) */
private List<String> labels = new ArrayList<>();
/** 每段一行:全部 + 各班人数 */
private List<BandRow> rows = new ArrayList<>();
private long total;
private double maxScoreSeen;
private double minScoreSeen;
@Data
public static class BandRow {
/** 区间标签 */
private String label;
/** 各班人数,key=班名;含 "全部" */
private List<Long> counts = new ArrayList<>();
}
}
@@ -0,0 +1,49 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 结果页图表数据(前端 SVG 渲染)。
*/
@Data
public class ChartsVo {
/** 各班平均分(无成绩学段为人数) */
private List<Bar> avgBars = new ArrayList<>();
/** 各班性别结构(堆叠条形) */
private List<GenderBar> genderBars = new ArrayList<>();
/** 各班分数段分布 */
private List<BandStack> bandStacks = new ArrayList<>();
@Data
public static class Bar {
private String name;
private double value;
}
@Data
public static class GenderBar {
private String name;
private int male;
private int female;
}
@Data
public static class BandStack {
private String name;
/** 与 bandCuts.labels 对齐的各段人数 */
private List<Long> counts = new ArrayList<>();
}
}
@@ -0,0 +1,61 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 班级卡片(结果页):统计 + 可展开名单。
*/
@Data
public class ClassCardVo {
private Integer classId;
private String name;
private Integer sortOrder;
private String teacherName;
/** A/B(高中 layer:A=实验班;within:无) */
private String abGroup;
private int count;
private int male;
private int female;
/** 总分均分(无成绩学段为空) */
private BigDecimal avg;
private BigDecimal max;
private BigDecimal min;
/** 单科均分 {科目:均值} */
private Map<String, BigDecimal> subjectAvg = new LinkedHashMap<>();
/** 数值字段均分 */
private Map<String, BigDecimal> numAvg = new LinkedHashMap<>();
/** 是否型字段人数 {字段:人数} */
private Map<String, Long> tagCount = new LinkedHashMap<>();
/** 分数段人数(与 bandCuts 对齐) */
private List<Long> bandCounts = new ArrayList<>();
/** A/B 层人数 {A:n,B:m}(within 模式) */
private Map<String, Integer> levelCounts = new LinkedHashMap<>();
/** 前若干名(mini 柱状图,按总分降序,最多12) */
private List<BigDecimal> topScores = new ArrayList<>();
/** 全班名单 */
private List<StudentVo> students = new ArrayList<>();
}
@@ -0,0 +1,37 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 班级设置项 / 保存请求行。
*/
@Data
public class ClassItemVo {
/** 班级id(保存时已有班级携带;无 id=新增) */
private Integer id;
/** 序号(1 起) */
private Integer sortOrder;
/** 班级名称 */
private String name;
/** 班主任平台教师id(可空;不存账号) */
private Integer teacherId;
/** 班主任姓名(展示冗余,服务端按平台教师列表回填) */
private String teacherName;
/** 目标人数(空=自动均分) */
private Integer targetCount;
/** 是否A班(高中分层) */
private Boolean abFlag;
/** 已预设学生数(只读,服务端计算) */
private Integer presetCount;
/** 剩余 = 目标人数 - 已预设(只读) */
private Integer remain;
}
@@ -0,0 +1,35 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 班级均分报表行(高中/初中)。
*/
@Data
public class ClassReportVo {
private Integer classId;
private String name;
private String teacherName;
private int count;
private int male;
private int female;
/** 各科均分 */
private Map<String, BigDecimal> subjectAvg = new LinkedHashMap<>();
/** 三科总分均分(语数英齐才时,参考项) */
private BigDecimal core3Avg;
/** 总分均分 */
private BigDecimal totalAvg;
}
@@ -0,0 +1,22 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 约束规则开关(硬约束,默认全开;换人优化与手动调班时强制校验)。
*/
@Data
public class ConstraintVo {
/** 同名学生分到不同班 */
private Boolean sameName;
/** 姓名读音相近分到不同班 */
private Boolean sameSound;
/** 预设「不同班」的学生叉开 */
private Boolean diffClass;
/** 预设「同班」的学生捆绑 */
private Boolean sameClass;
}
@@ -0,0 +1,25 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 粘贴文本导入请求。
*/
@Data
public class ImportPasteRequest {
private Integer stage;
private String year;
private Integer term;
/** 粘贴的原始文本(Tab/逗号/空格分隔) */
private String text;
/** 首行是否表头 */
private Boolean hasHeader;
/** replace 替换全部 / append 追加 */
private String mode;
}
@@ -0,0 +1,40 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 导入结果(统计条 + 告警)。
*/
@Data
public class ImportResultVo {
/** 本次导入入库人数 */
private int inserted;
/** 项目现有总人数 */
private long total;
/** 告警(列识别、数据异常) */
private List<String> warn = new ArrayList<>();
/** 男生数 */
private long male;
/** 女生数 */
private long female;
/** 识别到的单科列 */
private List<String> subjects = new ArrayList<>();
/** 是否型字段 */
private List<String> tags = new ArrayList<>();
/** 数值型字段 */
private List<String> nums = new ArrayList<>();
/** 毕业学校数 */
private int schools;
}
@@ -0,0 +1,44 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 均衡明细行:维度 / 最低班 / 最高班 / 极差 / 相对偏差 / 判定 / 权重。
*/
@Data
public class MetricItemVo {
/** 维度名(人数/总分均分/男女生比例/语文/视力分均值/特长生人数...) */
private String dimension;
/** 类型:count 人数型 / avg 均值型 */
private String type;
/** 权重 */
private double weight;
/** 最低班名 */
private String minClass;
private double minValue;
/** 最高班名 */
private String maxClass;
private double maxValue;
/** 极差 */
private double spread;
/** 相对偏差(极差/均值,%) */
private double relDev;
/** 判定:优/良/关注/偏差大/样本过小/信息项 */
private String grade;
/** 各班数值(与 classCards 顺序对齐) */
private List<Double> perClass = new ArrayList<>();
}
@@ -0,0 +1,24 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.List;
/**
* 按姓名批量预设班级请求。
*/
@Data
public class PresetBatchRequest {
private Integer stage;
private String year;
private Integer term;
/** 学生姓名(多个,分隔符已由前端拆分) */
private List<String> names;
/** 目标班级id */
private Integer classId;
}
@@ -0,0 +1,17 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 批量预设结果:未匹配姓名回填提示。
*/
@Data
public class PresetBatchResultVo {
private int updated;
private List<String> unmatched = new ArrayList<>();
}
@@ -0,0 +1,46 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
/**
* 工作台信息汇总(步骤1/2 页面加载入口)。
*/
@Data
public class ProjectInfoVo {
private Integer projectId;
private Integer stage;
private String year;
private Integer term;
/** 0草稿 1已提交(锁定) */
private Integer status;
private LocalDateTime submitTime;
private List<ClassItemVo> classes;
private RuleVo rule;
private ProjectStatsVo stats;
/** 平台当前学年学期(默认选中项) */
private String currentYear;
private Integer currentTerm;
/** 当前学年学期(NowYearTerm 接口返回) */
@Data
public static class CurrentYear {
private String year;
private Integer term;
}
}
@@ -0,0 +1,22 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 项目统计汇总(名单导入后实时统计)。
*/
@Data
public class ProjectStatsVo {
private long studentCount;
private long maleCount;
private long femaleCount;
/** 已落位班级的学生数 */
private long assignedCount;
/** 毕业学校数(高中/初中) */
private long schoolCount;
}
@@ -0,0 +1,68 @@
package com.yunhai.acaclassassign.model.assign;
import com.yunhai.acaclassassign.entity.AssignPush;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 推送状态(GET /api/assign/project/PushStatus)。
*/
@Getter
@Setter
public class PushStatusVo {
/** 0未推送 1已推送 2部分失败 3失败 4推送中 */
private Integer status;
private String statusText;
private LocalDateTime pushTime;
private String msg;
/** 班级映射数(已建立本地班→平台班映射的班级数) */
private Integer classCount;
/** 已成功学生数(分班结果中已推送成功的人数) */
private Integer okCount;
/** 未成功学生数 */
private Integer failCount;
/** 未成功明细 */
private List<FailItem> fails = new ArrayList<>();
@Getter
@Setter
public static class FailItem {
/** 本地学生id(aca_assign_student.id) */
private Integer studentId;
private String name;
private String reason;
}
public static String textOf(Integer status) {
if (status == null) {
return "未推送";
}
switch (status) {
case AssignPush.STATUS_OK:
return "已推送";
case AssignPush.STATUS_PARTIAL:
return "部分失败";
case AssignPush.STATUS_FAIL:
return "推送失败";
case AssignPush.STATUS_PUSHING:
return "推送中";
default:
return "未推送";
}
}
}
@@ -0,0 +1,32 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 分班规则(读写共用)。
*/
@Data
public class RuleVo {
private BalanceVo balance;
private ConstraintVo constraint;
/** 分数段模式:count 按段数 / step 按分数间隔(小学版空) */
private String bandMode;
/** 段数 3/4/5(上限 20) */
private Integer bandCount;
/** 分数间隔 1-200 */
private Integer bandStep;
/** 启用 A/B 分层(仅高中) */
private Boolean abEnabled;
/** layer 按总分分层编班 / within 均衡编班+班内分层 */
private String abMode;
/** A 班数量:1 ≤ K < 班级数 */
private Integer abClassCount;
}
@@ -0,0 +1,92 @@
package com.yunhai.acaclassassign.model.assign;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 分班结果页数据(指标卡/图表/均衡明细/日志/班级卡片)。
*/
@Data
public class RunResultVo {
/** 项目状态:0草稿 1已提交 */
private Integer status;
private LocalDateTime assignTime;
private Integer iterations;
private Long costMs;
/** 综合均衡度 0-100 */
private BigDecimal score;
/** 是否含手动调整 */
private Boolean adjusted;
/** 参与分班人数 */
private long total;
/** 人数极差 */
private int countSpread;
/** 均分极差(小学=0) */
private BigDecimal avgSpread;
/** 男女比例最大偏差%(相对全校平均) */
private double genderDev;
/** A/B 分层信息(高中):aCount/bCount/aAvg/bAvg/layerDiff */
private AbInfo abInfo;
/** 均衡明细 */
private List<MetricItemVo> metrics = new ArrayList<>();
/** 加权相对偏差(%) */
private double weightedDev;
/** 警告 */
private List<String> warns = new ArrayList<>();
/** 日志(算法/校验/手动调班/班主任匹配) */
private List<String> logs = new ArrayList<>();
/** 分数段切点标签 */
private List<String> bandLabels = new ArrayList<>();
private ChartsVo charts = new ChartsVo();
private List<ClassCardVo> classCards = new ArrayList<>();
@Data
public static class AbInfo {
private Boolean enabled;
private String mode;
/** Jackson 会把 getAClassCount() 推导成 aclassCount,须显式指定与前端一致的键名 */
@JsonProperty("aClassCount")
private int aClassCount;
@JsonProperty("aCount")
private int aCount;
@JsonProperty("aAvg")
private BigDecimal aAvg;
@JsonProperty("bCount")
private int bCount;
@JsonProperty("bAvg")
private BigDecimal bAvg;
/** 层间均分差 */
private BigDecimal layerDiff;
}
}
@@ -0,0 +1,21 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.List;
/**
* 保存班级设置请求。
*/
@Data
public class SaveClassesRequest {
private Integer stage;
private String year;
private Integer term;
/** 全量班级清单(以本列表为准重建:删/改/增) */
private List<ClassItemVo> classes;
}
@@ -0,0 +1,18 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 保存分班规则请求。
*/
@Data
public class SaveRulesRequest {
private Integer stage;
private String year;
private Integer term;
private RuleVo rule;
}
@@ -0,0 +1,37 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.List;
/**
* 生源分析:毕业学校 × 分数档交叉表(高中/初中;仅结构分析,不影响分班)。
*/
@Data
public class SourceAnalysisVo {
/** 分数线(升序) */
private List<Double> cuts;
/** 分数档标签(左闭右开) */
private List<String> labels;
/** 每校一行:counts 与 labels 对齐 */
private List<SchoolRow> rows;
/** 各档合计 */
private List<Long> sums;
/** 录取总人数 */
private long total;
@Data
public static class SchoolRow {
private String school;
private List<Long> counts;
private long total;
}
}
@@ -0,0 +1,26 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 学生名单查询(GET 参数绑定)。
*/
@Data
public class StudentPageRequest {
private Integer stage;
private String year;
private Integer term;
/** 全部=null/0;否则班级id */
private Integer classId;
/** 姓名关键字 */
private String keyword;
private Integer pageIndex = 1;
private Integer pageSize = 50;
}
@@ -0,0 +1,33 @@
package com.yunhai.acaclassassign.model.assign;
import com.yunhai.acaclassassign.model.BasePageResult;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 学生名单分页响应:在通用分页外壳上补充识别出的列名清单,
* 前端据此渲染单科 / 是否型 / 数值型自定义列(刷新后无需重新导入)。
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class StudentPageVo extends BasePageResult<StudentVo> {
/** 单科列名(按导入出现序,如 语文、数学、英语、物理、化学) */
private List<String> subjects;
/** 是否型列名(按导入出现序,如 特长生、住宿) */
private List<String> tags;
/** 数值型列名(按导入出现序,如 视力分) */
private List<String> nums;
/** 年级名称(项目全体学生同一入学年级;班级管理字典名,不可得回退 K12 标准新生年级名) */
private String gradeName;
public StudentPageVo(BasePageResult<StudentVo> page) {
super(page.getContent(), page.getTotal(), page.getPageIndex(),
page.getPageSize(), page.getTotalPages(), page.isHasNext());
}
}
@@ -0,0 +1,48 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 名单简单统计(全量学生,不分页):人数 / 性别 / 总分三值 / 均衡字段统计 / 毕业学校所数。
*/
@Data
public class StudentStatsVo {
private long total;
private long male;
private long female;
/** 总分均分(无成绩数据时为 null) */
private Double avgScore;
private Double maxScore;
private Double minScore;
/** 均衡字段统计(是否型计人数、数值型计班均值,按首次出现顺序) */
private List<FieldStat> fields = new ArrayList<>();
/** 非空毕业学校去重数 */
private int schoolCount;
@Data
public static class FieldStat {
/** 字段名 */
private String name;
/** tag=是否型(count 有效) / num=数值型(avg 有效) */
private String kind;
/** 是否型:取真人数 */
private Long count;
/** 数值型:全员均值(2 位小数) */
private Double avg;
}
}
@@ -0,0 +1,18 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
/**
* 单元格编辑保存请求。
*/
@Data
public class StudentUpdateRequest {
private Integer stage;
private String year;
private Integer term;
private StudentVo student;
}
@@ -0,0 +1,55 @@
package com.yunhai.acaclassassign.model.assign;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Map;
/**
* 学生行(列表/编辑/结果名单共用)。
*/
@Data
public class StudentVo {
private Integer id;
private String name;
/** 1男 2女 0未知 */
private Integer gender;
private BigDecimal totalScore;
/** 单科成绩 {"语文":95.5} */
private Map<String, Object> scores;
/** 是否型字段 {"特长生":true} */
private Map<String, Object> tags;
/** 数值型字段 {"视力分":4.8} */
private Map<String, Object> nums;
private String graduateSchool;
/** 学号(标识文本列,仅展示/导出) */
private String studentNo;
/** 账号(标识文本列,仅展示/导出) */
private String account;
/** 密码(标识文本列,生成=账号+@,仅展示/导出/推送初始密码) */
private String password;
private String remark;
private String presetRaw;
private Integer classId;
private String className;
/** A/B 层(高中) */
private String level;
private Integer srcRow;
}