自定义组开放接口
build / build-push (push) Failing after 48s

This commit is contained in:
wanghu
2026-09-29 11:03:02 +08:00
parent 9f3b49c30a
commit aecab2fd91
9 changed files with 123 additions and 14 deletions
@@ -15,7 +15,11 @@ import java.util.Optional;
@Repository
public interface SchStudentRepository extends JpaRepository<SchStudent, Integer>, JpaSpecificationExecutor<SchStudent> {
Optional<SchStudent> findByStuId(Integer stuId);
/**
* stu_id 是用户中心用户ID(非本表主键),学生在多所学校各有一条就学记录,
* 同一 stu_id 可能存在多行,必须返回 List;返回 Optional 会在多行时抛 NonUniqueResultException
*/
List<SchStudent> findByStuId(Integer stuId);
List<SchStudent> findByStuIdIn(List<Integer> stuIds);
@@ -20,7 +20,11 @@ public interface SchTeacherRepository extends JpaRepository<SchTeacher, Integer>
List<SchTeacher> findByTeaIdIn(List<Integer> teaIds);
Optional<SchTeacher> findByTeaId(Integer teaId);
/**
* tea_id 是用户中心用户ID(非本表主键),教师在多所学校各有一条记录,
* 同一 tea_id 可能存在多行,必须返回 List;返回 Optional 会在多行时抛 NonUniqueResultException
*/
List<SchTeacher> findByTeaId(Integer teaId);
@Query(value = "SELECT DISTINCT t.* FROM sch_teacher t " +
@@ -56,7 +56,8 @@ public class TeainfoController {
}
// 2. 鐩存帴浣跨敤 uid 鏌ヨ
return schTeacherRepository.findByTeaId(uid) // 鍋囪 findByTeaId 杩斿洖 Optional<SchTeacher>
return schTeacherRepository.findByTeaId(uid).stream()
.findFirst()
.map(teacher -> {
fillGroupList(Collections.singletonList(teacher), null);
return teacher;
@@ -160,7 +160,8 @@ public class UserInfoController {
return ResponseEntity.ok(new ArrayList<>());
}
Optional<SchTeacher> teacherOpt = schTeacherRepository.findByTeaId(userid);
// 同一 teaId/stuId 可能在多所学校各有记录,取第一条即可(不能按唯一查询)
Optional<SchTeacher> 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<SchStudent> studentOpt = schStudentRepository.findByStuId(userid);
Optional<SchStudent> studentOpt = schStudentRepository.findByStuId(userid).stream().findFirst();
if (studentOpt.isPresent()) {
UserInfoVO vo = convertToUserInfoVO(studentOpt.get());
if (vo != null) {
@@ -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<List<TeaCustomGroupTreeVO>> getTeaCustomGroupTree(@RequestParam(value = "schId", required = false) Integer schId,
public ResponseEntity<List<TeaCustomGroupTreeVO>> 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<List<OapiGroupVO>> getTeaCustomGroupList(@RequestParam(value = "schId") Integer schId,
@RequestParam(value = "groupType", required = false) Integer groupType) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
List<SchTeacherCustomGroup> 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<Integer> groupIds = groups.stream().map(SchTeacherCustomGroup::getId).collect(Collectors.toList());
Map<Integer, List<SchTeacherCustomGroupInGrade>> groupIdToGrades = groupInGradeRepository.findByCgGroupIdIn(groupIds).stream()
.collect(Collectors.groupingBy(SchTeacherCustomGroupInGrade::getCgGroupId));
Map<Integer, List<SchTeacherCustomGroupInSubject>> groupIdToSubjects = groupInSubjectRepository.findByCgGroupIdIn(groupIds).stream()
.collect(Collectors.groupingBy(SchTeacherCustomGroupInSubject::getCgGroupId));
// relationType:1组长 2组员
Map<Integer, List<SchTeacherCustomGroupInTeacher>> groupIdToTeachers = groupInTeacherRepository.findByCgGroupIdIn(groupIds).stream()
.filter(r -> r.getTeaId() != null)
.collect(Collectors.groupingBy(SchTeacherCustomGroupInTeacher::getCgGroupId));
Map<Integer, SchTeacher> teacherMap = schTeacherService.getSchTeacherCacheList(schId).stream()
.filter(t -> t.getTeaId() != null)
.collect(Collectors.toMap(SchTeacher::getTeaId, t -> t, (a, b) -> a));
Map<Integer, String> gradeNameMap = baseSchsystemGradeService.getGradeNameMap(schId, null, null);
Map<String, String> subjectNameMap = schDicSubjectService.toIdAndNameMap(schId, null);
List<OapiGroupVO> result = new ArrayList<>(groups.size());
for (SchTeacherCustomGroup group : groups) {
List<SchTeacherCustomGroupInTeacher> relations = groupIdToTeachers.getOrDefault(group.getId(), Collections.emptyList());
List<Integer> 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<Integer> resolveLeaders(SchTeacherCustomGroup group, List<SchTeacherCustomGroupInTeacher> relations) {
List<Integer> 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<SelectIntVO> toIdNameList(List<Integer> teaIds, Map<Integer, SchTeacher> 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<TeaCustomGroupTreeVO> buildTree(Integer schId, List<SchTeacherCustomGroup> groups, boolean flatTypeRoot) {
List<Integer> groupIds = groups.stream().map(SchTeacherCustomGroup::getId).collect(Collectors.toList());
@@ -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));
}
@@ -329,7 +329,7 @@ public class SchDicSubjectService implements ISchDicSubjectService {
public List<SelectStrVO> select(Integer schId, Integer schsystemId) {
List<SchDicSubject> 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
@@ -300,13 +300,15 @@ public class StudentClassHistoryService implements IStudentClassHistoryService {
*/
public Map<String, Object> getHistoryClassTeachByStuId(Integer schId, Integer stuId) {
// 1. 解析学生所属班级 & 姓名
// stu_id 是用户中心用户ID,学生在多所学校各有就学记录(同一 stu_id 多行),需按当前学校过滤后取一条
Integer classId = null;
String studentName = null;
Optional<SchStudent> 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<SchStudentHistory> hist = schStudentHistoryRepository.findBySchIdAndStuId(schId, stuId);
if (hist.isEmpty()) {
@@ -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));
// 清除所有涉及学校的缓存