diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java index 4e8b5b3..a7a118e 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java @@ -15,7 +15,11 @@ import java.util.Optional; @Repository public interface SchStudentRepository extends JpaRepository, JpaSpecificationExecutor { - Optional findByStuId(Integer stuId); + /** + * stu_id 是用户中心用户ID(非本表主键),学生在多所学校各有一条就学记录, + * 同一 stu_id 可能存在多行,必须返回 List;返回 Optional 会在多行时抛 NonUniqueResultException + */ + List findByStuId(Integer stuId); List findByStuIdIn(List stuIds); diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java index c69c4e2..7a856b4 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java @@ -20,7 +20,11 @@ public interface SchTeacherRepository extends JpaRepository List findByTeaIdIn(List teaIds); - Optional findByTeaId(Integer teaId); + /** + * tea_id 是用户中心用户ID(非本表主键),教师在多所学校各有一条记录, + * 同一 tea_id 可能存在多行,必须返回 List;返回 Optional 会在多行时抛 NonUniqueResultException + */ + List findByTeaId(Integer teaId); @Query(value = "SELECT DISTINCT t.* FROM sch_teacher t " + diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/TeainfoController.java b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/TeainfoController.java index 8f20419..38959eb 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/TeainfoController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/TeainfoController.java @@ -56,7 +56,8 @@ public class TeainfoController { } // 2. 鐩存帴浣跨敤 uid 鏌ヨ - return schTeacherRepository.findByTeaId(uid) // 鍋囪 findByTeaId 杩斿洖 Optional + return schTeacherRepository.findByTeaId(uid).stream() + .findFirst() .map(teacher -> { fillGroupList(Collections.singletonList(teacher), null); return teacher; diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/UserInfoController.java b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/UserInfoController.java index 31c97e5..81767b1 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/UserInfoController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/oa/UserInfoController.java @@ -160,7 +160,8 @@ public class UserInfoController { return ResponseEntity.ok(new ArrayList<>()); } - Optional teacherOpt = schTeacherRepository.findByTeaId(userid); + // 同一 teaId/stuId 可能在多所学校各有记录,取第一条即可(不能按唯一查询) + Optional teacherOpt = schTeacherRepository.findByTeaId(userid).stream().findFirst(); if (teacherOpt.isPresent()) { UserInfoVO vo = convertToUserInfoVO(teacherOpt.get()); if (vo != null) { @@ -168,7 +169,7 @@ public class UserInfoController { } } - Optional studentOpt = schStudentRepository.findByStuId(userid); + Optional studentOpt = schStudentRepository.findByStuId(userid).stream().findFirst(); if (studentOpt.isPresent()) { UserInfoVO vo = convertToUserInfoVO(studentOpt.get()); if (vo != null) { diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchGroupController.java b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchGroupController.java index 41073ea..88cc406 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchGroupController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchGroupController.java @@ -12,6 +12,9 @@ import com.yunhai.bschclassmanage.entity.SchTeacherCustomGroupInSubject; import com.yunhai.bschclassmanage.entity.SchTeacherCustomGroupInTeacher; import com.yunhai.bschclassmanage.enums.CustomGroupType; import com.yunhai.bschclassmanage.model.oa.TeaTreeVO; +import com.yunhai.bschclassmanage.model.vo.SelectIntVO; +import com.yunhai.bschclassmanage.model.vo.SelectStrVO; +import com.yunhai.bschclassmanage.model.vo.sch.OapiGroupVO; import com.yunhai.bschclassmanage.model.vo.sch.TeaCustomGroupTreeVO; import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService; import com.yunhai.bschclassmanage.service.IComSchTreeService; @@ -74,7 +77,7 @@ public class OapiSchGroupController { description = "不传 groupType 时返回三层:类型根节点(id=-1年级组/-2教研组/-3备课组)→ 组节点 → 教师叶子;" + "传 groupType(1年级组 2教研组 3备课组,教研组即教师学科组)时直接返回该类型组节点列表(两层)。" + "组节点携带组长、关联年级、关联学科;教师叶子携带 isLeader") - public ResponseEntity> getTeaCustomGroupTree(@RequestParam(value = "schId", required = false) Integer schId, + public ResponseEntity> getTeaCustomGroupTree(@RequestParam(value = "schId") Integer schId, @RequestParam(value = "groupType", required = false) Integer groupType) { if (schId == null) { return ResponseEntity.ok(Collections.emptyList()); @@ -91,6 +94,98 @@ public class OapiSchGroupController { return ResponseEntity.ok(buildTree(schId, groups, groupType != null)); } + @GetMapping("getTeaCustomGroupList") + @Operation(summary = "获取教师分组列表(组/组员/组长合一)", + description = "按学校查教师分组列表:组id、组名称、学科集合、年级集合、组员集合、组长集合;" + + "groupType 可选(1年级组 2教研组 3备课组,不传返回全部类型)。" + + "组长取关系表 group_type=1 的全部教师(取不到时兜底组记录 leader_id 字段),组员取 group_type=2 且排除组长") + public ResponseEntity> getTeaCustomGroupList(@RequestParam(value = "schId") Integer schId, + @RequestParam(value = "groupType", required = false) Integer groupType) { + if (schId == null) { + return ResponseEntity.ok(Collections.emptyList()); + } + List groups = (groupType != null) + ? customGroupRepository.findBySchIdAndGroupType(schId, groupType) + : customGroupRepository.findBySchId(schId); + if (groups == null || groups.isEmpty()) { + return ResponseEntity.ok(Collections.emptyList()); + } + groups = groups.stream() + .sorted(Comparator.comparing(SchTeacherCustomGroup::getSort, Comparator.nullsLast(Integer::compareTo))) + .collect(Collectors.toList()); + + List groupIds = groups.stream().map(SchTeacherCustomGroup::getId).collect(Collectors.toList()); + Map> groupIdToGrades = groupInGradeRepository.findByCgGroupIdIn(groupIds).stream() + .collect(Collectors.groupingBy(SchTeacherCustomGroupInGrade::getCgGroupId)); + Map> groupIdToSubjects = groupInSubjectRepository.findByCgGroupIdIn(groupIds).stream() + .collect(Collectors.groupingBy(SchTeacherCustomGroupInSubject::getCgGroupId)); + // relationType:1组长 2组员 + Map> groupIdToTeachers = groupInTeacherRepository.findByCgGroupIdIn(groupIds).stream() + .filter(r -> r.getTeaId() != null) + .collect(Collectors.groupingBy(SchTeacherCustomGroupInTeacher::getCgGroupId)); + + Map teacherMap = schTeacherService.getSchTeacherCacheList(schId).stream() + .filter(t -> t.getTeaId() != null) + .collect(Collectors.toMap(SchTeacher::getTeaId, t -> t, (a, b) -> a)); + Map gradeNameMap = baseSchsystemGradeService.getGradeNameMap(schId, null, null); + Map subjectNameMap = schDicSubjectService.toIdAndNameMap(schId, null); + + List result = new ArrayList<>(groups.size()); + for (SchTeacherCustomGroup group : groups) { + List relations = groupIdToTeachers.getOrDefault(group.getId(), Collections.emptyList()); + List leaderIds = resolveLeaders(group, relations); + + OapiGroupVO vo = new OapiGroupVO(); + vo.setGroupId(group.getId()); + vo.setGroupName(group.getGroupName()); + vo.setGroupType(group.getGroupType()); + vo.setGroupTypeName(group.getGroupType() == null ? null : CustomGroupType.nameById(group.getGroupType())); + vo.setSubjects(groupIdToSubjects.getOrDefault(group.getId(), Collections.emptyList()).stream() + .map(SchTeacherCustomGroupInSubject::getSubId) + .filter(Objects::nonNull) + .distinct() + .map(subId -> new SelectStrVO(subId, subjectNameMap.get(subId))) + .collect(Collectors.toList())); + vo.setGrades(groupIdToGrades.getOrDefault(group.getId(), Collections.emptyList()).stream() + .map(SchTeacherCustomGroupInGrade::getGradeId) + .filter(Objects::nonNull) + .distinct() + .map(gradeId -> new SelectIntVO(gradeId, gradeNameMap.get(gradeId))) + .collect(Collectors.toList())); + vo.setLeaders(toIdNameList(leaderIds, teacherMap)); + vo.setMembers(toIdNameList(relations.stream() + .filter(r -> Integer.valueOf(2).equals(r.getGroupType())) + .map(SchTeacherCustomGroupInTeacher::getTeaId) + .filter(id -> !leaderIds.contains(id)) + .distinct() + .collect(Collectors.toList()), teacherMap)); + result.add(vo); + } + return ResponseEntity.ok(result); + } + + /** 组长ID集合:关系表 group_type=1 的全部教师,取不到时兜底组记录 leader_id 字段(与 getSchCustomGroup 语义一致) */ + private List resolveLeaders(SchTeacherCustomGroup group, List relations) { + List leaderIds = relations.stream() + .filter(r -> Integer.valueOf(1).equals(r.getGroupType())) + .map(SchTeacherCustomGroupInTeacher::getTeaId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + if (leaderIds.isEmpty() && group.getLeaderId() != null) { + leaderIds = Collections.singletonList(group.getLeaderId()); + } + return leaderIds; + } + + /** 教师ID集合 → [{id,姓名}],按入参顺序;姓名取不到时与 getSchCustomGroup 一致回退"未知教师" */ + private List toIdNameList(List teaIds, Map teacherMap) { + return teaIds.stream() + .map(teaId -> new SelectIntVO(teaId, + Optional.ofNullable(teacherMap.get(teaId)).map(SchTeacher::getName).orElse("未知教师"))) + .collect(Collectors.toList()); + } + /** 组装类型节点→组节点→教师叶子树(flatTypeRoot=true 时不建类型根,组节点直接作为顶层) */ private List buildTree(Integer schId, List groups, boolean flatTypeRoot) { List groupIds = groups.stream().map(SchTeacherCustomGroup::getId).collect(Collectors.toList()); diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchStudentController.java b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchStudentController.java index ec1e196..25c6926 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchStudentController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sch/OapiSchStudentController.java @@ -44,7 +44,9 @@ public class OapiSchStudentController { if (stuId == null) { return ResponseEntity.ok(null); } - return ResponseEntity.ok(schStudentRepository.findByStuId(stuId) + // 同一 stu_id 可能在多所学校各有记录,取第一条即可(不能按唯一查询) + return ResponseEntity.ok(schStudentRepository.findByStuId(stuId).stream() + .findFirst() .map(stu -> toVOList(stu.getSchId(), Collections.singletonList(stu)).get(0)) .orElse(null)); } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/SchDicSubjectService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/SchDicSubjectService.java index ba02a01..db6ce07 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/SchDicSubjectService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/SchDicSubjectService.java @@ -329,7 +329,7 @@ public class SchDicSubjectService implements ISchDicSubjectService { public List select(Integer schId, Integer schsystemId) { List list = getSchDicSubjectCacheList(schId, schsystemId); // 按 code 去重,保留顺序(若需要保持原顺序,可用 LinkedHashSet 包装) - list = list.stream() + list = list.stream().filter(s -> Boolean.TRUE.equals(s.getEnable())) .collect(Collectors.collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SchDicSubject::getCode))), ArrayList::new 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 a1182a7..45b15a0 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/StudentClassHistoryService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/StudentClassHistoryService.java @@ -300,13 +300,15 @@ public class StudentClassHistoryService implements IStudentClassHistoryService { */ public Map getHistoryClassTeachByStuId(Integer schId, Integer stuId) { // 1. 解析学生所属班级 & 姓名 + // stu_id 是用户中心用户ID,学生在多所学校各有就学记录(同一 stu_id 多行),需按当前学校过滤后取一条 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(); + SchStudent liveMatch = schStudentRepository.findByStuId(stuId).stream() + .filter(s -> s.getClassId() != null && Objects.equals(s.getSchId(), schId)) + .findFirst().orElse(null); + if (liveMatch != null) { + classId = liveMatch.getClassId(); + studentName = liveMatch.getName(); } else { List hist = schStudentHistoryRepository.findBySchIdAndStuId(schId, stuId); if (hist.isEmpty()) { diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/teacher/SchTeacherRelationService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/teacher/SchTeacherRelationService.java index 05894f0..776d1be 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/teacher/SchTeacherRelationService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/teacher/SchTeacherRelationService.java @@ -191,7 +191,7 @@ public class SchTeacherRelationService { } // 异步记录操作日志 - schTeacherRepository.findByTeaId(teaId).ifPresent(teacher -> + schTeacherRepository.findByTeaId(teaId).stream().findFirst().ifPresent(teacher -> logService.setTransferInLogs(user, Collections.singletonList(teacher), targetGroupId)); // 清除所有涉及学校的缓存