From 290af59e9bb6d53b68ee29fd9c1ffcb463ace895 Mon Sep 17 00:00:00 2001 From: wanghu Date: Thu, 27 Aug 2026 18:50:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E7=8F=AD=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/com/ComSchTreeService.java | 58 +++++++++++++++---- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/com/ComSchTreeService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/com/ComSchTreeService.java index 303175c..b87d320 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/com/ComSchTreeService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/com/ComSchTreeService.java @@ -1089,9 +1089,11 @@ public class ComSchTreeService implements IComSchTreeService { } } - // 8. 生成所有年份节点 + // 8. 生成所有年份节点(上界取 max(当前学年, 最大入学年份),避免预建的未来届班级不出现在任何节点) List gradeNodes = new ArrayList<>(); - for (int year = currentYear ; year >=minYear ; year--) { + int maxYear = classByYear.keySet().stream().mapToInt(Integer::intValue).max().orElse(currentYear); + maxYear = Math.max(currentYear, maxYear); + for (int year = maxYear; year >= minYear; year--) { List classList = classByYear.getOrDefault(year, Collections.emptyList()); String gradeName = yearToGradeName.getOrDefault(year, year + "级"); SchSystemTreeVO gradeNode = buildGradeNodeWithFullNameByYear( @@ -1110,7 +1112,8 @@ public class ComSchTreeService implements IComSchTreeService { List classList) { SchSystemTreeVO gradeNode = new SchSystemTreeVO(); gradeNode.setId(enrollYear); - gradeNode.setGradeId(enrollYear); + // 年份节点表示"届"(入学年份),其所属年级取该届班级的真实年级ID(全班一致时有效),不再用年份冒充年级ID + gradeNode.setGradeId(deriveCohortGradeId(classList)); gradeNode.setEnrollYear(enrollYear); // 计算毕业状态 @@ -1126,7 +1129,11 @@ public class ComSchTreeService implements IComSchTreeService { if (graduation == 1) { displayName += "(已毕业)"; } else { - displayName += "(" + gradeName + ")"; + // 未推导出年级名(如未来届超出当前学年映射范围)时不再追加重复的"XX级"后缀 + boolean nameValid = StringUtils.isNotBlank(gradeName) && !gradeName.equals(enrollYear + "级"); + if (nameValid) { + displayName += "(" + gradeName + ")"; + } } gradeNode.setName(displayName); gradeNode.setGraduation(graduation); @@ -1136,8 +1143,13 @@ public class ComSchTreeService implements IComSchTreeService { gradeNode.setExpand(true); if (!CollectionUtils.isEmpty(classList)) { - gradeNode.setChildren(classList.stream() - .map(clazz -> buildClassNode(clazz, enrollYear, systemId, enrollYear)) + // 班级节点排序:按班级序号 sort 升序(班号顺序),与正常树一致;不依赖缓存列表(gradeId, sort)顺序 + List sortedClasses = classList.stream() + .sorted(Comparator.comparing(SchClass::getSort, Comparator.nullsLast(Integer::compareTo))) + .collect(Collectors.toList()); + // 班级节点 gradeId 传真实年级ID(clazz.getGradeId()),供前端按年级查学生/做操作 + gradeNode.setChildren(sortedClasses.stream() + .map(clazz -> buildClassNode(clazz, clazz.getGradeId(), systemId, enrollYear)) .collect(Collectors.toList())); } else { gradeNode.setChildren(Collections.emptyList()); @@ -1145,6 +1157,22 @@ public class ComSchTreeService implements IComSchTreeService { return gradeNode; } + /** + * 推导"届"节点(入学年份节点)的所属年级ID: + * 取其下全部班级的真实年级ID,仅当所有班级一致时返回该值,否则返回 null(避免用年份冒充年级ID) + */ + private Integer deriveCohortGradeId(List classList) { + if (CollectionUtils.isEmpty(classList)) { + return null; + } + List distinctGradeIds = classList.stream() + .map(SchClass::getGradeId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + return distinctGradeIds.size() == 1 ? distinctGradeIds.get(0) : null; + } + private SchSystemTreeVO buildVocationalTree(Integer schId) { // 1. 构建学校根节点 SchSystemTreeVO root = buildSchoolRoot(schId); @@ -1183,10 +1211,12 @@ public class ComSchTreeService implements IComSchTreeService { return root; } - // 5. 生成年级节点(从 currentYear 倒序到 minYear) + // 5. 生成年级节点(从最大年份倒序到 minYear;上界取 max(当前学年, 最大入学年份),避免预建的未来届班级丢失) List gradeNodes = new ArrayList<>(); + int maxYear = classByYear.keySet().stream().mapToInt(Integer::intValue).max().orElse(currentYear); + maxYear = Math.max(currentYear, maxYear); // 职业教育学制通常为3年,但这里根据班级实际年份生成,毕业状态可按需计算 - for (int year = currentYear; year >= minYear; year--) { + for (int year = maxYear; year >= minYear; year--) { List classList = classByYear.getOrDefault(year, Collections.emptyList()); // 计算毕业状态(按学校高职学制长度,与 getHigherSchGradeClassTree 保持一致) @@ -1197,7 +1227,8 @@ public class ComSchTreeService implements IComSchTreeService { // 构建年级节点 SchSystemTreeVO gradeNode = new SchSystemTreeVO(); gradeNode.setId(year); - gradeNode.setGradeId(year); + // 职业教育的年级模型即以入学年份作为年级ID,此处取班级真实 gradeId(与 enrollYear 一致),不再硬编码年份 + gradeNode.setGradeId(deriveCohortGradeId(classList)); gradeNode.setEnrollYear(year); gradeNode.setName(year + "级"); gradeNode.setGraduation(graduation); @@ -1207,9 +1238,12 @@ public class ComSchTreeService implements IComSchTreeService { // 构建班级子节点(schsystemId 传 null,班级节点不依赖学制) if (!CollectionUtils.isEmpty(classList)) { - Integer gradeYear=year; - List classNodes = classList.stream() - .map(clazz -> buildClassNode(clazz, gradeYear, null, gradeYear)) + // 班级节点排序:按班级序号 sort 升序(班号顺序) + List sortedClasses = classList.stream() + .sorted(Comparator.comparing(SchClass::getSort, Comparator.nullsLast(Integer::compareTo))) + .collect(Collectors.toList()); + List classNodes = sortedClasses.stream() + .map(clazz -> buildClassNode(clazz, clazz.getGradeId(), null, year)) .collect(Collectors.toList()); gradeNode.setChildren(classNodes); } else {