From be754dc22c9b9bf0fb44b284c1b4f1c4ecbb8ca6 Mon Sep 17 00:00:00 2001 From: wanghu Date: Thu, 20 Aug 2026 00:38:26 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8F=AD=E7=BA=A7=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/api/SchTreeController.java | 4 +- .../service/IComSchTreeService.java | 17 ++- .../service/ISendUserBaseService.java | 4 +- .../service/impl/SchBinSchsystemService.java | 8 +- .../service/impl/SchTeacherService.java | 2 +- .../impl/classes/SchClassInfoService.java | 58 +++++++-- .../service/impl/com/ComSchTreeService.java | 123 +++++++++++++++--- .../service/impl/com/SendUserBaseService.java | 18 ++- 8 files changed, 196 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/yunhai/bschclassmanage/controller/api/SchTreeController.java b/src/main/java/com/yunhai/bschclassmanage/controller/api/SchTreeController.java index c28a3b9..5dbd8f1 100644 --- a/src/main/java/com/yunhai/bschclassmanage/controller/api/SchTreeController.java +++ b/src/main/java/com/yunhai/bschclassmanage/controller/api/SchTreeController.java @@ -74,9 +74,9 @@ public class SchTreeController { @GetMapping("getTeaTree") - public BoaGroup getTeaTree() + public BoaGroup getTeaTree(@RequestParam(required = false, defaultValue = "true") Boolean withSub) { - return comSchTreeService.getTeaTree(UserContext.getSchId()); + return comSchTreeService.getTeaTree(UserContext.getSchId(), withSub); } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/IComSchTreeService.java b/src/main/java/com/yunhai/bschclassmanage/service/IComSchTreeService.java index 4faa876..43ff91c 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/IComSchTreeService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/IComSchTreeService.java @@ -30,7 +30,11 @@ public interface IComSchTreeService { List getSchoolList(); - BoaGroup getTeaTree(Integer schId); + BoaGroup getTeaTree(Integer schId, Boolean withSub); + + BoaGroup getStuTree(Integer schId, Boolean withSub); + + List getAcademicStageGroupList(Integer schId); void validateGroupsBelongToSchool(Integer schId,List groupIds); @@ -43,4 +47,15 @@ public interface IComSchTreeService { String getSchoolName(Integer schId); Map> getSchGroupTypeList(Integer schId, int type); + + /** + * 清除全部缓存(Redis 组树/学校列表 + 本地内存缓存) + */ + void clearCache(); + + /** + * 清除指定学校的缓存(学校组树 + 全局缓存) + * @param schId 学校ID,为 null 时等同清除全部 + */ + void clearCache(Integer schId); } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/ISendUserBaseService.java b/src/main/java/com/yunhai/bschclassmanage/service/ISendUserBaseService.java index e281cb0..02fc6bf 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/ISendUserBaseService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/ISendUserBaseService.java @@ -16,9 +16,9 @@ import java.util.List; @Service public interface ISendUserBaseService { - BoaGroup addGroup(String name,Integer parentId,Integer sort, NodeType type); + BoaGroup addGroup(String name,Integer parentId,Integer sort, NodeType type,Integer schId); - void editGroup(Integer id,String name,Integer parentId,Integer sort, NodeType type); + void editGroup(Integer id,String name,Integer parentId,Integer sort, NodeType type,Integer schId); BoaUser addTeacher(SchTeacher teacher, String pwd, Integer groupId); diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/SchBinSchsystemService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/SchBinSchsystemService.java index 33e7287..bb087e1 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/SchBinSchsystemService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/SchBinSchsystemService.java @@ -243,11 +243,11 @@ public class SchBinSchsystemService implements ISchBinSchsystemService { private void SchGroupInitialization(Integer schId,List newList) { //添加学生组 - BoaGroup teaGroup= sendUserBaseService.addGroup("教师组",schId,1,NodeType.TEACHER); - BoaGroup stuGroup= sendUserBaseService.addGroup("学生组",schId,2,NodeType.STUDENT); + BoaGroup teaGroup= sendUserBaseService.addGroup("教师组",schId,1,NodeType.TEACHER,schId); + BoaGroup stuGroup= sendUserBaseService.addGroup("学生组",schId,2,NodeType.STUDENT,schId); //创建校长室 - sendUserBaseService.addGroup("校长室", teaGroup.getId(),1,NodeType.NORMAL); + sendUserBaseService.addGroup("校长室", teaGroup.getId(),1,NodeType.NORMAL,schId); //获取学制 @@ -261,7 +261,7 @@ public class SchBinSchsystemService implements ISchBinSchsystemService { Integer scort=1; for (SchBinSchsystem schsystem:newList) { //添加学段组 - BoaGroup sectionGroup= sendUserBaseService.addGroup(schsystemMap.get(schsystem.getSchSystemId()),stuGroup.getId(),scort,NodeType.SECTION); + BoaGroup sectionGroup= sendUserBaseService.addGroup(schsystemMap.get(schsystem.getSchSystemId()),stuGroup.getId(),scort,NodeType.SECTION,schId); schsystem.setGroupId(sectionGroup.getId()); scort++; } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/SchTeacherService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/SchTeacherService.java index 11f1de3..a04d4b2 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/SchTeacherService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/SchTeacherService.java @@ -244,7 +244,7 @@ public class SchTeacherService implements ISchTeacherService { return Collections.emptyList(); } - BoaGroup teacherGroupTree = comSchTreeService.getTeaTree(schId); + BoaGroup teacherGroupTree = comSchTreeService.getTeaTree(schId,true); if (teacherGroupTree == null) { return Collections.emptyList(); } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/classes/SchClassInfoService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/classes/SchClassInfoService.java index 08d7240..e423b64 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/classes/SchClassInfoService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/classes/SchClassInfoService.java @@ -2,13 +2,16 @@ package com.yunhai.bschclassmanage.service.impl.classes; import com.yunhai.bschclassmanage.Repository.SchClassRepository; import com.yunhai.bschclassmanage.entity.SchClass; +import com.yunhai.bschclassmanage.enums.AcademicStage; import com.yunhai.bschclassmanage.enums.NodeType; import com.yunhai.bschclassmanage.model.vo.SelectIntVO; import com.yunhai.bschclassmanage.service.*; import com.yunhai.bschclassmanage.utils.LogContextHolder; import com.yunhai.bschclassmanage.utils.OtherUtil; import com.yunhai.bschclassmanage.utils.UserContext; +import com.yunhai.platform.openapi.client.YschBaseOpenApi; import com.yunhai.platform.utils.exception.DException; +import com.yunhai.platform.utils.model.BoaGroup; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -44,6 +47,9 @@ public class SchClassInfoService { @Autowired private SchClassQueryService queryService; + @Autowired + private ISendUserBaseService sendUserBaseService; + @Autowired private SchClassLogService logService; @@ -53,8 +59,33 @@ public class SchClassInfoService { if (number == null || number <= 0) throw new DException("新增班级数量必须大于0"); Integer schId = user.getSchId(); + + BoaGroup stuGroup= comSchTreeService.getStuTree(schId,false); + if(stuGroup==null){ + throw new DException("学生组不存在!"); + } + Integer parentId=stuGroup.getId(); + Integer schsystemId = baseSchsystemGradeService.getSchGradeIdBySchsystemId(schId, gradeId); + Map schsystemMap = schBinSchsystemService.getSchBinSchsystemMap(schId); + + if(schsystemMap.size()>1) + { + String academicStageName= schsystemMap.get(schsystemId); + List schAcademicStageList= comSchTreeService.getAcademicStageGroupList(schId); + Optional academicStageFirst= schAcademicStageList.stream().filter(s->Objects.equals(s.getName(),academicStageName)).findFirst(); + + if(!academicStageFirst.isPresent()) + { + BoaGroup academicGroup= sendUserBaseService.addGroup(academicStageName,stuGroup.getId(),schsystemId,NodeType.SECTION,schId); + parentId=academicGroup.getId(); + }else { + parentId=academicStageFirst.get().getId(); + } + } + + // 获取当前最大排序 Integer maxSort = schClassRepository.findMaxCodeNumber(gradeId, schId); int startSort = (maxSort == null) ? 1 : maxSort + 1; @@ -62,12 +93,21 @@ public class SchClassInfoService { Map nowYearGradeMap = baseSchsystemGradeService.getNowYearGradeMap(schId, schsystemId); Integer year = nowYearGradeMap.get(gradeId); + //获取年级组 List gradeGroupList = comSchTreeService.getSchGroupTypeList(schId, NodeType.GRADE.getId()).get(schsystemId); - if (gradeGroupList == null || gradeGroupList.isEmpty()) { - throw new DException("该学制下没有年级组,请先同步年级组数据!"); + if (gradeGroupList != null) { + BoaGroup academicGroup= sendUserBaseService.addGroup(year.toString(),parentId,year,NodeType.GRADE,schId); + parentId=academicGroup.getId(); + }else { + Optional gradeGroupFirst=gradeGroupList.stream().filter(s->Objects.equals(year.toString(),s.getName())).findFirst(); + if(!gradeGroupFirst.isPresent()) + { + BoaGroup academicGroup= sendUserBaseService.addGroup(year.toString(),parentId,year,NodeType.GRADE,schId); + parentId=academicGroup.getId(); + }else { + parentId=gradeGroupFirst.get().getId(); + } } - Map gradeNameToIdMap = gradeGroupList.stream() - .collect(Collectors.toMap(SelectIntVO::getName, SelectIntVO::getId, (a, b) -> a)); List classGroupList = comSchTreeService.getSchGroupTypeList(schId, NodeType.CLASS.getId()).get(schsystemId); Map classNameToIdMap = new HashMap<>(); @@ -87,18 +127,14 @@ public class SchClassInfoService { clazz.setCode(code); clazz.setName(sort + "班"); - Integer groupId = gradeNameToIdMap.get(year.toString()); - if (groupId == null) { - throw new DException("年级组 '" + year + "' 不存在,请检查年级组名称或同步树结构!"); - } - clazz.setGroupId(groupId); + clazz.setGroupId(parentId); Integer classId = classNameToIdMap.get(code); if (classId == null) { - throw new DException("班级组 '" + code + "' 不存在,请检查班级组数据或同步树结构!"); + BoaGroup academicGroup= sendUserBaseService.addGroup(code,parentId,sort,NodeType.CLASS,schId); + classId=academicGroup.getId(); } clazz.setClassId(classId); - clazz.setGraduate(false); clazz.setEnrollYear(year); OtherUtil.setBaseEntityValue(user, clazz); 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 ae656d0..3bfd64e 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 @@ -65,6 +65,32 @@ public class ComSchTreeService implements IComSchTreeService { private Map baseSchsystemMap; private final Object lock = new Object(); + /** + * 清除全部缓存(Redis 组树/学校列表 + 本地内存缓存) + * 调用时机:组树、学校组织信息变更后 + */ + public void clearCache() { + // 1. 清除 Redis 缓存 + redisUtil.del(RedisConstants.SYSTEM_GROUP_TREE, RedisConstants.SCHOOL_LIST); + // 2. 清除本地内存缓存 + synchronized (lock) { + baseSchsystemMap = null; + } + idToNameCache = null; + } + + /** + * 清除指定学校的缓存(学校组树 + 全局缓存) + * @param schId 学校ID,为 null 时等同清除全部 + */ + public void clearCache(Integer schId) { + if (schId != null) { + redisUtil.del(RedisConstants.SCHOOL_TREE + "_" + schId); + } + // 学校树变更可能影响学校列表/全局组树,一并清除 + clearCache(); + } + /** * 获取基础学制映射(带双重检查锁) */ @@ -126,19 +152,21 @@ public class ComSchTreeService implements IComSchTreeService { } + /** - * 获取 type=7 的节点及其所有子节点(教师组子树) + * 获取 type=7 的节点(教师组节点) * @param schId 学校ID - * @return 教师组节点(含子节点),若未找到则返回 null + * @param withSub true=返回该节点及整棵子树;false=仅返回节点本身(不含子节点) + * @return 教师组节点,若未找到则返回 null */ - public BoaGroup getTeaTree(Integer schId) { + public BoaGroup getTeaTree(Integer schId,Boolean withSub) { List treeList = getSchTree(schId); if (treeList == null || treeList.isEmpty()) { return null; } // 遍历根节点列表(通常只有一个),递归查找 type=7 for (BoaGroup root : treeList) { - BoaGroup result = findNodeByType(root, NodeType.TEACHER.getId()); + BoaGroup result = findNodeByType(root, NodeType.TEACHER.getId(),withSub); if (result != null) { return result; } @@ -146,6 +174,34 @@ public class ComSchTreeService implements IComSchTreeService { return null; } + public BoaGroup getStuTree(Integer schId,Boolean withSub) { + List treeList = getSchTree(schId); + if (treeList == null || treeList.isEmpty()) { + return null; + } + // 遍历根节点列表(通常只有一个),递归查找 type=7 + for (BoaGroup root : treeList) { + BoaGroup result = findNodeByType(root, NodeType.STUDENT.getId(), withSub); + if (result != null) { + return result; + } + } + return null; + } + + public List getAcademicStageGroupList(Integer schId) + { + List treeList = getSchTree(schId); + if (treeList == null || treeList.isEmpty()) { + return null; + } + List academicStageList = new ArrayList<>(); + // 遍历根节点列表(通常只有一个),收集所有学段组(type=6)节点 + for (BoaGroup root : treeList) { + collectGroupNodesByType(root, NodeType.SECTION.getId(), false, academicStageList); + } + return academicStageList; + } @@ -161,7 +217,7 @@ public class ComSchTreeService implements IComSchTreeService { } // 方式一:通过教师树校验(如有缓存) - BoaGroup teaTree = getTeaTree(schId); + BoaGroup teaTree = getTeaTree(schId,true); if (teaTree == null) { throw new DException("该校暂无教师组"); } @@ -178,9 +234,10 @@ public class ComSchTreeService implements IComSchTreeService { } public List getGroupTree() { - List treeList = getCacheSysGroupTree(); + return getCacheSysGroupTree(); + //List treeList = getCacheSysGroupTree(); // 过滤并处理:type=2的节点停止递归 - return filterTreeByType(treeList, NodeType.SCHOOL.getId()); + //return filterTreeByType(treeList, NodeType.SCHOOL.getId()); } public List getCacheSysGroupTree() { @@ -212,7 +269,7 @@ public class ComSchTreeService implements IComSchTreeService { } public List getSchTree(Integer schId) { - String cacheKey= RedisConstants.SYSTEM_GROUP_TREE+"_"+schId; + String cacheKey= RedisConstants.SCHOOL_TREE+"_"+schId; List cached = redisUtil.getList(cacheKey, BoaGroup.class); if (cached != null && !cached.isEmpty()) { return cached; @@ -303,7 +360,7 @@ public class ComSchTreeService implements IComSchTreeService { public String getTeaGroupName(Integer schId, Integer id) { - BoaGroup tree = getTeaTree(schId); + BoaGroup tree = getTeaTree(schId,true); if (tree == null) return null; // 懒加载缓存(若树结构不变) if (idToNameCache == null) { @@ -317,7 +374,7 @@ public class ComSchTreeService implements IComSchTreeService { public List getTeaGroupNameList(Integer schId, List ids) { // 1. 构建缓存(如果尚未构建) if (idToNameCache == null) { - BoaGroup tree = getTeaTree(schId); + BoaGroup tree = getTeaTree(schId,true); if (tree == null) { return Collections.emptyList(); } @@ -367,7 +424,7 @@ public class ComSchTreeService implements IComSchTreeService { */ public BoaGroup getTeacherTree(Integer schId) { // 1. 获取教师组织树(组织骨架) - BoaGroup teaTree = getTeaTree(schId); + BoaGroup teaTree = getTeaTree(schId,true); if (teaTree == null) { teaTree = new BoaGroup(); teaTree.setId(0); @@ -598,18 +655,26 @@ public class ComSchTreeService implements IComSchTreeService { } /** - * 递归查找指定 type 的节点(返回该节点及子树) + * 递归查找指定 type 的节点 + * @param node 当前节点 + * @param targetType 目标类型 + * @param withSub true=返回该节点及子树;false=仅返回节点本身(清空 children) */ - private BoaGroup findNodeByType(BoaGroup node, int targetType) { + private BoaGroup findNodeByType(BoaGroup node, int targetType,Boolean withSub) { if (node == null) { return null; } if (node.getType() != null && node.getType() == targetType) { - return node; // 找到目标节点,返回整个节点(含其 children) + // withSub=false 时仅返回节点本身,不带子节点 + //(getSchTree 每次从缓存反序列化出新对象,直接清空 children 不会污染缓存) + if (Boolean.FALSE.equals(withSub)) { + node.setChildren(new ArrayList<>()); + } + return node; // 找到目标节点 } if (node.getChildren() != null) { for (BoaGroup child : node.getChildren()) { - BoaGroup found = findNodeByType(child, targetType); + BoaGroup found = findNodeByType(child, targetType,withSub); if (found != null) { return found; } @@ -618,6 +683,31 @@ public class ComSchTreeService implements IComSchTreeService { return null; } + /** + * 递归收集指定 type 的【所有】节点(与 findNodeByType 只返回第一个不同) + * @param node 当前节点 + * @param targetType 目标类型 + * @param withSub true=保留该节点的子节点;false=仅返回节点本身(清空 children) + * @param collector 结果收集器 + */ + private void collectGroupNodesByType(BoaGroup node, int targetType, Boolean withSub, List collector) { + if (node == null) { + return; + } + if (node.getType() != null && node.getType() == targetType) { + // withSub=false 时仅返回节点本身,不带子节点 + if (Boolean.FALSE.equals(withSub)) { + node.setChildren(new ArrayList<>()); + } + collector.add(node); + } + if (node.getChildren() != null) { + for (BoaGroup child : node.getChildren()) { + collectGroupNodesByType(child, targetType, withSub, collector); + } + } + } + @@ -1162,4 +1252,7 @@ public class ComSchTreeService implements IComSchTreeService { root.setChildren(gradeNodes); return root; } + + + } diff --git a/src/main/java/com/yunhai/bschclassmanage/service/impl/com/SendUserBaseService.java b/src/main/java/com/yunhai/bschclassmanage/service/impl/com/SendUserBaseService.java index 057cbb5..6052abd 100644 --- a/src/main/java/com/yunhai/bschclassmanage/service/impl/com/SendUserBaseService.java +++ b/src/main/java/com/yunhai/bschclassmanage/service/impl/com/SendUserBaseService.java @@ -6,6 +6,7 @@ import com.yunhai.bschclassmanage.enums.NodeType; import com.yunhai.bschclassmanage.enums.UserRole; import com.yunhai.bschclassmanage.annotation.SyncOpLog; import com.yunhai.bschclassmanage.enums.SyncDataType; +import com.yunhai.bschclassmanage.service.IComSchTreeService; import com.yunhai.bschclassmanage.service.ISendUserBaseService; import com.yunhai.platform.openapi.client.YschBaseOpenApi; import com.yunhai.platform.openapi.model.SysGroupRequest; @@ -15,6 +16,7 @@ import com.yunhai.platform.utils.exception.DException; import com.yunhai.platform.utils.model.BoaGroup; import com.yunhai.platform.utils.model.BoaUser; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -25,8 +27,14 @@ import java.util.List; @Service public class SendUserBaseService implements ISendUserBaseService { + @Autowired + private IComSchTreeService comSchTreeService; + @SyncOpLog(SyncDataType.SEND_ADD_GROUP) - public BoaGroup addGroup(String name, Integer parentId, Integer sort, NodeType type){ + public BoaGroup addGroup(String name, Integer parentId, Integer sort, NodeType type,Integer schId){ + + comSchTreeService.clearCache(schId); + SysGroupRequest group=new SysGroupRequest(); group.setName(name); group.setParentId(parentId); @@ -37,7 +45,10 @@ public class SendUserBaseService implements ISendUserBaseService { @SyncOpLog(SyncDataType.SEND_EDIT_GROUP) - public void editGroup(Integer id,String name,Integer parentId,Integer sort, NodeType type){ + public void editGroup(Integer id,String name,Integer parentId,Integer sort, NodeType type,Integer schId){ + + comSchTreeService.clearCache(schId); + SysGroupRequest group=new SysGroupRequest(); group.setName(name); group.setParentId(parentId); @@ -48,6 +59,9 @@ public class SendUserBaseService implements ISendUserBaseService { @SyncOpLog(SyncDataType.SEND_DELETE_GROUP) public void deleteGroup(Integer id,Integer schId){ + + comSchTreeService.clearCache(schId); + YschBaseOpenApi.deleteGroup(id,schId); }