状态修改

This commit is contained in:
2026-08-18 09:46:53 +08:00
parent 96dd81860e
commit 1b3a457dba
12 changed files with 125 additions and 112 deletions
@@ -25,9 +25,18 @@ public interface SchStudentRepository extends JpaRepository<SchStudent, Integer>
Optional<SchStudent> 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<SchStudent> 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<SchStudent> findBySchIdAndClassIdAndTransferStatus(@Param("schId") Integer schId,
@Param("classId") Integer classId,
@Param("transferStatus") Integer transferStatus);
List<SchStudent> findAllByIdInAndSchId(List<Integer> ids, Integer schId);
@@ -45,7 +54,7 @@ public interface SchStudentRepository extends JpaRepository<SchStudent, Integer>
@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<Integer> ids,
@Param("schId") Integer schId, // 目标学校ID
@Param("newClassId") Integer newClassId,
@@ -104,11 +113,11 @@ public interface SchStudentRepository extends JpaRepository<SchStudent, Integer>
/**
* 获取所有转出学生的学校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<Integer> findDistinctSchIdsByTransferOut();
}
@@ -35,10 +35,16 @@ public interface SchTeacherGroupRepository extends JpaRepository<SchTeacherGroup
/**
* 根据 teaId 列表、学校 ID 和转入状态查询组关联
* 适用场景:只查询转入状态的记录(transferStatus = 1)
* 适用场景:只查询转入状态的记录(transferStatus = 0)
*/
List<SchTeacherGroup> findByTeaIdInAndSchIdAndTransferStatus(List<Integer> teaIds, Integer schId, Integer transferStatus);
/**
* 根据学校 ID 和转入状态查询教师分组实体
* 适用场景:同步回收时定位某校当前“转入/转出”的教师分组,用于把用户中心已移除的教师标记为转出
*/
List<SchTeacherGroup> findBySchIdAndTransferStatus(Integer schId, Integer transferStatus);
/**
* 根据学校 ID 查询该学校所有教师的 teaId(去重)
* 适用场景:获取该校所有教师列表
@@ -26,13 +26,13 @@ public interface SchTeacherRepository extends JpaRepository<SchTeacher, Integer>
@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<SchTeacher, Integer>
@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<SchTeacher, Integer>
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, '%'))",
@@ -38,6 +38,7 @@ public class SyncGroupController {
@PostMapping("DeleteGroup")
public void DeleteGroup(@RequestBody String jsonString) {
log.info("DeleteGroup jsonString="+jsonString);
}
@PostMapping("SyncGroup")
@@ -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<Question> list()
{
return new ArrayList<>(EnumSet.allOf(Question.class));
}
public static Map<Integer, Question> 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;
}
}
@@ -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,"其他");
@@ -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;
@@ -16,6 +16,7 @@ public enum UserRole {
BUSINESS(6,"工作号"),
GENERAL_USER(8,"普通用户");
private Integer value;
private String name;
@@ -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;
@@ -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;
}
@@ -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<Integer> Ids)
{
}
@@ -177,6 +177,8 @@ public class SyncUserService implements ISyncUserService {
List<SchStudent> saveList = new ArrayList<>();
// 受影响班级缓存键 (schId -> classId 集合),用于同步后失效
Map<Integer, Set<Integer>> classKeys = new HashMap<>();
// 本次同步下发的学生分组键(stuId_classId),用于回收对账
Set<String> 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<Integer> 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<Integer> schIds, Map<Integer, Set<Integer>> classKeys, Set<String> incomingStudentKeys) {
for (Integer schId : schIds) {
Set<Integer> classIds = classKeys.get(schId);
if (classIds == null) continue;
for (Integer classId : classIds) {
if (classId == null) continue;
List<SchStudent> currentIn = schStudentRepository.findBySchIdAndClassIdAndTransferStatus(schId, classId, TransferStatus.IN.getId());
List<SchStudent> 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<SyncUserDTO> teacherUsers, Date now) {
List<Integer> teaIds = teacherUsers.stream().map(SyncUserDTO::getId).distinct().collect(Collectors.toList());
// 教师主体(唯一)
@@ -257,6 +296,8 @@ public class SyncUserService implements ISyncUserService {
List<SchTeacherGroup> saveGroupList = new ArrayList<>();
// 受影响学校缓存键,用于同步后失效
Set<Integer> schIds = new HashSet<>();
// 本次同步下发的教师分组键(teaId_groupId_schId),用于回收对账
Set<String> 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<Integer> schIds,Set<String> incomingGroupKeys)
{
for (Integer schId : schIds) {
List<SchTeacherGroup> currentInGroups = schTeacherGroupRepository.findBySchIdAndTransferStatus(schId, TransferStatus.IN.getId());
List<SchTeacherGroup> 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());