diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassHistoryRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassHistoryRepository.java index 8713adc..9c43cce 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassHistoryRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassHistoryRepository.java @@ -16,5 +16,15 @@ import java.util.Optional; @Repository public interface SchClassHistoryRepository extends JpaRepository, JpaSpecificationExecutor { + /** + * 按学校、班级组(classId=group_class_id)、学年、学期查询班级历史快照 + * 历史任教统一取第二学期(term=2) + */ + List findBySchIdAndClassIdAndYearAndTerm(Integer schId, Integer classId, Integer year, Integer term); + + /** + * 取某班级最新学年的第二学期(term=2)历史快照,用于“历史学生”页班级头信息 + */ + SchClassHistory findTopBySchIdAndClassIdAndTermOrderByYearDesc(Integer schId, Integer classId, Integer term); } diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassTeachHistoryRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassTeachHistoryRepository.java index 64abefe..fcd1168 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassTeachHistoryRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchClassTeachHistoryRepository.java @@ -6,7 +6,15 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface SchClassTeachHistoryRepository extends JpaRepository, JpaSpecificationExecutor { + /** + * 按学校、班级组(classId=group_class_id)、学年、学期查询班级任教历史 + * 历史任教统一取第二学期(term=2) + */ + List findBySchIdAndClassIdAndYearAndTerm(Integer schId, Integer classId, Integer year, Integer term); + } diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentHistoryRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentHistoryRepository.java index f0ad159..c24dcb3 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentHistoryRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentHistoryRepository.java @@ -6,7 +6,18 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface SchStudentHistoryRepository extends JpaRepository, JpaSpecificationExecutor { + /** + * 按学校、班级、学年、学期查询历史学生(term=2 为学年快照) + */ + List findBySchIdAndClassIdAndYearAndTerm(Integer schId, Integer classId, Integer year, Integer term); + + /** + * 按学校、学生(stuId)查询历史学生记录,用于解析学生所属班级 + */ + List findBySchIdAndStuId(Integer schId, Integer stuId); } diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/api/SchHistoryController.java b/src/main/java/com/yunhai/bschclassmanage/controller/api/SchHistoryController.java index 5c08293..4b7a0aa 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/api/SchHistoryController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/api/SchHistoryController.java @@ -1,7 +1,9 @@ package com.yunhai.bschclassmanage.controller.api; import com.yunhai.bschclassmanage.config.Config; +import com.yunhai.bschclassmanage.model.vo.HistoryClassTeachVO; import com.yunhai.bschclassmanage.model.vo.HistorySchClassVO; +import com.yunhai.bschclassmanage.model.vo.HistorySchStudentVO; import com.yunhai.bschclassmanage.model.vo.SelectIntVO; import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService; import com.yunhai.bschclassmanage.service.IStudentClassHistoryService; @@ -10,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; @RestController @@ -25,6 +28,22 @@ public class SchHistoryController { return studentClassHistoryService.GetClassFirst(UserContext.getSchId(),classId); } + //获取历史学生信息(逐年倒序) + @GetMapping("getHistoryClassStudent") + public List getHistoryClassStudent(Integer classId) { + return studentClassHistoryService.getHistoryClassStudent(UserContext.getSchId(),classId); + } + //获取历史任教信息 + @GetMapping("getHistoryClassTeach") + public List getHistoryClassTeach(Integer classId) { + return studentClassHistoryService.getHistoryClassTeach(UserContext.getSchId(),classId); + } + + //通过学生stuId获取历史任教信息 + @GetMapping("getHistoryClassTeachByStuId") + public Map getHistoryClassTeachByStuId(Integer stuId) { + return studentClassHistoryService.getHistoryClassTeachByStuId(UserContext.getSchId(),stuId); + } } diff --git a/src/main/java/com/yunhai/bschclassmanage/entity/SchClass.java b/src/main/java/com/yunhai/bschclassmanage/entity/SchClass.java index 1431180..01482e1 100644 --- a/src/main/java/com/yunhai/bschclassmanage/entity/SchClass.java +++ b/src/main/java/com/yunhai/bschclassmanage/entity/SchClass.java @@ -110,6 +110,12 @@ public class SchClass extends BaseEntity { @Column(name = "graduate") private Boolean graduate; + /** + * 毕业日期 + */ + @Column(name = "graduate_date") + private Date graduateDate; + /** * 序号 K12班 根据 sort 定位 职业 班 sort 排序 */ diff --git a/src/main/java/com/yunhai/bschclassmanage/entity/SchClassHistory.java b/src/main/java/com/yunhai/bschclassmanage/entity/SchClassHistory.java index f705310..e70f996 100644 --- a/src/main/java/com/yunhai/bschclassmanage/entity/SchClassHistory.java +++ b/src/main/java/com/yunhai/bschclassmanage/entity/SchClassHistory.java @@ -82,6 +82,41 @@ public class SchClassHistory extends BaseEntity { @Column(name = "second_teacher_id") private Integer secondTeacherId; + /** + * 班主任名称(冗余字段) + */ + @Size(max = 255, message = "班主任名称长度不能超过255") + @Column(name = "first_teacher_name", length = 255) + private String firstTeacherName; + + /** + * 副班主任名称(冗余字段) + */ + @Size(max = 255, message = "副班主任名称长度不能超过255") + @Column(name = "second_teacher_name", length = 255) + private String secondTeacherName; + + /** + * 校区名称(冗余字段) + */ + @Size(max = 255, message = "校区名称长度不能超过255") + @Column(name = "campus_name", length = 255) + private String campusName; + + /** + * 系部名称(冗余字段) + */ + @Size(max = 255, message = "系部名称长度不能超过255") + @Column(name = "division_name", length = 255) + private String divisionName; + + /** + * 专业名称(冗余字段) + */ + @Size(max = 255, message = "专业名称长度不能超过255") + @Column(name = "majors_name", length = 255) + private String majorsName; + /** @@ -115,13 +150,6 @@ public class SchClassHistory extends BaseEntity { private Integer enrollYear; - - /** - * 是否毕业(默认0) - */ - @Column(name = "graduate") - private Boolean graduate; - /** * 序号 K12班 根据 sort 定位 职业 班 sort 排序 */ diff --git a/src/main/java/com/yunhai/bschclassmanage/entity/SchClassTeachHistory.java b/src/main/java/com/yunhai/bschclassmanage/entity/SchClassTeachHistory.java index 5e4a411..ee2c030 100644 --- a/src/main/java/com/yunhai/bschclassmanage/entity/SchClassTeachHistory.java +++ b/src/main/java/com/yunhai/bschclassmanage/entity/SchClassTeachHistory.java @@ -56,6 +56,20 @@ public class SchClassTeachHistory extends BaseEntity { @Column(name = "tea_id") private Integer teaId; + /** + * 学科名称(冗余字段) + */ + @Size(max = 255, message = "学科名称长度不能超过255") + @Column(name = "sub_name", length = 255) + private String subName; + + /** + * 教师名称(冗余字段) + */ + @Size(max = 255, message = "教师名称长度不能超过255") + @Column(name = "tea_name", length = 255) + private String teaName; + /** * 更新校验分组 diff --git a/src/main/java/com/yunhai/bschclassmanage/model/vo/HistoryClassTeachVO.java b/src/main/java/com/yunhai/bschclassmanage/model/vo/HistoryClassTeachVO.java new file mode 100644 index 0000000..074f98b --- /dev/null +++ b/src/main/java/com/yunhai/bschclassmanage/model/vo/HistoryClassTeachVO.java @@ -0,0 +1,38 @@ +package com.yunhai.bschclassmanage.model.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class HistoryClassTeachVO { + + private Integer gradeId; + + private String gradeName; + + private String yearDate; + + /** 班主任名称(冗余) */ + private String headTeacherName; + + /** 副班主任名称(冗余) */ + private String deputyHeadTeacherName; + + /** 校区名称(冗余) */ + private String campusName; + + /** 系部名称(冗余) */ + private String divisionName; + + /** 专业名称(冗余) */ + private String majorName; + + private String schName; + + /** 当前班级是否毕业 */ + private Boolean graduate; + + private List teach; + +} diff --git a/src/main/java/com/yunhai/bschclassmanage/model/vo/HistorySchStudentVO.java b/src/main/java/com/yunhai/bschclassmanage/model/vo/HistorySchStudentVO.java new file mode 100644 index 0000000..9b097d8 --- /dev/null +++ b/src/main/java/com/yunhai/bschclassmanage/model/vo/HistorySchStudentVO.java @@ -0,0 +1,37 @@ +package com.yunhai.bschclassmanage.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import javax.persistence.Column; +import java.util.Date; +import java.util.List; + +/** + * @Author wanghu + * @Date 2026-6-10 15:09 (可以根据需要修改) + * @Description: + */ +@Data +public class HistorySchStudentVO { + + private Integer gradeId; + + private String gradeName; + + private String yearDate; + + //学生数量 + private Integer count; + + /** 班级所在学校名称 */ + private String schName; + + /** 当前学生姓名(byStuId 入口时填充,classId 入口为 null) */ + private String studentName; + + /** 当前班级是否毕业 */ + private Boolean graduate; + + private List student; +} diff --git a/src/main/java/com/yunhai/bschclassmanage/service/IStudentClassHistoryService.java b/src/main/java/com/yunhai/bschclassmanage/service/IStudentClassHistoryService.java index af0b16e..445c7f0 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/IStudentClassHistoryService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/IStudentClassHistoryService.java @@ -1,13 +1,21 @@ package com.yunhai.bschclassmanage.service; -import com.yunhai.bschclassmanage.entity.BaseDicGrade; +import com.yunhai.bschclassmanage.model.vo.HistoryClassTeachVO; import com.yunhai.bschclassmanage.model.vo.HistorySchClassVO; +import com.yunhai.bschclassmanage.model.vo.HistorySchStudentVO; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; @Service public interface IStudentClassHistoryService { HistorySchClassVO GetClassFirst(Integer schId, Integer classId); + + List getHistoryClassTeach(Integer schId, Integer classId); + + Map getHistoryClassTeachByStuId(Integer schId, Integer stuId); + + List getHistoryClassStudent(Integer schId, Integer classId); } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/StudentClassHistoryService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/StudentClassHistoryService.java index a586e9c..371e4ec 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/StudentClassHistoryService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/StudentClassHistoryService.java @@ -1,8 +1,24 @@ package com.yunhai.bschclassmanage.service.impl; +import com.yunhai.bschclassmanage.Repository.SchClassHistoryRepository; +import com.yunhai.bschclassmanage.Repository.SchClassTeachHistoryRepository; +import com.yunhai.bschclassmanage.Repository.SchClassTeachRepository; +import com.yunhai.bschclassmanage.Repository.SchStudentHistoryRepository; +import com.yunhai.bschclassmanage.Repository.SchStudentRepository; +import com.yunhai.bschclassmanage.entity.BaseYearTerm; import com.yunhai.bschclassmanage.entity.SchClass; +import com.yunhai.bschclassmanage.entity.SchClassHistory; +import com.yunhai.bschclassmanage.entity.SchClassTeach; +import com.yunhai.bschclassmanage.entity.SchClassTeachHistory; +import com.yunhai.bschclassmanage.entity.SchStudent; +import com.yunhai.bschclassmanage.entity.SchStudentHistory; import com.yunhai.bschclassmanage.enums.SchType; +import com.yunhai.bschclassmanage.model.tool.YearTerm; +import com.yunhai.bschclassmanage.model.vo.HistoryClassTeachVO; import com.yunhai.bschclassmanage.model.vo.HistorySchClassVO; +import com.yunhai.bschclassmanage.model.vo.HistorySchStudentVO; +import com.yunhai.bschclassmanage.model.vo.SelectIntVO; +import com.yunhai.bschclassmanage.model.vo.SchTeachMapIdVO; import com.yunhai.bschclassmanage.service.*; import com.yunhai.bschclassmanage.utils.ModelMapperUtil; import com.yunhai.bschclassmanage.utils.RedisUtil; @@ -10,13 +26,25 @@ import com.yunhai.platform.utils.exception.DException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; @Service public class StudentClassHistoryService implements IStudentClassHistoryService { + /** 班主任在任教列表中的 subId 标识 */ + private static final String SUB_BZR = "SUBBZR"; + /** 副班主任在任教列表中的 subId 标识 */ + private static final String SUB_FBZR = "SUBFBZR"; + private static final String NAME_BZR = "班主任"; + private static final String NAME_FBZR = "副班主任"; + /** 历史任教统一取第二学期 */ + private static final int SECOND_TERM = 2; + /** 日期格式化:yyyy-MM-dd */ + private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ISO_LOCAL_DATE; + @Autowired private ISchClassService schClassService; @@ -38,6 +66,30 @@ public class StudentClassHistoryService implements IStudentClassHistoryService { @Autowired private ISchTeacherService schTeacherService; + @Autowired + private IBaseYearTermService baseYearTermService; + + @Autowired + private ISchDicSubjectService schDicSubjectService; + + @Autowired + private SchClassTeachRepository schClassTeachRepository; + + @Autowired + private SchClassHistoryRepository schClassHistoryRepository; + + @Autowired + private SchClassTeachHistoryRepository schClassTeachHistoryRepository; + + @Autowired + private SchStudentHistoryRepository schStudentHistoryRepository; + + @Autowired + private SchStudentRepository schStudentRepository; + + @Autowired + private IComSchTreeService comSchTreeService; + @Autowired private RedisUtil redisUtil; @@ -46,7 +98,7 @@ public class StudentClassHistoryService implements IStudentClassHistoryService { public HistorySchClassVO GetClassFirst(Integer schId,Integer classId) { Integer schType=schBinSchsystemService.getSchType(schId); Integer gradeId=null; - Optional classInfo= schClassService.getSchClassCacheFilter(schId,gradeId,classId).stream().findFirst(); + Optional classInfo= schClassService.getSchAllClassCacheFilter(schId,gradeId,classId).stream().findFirst(); if(!classInfo.isPresent()) throw new DException("班级未找到!"); HistorySchClassVO vo = ModelMapperUtil.map(classInfo.get(), HistorySchClassVO.class); vo.setSchType(schType); @@ -59,5 +111,267 @@ public class StudentClassHistoryService implements IStudentClassHistoryService { return vo; } + /** + * 获取班级历史学生信息(逐年倒序,类比 getHistoryClassTeach) + * yearList:未毕业 year..enrollYear(含当前学年,当前学年用实时表 sch_student); + * 已毕业 全部用历史表 sch_student_history。历史表固定 term=2。 + * 每学年组装一个 HistorySchStudentVO:student(id=stuId, name=姓名)、gradeId、gradeName、yearDate、count。 + */ + public List getHistoryClassStudent(Integer schId, Integer classId) { + // 1. 当前学年(依据学年开始日期-结束日期匹配) + YearTerm yearTerm = baseYearTermService.getCurrentYearTerm(); + int currentYear = yearTerm.getYear(); + + // 2. 当前班级 & 是否毕业(缓存) + SchClass schClass = schClassService.getSchAllClassCacheFilter(schId, (Integer) null, classId) + .stream().findFirst().orElseThrow(() -> new DException("班级未找到!")); + Integer enrollYear = schClass.getEnrollYear() != null ? schClass.getEnrollYear() : currentYear; + boolean graduated = Boolean.TRUE.equals(schClass.getGraduate()); + + // 班级所在学校名称 + String schName = comSchTreeService.getSchoolName(schId); + + // 学年学期 Map:year -> BaseYearTerm(含开始/结束日期),用于 yearDate + Map yearTermMap = baseYearTermService.getAllYearTerm().stream() + .filter(t -> t.getYear() != null) + .collect(Collectors.toMap(BaseYearTerm::getYear, t -> t, (a, b) -> a)); + + boolean k12=Objects.equals( schBinSchsystemService.getSchType(schId),SchType.BASICEDUCATION.getKey()); + + Map getGradeNameMap=baseSchsystemGradeService.getGradeNameMap(schId,null,schClass.getGradeId()); + + // 3. 年份区间(倒序) + List yearList = new ArrayList<>(); + for (int y = currentYear; y >= enrollYear; y--) yearList.add(y); + + // 4. 逐学年组装 + List result = new ArrayList<>(); + for (Integer y : yearList) { + boolean isLive = (y == currentYear) && !graduated; + + List studentList; + if (isLive) { + // 当前学年:实时表 sch_student + List live = schStudentRepository.findBySchIdAndClassId(schId, classId); + studentList = live.stream() + .filter(s -> s.getStuId() != null) + .map(s -> new SelectIntVO(s.getStuId(), s.getName())) + .collect(Collectors.toList()); + } else { + // 历史表:固定取第二学期(term=2) + List hist = schStudentHistoryRepository + .findBySchIdAndClassIdAndYearAndTerm(schId, classId, y, SECOND_TERM); + studentList = hist.stream() + .filter(s -> s.getStuId() != null) + .map(s -> new SelectIntVO(s.getStuId(), s.getName())) + .collect(Collectors.toList()); + } + + HistorySchStudentVO vo = new HistorySchStudentVO(); + vo.setGradeId(schClass.getGradeId()); + vo.setGradeName(k12?getGradeNameMap.get(schClass.getGradeId()):( schClass.getEnrollYear() != null ? schClass.getEnrollYear() + "级" : null)); + vo.setYearDate(buildYearDate(y, yearTermMap.get(y))); + vo.setCount(studentList.size()); + vo.setSchName(schName); + vo.setGraduate(graduated); + vo.setStudent(studentList); + result.add(vo); + } + return result; + } + + + /** + * 获取班级历史任教信息 + * 年份区间 yearList 倒序: + * - 未毕业:year, year-1, ..., enrollYear(含当前学年,当前学年用实时表 sch_class+sch_class_teach,其余用历史表) + * - 已毕业:year ... enrollYear(全部用历史表 sch_class_history+sch_class_teach_history) + * 历史表查询固定取第二学期(term=2)。 + * 班主任(SUBBZR)/副班主任(SUBFBZR) 作为特殊任教条目并入 teache 列表。 + */ + public List getHistoryClassTeach(Integer schId, Integer classId) + { + // 1. 当前学年(依据学年开始日期-结束日期匹配) + YearTerm yearTerm = baseYearTermService.getCurrentYearTerm(); + int currentYear = yearTerm.getYear(); + + // 2. 当前班级 & 是否毕业(缓存) + SchClass schClass = schClassService.getSchAllClassCacheFilter(schId, (Integer)null, classId) + .stream().findFirst().orElseThrow(() -> new DException("班级未找到!")); + Integer enrollYear = schClass.getEnrollYear() != null ? schClass.getEnrollYear() : currentYear; + boolean graduated = Boolean.TRUE.equals(schClass.getGraduate()); + + boolean k12=Objects.equals( schBinSchsystemService.getSchType(schId),SchType.BASICEDUCATION.getKey()); + + // 班级所在学校名称 + String schName = comSchTreeService.getSchoolName(schId); + + + // 3. 一次性名称映射,避免循环查库 + Map teacherNameMap = Optional + .ofNullable(schTeacherService.toIdAndNameMap(schId)).orElse(Collections.emptyMap()); + Integer schsystemId = baseSchsystemGradeService.getSchsystemIdByGradeId(schId, schClass.getGradeId()); + Map subjectNameMap = Optional + .ofNullable(schDicSubjectService.toIdAndNameMap(schId, schsystemId)).orElse(Collections.emptyMap()); + Map gradeNameMap = Optional + .ofNullable(baseSchsystemGradeService.getGradeNameMap(schId, schsystemId, null)).orElse(Collections.emptyMap()); + + // 学年学期 Map:year -> BaseYearTerm(含开始/结束日期),用于 yearDate + Map yearTermMap = baseYearTermService.getAllYearTerm().stream() + .filter(t -> t.getYear() != null) + .collect(Collectors.toMap(BaseYearTerm::getYear, t -> t, (a, b) -> a)); + + // 4. 年份区间(倒序):未毕业含当前学年(实时表),已毕业全部历史表 + List yearList = new ArrayList<>(); + for (int y = currentYear; y >= enrollYear; y--) yearList.add(y); + + // 5. 逐学年组装 + List result = new ArrayList<>(); + for (Integer y : yearList) { + boolean isLive = (y == currentYear) && !graduated; + + Integer gradeId; + Integer firstTeacherId; + Integer secondTeacherId; + + // 班主任/副班主任 + 学科任教(按 sub_id 合并) + Map subMap = new LinkedHashMap<>(); + if (isLive) { + gradeId = schClass.getGradeId(); + firstTeacherId = schClass.getFirstTeacherId(); + secondTeacherId = schClass.getSecondTeacherId(); + for (SchClassTeach t : schClassTeachRepository.findBySchIdAndClassId(schId, classId)) { + if (t.getSubId() == null) continue; + subMap.put(t.getSubId(), buildSubjectVO(t.getSubId(), t.getTeaId(), subjectNameMap, teacherNameMap)); + } + } else { + // 历史表:固定取第二学期(term=2) + SchClassHistory histClass = schClassHistoryRepository + .findBySchIdAndClassIdAndYearAndTerm(schId, classId, y, SECOND_TERM).stream().findFirst().orElse(null); + if (histClass != null) { + gradeId = histClass.getGradeId(); + firstTeacherId = histClass.getFirstTeacherId(); + secondTeacherId = histClass.getSecondTeacherId(); + } else { + gradeId = schClass.getGradeId(); + firstTeacherId = null; + secondTeacherId = null; + } + schClassTeachHistoryRepository + .findBySchIdAndClassIdAndYearAndTerm(schId, classId, y, SECOND_TERM).stream() + .filter(t -> t.getSubId() != null) + .forEach(t -> subMap.put(t.getSubId(), + buildSubjectVO(t.getSubId(), t.getTeaId(), subjectNameMap, teacherNameMap))); + } + + // 组装 teache:班主任 -> 副班主任 -> 学科任教 + List teache = new ArrayList<>(); + teache.add(buildBzrVO(SUB_BZR, NAME_BZR, firstTeacherId, teacherNameMap)); + teache.add(buildBzrVO(SUB_FBZR, NAME_FBZR, secondTeacherId, teacherNameMap)); + teache.addAll(subMap.values()); + + HistoryClassTeachVO vo = new HistoryClassTeachVO(); + vo.setGradeId(gradeId); + // 年级显示按 schType 区分:K12(基础教育)用年级名(逐年变化),职业教育用入学年份级(固定) + vo.setGradeName(k12 ? gradeNameMap.get(gradeId) + : (schClass.getEnrollYear() != null ? schClass.getEnrollYear() + "级" : null)); + vo.setYearDate(buildYearDate(y, yearTermMap.get(y))); + // 冗余字段 + vo.setHeadTeacherName(firstTeacherId != null ? teacherNameMap.get(firstTeacherId) : null); + vo.setDeputyHeadTeacherName(secondTeacherId != null ? teacherNameMap.get(secondTeacherId) : null); + vo.setSchName(schName); + vo.setGraduate(graduated); + + vo.setTeach(teache); + result.add(vo); + } + return result; + } + + /** + * 通过学生 stuId 获取其历史班级任教信息。 + * 先由 stuId 解析学生所属班级(classId): + * - 优先取实时表 sch_student(且属于当前学校 schId)的 classId; + * - 否则取历史表 sch_student_history,按学年最大的一条作为最近班级。 + * 再复用 getHistoryClassTeach(schId, classId) 返回逐年任教历史。 + */ + public Map getHistoryClassTeachByStuId(Integer schId, Integer stuId) { + // 1. 解析学生所属班级 & 姓名 + Integer classId = null; + String studentName = null; + Optional live = schStudentRepository.findByStuId(stuId); + if (live.isPresent() && live.get().getClassId() != null + && Objects.equals(live.get().getSchId(), schId)) { + classId = live.get().getClassId(); + studentName = live.get().getName(); + } else { + List hist = schStudentHistoryRepository.findBySchIdAndStuId(schId, stuId); + if (hist.isEmpty()) { + throw new DException("学生未找到!"); + } + SchStudentHistory latest = hist.stream() + .max(Comparator.comparingInt(SchStudentHistory::getYear)) + .orElse(null); + classId = latest != null ? latest.getClassId() : null; + studentName = latest != null ? latest.getName() : null; + } + if (classId == null) { + throw new DException("学生未找到!"); + } + + // 2. 班级名称 + SchClass schClass = schClassService.getSchAllClassCacheFilter(schId, (Integer) null, classId) + .stream().findFirst().orElseThrow(() -> new DException("班级未找到!")); + String className = schClass.getName(); + + // 3. 复用班级历史任教逻辑(年级按 schType 显示:基础教育显示年级名,职业教育显示入学年份级) + List classTeachs = getHistoryClassTeach(schId, classId); + + // 4. 用 Map 包裹返回:stuName / className / classTeachs + Map result = new LinkedHashMap<>(); + result.put("stuName", studentName); + result.put("className", className); + result.put("classTeachs", classTeachs); + return result; + } + + /** 构建一个学科任教条目 VO */ + private SchTeachMapIdVO buildSubjectVO(String subId, Integer teaId, + Map subjectNameMap, + Map teacherNameMap) { + SchTeachMapIdVO vo = new SchTeachMapIdVO(); + vo.setSubId(subId); + vo.setSubName(subjectNameMap.get(subId)); + vo.setTeacherId(teaId); + vo.setTeacherName(teaId != null ? teacherNameMap.get(teaId) : null); + return vo; + } + + /** 构建班主任/副班主任条目 VO */ + private SchTeachMapIdVO buildBzrVO(String subId, String subName, Integer teacherId, + Map teacherNameMap) { + SchTeachMapIdVO vo = new SchTeachMapIdVO(); + vo.setSubId(subId); + vo.setSubName(subName); + vo.setTeacherId(teacherId); + vo.setTeacherName(teacherId != null ? teacherNameMap.get(teacherId) : null); + return vo; + } + + /** + * 根据 base 学年学期 构建 yearDate:取该学年的 开始日期 ~ 结束日期; + * 若该年无学期配置或日期缺失,则回退为 year-(year+1)。 + */ + private String buildYearDate(Integer year, BaseYearTerm term) { + if (term == null || term.getYearStartDate() == null || term.getYearEndDate() == null) { + return year + "-" + (year + 1); + } + String start = term.getYearStartDate().toInstant() + .atZone(ZoneId.systemDefault()).toLocalDate().format(DATE_FMT); + String end = term.getYearEndDate().toInstant() + .atZone(ZoneId.systemDefault()).toLocalDate().format(DATE_FMT); + return start + " ~ " + end; + } + }