Compare commits

...
3 Commits
Author SHA1 Message Date
wanghu 43484a8936 Merge remote-tracking branch 'origin/main'
build / build-push (push) Successful in 2m12s
2026-09-20 19:12:33 +08:00
wanghu 8a61c77b12 添加接口 2026-09-20 19:12:13 +08:00
wanghu 0b1d8a3ecf 修改学科 2026-09-20 19:11:42 +08:00
21 changed files with 1270 additions and 9 deletions
@@ -28,7 +28,7 @@ public class SchSubController {
if (SchID == null || SchID.trim().isEmpty()) return ResponseEntity.ok(Collections.emptyList()); if (SchID == null || SchID.trim().isEmpty()) return ResponseEntity.ok(Collections.emptyList());
Optional<SchInfo> school = schInfoRepository.findBySchSerId(SchID); Optional<SchInfo> school = schInfoRepository.findBySchSerId(SchID);
if (!school.isPresent()) return ResponseEntity.ok(Collections.emptyList()); if (!school.isPresent()) return ResponseEntity.ok(Collections.emptyList());
return ResponseEntity.ok(subjectService.getSchSubList(school.get().getSchId(), schooling).stream().map(s -> subject(s, school.get().getSchSerId())).collect(Collectors.toList())); return ResponseEntity.ok(subjectService.getSchSubList(school.get().getSchId(), schooling).stream().filter(this::enabled).map(s -> subject(s, school.get().getSchSerId())).collect(Collectors.toList()));
} }
@GetMapping("GetSchIdsSublist") @GetMapping("GetSchIdsSublist")
@@ -37,7 +37,7 @@ public class SchSubController {
if (SchIds == null || SchIds.trim().isEmpty()) return ResponseEntity.ok(Collections.emptyList()); if (SchIds == null || SchIds.trim().isEmpty()) return ResponseEntity.ok(Collections.emptyList());
List<String> ids = OaCompatSupport.strings(SchIds); List<String> ids = OaCompatSupport.strings(SchIds);
List<Map<String,Object>> out = new ArrayList<>(); List<Map<String,Object>> out = new ArrayList<>();
for (String id : ids) schInfoRepository.findBySchSerId(id).ifPresent(s -> subjectService.getSchSubList(s.getSchId(), null).forEach(sub -> out.add(subject(sub, s.getSchSerId())))); for (String id : ids) schInfoRepository.findBySchSerId(id).ifPresent(s -> subjectService.getSchSubList(s.getSchId(), null).stream().filter(this::enabled).forEach(sub -> out.add(subject(sub, s.getSchSerId()))));
return ResponseEntity.ok(out); return ResponseEntity.ok(out);
} }
@@ -47,7 +47,10 @@ public class SchSubController {
if (UserTeaSerID == null) return ResponseEntity.ok(Collections.emptyList()); if (UserTeaSerID == null) return ResponseEntity.ok(Collections.emptyList());
try { try {
Integer teaId = Integer.valueOf(UserTeaSerID); Integer teaId = Integer.valueOf(UserTeaSerID);
return ResponseEntity.ok(teachRepository.findAll().stream().filter(t -> Objects.equals(t.getTeaId(), teaId)).map(SchClassTeach::getSubId).filter(Objects::nonNull).distinct().collect(Collectors.toList())); List<SchClassTeach> teaches = teachRepository.findAll().stream().filter(t -> Objects.equals(t.getTeaId(), teaId)).collect(Collectors.toList());
Set<String> enabledCodes = new HashSet<>();
teaches.stream().map(SchClassTeach::getSchId).filter(Objects::nonNull).distinct().forEach(schId -> enabledCodes.addAll(enabledSubjectCodes(schId)));
return ResponseEntity.ok(teaches.stream().map(SchClassTeach::getSubId).filter(c -> c != null && enabledCodes.contains(c)).distinct().collect(Collectors.toList()));
} catch (NumberFormatException e) { return ResponseEntity.ok(Collections.emptyList()); } } catch (NumberFormatException e) { return ResponseEntity.ok(Collections.emptyList()); }
} }
@@ -57,9 +60,14 @@ public class SchSubController {
if (SchID == null) return ResponseEntity.ok(Collections.emptyList()); if (SchID == null) return ResponseEntity.ok(Collections.emptyList());
Optional<SchInfo> school = schInfoRepository.findBySchSerId(SchID); Optional<SchInfo> school = schInfoRepository.findBySchSerId(SchID);
if (!school.isPresent()) return ResponseEntity.ok(Collections.emptyList()); if (!school.isPresent()) return ResponseEntity.ok(Collections.emptyList());
return ResponseEntity.ok(teachRepository.findAll().stream().filter(t -> Objects.equals(t.getSchId(), school.get().getSchId())).map(SchClassTeach::getSubId).filter(Objects::nonNull).map(s -> s.toLowerCase(Locale.ROOT)).distinct().collect(Collectors.toList())); Set<String> enabledCodes = enabledSubjectCodes(school.get().getSchId()).stream().map(c -> c.toLowerCase(Locale.ROOT)).collect(Collectors.toSet());
return ResponseEntity.ok(teachRepository.findAll().stream().filter(t -> Objects.equals(t.getSchId(), school.get().getSchId())).map(SchClassTeach::getSubId).filter(Objects::nonNull).map(s -> s.toLowerCase(Locale.ROOT)).filter(enabledCodes::contains).distinct().collect(Collectors.toList()));
} }
private boolean enabled(SchDicSubject s) { return Boolean.TRUE.equals(s.getEnable()); }
private Set<String> enabledSubjectCodes(Integer schId) { return subjectService.toEnableIdAndNameMap(schId, null).keySet(); }
private Map<String,Object> subject(SchDicSubject s, String schSerId) { private Map<String,Object> subject(SchDicSubject s, String schSerId) {
Map<String,Object> m = new LinkedHashMap<>(); m.put("SchSerID", schSerId); m.put("SubID", s.getCode() == null ? String.valueOf(s.getId()) : s.getCode()); m.put("SubName", s.getName()); m.put("No", s.getSort()); return m; Map<String,Object> m = new LinkedHashMap<>(); m.put("SchSerID", schSerId); m.put("SubID", s.getCode() == null ? String.valueOf(s.getId()) : s.getCode()); m.put("SubName", s.getName()); m.put("No", s.getSort()); return m;
} }
@@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import com.yunhai.bschclassmanage.Repository.*; import com.yunhai.bschclassmanage.Repository.*;
import com.yunhai.bschclassmanage.config.Config; import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.*; import com.yunhai.bschclassmanage.entity.*;
import com.yunhai.bschclassmanage.service.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -19,12 +20,16 @@ import java.util.stream.Collectors;
public class TeaChesController { public class TeaChesController {
@Autowired private SchClassTeachRepository teachingRepository; @Autowired private SchClassTeachRepository teachingRepository;
@Autowired private SchInfoRepository schoolRepository; @Autowired private SchInfoRepository schoolRepository;
@Autowired private ISchTeacherService teacherService;
@Autowired private ISchClassService classService;
@Autowired private ISchDicSubjectService subjectService;
@GetMapping("GetSchTeachlist") @GetMapping("GetSchTeachlist")
@Operation(summary = "GetSchTeach") @Operation(summary = "GetSchTeach")
public ResponseEntity<List<Map<String,Object>>> GetSchTeach(@RequestParam(required=false) String SchID, @RequestParam(required=false) Integer UserTeaSerID) { public ResponseEntity<List<Map<String,Object>>> GetSchTeach(@RequestParam(required=false) String SchID, @RequestParam(required=false) Integer UserTeaSerID) {
Integer schId = SchID == null ? null : schoolRepository.findBySchSerId(SchID).map(SchInfo::getSchId).orElse(null); Integer schId = SchID == null ? null : schoolRepository.findBySchSerId(SchID).map(SchInfo::getSchId).orElse(null);
return ResponseEntity.ok(teachingRepository.findAll().stream().filter(t -> (schId == null || Objects.equals(t.getSchId(), schId)) && (UserTeaSerID == null || Objects.equals(t.getTeaId(), UserTeaSerID))).map(t -> OaCompatSupport.teaching(t, schoolSer(t.getSchId()))).collect(Collectors.toList())); List<SchClassTeach> list = teachingRepository.findAll().stream().filter(t -> (schId == null || Objects.equals(t.getSchId(), schId)) && (UserTeaSerID == null || Objects.equals(t.getTeaId(), UserTeaSerID))).collect(Collectors.toList());
return ResponseEntity.ok(normalFiltered(list).stream().map(t -> OaCompatSupport.teaching(t, schoolSer(t.getSchId()))).collect(Collectors.toList()));
} }
@GetMapping("GetEleSchTeachlist") @GetMapping("GetEleSchTeachlist")
@Operation(summary = "GetEleSchTeachlist") @Operation(summary = "GetEleSchTeachlist")
@@ -39,7 +44,8 @@ public class TeaChesController {
@Operation(summary = "GetClassTeach") @Operation(summary = "GetClassTeach")
public ResponseEntity<List<Map<String,Object>>> GetClassTeach(@RequestParam(required=false) String ClassID) { public ResponseEntity<List<Map<String,Object>>> GetClassTeach(@RequestParam(required=false) String ClassID) {
Integer classId = intValue(ClassID); Integer classId = intValue(ClassID);
return ResponseEntity.ok(teachingRepository.findAll().stream().filter(t -> classId != null && Objects.equals(t.getClassId(), classId)).map(t -> OaCompatSupport.teaching(t, schoolSer(t.getSchId()))).collect(Collectors.toList())); List<SchClassTeach> list = teachingRepository.findAll().stream().filter(t -> classId != null && Objects.equals(t.getClassId(), classId)).collect(Collectors.toList());
return ResponseEntity.ok(normalFiltered(list).stream().map(t -> OaCompatSupport.teaching(t, schoolSer(t.getSchId()))).collect(Collectors.toList()));
} }
@GetMapping("GetEleSchClaTeachlist") @GetMapping("GetEleSchClaTeachlist")
@Operation(summary = "GetEleSchClaTeachlist") @Operation(summary = "GetEleSchClaTeachlist")
@@ -53,7 +59,22 @@ public class TeaChesController {
private ResponseEntity<List<Map<String,Object>>> bySchools(String value) { private ResponseEntity<List<Map<String,Object>>> bySchools(String value) {
Set<Integer> ids = new HashSet<>(); for (String ser : OaCompatSupport.strings(value)) schoolRepository.findBySchSerId(ser).ifPresent(s -> ids.add(s.getSchId())); Set<Integer> ids = new HashSet<>(); for (String ser : OaCompatSupport.strings(value)) schoolRepository.findBySchSerId(ser).ifPresent(s -> ids.add(s.getSchId()));
return ResponseEntity.ok(teachingRepository.findAll().stream().filter(t -> ids.contains(t.getSchId())).map(t -> OaCompatSupport.teaching(t, schoolSer(t.getSchId()))).collect(Collectors.toList())); List<SchClassTeach> list = teachingRepository.findAll().stream().filter(t -> ids.contains(t.getSchId())).collect(Collectors.toList());
return ResponseEntity.ok(normalFiltered(list).stream().map(t -> OaCompatSupport.teaching(t, schoolSer(t.getSchId()))).collect(Collectors.toList()));
}
/** 只保留正常教师(status=1)、正常班级(未毕业)、启用学科(enable=true)的任教记录,按学校分别过滤 */
private List<SchClassTeach> normalFiltered(List<SchClassTeach> teaches) {
List<SchClassTeach> out = new ArrayList<>();
Map<Integer, List<SchClassTeach>> bySch = new HashMap<>();
for (SchClassTeach t : teaches) if (t.getSchId() != null) bySch.computeIfAbsent(t.getSchId(), k -> new ArrayList<>()).add(t);
for (Map.Entry<Integer, List<SchClassTeach>> e : bySch.entrySet()) {
Integer schId = e.getKey();
Set<Integer> teaIds = teacherService.getSchTeacherCacheList(schId).stream().filter(t -> t.getStatus() == 1).map(SchTeacher::getTeaId).collect(Collectors.toSet());
Set<Integer> classIds = classService.getSchAllClassCacheList(schId).stream().filter(c -> !Boolean.TRUE.equals(c.getGraduate()) && c.getClassId() != null).map(SchClass::getClassId).collect(Collectors.toSet());
Set<String> subCodes = subjectService.toEnableIdAndNameMap(schId, null).keySet();
for (SchClassTeach t : e.getValue()) if (teaIds.contains(t.getTeaId()) && classIds.contains(t.getClassId()) && t.getSubId() != null && subCodes.contains(t.getSubId())) out.add(t);
}
return out;
} }
private Integer intValue(String s) { try { return s == null ? null : Integer.valueOf(s); } catch (Exception e) { return null; } } private Integer intValue(String s) { try { return s == null ? null : Integer.valueOf(s); } catch (Exception e) { return null; } }
private String schoolSer(Integer id) { return id == null ? null : schoolRepository.findBySchId(id).map(SchInfo::getSchSerId).orElse(null); } private String schoolSer(Integer id) { return id == null ? null : schoolRepository.findBySchId(id).map(SchInfo::getSchSerId).orElse(null); }
@@ -0,0 +1,128 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.Repository.SchClassRepository;
import com.yunhai.bschclassmanage.Repository.SchInfoRepository;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.SchClass;
import com.yunhai.bschclassmanage.model.vo.sch.OapiClassVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
import com.yunhai.bschclassmanage.service.ISchClassService;
import com.yunhai.bschclassmanage.service.ISchTeacherService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "OapiSchClass", description = "开放接口-班级(含班主任)")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiSchClassController {
@Autowired
private SchClassRepository schClassRepository;
@Autowired
private SchInfoRepository schInfoRepository;
@Autowired
private ISchClassService schClassService;
@Autowired
private ISchTeacherService schTeacherService;
@Autowired
private IBaseSchsystemGradeService baseSchsystemGradeService;
@GetMapping("getClassInfo")
@Operation(summary = "获取班级信息", description = "按班级ID(班级组ID)查询班级信息,含班主任/副班主任ID与姓名;可传 schId 精确到学校")
public ResponseEntity<OapiClassVO> getClassInfo(@RequestParam(value = "classId", required = false) Integer classId,
@RequestParam(value = "schId", required = false) Integer schId) {
if (classId == null) {
return ResponseEntity.ok(null);
}
Optional<SchClass> first = schId != null
? schClassRepository.findByClassIdAndSchId(classId, schId)
: schClassRepository.findAll().stream()
.filter(c -> classId.equals(c.getClassId()))
.findFirst();
return ResponseEntity.ok(first.map(c -> toVOList(Collections.singletonList(c)).get(0)).orElse(null));
}
@GetMapping("getGradeClassList")
@Operation(summary = "获取年级班级列表", description = "按年级编码查询班级列表;建议同时传 schId(走学校缓存),不传则跨校查询")
public ResponseEntity<List<OapiClassVO>> getGradeClassList(@RequestParam(value = "gradeId", required = false) Integer gradeId,
@RequestParam(value = "schId", required = false) Integer schId) {
if (gradeId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
List<SchClass> classes = schId != null
? schClassService.getSchClassCacheFilter(schId, gradeId, null)
: schClassRepository.findAll().stream()
.filter(c -> gradeId.equals(c.getGradeId()) && !Boolean.TRUE.equals(c.getGraduate()))
.collect(Collectors.toList());
return ResponseEntity.ok(toVOList(classes));
}
@GetMapping("getSchClassList")
@Operation(summary = "获取全校班级列表", description = "按学校ID查询全部班级(含班主任);默认不含毕业班,includeGraduate=true 时含毕业班")
public ResponseEntity<List<OapiClassVO>> getSchClassList(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "includeGraduate", required = false, defaultValue = "false") boolean includeGraduate) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
List<SchClass> classes = includeGraduate
? schClassService.getSchAllClassCacheList(schId)
: schClassService.getSchClassCacheList(schId);
return ResponseEntity.ok(toVOList(classes));
}
/** 批量转 VO:按学校分组后统一回填学校名/年级名/班主任姓名 */
private List<OapiClassVO> toVOList(List<SchClass> classes) {
if (classes == null || classes.isEmpty()) {
return Collections.emptyList();
}
Map<Integer, List<SchClass>> bySchool = classes.stream()
.filter(c -> c.getSchId() != null)
.collect(Collectors.groupingBy(SchClass::getSchId, LinkedHashMap::new, Collectors.toList()));
List<OapiClassVO> result = new ArrayList<>();
for (Map.Entry<Integer, List<SchClass>> entry : bySchool.entrySet()) {
Integer schId = entry.getKey();
String schName = schInfoRepository.findBySchId(schId).map(s -> s.getName()).orElse(null);
Map<Integer, String> gradeNameMap = baseSchsystemGradeService.getGradeNameMap(schId, null, null);
Map<Integer, String> teacherNameMap = schTeacherService.toIdAndNameMap(schId);
for (SchClass clazz : entry.getValue()) {
result.add(toVO(clazz, schName, gradeNameMap, teacherNameMap));
}
}
// 无学校ID的脏数据兜底转换
classes.stream()
.filter(c -> c.getSchId() == null)
.forEach(c -> result.add(toVO(c, null, Collections.emptyMap(), Collections.emptyMap())));
return result;
}
private OapiClassVO toVO(SchClass clazz, String schName,
Map<Integer, String> gradeNameMap, Map<Integer, String> teacherNameMap) {
OapiClassVO vo = new OapiClassVO();
vo.setId(clazz.getId());
vo.setClassId(clazz.getClassId());
vo.setCode(clazz.getCode());
vo.setName(clazz.getName());
vo.setCname(clazz.getCname());
vo.setGradeId(clazz.getGradeId());
vo.setGradeName(clazz.getGradeId() == null ? null : gradeNameMap.get(clazz.getGradeId()));
vo.setSchId(clazz.getSchId());
vo.setSchName(schName);
vo.setFirstTeacherId(clazz.getFirstTeacherId());
vo.setFirstTeacherName(clazz.getFirstTeacherId() == null ? null : teacherNameMap.get(clazz.getFirstTeacherId()));
vo.setSecondTeacherId(clazz.getSecondTeacherId());
vo.setSecondTeacherName(clazz.getSecondTeacherId() == null ? null : teacherNameMap.get(clazz.getSecondTeacherId()));
vo.setCampusId(clazz.getCampusId());
vo.setEnrollYear(clazz.getEnrollYear());
vo.setGraduate(clazz.getGraduate());
vo.setSort(clazz.getSort());
return vo;
}
}
@@ -0,0 +1,214 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.Repository.SchTeacherCustomGroupInGradeRepository;
import com.yunhai.bschclassmanage.Repository.SchTeacherCustomGroupInSubjectRepository;
import com.yunhai.bschclassmanage.Repository.SchTeacherCustomGroupInTeacherRepository;
import com.yunhai.bschclassmanage.Repository.SchTeacherCustomGroupRepository;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.SchTeacher;
import com.yunhai.bschclassmanage.entity.SchTeacherCustomGroup;
import com.yunhai.bschclassmanage.entity.SchTeacherCustomGroupInGrade;
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.sch.TeaCustomGroupTreeVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
import com.yunhai.bschclassmanage.service.IComSchTreeService;
import com.yunhai.bschclassmanage.service.ISchDicSubjectService;
import com.yunhai.bschclassmanage.service.ISchTeacherService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "OapiSchGroup", description = "开放接口-学校组(教师组树/学生组树/年级组教研组等自定义组树)")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiSchGroupController {
@Autowired
private IComSchTreeService comSchTreeService;
@Autowired
private ISchTeacherService schTeacherService;
@Autowired
private IBaseSchsystemGradeService baseSchsystemGradeService;
@Autowired
private ISchDicSubjectService schDicSubjectService;
@Autowired
private SchTeacherCustomGroupRepository customGroupRepository;
@Autowired
private SchTeacherCustomGroupInGradeRepository groupInGradeRepository;
@Autowired
private SchTeacherCustomGroupInSubjectRepository groupInSubjectRepository;
@Autowired
private SchTeacherCustomGroupInTeacherRepository groupInTeacherRepository;
@GetMapping("getTeaGroupTree")
@Operation(summary = "获取教师组树+教师", description = "学校→教师组(含子组)→教师;toUser=false 时仅返回组骨架。与 oa/SchGroup/GetTeaTree 同源同结构")
public ResponseEntity<List<TeaTreeVO>> getTeaGroupTree(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "toUser", required = false, defaultValue = "true") boolean toUser) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
return ResponseEntity.ok(comSchTreeService.getSchTeaTree(schId, toUser));
}
@GetMapping("getStuGroupTree")
@Operation(summary = "获取学生组树+学生", description = "学校→学段→年级→班级→学生;toUser=false 时仅返回组织骨架。与 oa/SchGroup/GetStuTree 同源同结构")
public ResponseEntity<List<TeaTreeVO>> getStuGroupTree(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "toUser", required = false, defaultValue = "true") boolean toUser) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
return ResponseEntity.ok(comSchTreeService.getSchStuTree(schId, toUser));
}
@GetMapping("getTeaCustomGroupTree")
@Operation(summary = "获取教师自定义组树+教师(年级组/教研组/备课组)",
description = "不传 groupType 时返回三层:类型根节点(id=-1年级组/-2教研组/-3备课组)→ 组节点 → 教师叶子;"
+ "传 groupType(1年级组 2教研组 3备课组,教研组即教师学科组)时直接返回该类型组节点列表(两层)。"
+ "组节点携带组长、关联年级、关联学科;教师叶子携带 isLeader")
public ResponseEntity<List<TeaCustomGroupTreeVO>> getTeaCustomGroupTree(@RequestParam(value = "schId", required = false) 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());
return ResponseEntity.ok(buildTree(schId, groups, groupType != null));
}
/** 组装类型节点→组节点→教师叶子树(flatTypeRoot=true 时不建类型根,组节点直接作为顶层) */
private List<TeaCustomGroupTreeVO> buildTree(Integer schId, List<SchTeacherCustomGroup> groups, boolean flatTypeRoot) {
List<Integer> groupIds = groups.stream().map(SchTeacherCustomGroup::getId).collect(Collectors.toList());
Map<Integer, List<Integer>> groupIdToGradeIds = groupInGradeRepository.findByCgGroupIdIn(groupIds).stream()
.collect(Collectors.groupingBy(SchTeacherCustomGroupInGrade::getCgGroupId,
Collectors.mapping(SchTeacherCustomGroupInGrade::getGradeId, Collectors.toList())));
Map<Integer, List<String>> groupIdToSubIds = groupInSubjectRepository.findByCgGroupIdIn(groupIds).stream()
.collect(Collectors.groupingBy(SchTeacherCustomGroupInSubject::getCgGroupId,
Collectors.mapping(SchTeacherCustomGroupInSubject::getSubId, Collectors.toList())));
// 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);
Map<Integer, List<TeaCustomGroupTreeVO>> groupNodesByType = new LinkedHashMap<>();
for (SchTeacherCustomGroup group : groups) {
TeaCustomGroupTreeVO groupNode = buildGroupNode(group, flatTypeRoot,
groupIdToGradeIds, groupIdToSubIds, groupIdToTeachers, teacherMap, gradeNameMap, subjectNameMap);
groupNodesByType.computeIfAbsent(group.getGroupType(), k -> new ArrayList<>()).add(groupNode);
}
if (flatTypeRoot) {
return groupNodesByType.values().stream().flatMap(List::stream).collect(Collectors.toList());
}
// 类型根节点(id = -groupType),只输出实际有组的类型,按 1年级组 2教研组 3备课组 顺序
List<TeaCustomGroupTreeVO> roots = new ArrayList<>();
for (CustomGroupType type : CustomGroupType.list()) {
List<TeaCustomGroupTreeVO> children = groupNodesByType.get(type.getId());
if (children == null || children.isEmpty()) {
continue;
}
TeaCustomGroupTreeVO typeNode = new TeaCustomGroupTreeVO();
typeNode.setId(-type.getId());
typeNode.setName(type.getName());
typeNode.setPid(0);
typeNode.setNo(type.getId());
typeNode.setType(1);
typeNode.setIsParent(true);
typeNode.setGroupType(type.getId());
typeNode.setGroupTypeName(type.getName());
typeNode.setChildren(children);
roots.add(typeNode);
}
return roots;
}
private TeaCustomGroupTreeVO buildGroupNode(SchTeacherCustomGroup group, boolean flatTypeRoot,
Map<Integer, List<Integer>> groupIdToGradeIds,
Map<Integer, List<String>> groupIdToSubIds,
Map<Integer, List<SchTeacherCustomGroupInTeacher>> groupIdToTeachers,
Map<Integer, SchTeacher> teacherMap,
Map<Integer, String> gradeNameMap,
Map<String, String> subjectNameMap) {
TeaCustomGroupTreeVO node = new TeaCustomGroupTreeVO();
node.setId(group.getId());
node.setName(group.getGroupName());
node.setPid(flatTypeRoot ? 0 : (group.getGroupType() == null ? null : -group.getGroupType()));
node.setNo(group.getSort());
node.setType(1);
node.setIsParent(true);
node.setGroupType(group.getGroupType());
node.setGroupTypeName(group.getGroupType() == null ? null : CustomGroupType.nameById(group.getGroupType()));
node.setLeaderId(group.getLeaderId());
node.setLeaderName(group.getLeaderId() == null ? null
: Optional.ofNullable(teacherMap.get(group.getLeaderId())).map(SchTeacher::getName).orElse(null));
List<Integer> gradeIds = groupIdToGradeIds.getOrDefault(group.getId(), Collections.emptyList());
node.setGradeIds(gradeIds);
node.setGradeNames(gradeIds.stream()
.map(gradeNameMap::get)
.filter(Objects::nonNull)
.collect(Collectors.toList()));
List<String> subIds = groupIdToSubIds.getOrDefault(group.getId(), Collections.emptyList());
node.setSubjectIds(subIds);
node.setSubjectNames(subIds.stream()
.map(subjectNameMap::get)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList()));
// 教师叶子:组长(relationType=1)在前,组员在后;同组内按 teaId 去重
List<SchTeacherCustomGroupInTeacher> relations = groupIdToTeachers.getOrDefault(group.getId(), Collections.emptyList());
List<TeaCustomGroupTreeVO> teacherNodes = new ArrayList<>();
Set<Integer> seenTeaIds = new HashSet<>();
relations.stream().filter(r -> Integer.valueOf(1).equals(r.getGroupType()))
.forEach(r -> addTeacherNode(teacherNodes, seenTeaIds, r, group.getId(), teacherMap));
relations.stream().filter(r -> !Integer.valueOf(1).equals(r.getGroupType()))
.forEach(r -> addTeacherNode(teacherNodes, seenTeaIds, r, group.getId(), teacherMap));
node.setChildren(teacherNodes);
return node;
}
private void addTeacherNode(List<TeaCustomGroupTreeVO> teacherNodes, Set<Integer> seenTeaIds,
SchTeacherCustomGroupInTeacher relation, Integer groupId,
Map<Integer, SchTeacher> teacherMap) {
if (!seenTeaIds.add(relation.getTeaId())) {
return;
}
SchTeacher teacher = teacherMap.get(relation.getTeaId());
if (teacher == null) {
return;
}
TeaCustomGroupTreeVO leaf = new TeaCustomGroupTreeVO();
leaf.setId(relation.getTeaId());
leaf.setName(teacher.getName());
leaf.setPid(groupId);
leaf.setNo(0);
leaf.setType(2);
leaf.setIsParent(false);
leaf.setIsLeader(Integer.valueOf(1).equals(relation.getGroupType()));
teacherNodes.add(leaf);
}
}
@@ -0,0 +1,127 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.Repository.BaseSchsystemRepository;
import com.yunhai.bschclassmanage.Repository.SchInfoRepository;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.BaseSchsystem;
import com.yunhai.bschclassmanage.entity.BaseSchsystemGrade;
import com.yunhai.bschclassmanage.entity.SchInfo;
import com.yunhai.bschclassmanage.enums.AcademicStage;
import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
import com.yunhai.bschclassmanage.model.vo.sch.GradeItemVO;
import com.yunhai.bschclassmanage.model.vo.sch.SchInfoDetailVO;
import com.yunhai.bschclassmanage.model.vo.sch.SchSystemDetailVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
import com.yunhai.bschclassmanage.service.ISchBinSchsystemService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "OapiSchInfo", description = "开放接口-学校信息(含学段/学制)")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiSchInfoController {
@Autowired
private SchInfoRepository schInfoRepository;
@Autowired
private BaseSchsystemRepository baseSchsystemRepository;
@Autowired
private ISchBinSchsystemService schBinSchsystemService;
@Autowired
private IBaseSchsystemGradeService baseSchsystemGradeService;
@GetMapping("getSchInfo")
@Operation(summary = "获取学校信息", description = "按 schId(用户中心学校组ID)查询学校信息,含学段/学制信息")
public ResponseEntity<SchInfoDetailVO> getSchInfo(@RequestParam(value = "schId", required = false) Integer schId) {
if (schId == null) {
return ResponseEntity.ok(null);
}
return ResponseEntity.ok(schInfoRepository.findBySchId(schId).map(this::toDetail).orElse(null));
}
@GetMapping("getSchInfoList")
@Operation(summary = "获取学校列表", description = "按 schIds(逗号分隔)查询学校列表,schIds 为空时返回全部学校,含学段/学制信息")
public ResponseEntity<List<SchInfoDetailVO>> getSchInfoList(@RequestParam(value = "schIds", required = false) String schIds) {
List<SchInfo> schools;
Set<Integer> idSet = parseInts(schIds);
if (idSet.isEmpty()) {
schools = schInfoRepository.findAll();
} else {
schools = schInfoRepository.findAll().stream()
.filter(s -> idSet.contains(s.getSchId()))
.collect(Collectors.toList());
}
return ResponseEntity.ok(schools.stream().map(this::toDetail).collect(Collectors.toList()));
}
/** 学校实体 → 详情 VO(拼装学段/学制信息) */
private SchInfoDetailVO toDetail(SchInfo schInfo) {
SchInfoDetailVO vo = new SchInfoDetailVO();
vo.setSchId(schInfo.getSchId());
vo.setSchName(schInfo.getName());
vo.setSchSerId(schInfo.getSchSerId());
vo.setSort(schInfo.getSort());
List<SelectIntVO> systemList = schBinSchsystemService.selectSchBinSchsystem(schInfo.getSchId());
if (systemList == null || systemList.isEmpty()) {
vo.setSchSystemList(Collections.emptyList());
return vo;
}
List<Integer> systemIds = systemList.stream().map(SelectIntVO::getId).collect(Collectors.toList());
Map<Integer, BaseSchsystem> systemMap = baseSchsystemRepository.findAllById(systemIds).stream()
.collect(Collectors.toMap(BaseSchsystem::getId, s -> s, (a, b) -> a));
vo.setSchSystemList(systemIds.stream()
.map(systemMap::get)
.filter(Objects::nonNull)
.map(system -> toSystemDetail(schInfo.getSchId(), system))
.collect(Collectors.toList()));
return vo;
}
/** 学制实体 → 学制 VO(含学段名称与该学制年级) */
private SchSystemDetailVO toSystemDetail(Integer schId, BaseSchsystem system) {
SchSystemDetailVO vo = new SchSystemDetailVO();
vo.setId(system.getId());
vo.setName(system.getName());
vo.setAcademicStage(system.getAcademicStage());
vo.setAcademicStageName(system.getAcademicStage() == null ? null : AcademicStage.nameById(system.getAcademicStage()));
vo.setStartGradeCode(system.getStartGradeCode());
vo.setEndGradeCode(system.getEndGradeCode());
vo.setGraduationLeng(system.getGraduationLeng());
vo.setType(system.getType());
List<BaseSchsystemGrade> gradeList = baseSchsystemGradeService.getSchGradeCacheList(schId, system.getId(), null);
vo.setGradeList(gradeList == null ? Collections.emptyList() : gradeList.stream()
.map(g -> {
GradeItemVO item = new GradeItemVO();
item.setGradeId(g.getGradeId());
item.setGradeNickname(g.getGradeNickname());
return item;
})
.collect(Collectors.toList()));
return vo;
}
private Set<Integer> parseInts(String value) {
Set<Integer> result = new LinkedHashSet<>();
if (value == null || value.trim().isEmpty()) {
return result;
}
for (String token : value.split(",")) {
try {
result.add(Integer.valueOf(token.trim()));
} catch (NumberFormatException ignored) {
}
}
return result;
}
}
@@ -0,0 +1,109 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.Repository.SchClassRepository;
import com.yunhai.bschclassmanage.Repository.SchInfoRepository;
import com.yunhai.bschclassmanage.Repository.SchStudentRepository;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.SchClass;
import com.yunhai.bschclassmanage.entity.SchStudent;
import com.yunhai.bschclassmanage.model.vo.sch.OapiStudentVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
import com.yunhai.bschclassmanage.service.ISchClassService;
import com.yunhai.bschclassmanage.service.ISchStudentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "OapiSchStudent", description = "开放接口-学生")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiSchStudentController {
@Autowired
private SchStudentRepository schStudentRepository;
@Autowired
private SchClassRepository schClassRepository;
@Autowired
private SchInfoRepository schInfoRepository;
@Autowired
private ISchStudentService schStudentService;
@Autowired
private ISchClassService schClassService;
@Autowired
private IBaseSchsystemGradeService baseSchsystemGradeService;
@GetMapping("getStudentInfo")
@Operation(summary = "获取学生信息", description = "按学生ID(用户中心用户ID)查询学生信息,含班级/年级/学校名称")
public ResponseEntity<OapiStudentVO> getStudentInfo(@RequestParam(value = "stuId", required = false) Integer stuId) {
if (stuId == null) {
return ResponseEntity.ok(null);
}
return ResponseEntity.ok(schStudentRepository.findByStuId(stuId)
.map(stu -> toVOList(stu.getSchId(), Collections.singletonList(stu)).get(0))
.orElse(null));
}
@GetMapping("getClassStudentList")
@Operation(summary = "获取班级学生列表", description = "按学校ID+班级ID(班级组ID)查询班级学生列表(在读正常)")
public ResponseEntity<List<OapiStudentVO>> getClassStudentList(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "classId", required = false) Integer classId) {
if (schId == null || classId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
List<SchStudent> students = schStudentService.getSchGradeClassStudentCacheList(schId, null, null, classId);
return ResponseEntity.ok(toVOList(schId, students));
}
@GetMapping("getSchStudentList")
@Operation(summary = "获取全校学生列表", description = "按学校ID查询全校学生列表(在读正常)")
public ResponseEntity<List<OapiStudentVO>> getSchStudentList(@RequestParam(value = "schId", required = false) Integer schId) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
List<SchStudent> students = schStudentService.getSchGradeClassStudentCacheList(schId, null, null, null);
return ResponseEntity.ok(toVOList(schId, students));
}
/** 批量转 VO:统一回填学校/年级/班级名称 */
private List<OapiStudentVO> toVOList(Integer schId, List<SchStudent> students) {
if (students == null || students.isEmpty()) {
return Collections.emptyList();
}
String schName = schId == null ? null
: schInfoRepository.findBySchId(schId).map(s -> s.getName()).orElse(null);
Map<Integer, String> gradeNameMap = schId == null ? Collections.emptyMap()
: baseSchsystemGradeService.getGradeNameMap(schId, null, null);
Map<Integer, SchClass> classMap = schId == null ? Collections.emptyMap()
: schClassService.getSchAllClassCacheList(schId).stream()
.filter(c -> c.getClassId() != null)
.collect(Collectors.toMap(SchClass::getClassId, c -> c, (a, b) -> a));
return students.stream().map(stu -> {
OapiStudentVO vo = new OapiStudentVO();
vo.setId(stu.getId());
vo.setStuId(stu.getStuId());
vo.setAccount(stu.getAccount());
vo.setName(stu.getName());
vo.setGender(stu.getGender());
vo.setStuClassNo(stu.getStuClassNo());
vo.setClassId(stu.getClassId());
vo.setStatus(stu.getStatus());
vo.setSchId(schId);
vo.setSchName(schName);
SchClass clazz = stu.getClassId() == null ? null : classMap.get(stu.getClassId());
if (clazz != null) {
vo.setClassName(clazz.getCname() == null || clazz.getCname().trim().isEmpty()
? clazz.getName() : clazz.getCname());
vo.setGradeId(clazz.getGradeId());
}
vo.setGradeName(vo.getGradeId() == null ? null : gradeNameMap.get(vo.getGradeId()));
return vo;
}).collect(Collectors.toList());
}
}
@@ -0,0 +1,68 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.SchDicSubject;
import com.yunhai.bschclassmanage.model.vo.sch.OapiSubjectVO;
import com.yunhai.bschclassmanage.service.ISchDicSubjectService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Tag(name = "OapiSchSubject", description = "开放接口-学科")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiSchSubjectController {
@Autowired
private ISchDicSubjectService schDicSubjectService;
@GetMapping("getSubjectInfo")
@Operation(summary = "获取学科信息", description = "按学校ID+学科ID(sch_dic_subject.id 主键,兼容传学科编码 code)查询单个学科")
public ResponseEntity<OapiSubjectVO> getSubjectInfo(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "subjectId", required = false) String subjectId) {
if (schId == null || subjectId == null || subjectId.trim().isEmpty()) {
return ResponseEntity.ok(null);
}
String code = subjectId.trim();
return schDicSubjectService.getSchSubList(schId, null).stream()
.filter(s -> code.equals(String.valueOf(s.getId())) || code.equals(s.getCode()))
.findFirst()
.map(this::toVO)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.ok(null));
}
@GetMapping("getSchSubjectList")
@Operation(summary = "获取学校学科列表", description = "按学校ID查询学科列表,可传 schSystemId 按学制过滤")
public ResponseEntity<List<OapiSubjectVO>> getSchSubjectList(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "schSystemId", required = false) Integer schSystemId) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
return ResponseEntity.ok(schDicSubjectService.getSchSubList(schId, schSystemId).stream()
.filter(Objects::nonNull)
.map(this::toVO)
.collect(Collectors.toList()));
}
private OapiSubjectVO toVO(SchDicSubject subject) {
OapiSubjectVO vo = new OapiSubjectVO();
vo.setId(subject.getId());
vo.setCode(subject.getCode());
vo.setName(subject.getName());
vo.setSchSystemId(subject.getSchSystemId());
vo.setEnable(subject.getEnable());
vo.setSource(subject.getSource());
vo.setSort(subject.getSort());
vo.setSchId(subject.getSchId());
return vo;
}
}
@@ -0,0 +1,116 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.Repository.SchClassTeachRepository;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.SchClass;
import com.yunhai.bschclassmanage.entity.SchClassTeach;
import com.yunhai.bschclassmanage.model.vo.sch.OapiTeachVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
import com.yunhai.bschclassmanage.service.ISchClassService;
import com.yunhai.bschclassmanage.service.ISchClassTeachService;
import com.yunhai.bschclassmanage.service.ISchDicSubjectService;
import com.yunhai.bschclassmanage.service.ISchTeacherService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
@Tag(name = "OapiSchTeach", description = "开放接口-班级任教")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiSchTeachController {
@Autowired
private SchClassTeachRepository schClassTeachRepository;
@Autowired
private ISchClassTeachService schClassTeachService;
@Autowired
private ISchClassService schClassService;
@Autowired
private ISchTeacherService schTeacherService;
@Autowired
private ISchDicSubjectService schDicSubjectService;
@Autowired
private IBaseSchsystemGradeService baseSchsystemGradeService;
@GetMapping("getClassTeachList")
@Operation(summary = "获取班级任教列表", description = "按学校ID+班级ID(班级组ID)查询班级任教的教师与学科")
public ResponseEntity<List<OapiTeachVO>> getClassTeachList(@RequestParam(value = "schId", required = false) Integer schId,
@RequestParam(value = "classId", required = false) Integer classId) {
if (schId == null || classId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
return ResponseEntity.ok(toVOList(schId, schClassTeachService.getSchClassTeachCacheList(schId, null, classId)));
}
@GetMapping("getTeacherTeachList")
@Operation(summary = "获取教师任教列表", description = "按教师ID(teaId)查询任教记录;可传 schId 限定学校(走缓存),不传则跨校查询")
public ResponseEntity<List<OapiTeachVO>> getTeacherTeachList(@RequestParam(value = "teaId", required = false) Integer teaId,
@RequestParam(value = "schId", required = false) Integer schId) {
if (teaId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
if (schId != null) {
List<SchClassTeach> teaches = schClassTeachService.getSchClassTeachCacheList(schId, null, null).stream()
.filter(t -> teaId.equals(t.getTeaId()))
.collect(Collectors.toList());
return ResponseEntity.ok(toVOList(schId, teaches));
}
Map<Integer, List<SchClassTeach>> bySchool = schClassTeachRepository.findAll().stream()
.filter(t -> teaId.equals(t.getTeaId()) && t.getSchId() != null)
.collect(Collectors.groupingBy(SchClassTeach::getSchId, LinkedHashMap::new, Collectors.toList()));
List<OapiTeachVO> result = new ArrayList<>();
bySchool.forEach((schoolId, teaches) -> result.addAll(toVOList(schoolId, teaches)));
return ResponseEntity.ok(result);
}
@GetMapping("getSchTeachList")
@Operation(summary = "获取全校任教列表", description = "按学校ID查询全校任教记录(未毕业班级)")
public ResponseEntity<List<OapiTeachVO>> getSchTeachList(@RequestParam(value = "schId", required = false) Integer schId) {
if (schId == null) {
return ResponseEntity.ok(Collections.emptyList());
}
return ResponseEntity.ok(toVOList(schId, schClassTeachService.getSchClassTeachCacheList(schId, null, null)));
}
/** 批量转 VO:按学校统一回填教师姓名/学科名称/班级名称/年级名称 */
private List<OapiTeachVO> toVOList(Integer schId, List<SchClassTeach> teaches) {
if (teaches == null || teaches.isEmpty()) {
return Collections.emptyList();
}
Map<Integer, String> teacherNameMap = schTeacherService.toIdAndNameMap(schId);
Map<String, String> subjectNameMap = schDicSubjectService.toIdAndNameMap(schId, null);
Map<Integer, String> gradeNameMap = baseSchsystemGradeService.getGradeNameMap(schId, null, null);
Map<Integer, SchClass> classMap = schClassService.getSchAllClassCacheList(schId).stream()
.filter(c -> c.getClassId() != null)
.collect(Collectors.toMap(SchClass::getClassId, c -> c, (a, b) -> a));
return teaches.stream().map(t -> {
OapiTeachVO vo = new OapiTeachVO();
vo.setId(t.getId());
vo.setSchId(t.getSchId());
vo.setGradeId(t.getGradeId());
vo.setGradeName(t.getGradeId() == null ? null : gradeNameMap.get(t.getGradeId()));
vo.setClassId(t.getClassId());
vo.setTeaId(t.getTeaId());
vo.setTeaName(t.getTeaId() == null ? null : teacherNameMap.get(t.getTeaId()));
vo.setSubId(t.getSubId());
vo.setSubName(t.getSubId() == null ? null : subjectNameMap.get(t.getSubId()));
SchClass clazz = t.getClassId() == null ? null : classMap.get(t.getClassId());
if (clazz != null) {
vo.setClassName(clazz.getCname() == null || clazz.getCname().trim().isEmpty()
? clazz.getName() : clazz.getCname());
if (vo.getGradeId() == null) {
vo.setGradeId(clazz.getGradeId());
vo.setGradeName(clazz.getGradeId() == null ? null : gradeNameMap.get(clazz.getGradeId()));
}
}
return vo;
}).collect(Collectors.toList());
}
}
@@ -0,0 +1,57 @@
package com.yunhai.bschclassmanage.controller.oapi.sch;
import com.yunhai.bschclassmanage.config.Config;
import com.yunhai.bschclassmanage.entity.BaseYearTerm;
import com.yunhai.bschclassmanage.model.tool.YearTerm;
import com.yunhai.bschclassmanage.model.vo.BaseYearTermVO;
import com.yunhai.bschclassmanage.model.vo.sch.NowYearTermVO;
import com.yunhai.bschclassmanage.service.IBaseYearTermService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "OapiYearTerm", description = "开放接口-学年学期")
@RestController
@RequestMapping(Config.OAPI + "/sch/")
@CrossOrigin(originPatterns = {"*"}, allowCredentials = "true")
public class OapiYearTermController {
@Autowired
private IBaseYearTermService baseYearTermService;
@GetMapping("getNowYearTerm")
@Operation(summary = "获取当前学年学期", description = "返回当前学年(nowYear=true)、当前学期 term(1第一学期 2第二学期)及当前学期起止日期")
public ResponseEntity<NowYearTermVO> getNowYearTerm() {
BaseYearTerm nowTerm = baseYearTermService.getNowYearTerm();
YearTerm current = baseYearTermService.getCurrentYearTerm();
return ResponseEntity.ok(toVO(nowTerm, current));
}
@GetMapping("getYearTermList")
@Operation(summary = "获取学年学期列表", description = "返回全部学年学期列表(按学年倒序),当前学年带 nowYear=true 标记")
public ResponseEntity<List<BaseYearTermVO>> getYearTermList() {
return ResponseEntity.ok(baseYearTermService.getAllYearTermVO());
}
private NowYearTermVO toVO(BaseYearTerm entity, YearTerm current) {
NowYearTermVO vo = new NowYearTermVO();
vo.setId(entity.getId());
vo.setYear(current != null && current.getYear() != null ? current.getYear() : entity.getYear());
vo.setTerm(current == null ? null : current.getTerm());
vo.setYearStartDate(entity.getYearStartDate());
vo.setYearEndDate(entity.getYearEndDate());
vo.setFirstTermStartDate(entity.getFirstTermStartDate());
vo.setFirstTermEndDate(entity.getFirstTermEndDate());
vo.setSecondTermStartDate(entity.getSecondTermStartDate());
vo.setSecondTermEndDate(entity.getSecondTermEndDate());
vo.setUpgradeDate(entity.getUpgradeDate());
vo.setTermStartDate(Integer.valueOf(2).equals(vo.getTerm()) ? entity.getSecondTermStartDate() : entity.getFirstTermStartDate());
vo.setTermEndDate(Integer.valueOf(2).equals(vo.getTerm()) ? entity.getSecondTermEndDate() : entity.getFirstTermEndDate());
vo.setNowYear(true);
return vo;
}
}
@@ -0,0 +1,18 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* 学制年级项(oapi/sch 学校信息内的 gradeList 元素)
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GradeItemVO {
/** 年级编码(BaseSchsystemGrade.gradeId,与 sch_class.grade_id 同源) */
private Integer gradeId;
/** 年级别称 */
private String gradeNickname;
}
@@ -0,0 +1,56 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.Date;
/**
* 当前学年学期(oapi/sch/getNowYearTerm 输出)
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class NowYearTermVO {
/** 学年(如 2026) */
private Integer year;
/** 当前学期(1第一学期 2第二学期),按当前日期落在学期区间判定 */
private Integer term;
/** 学年学期记录ID(base_year_term.id) */
private Integer id;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date yearStartDate;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date yearEndDate;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date firstTermStartDate;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date firstTermEndDate;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date secondTermStartDate;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date secondTermEndDate;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date upgradeDate;
/** 当前学期开始日期(按 term 取一/二学期开始日期) */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date termStartDate;
/** 当前学期结束日期(按 term 取一/二学期结束日期) */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date termEndDate;
/** 是否当前学年学期,恒为 true */
private Boolean nowYear;
}
@@ -0,0 +1,63 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* 班级信息(oapi/sch 班级接口输出),含班主任
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OapiClassVO {
/** 班级记录ID(sch_class.id 主键) */
private Integer id;
/** 班级ID(班级组ID group_class_id,学生/任教的 classId 同源) */
private Integer classId;
/** 班级编码 */
private String code;
/** 班级名称 */
private String name;
/** 班级别称 */
private String cname;
/** 年级编码(base_sch_system_grade.grade_id) */
private Integer gradeId;
/** 年级名称 */
private String gradeName;
/** 学校ID */
private Integer schId;
/** 学校名称 */
private String schName;
/** 班主任ID(教师 teaId) */
private Integer firstTeacherId;
/** 班主任姓名 */
private String firstTeacherName;
/** 副班主任ID(教师 teaId) */
private Integer secondTeacherId;
/** 副班主任姓名 */
private String secondTeacherName;
/** 校区ID */
private Integer campusId;
/** 注册年份 */
private Integer enrollYear;
/** 是否毕业 */
private Boolean graduate;
/** 序号 */
private Integer sort;
}
@@ -0,0 +1,51 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* 学生信息(oapi/sch 学生接口输出)
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OapiStudentVO {
/** 学生记录ID(sch_student.id 主键) */
private Integer id;
/** 学生ID(用户中心用户ID stu_id) */
private Integer stuId;
/** 学生账户 */
private String account;
/** 学生姓名 */
private String name;
/** 性别(0女 1男) */
private Integer gender;
/** 班级学号 */
private String stuClassNo;
/** 班级ID(班级组ID,与班级接口的 classId 同源) */
private Integer classId;
/** 班级名称 */
private String className;
/** 年级编码 */
private Integer gradeId;
/** 年级名称 */
private String gradeName;
/** 学校ID */
private Integer schId;
/** 学校名称 */
private String schName;
/** 状态(0正常 1禁用) */
private Integer status;
}
@@ -0,0 +1,36 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* 学科信息(oapi/sch 学科接口输出)
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OapiSubjectVO {
/** 学科ID(sch_dic_subject.id 主键) */
private Integer id;
/** 学科编码(任教/自定义组关联的 subId 即该编码) */
private String code;
/** 学科名称 */
private String name;
/** 学制ID */
private Integer schSystemId;
/** 是否启用 */
private Boolean enable;
/** 数据来源(0系统 1学校) */
private Integer source;
/** 序号 */
private Integer sort;
/** 学校ID */
private Integer schId;
}
@@ -0,0 +1,42 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* 任教信息(oapi/sch 任教接口输出)
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OapiTeachVO {
/** 任教记录ID(sch_class_teach.id 主键) */
private Integer id;
/** 学校ID */
private Integer schId;
/** 班级ID(班级组ID) */
private Integer classId;
/** 班级名称 */
private String className;
/** 年级编码 */
private Integer gradeId;
/** 年级名称 */
private String gradeName;
/** 教师ID(teaId) */
private Integer teaId;
/** 教师姓名 */
private String teaName;
/** 学科ID(sch_dic_subject.code) */
private String subId;
/** 学科名称 */
private String subName;
}
@@ -0,0 +1,29 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.List;
/**
* 学校信息(oapi/sch/getSchInfo、getSchInfoList 输出),含学段/学制信息
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SchInfoDetailVO {
/** 学校ID(用户中心学校组ID,sch_info.sch_id) */
private Integer schId;
/** 学校名称 */
private String schName;
/** 学校序列号(sch_info.sch_serid) */
private String schSerId;
/** 排序号 */
private Integer sort;
/** 学段/学制信息(学校绑定的学制列表,每个学制含其年级) */
private List<SchSystemDetailVO> schSystemList;
}
@@ -0,0 +1,41 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.List;
/**
* 学制信息(oapi/sch 学校信息内的 schSystemList 元素,含学段编码与该学制下的年级)
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SchSystemDetailVO {
/** 学制ID(base_sch_system.id) */
private Integer id;
/** 学制名称 */
private String name;
/** 学段编码(0学前 1小学 2初中 3高中 4高等) */
private Integer academicStage;
/** 学段名称 */
private String academicStageName;
/** 开始年级编码 */
private Integer startGradeCode;
/** 结束年级编码 */
private Integer endGradeCode;
/** 毕业年长度 */
private Integer graduationLeng;
/** 教育类型(1基础教育 2职业教育) */
private Integer type;
/** 该学制下的年级列表 */
private List<GradeItemVO> gradeList;
}
@@ -0,0 +1,64 @@
package com.yunhai.bschclassmanage.model.vo.sch;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 教师自定义组树节点(oapi/sch/getTeaCustomGroupTree 输出)。
* 节点契约与 SchGroup/GetTeaTree 的 TeaTreeVO 一致:
* type=1 组节点(isParent=true),type=2 教师叶子(isParent=false、children 省略)。
* 组节点额外携带组类型/组长/年级/学科信息,教师叶子额外携带 isLeader。
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TeaCustomGroupTreeVO {
/** 组节点:组ID(sch_teacher_custom_group.id);类型节点:-1/-2/-3;教师叶子:teaId */
private Integer id;
private String name;
/** 父节点ID(类型节点 pid=0) */
private Integer pid;
/** 排序号 */
private Integer no;
/** 1组节点 2教师叶子 */
private Integer type;
@JsonProperty("isParent")
private Boolean isParent;
/** 组节点:组类型(1年级组 2教研组 3备课组) */
private Integer groupType;
/** 组节点:组类型名称 */
private String groupTypeName;
/** 组节点:组长ID(teaId) */
private Integer leaderId;
/** 组节点:组长姓名 */
private String leaderName;
/** 组节点:关联年级编码列表 */
private List<Integer> gradeIds;
/** 组节点:关联年级名称列表 */
private List<String> gradeNames;
/** 组节点:关联学科编码列表 */
private List<String> subjectIds;
/** 组节点:关联学科名称列表 */
private List<String> subjectNames;
/** 教师叶子:是否组长 */
private Boolean isLeader;
private List<TeaCustomGroupTreeVO> children;
}
@@ -22,4 +22,9 @@ public interface ISchDicSubjectService {
List<SelectStrVO> select(Integer schId,Integer schsystemId); List<SelectStrVO> select(Integer schId,Integer schsystemId);
Map<String, String> toIdAndNameMap(Integer schId, Integer schsystemId); Map<String, String> toIdAndNameMap(Integer schId, Integer schsystemId);
/**
* 获取学校学科 code -> name 映射(仅启用的学科)
*/
Map<String, String> toEnableIdAndNameMap(Integer schId, Integer schsystemId);
} }
@@ -342,4 +342,12 @@ public class SchDicSubjectService implements ISchDicSubjectService {
List<SchDicSubject> list = getSchDicSubjectCacheList(schId,schsystemId); List<SchDicSubject> list = getSchDicSubjectCacheList(schId,schsystemId);
return ModelMapperUtil.toMap(list, SchDicSubject::getCode, SchDicSubject::getName); return ModelMapperUtil.toMap(list, SchDicSubject::getCode, SchDicSubject::getName);
} }
public Map<String, String> toEnableIdAndNameMap(Integer schId, Integer schsystemId)
{
List<SchDicSubject> list = getSchDicSubjectCacheList(schId, schsystemId).stream()
.filter(s -> Boolean.TRUE.equals(s.getEnable()))
.collect(Collectors.toList());
return ModelMapperUtil.toMap(list, SchDicSubject::getCode, SchDicSubject::getName);
}
} }
@@ -133,8 +133,8 @@ public class SchClassTeachQueryService {
return buildEmptyResult(); return buildEmptyResult();
} }
// 2. 获取学科数据 // 2. 获取学科数据(仅启用的学科)
Map<String, String> subjectNameMap = schDicSubjectService.toIdAndNameMap(schId, schsystemId); Map<String, String> subjectNameMap = schDicSubjectService.toEnableIdAndNameMap(schId, schsystemId);
if (subjectNameMap == null || subjectNameMap.isEmpty()) { if (subjectNameMap == null || subjectNameMap.isEmpty()) {
return buildEmptyResult(); return buildEmptyResult();
} }