diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java index 19aee54..3143981 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchStudentRepository.java @@ -25,9 +25,18 @@ public interface SchStudentRepository extends JpaRepository Optional findByIdAndSchId(Integer Id, Integer schId); - @Query("SELECT s FROM SchStudent s WHERE s.schId = :schId AND s.classId = :classId AND s.abnormalStatus = 1 AND s.transferStatus=1 AND s.status = 1") + @Query("SELECT s FROM SchStudent s WHERE s.schId = :schId AND s.classId = :classId AND s.abnormalStatus = 0 AND s.transferStatus= 0 AND s.status = 0") List findBySchIdAndClassId(@Param("schId") Integer schId, @Param("classId") Integer classId); + /** + * 根据学校、班级和转入状态查询学生实体 + * 适用场景:同步回收时定位某班当前“转入/转出”的学生,用于把用户中心已移除的学生标记为转出 + */ + @Query("SELECT s FROM SchStudent s WHERE s.schId = :schId AND s.classId = :classId AND s.transferStatus = :transferStatus") + List findBySchIdAndClassIdAndTransferStatus(@Param("schId") Integer schId, + @Param("classId") Integer classId, + @Param("transferStatus") Integer transferStatus); + List findAllByIdInAndSchId(List ids, Integer schId); @@ -45,7 +54,7 @@ public interface SchStudentRepository extends JpaRepository @Param("updateUserId") Integer updateUserId); @Modifying - @Query("UPDATE SchStudent s SET s.schId = :schId, s.classId = :newClassId,s.groupId = :newClassId, s.updateDate = :updateDate, s.updateUserId = :updateUserId , s.transferStatus =1 WHERE s.id IN :ids") + @Query("UPDATE SchStudent s SET s.schId = :schId, s.classId = :newClassId,s.groupId = :newClassId, s.updateDate = :updateDate, s.updateUserId = :updateUserId , s.transferStatus = 0 WHERE s.id IN :ids") int batchUpdateSchIdAndClassId(@Param("ids") List ids, @Param("schId") Integer schId, // 目标学校ID @Param("newClassId") Integer newClassId, @@ -104,11 +113,11 @@ public interface SchStudentRepository extends JpaRepository /** * 获取所有转出学生的学校ID(去重) - * 转出条件:transfer_status = 0 + * 转出条件:transfer_status = 1 * 关联:s.class_id = c.group_class_id */ @Query(value = "SELECT DISTINCT c.sch_id FROM sch_student s " + "INNER JOIN sch_class c ON s.class_id = c.group_class_id " + - "WHERE s.transfer_status = 0 AND s.sch_id = c.sch_id AND s.status=1 ", nativeQuery = true) + "WHERE s.transfer_status = 0 AND s.sch_id = c.sch_id AND s.status= 0 ", nativeQuery = true) List findDistinctSchIdsByTransferOut(); } diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherGroupRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherGroupRepository.java index 63b7cfb..2864189 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherGroupRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherGroupRepository.java @@ -35,10 +35,16 @@ public interface SchTeacherGroupRepository extends JpaRepository findByTeaIdInAndSchIdAndTransferStatus(List teaIds, Integer schId, Integer transferStatus); + /** + * 根据学校 ID 和转入状态查询教师分组实体 + * 适用场景:同步回收时定位某校当前“转入/转出”的教师分组,用于把用户中心已移除的教师标记为转出 + */ + List findBySchIdAndTransferStatus(Integer schId, Integer transferStatus); + /** * 根据学校 ID 查询该学校所有教师的 teaId(去重) * 适用场景:获取该校所有教师列表 diff --git a/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java b/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java index 4632a14..c69c4e2 100644 --- a/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java +++ b/src/main/java/com/yunhai/bschclassmanage/Repository/SchTeacherRepository.java @@ -26,13 +26,13 @@ public interface SchTeacherRepository extends JpaRepository @Query(value = "SELECT DISTINCT t.* FROM sch_teacher t " + "INNER JOIN sch_teacher_group g ON t.tea_id = g.tea_id " + "WHERE g.sch_id = :schId " + - "AND g.transfer_status = 1 " + // 只查转入状态的教师 + "AND g.transfer_status = 0 " + // 只查转入状态的教师 "AND (:groupId IS NULL OR g.group_id = :groupId) " + "AND (:keyword IS NULL OR t.name LIKE CONCAT('%', :keyword, '%') OR t.account LIKE CONCAT('%', :keyword, '%')) " , countQuery = "SELECT COUNT(DISTINCT t.id) FROM sch_teacher t " + "INNER JOIN sch_teacher_group g ON t.tea_id = g.tea_id " + "WHERE g.sch_id = :schId " + - "AND g.transfer_status = 1 " + + "AND g.transfer_status = 0 " + "AND (:groupId IS NULL OR g.group_id = :groupId) " + "AND (:keyword IS NULL OR t.name LIKE CONCAT('%', :keyword, '%') OR t.account LIKE CONCAT('%', :keyword, '%'))", nativeQuery = true) @@ -45,8 +45,8 @@ public interface SchTeacherRepository extends JpaRepository @Query(value = "SELECT DISTINCT g.tea_id AS teaId, g.sch_id AS schId, t.name AS teaName, t.id_card AS idCard " + "FROM sch_teacher_group g " + "INNER JOIN sch_teacher t ON t.tea_id = g.tea_id " + - "WHERE g.transfer_status = 0 " + - "AND t.status = 1 " + + "WHERE g.transfer_status = 1 " + + "AND t.status = 0 " + "AND (:schId IS NULL OR g.sch_id = :schId) " + "AND (:groupId IS NULL OR g.group_id = :groupId) " + "AND (:keyword IS NULL OR t.name LIKE CONCAT('%', :keyword, '%') OR t.account LIKE CONCAT('%', :keyword, '%')) " + @@ -54,8 +54,8 @@ public interface SchTeacherRepository extends JpaRepository countQuery = "SELECT COUNT(DISTINCT CONCAT(g.tea_id, '_', g.sch_id)) " + "FROM sch_teacher_group g " + "INNER JOIN sch_teacher t ON t.tea_id = g.tea_id " + - "WHERE g.transfer_status = 0 " + - "AND t.status = 1 " + + "WHERE g.transfer_status = 1 " + + "AND t.status = 0 " + "AND (:schId IS NULL OR g.sch_id = :schId) " + "AND (:groupId IS NULL OR g.group_id = :groupId) " + "AND (:keyword IS NULL OR t.name LIKE CONCAT('%', :keyword, '%') OR t.account LIKE CONCAT('%', :keyword, '%'))", diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sync/SyncGroupController.java b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sync/SyncGroupController.java index 6fcff54..e0fc9f0 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sync/SyncGroupController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/oapi/sync/SyncGroupController.java @@ -38,6 +38,7 @@ public class SyncGroupController { @PostMapping("DeleteGroup") public void DeleteGroup(@RequestBody String jsonString) { log.info("DeleteGroup jsonString="+jsonString); + } @PostMapping("SyncGroup") diff --git a/src/main/java/com/yunhai/bschclassmanage/enums/Question.java b/src/main/java/com/yunhai/bschclassmanage/enums/Question.java deleted file mode 100644 index 54583f8..0000000 --- a/src/main/java/com/yunhai/bschclassmanage/enums/Question.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.yunhai.bschclassmanage.enums; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public enum Question -{ - I(1, "单选题"), - II(2, "多选题"), - III(3, "判断题"), - IV(4, "解答题"), - V(6, "组合题"), - VI(5, "填空题"), - VII(7, "英语题"); - - private int id; - private String name; - - Question(int id, String name) - { - this.id = id; - this.name = name; - } - - public int getId() - { - return id; - } - - public void setId(int id) - { - this.id = id; - } - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public static List list() - { - return new ArrayList<>(EnumSet.allOf(Question.class)); - } - - public static Map map() - { - return list().stream().collect(Collectors.toMap(Question::getId, QuestionType->QuestionType)); - } - - public static String nameById(int id) { - for (Question type : list()) { - if (type.getId() == id) return type.getName(); - } - return null; - } - public static Integer getIdByName(String name) { - for (Question type : list()) { - if (type.getName().equals(name)) return type.getId(); - } - return null; - } - public static Question getById(int id) - { - for (Question na : list()) - { - if (na.getId() == id) - { - return na; - } - } - - return null; - } -} diff --git a/src/main/java/com/yunhai/bschclassmanage/enums/StuAbnormalStatus.java b/src/main/java/com/yunhai/bschclassmanage/enums/StuAbnormalStatus.java index 64ebc64..3591cbf 100644 --- a/src/main/java/com/yunhai/bschclassmanage/enums/StuAbnormalStatus.java +++ b/src/main/java/com/yunhai/bschclassmanage/enums/StuAbnormalStatus.java @@ -14,15 +14,15 @@ import java.util.stream.Collectors; @NoArgsConstructor public enum StuAbnormalStatus { - NORMAL(1,"正常"), - SUSPEND_SCHOOLING(2,"休学"), - GO_ABROAD(3,"出国"), - STUDY_ABROAD(4,"留学"), - RESUME_SCHOOLING(5,"复学"), - STOP_SCHOOLING(6,"停学"), - VOLUNTARY_RETREAT_SCHOOLING(7,"自愿退学"), - VOLUNTARY_REPEAT_GRADE(8,"自愿留级"), - VOLUNTARY_DROP_GRADE(9,"自愿降级"), + NORMAL(0,"正常"), + SUSPEND_SCHOOLING(1,"休学"), + GO_ABROAD(2,"出国"), + STUDY_ABROAD(3,"留学"), + RESUME_SCHOOLING(4,"复学"), + STOP_SCHOOLING(5,"停学"), + VOLUNTARY_RETREAT_SCHOOLING(6,"自愿退学"), + VOLUNTARY_REPEAT_GRADE(7,"自愿留级"), + VOLUNTARY_DROP_GRADE(8,"自愿降级"), ELSE(99,"其他"); diff --git a/src/main/java/com/yunhai/bschclassmanage/enums/TransferStatus.java b/src/main/java/com/yunhai/bschclassmanage/enums/TransferStatus.java index 02fadfd..045367e 100644 --- a/src/main/java/com/yunhai/bschclassmanage/enums/TransferStatus.java +++ b/src/main/java/com/yunhai/bschclassmanage/enums/TransferStatus.java @@ -16,8 +16,8 @@ import java.util.stream.Collectors; @AllArgsConstructor public enum TransferStatus { - OUT(0,"转出"), - IN(1,"转入"); + IN(0,"转入"), + OUT(1,"转出"); private Integer id; private String name; diff --git a/src/main/java/com/yunhai/bschclassmanage/enums/UserRole.java b/src/main/java/com/yunhai/bschclassmanage/enums/UserRole.java index be9554a..9254ba8 100644 --- a/src/main/java/com/yunhai/bschclassmanage/enums/UserRole.java +++ b/src/main/java/com/yunhai/bschclassmanage/enums/UserRole.java @@ -16,6 +16,7 @@ public enum UserRole { BUSINESS(6,"工作号"), GENERAL_USER(8,"普通用户"); + private Integer value; private String name; diff --git a/src/main/java/com/yunhai/bschclassmanage/enums/UserStatus.java b/src/main/java/com/yunhai/bschclassmanage/enums/UserStatus.java index 8ff7e9b..9778761 100644 --- a/src/main/java/com/yunhai/bschclassmanage/enums/UserStatus.java +++ b/src/main/java/com/yunhai/bschclassmanage/enums/UserStatus.java @@ -16,10 +16,9 @@ import java.util.stream.Collectors; @AllArgsConstructor public enum UserStatus { - //状态 0禁用 1 正常 2休学 3出国 4留学 5复学 6停学 7退学 8留级 9其他 - - DISABLED(0,"禁用"), - NORMAL(1,"正常"); + //状态 0 正常 1禁用 2休学 3出国 4留学 5复学 6停学 7退学 8留级 9其他 + NORMAL(0,"正常"), + DISABLED(1,"禁用"); private Integer id; private String name; diff --git a/src/main/java/com/yunhai/bschclassmanage/interceptor/UserContextInterceptor.java b/src/main/java/com/yunhai/bschclassmanage/interceptor/UserContextInterceptor.java index 43a7638..4b653b9 100644 --- a/src/main/java/com/yunhai/bschclassmanage/interceptor/UserContextInterceptor.java +++ b/src/main/java/com/yunhai/bschclassmanage/interceptor/UserContextInterceptor.java @@ -21,6 +21,8 @@ public class UserContextInterceptor implements HandlerInterceptor { UserContext.setUserId(currentUser.getId()); UserContext.setUserName(currentUser.getName()); UserContext.setType(currentUser.getType()); + UserContext.setSchId(currentUser.getSchool()==null?null:currentUser.getSchool().getId()); + UserContext.setRoleId(currentUser.getRoleIds().get(0)); } return true; } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncGroupService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncGroupService.java index 3b56873..bc73144 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncGroupService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncGroupService.java @@ -10,6 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -22,11 +24,11 @@ public class SyncGroupService implements ISyncGroupService { public void syncAddOrUpdate(SyncGroupDTO group) { - //学校组 年级组 班级组 - if(group.getType().equals(NodeType.SCHOOL.getId())){ + //学校组-年级组-班级组 + if(Objects.equals(group.getType(),NodeType.SCHOOL.getId())){ addOrUpdateSchool(group); } - if(group.getType().equals(NodeType.CLASS.getId())){ + if(Objects.equals(group.getType(),NodeType.CLASS.getId())){ //添加班级组 202406 @@ -57,6 +59,11 @@ public class SyncGroupService implements ISyncGroupService { } } + public void DeleteGroup(List Ids) + { + + } + diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncUserService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncUserService.java index 26bc4f7..731878d 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncUserService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/sync/SyncUserService.java @@ -177,6 +177,8 @@ public class SyncUserService implements ISyncUserService { List saveList = new ArrayList<>(); // 受影响班级缓存键 (schId -> classId 集合),用于同步后失效 Map> classKeys = new HashMap<>(); + // 本次同步下发的学生分组键(stuId_classId),用于回收对账 + Set incomingStudentKeys = new HashSet<>(); for (SyncUserDTO user : studentUsers) { if (user.getGroups() == null) continue; @@ -195,16 +197,52 @@ public class SyncUserService implements ISyncUserService { } saveList.add(student); classKeys.computeIfAbsent(schId, k -> new HashSet<>()).add(groupId); + incomingStudentKeys.add(key); } } if (!saveList.isEmpty()) { schStudentRepository.saveAll(saveList); - // 同步后使受影响班级的学生缓存失效,避免读到旧数据 + } + + // 清理用户中心不存在的学生(与教师相同逻辑:标记转出,可逆向恢复) + Set schIds = classKeys.keySet(); + setTransferStudent(schIds, classKeys, incomingStudentKeys); + + // 同步后使受影响班级的学生缓存失效,避免读到旧数据 + if (!classKeys.isEmpty()) { classKeys.forEach((schId, classIds) -> schStudentCacheService.clearClassStudentCaches(schId, classIds)); } } + /** + * 清理用户中心不存在的学生:学校/班级已存在、但用户中心(incomingStudentKeys)已不存在的学生, + * 标记为转出(OUT),从活跃名单中清理;同时保留转出记录,可随下次同步逆向恢复(重新 IN)。 + * 仅针对本次同步覆盖的学校/班级,避免误删未参与本批次的其他班级学生。 + */ + private void setTransferStudent(Set schIds, Map> classKeys, Set incomingStudentKeys) { + for (Integer schId : schIds) { + Set classIds = classKeys.get(schId); + if (classIds == null) continue; + for (Integer classId : classIds) { + if (classId == null) continue; + List currentIn = schStudentRepository.findBySchIdAndClassIdAndTransferStatus(schId, classId, TransferStatus.IN.getId()); + List toTransferOut = new ArrayList<>(); + for (SchStudent s : currentIn) { + String key = buildStudentKey(s.getStuId(), s.getClassId()); + if (!incomingStudentKeys.contains(key)) { + s.setTransferStatus(TransferStatus.OUT.getId()); + toTransferOut.add(s); + } + } + if (!toTransferOut.isEmpty()) { + schStudentRepository.saveAll(toTransferOut); + log.info("清理用户中心不存在的学生:schId={}, classId={}, 转出学生数={}", schId, classId, toTransferOut.size()); + } + } + } + } + private void updateStudent(SchStudent student, SyncUserDTO user, SyncUserGroupDTO group, Date now) { student.setAccount(user.getAccount()); student.setName(user.getName()); @@ -240,6 +278,7 @@ public class SyncUserService implements ISyncUserService { // ==================== 教师同步 ==================== private void syncTeachers(List teacherUsers, Date now) { + List teaIds = teacherUsers.stream().map(SyncUserDTO::getId).distinct().collect(Collectors.toList()); // 教师主体(唯一) @@ -257,6 +296,8 @@ public class SyncUserService implements ISyncUserService { List saveGroupList = new ArrayList<>(); // 受影响学校缓存键,用于同步后失效 Set schIds = new HashSet<>(); + // 本次同步下发的教师分组键(teaId_groupId_schId),用于回收对账 + Set incomingGroupKeys = new HashSet<>(); for (SyncUserDTO user : teacherUsers) { // 教师主体(只存一条) @@ -285,6 +326,7 @@ public class SyncUserService implements ISyncUserService { } saveGroupList.add(tg); schIds.add(schId); + incomingGroupKeys.add(key); } } @@ -294,12 +336,40 @@ public class SyncUserService implements ISyncUserService { if (!saveGroupList.isEmpty()) { schTeacherGroupRepository.saveAll(saveGroupList); } + + // 清理用户中心不存在的教师: + // 学校已存在、但用户中心(teacherUsers)已不存在的教师,需从活跃名单中清理。 + // 对本次同步涉及的每所学校,将「当前为转入状态、但不在本次下发分组列表」的教师分组标记为转出(OUT)。 + // 这样既把已从用户中心移除/调离的教师清理出活跃名单,又保留转出记录、可随下次同步逆向恢复(重新 IN)。 + // 仅针对本次同步覆盖的学校,避免误删未参与本批次的其他学校教师。 + setTransferTeacher(schIds,incomingGroupKeys); + // 同步后使受影响学校的教师缓存失效 if (!schIds.isEmpty()) { schTeacherCacheService.clearTeacherCaches(schIds); } } + private void setTransferTeacher( Set schIds,Set incomingGroupKeys) + { + for (Integer schId : schIds) { + List currentInGroups = schTeacherGroupRepository.findBySchIdAndTransferStatus(schId, TransferStatus.IN.getId()); + List toTransferOut = new ArrayList<>(); + for (SchTeacherGroup g : currentInGroups) { + String key = buildTeacherGroupKeyWithSchId(g.getTeaId(), g.getGroupId(), g.getSchId()); + if (!incomingGroupKeys.contains(key)) { + g.setTransferStatus(TransferStatus.OUT.getId()); + toTransferOut.add(g); + } + } + if (!toTransferOut.isEmpty()) { + schTeacherGroupRepository.saveAll(toTransferOut); + log.info("清理用户中心不存在的教师:schId={}, 转出教师分组数={}", schId, toTransferOut.size()); + } + } + } + + private void updateTeacher(SchTeacher teacher, SyncUserDTO user, Date now) { teacher.setAccount(user.getAccount()); teacher.setName(user.getName());