From 2d549eb0653baa4302bbfac3a847b2be58ce0b77 Mon Sep 17 00:00:00 2001 From: wanghu Date: Sun, 20 Sep 2026 20:55:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=BB=BB=E6=95=99=E7=8F=AD?= =?UTF-8?q?=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/StudentHomeworkController.java | 2 +- .../api/TeacherHomeworkV2Controller.java | 21 +- .../yunhai/homework/entity/ClassStudent.java | 59 ----- .../yunhai/homework/entity/HomeworkClass.java | 4 +- .../homework/entity/HomeworkReadRecord.java | 4 +- .../homework/entity/HomeworkSubmission.java | 4 +- .../yunhai/homework/entity/SchClassTeach.java | 46 ---- .../homework/job/HomeworkScheduledJobs.java | 20 -- .../yunhai/homework/model/v2/ClassItem.java | 2 +- .../homework/model/v2/ClassTreeNode.java | 4 +- .../homework/model/v2/HomeworkStatsVo.java | 2 +- .../homework/model/v2/HomeworkV2Request.java | 2 +- .../homework/model/v2/StudentMatrixQuery.java | 2 +- .../homework/model/v2/StudentMatrixVo.java | 2 +- .../homework/model/v2/TeachingClassVo.java | 2 +- .../repository/ClassStudentRepository.java | 31 --- .../repository/HomeworkClassRepository.java | 2 +- .../repository/SchClassTeachRepository.java | 22 -- .../service/impl/ClassStudentService.java | 81 ------- .../impl/HomeworkProgressCalculator.java | 50 ++-- .../service/impl/HomeworkService.java | 11 +- .../service/impl/StudentHomeworkService.java | 62 +++-- .../impl/TeacherHomeworkV2Service.java | 214 ++++++++++-------- 23 files changed, 189 insertions(+), 460 deletions(-) delete mode 100644 src/main/java/com/yunhai/homework/entity/ClassStudent.java delete mode 100644 src/main/java/com/yunhai/homework/entity/SchClassTeach.java delete mode 100644 src/main/java/com/yunhai/homework/repository/ClassStudentRepository.java delete mode 100644 src/main/java/com/yunhai/homework/repository/SchClassTeachRepository.java delete mode 100644 src/main/java/com/yunhai/homework/service/impl/ClassStudentService.java diff --git a/src/main/java/com/yunhai/homework/controller/api/StudentHomeworkController.java b/src/main/java/com/yunhai/homework/controller/api/StudentHomeworkController.java index 56a37b0..66d42b1 100644 --- a/src/main/java/com/yunhai/homework/controller/api/StudentHomeworkController.java +++ b/src/main/java/com/yunhai/homework/controller/api/StudentHomeworkController.java @@ -25,7 +25,7 @@ import java.util.Map; /** * 课堂作业 V2 学生端接口(PRD §18 路径一字对齐:/student/homeworks…)。 *

- * 身份:当前登录用户ID ↔ class_student 名册;仅可见本人班级作业,禁 IDOR。 + * 身份:当前登录用户ID ↔ bschclass 学生名册(实时匹配);仅可见本人班级作业,禁 IDOR。 */ @RestController @RequestMapping(value = Config.API_PATH + "/student/homeworks") diff --git a/src/main/java/com/yunhai/homework/controller/api/TeacherHomeworkV2Controller.java b/src/main/java/com/yunhai/homework/controller/api/TeacherHomeworkV2Controller.java index 5335083..f949049 100644 --- a/src/main/java/com/yunhai/homework/controller/api/TeacherHomeworkV2Controller.java +++ b/src/main/java/com/yunhai/homework/controller/api/TeacherHomeworkV2Controller.java @@ -17,7 +17,6 @@ import com.yunhai.homework.model.v2.SubmissionVersionVo; import com.yunhai.homework.model.v2.SubjectDto; import com.yunhai.homework.model.v2.TeacherHomeworkQuery; import com.yunhai.homework.model.v2.TeachingClassVo; -import com.yunhai.homework.service.impl.ClassStudentService; import com.yunhai.homework.service.impl.TeacherHomeworkV2Service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; @@ -51,9 +50,6 @@ public class TeacherHomeworkV2Controller { @Autowired private TeacherHomeworkV2Service teacherHomeworkV2Service; - @Autowired - private ClassStudentService classStudentService; - // ============================ 页 1:发布作业 ============================ /** 创建作业(落草稿) */ @@ -198,22 +194,15 @@ public class TeacherHomeworkV2Controller { /** 按学科筛选我的任教班级(subId=学科编码;班级名称取学校班级列表) */ @GetMapping("/subjects/classes") - public List teachingClasses(@RequestParam("subId") String subId) { - return teacherHomeworkV2Service.teachingClasses(subId); + public List teachingClasses(@RequestParam("subject") String subject) { + return teacherHomeworkV2Service.teachingClasses(subject); } // ============================ 辅助:班级树 / 名册同步 ============================ - /** 年级→班级树(发布选班;名册快照聚合) */ + /** 年级→班级树(发布选班;subId 传学科编码时仅返回该学科任教班级) */ @GetMapping("/classes") - public List classTree() { - return teacherHomeworkV2Service.classTree(); - } - - /** 手动触发名册同步(bschclass 接口就绪前为空操作) */ - @PostMapping("/classes/sync") - public Map syncClasses() { - int synced = classStudentService.syncAll(); - return java.util.Collections.singletonMap("synced", synced); + public List classTree(@RequestParam(value = "subject", required = false) String subject) { + return teacherHomeworkV2Service.classTree(subject); } } diff --git a/src/main/java/com/yunhai/homework/entity/ClassStudent.java b/src/main/java/com/yunhai/homework/entity/ClassStudent.java deleted file mode 100644 index 793e295..0000000 --- a/src/main/java/com/yunhai/homework/entity/ClassStudent.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.yunhai.homework.entity; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; -import java.time.LocalDateTime; - -/** - * 班级学生名册快照(PRD class_student)。 - *

- * 由同步任务从 bschclass 拉取(接口未就绪前用种子数据),每日全量刷 + 手动触发; - * 同步不物理删,转出置 status=0。学生身份口径:用户中心数字ID(UserContext.getUserId()) - * ↔ student_id(SchStudent.UserStuSerID),名册仅存学生ID + 姓名快照。 - */ -@NoArgsConstructor -@Data -@Entity -@Table(name = "class_student", - uniqueConstraints = @UniqueConstraint(name = "uk_class_student", columnNames = {"class_id", "student_id"})) -@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) -public class ClassStudent extends BaseEntity { - - /** 学校ID */ - @Column(name = "school_id", nullable = false) - private Integer schoolId; - - /** 班级ID */ - @Column(name = "class_id", nullable = false, length = 64) - private String classId; - - /** 班级名快照 */ - @Column(name = "class_name", length = 50) - private String className; - - /** 年级名快照 */ - @Column(name = "grade_name", length = 50) - private String gradeName; - - /** 学生ID(用户中心数字ID,即 SchStudent.UserStuSerID) */ - @Column(name = "student_id", nullable = false) - private Integer studentId; - - /** 学生姓名 */ - @Column(name = "student_name", nullable = false, length = 50) - private String studentName; - - /** 在班状态:1 在班 / 0 已转出退课 */ - @Column(name = "status", nullable = false) - private Integer status = 1; - - /** 离班时间 */ - @Column(name = "leave_at") - private LocalDateTime leaveAt; -} diff --git a/src/main/java/com/yunhai/homework/entity/HomeworkClass.java b/src/main/java/com/yunhai/homework/entity/HomeworkClass.java index c01cefb..857f91a 100644 --- a/src/main/java/com/yunhai/homework/entity/HomeworkClass.java +++ b/src/main/java/com/yunhai/homework/entity/HomeworkClass.java @@ -26,8 +26,8 @@ public class HomeworkClass extends BaseEntity { private Integer homeworkId; /** 班级ID */ - @Column(name = "class_id", nullable = false, length = 64) - private String classId; + @Column(name = "class_id", nullable = false) + private Integer classId; /** 班级名快照 */ @Column(name = "class_name", length = 50) diff --git a/src/main/java/com/yunhai/homework/entity/HomeworkReadRecord.java b/src/main/java/com/yunhai/homework/entity/HomeworkReadRecord.java index 8179e79..3843c1b 100644 --- a/src/main/java/com/yunhai/homework/entity/HomeworkReadRecord.java +++ b/src/main/java/com/yunhai/homework/entity/HomeworkReadRecord.java @@ -37,8 +37,8 @@ public class HomeworkReadRecord extends BaseEntity { private String studentName; /** 班级ID */ - @Column(name = "class_id", length = 64) - private String classId; + @Column(name = "class_id") + private Integer classId; /** 阅读状态:0 UNREAD / 1 READ */ @Column(name = "is_read", nullable = false) diff --git a/src/main/java/com/yunhai/homework/entity/HomeworkSubmission.java b/src/main/java/com/yunhai/homework/entity/HomeworkSubmission.java index 4626044..cfd95bb 100644 --- a/src/main/java/com/yunhai/homework/entity/HomeworkSubmission.java +++ b/src/main/java/com/yunhai/homework/entity/HomeworkSubmission.java @@ -41,8 +41,8 @@ public class HomeworkSubmission extends BaseEntity { private String studentName; /** 班级ID */ - @Column(name = "class_id", nullable = false, length = 64) - private String classId; + @Column(name = "class_id", nullable = false) + private Integer classId; /** 班级名快照 */ @Column(name = "class_name", nullable = false, length = 50) diff --git a/src/main/java/com/yunhai/homework/entity/SchClassTeach.java b/src/main/java/com/yunhai/homework/entity/SchClassTeach.java deleted file mode 100644 index d1a091f..0000000 --- a/src/main/java/com/yunhai/homework/entity/SchClassTeach.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.yunhai.homework.entity; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; - -/** - * 班级任教关系快照(bschclass sch_class_teach 本地镜像,PRD 口径同 class_student)。 - *

- * 由同步任务从 bschclass 拉取(接口未就绪前用种子数据);bschclass 任教接口 - * 不可用时,任教学科链路降级读本表。教师口径:用户中心数字ID(UserContext.getUserId()); - * class_id 与 class_student.class_id 同一取值域。 - */ -@NoArgsConstructor -@Data -@Entity -@Table(name = "sch_class_teach", - uniqueConstraints = @UniqueConstraint(name = "uk_sch_class_teach", columnNames = {"school_id", "class_id", "tea_id", "sub_id"})) -@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) -public class SchClassTeach extends BaseEntity { - - /** 学校ID */ - @Column(name = "school_id", nullable = false) - private Integer schoolId; - - /** 班级ID(与 class_student.class_id 同一取值域) */ - @Column(name = "class_id", nullable = false, length = 64) - private String classId; - - /** 教师ID(用户中心数字ID) */ - @Column(name = "tea_id", nullable = false) - private Integer teaId; - - /** 学科编码(bschclass SubID;本地无字典时编码即展示名) */ - @Column(name = "sub_id", nullable = false, length = 64) - private String subId; - - /** 有效状态:1 有效 / 0 失效 */ - @Column(name = "status", nullable = false) - private Integer status = 1; -} diff --git a/src/main/java/com/yunhai/homework/job/HomeworkScheduledJobs.java b/src/main/java/com/yunhai/homework/job/HomeworkScheduledJobs.java index 5377254..cdb013c 100644 --- a/src/main/java/com/yunhai/homework/job/HomeworkScheduledJobs.java +++ b/src/main/java/com/yunhai/homework/job/HomeworkScheduledJobs.java @@ -3,9 +3,7 @@ package com.yunhai.homework.job; import com.yunhai.homework.entity.Homework; import com.yunhai.homework.enums.HwStatusEnum; import com.yunhai.homework.enums.NotificationTypeEnum; -import com.yunhai.homework.repository.HomeworkClassRepository; import com.yunhai.homework.repository.HomeworkRepository; -import com.yunhai.homework.service.impl.ClassStudentService; import com.yunhai.homework.service.impl.HomeworkStateService; import com.yunhai.homework.service.impl.NotificationService; import com.yunhai.homework.service.impl.TeacherHomeworkV2Service; @@ -33,9 +31,6 @@ public class HomeworkScheduledJobs { @Autowired private HomeworkRepository homeworkRepository; - @Autowired - private HomeworkClassRepository homeworkClassRepository; - @Autowired private HomeworkStateService stateService; @@ -45,9 +40,6 @@ public class HomeworkScheduledJobs { @Autowired private TeacherHomeworkV2Service teacherHomeworkV2Service; - @Autowired - private ClassStudentService classStudentService; - /** * 定时发布:每分钟扫描到点的 DRAFT_SCHEDULED 作业 → PUBLISHED + 作业发布通知; * 失败回退 DRAFT_UNPUBLISHED 并站内通知教师。 @@ -146,16 +138,4 @@ public class HomeworkScheduledJobs { NotificationService.deadlineReminderContent(homework) + "(剩余不足 " + slotDesc + ")"); log.info("[deadlineReminder] homeworkId={}, slot={}, sent={}", homework.getId(), slot, sent); } - - /** - * 名册同步:每日 02:00 全量刷新 class_student(bschclass 接口就绪前仅日志)。 - */ - @Scheduled(cron = "${homework.sync.class-data-cron:0 0 2 * * ?}") - public void classDataSync() { - try { - classStudentService.syncAll(); - } catch (Exception e) { - log.error("[classDataSync] 名册同步失败", e); - } - } } diff --git a/src/main/java/com/yunhai/homework/model/v2/ClassItem.java b/src/main/java/com/yunhai/homework/model/v2/ClassItem.java index 459ea80..da3c3a0 100644 --- a/src/main/java/com/yunhai/homework/model/v2/ClassItem.java +++ b/src/main/java/com/yunhai/homework/model/v2/ClassItem.java @@ -12,7 +12,7 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class ClassItem { - private String classId; + private Integer classId; private String className; } diff --git a/src/main/java/com/yunhai/homework/model/v2/ClassTreeNode.java b/src/main/java/com/yunhai/homework/model/v2/ClassTreeNode.java index c0f400b..4ea7896 100644 --- a/src/main/java/com/yunhai/homework/model/v2/ClassTreeNode.java +++ b/src/main/java/com/yunhai/homework/model/v2/ClassTreeNode.java @@ -7,12 +7,12 @@ import java.util.List; /** * 年级→班级树(发布作业选班 + 应交名单基数来源)。 - * 叶子节点 id = 班级 id(class_student 快照聚合)。 + * 叶子节点 id = 班级 id(bschclass 班级/年级实时组装)。 */ @Data public class ClassTreeNode { - /** 年级节点为 gradeName,班级叶子为 classId */ + /** 年级节点为年级ID(无年级归属时为「未分组」文案),班级叶子为 classId */ private String id; /** 展示名 */ diff --git a/src/main/java/com/yunhai/homework/model/v2/HomeworkStatsVo.java b/src/main/java/com/yunhai/homework/model/v2/HomeworkStatsVo.java index 1ac46f8..1cf2c88 100644 --- a/src/main/java/com/yunhai/homework/model/v2/HomeworkStatsVo.java +++ b/src/main/java/com/yunhai/homework/model/v2/HomeworkStatsVo.java @@ -27,7 +27,7 @@ public class HomeworkStatsVo { @Data public static class ByClass { - private String classId; + private Integer classId; private String className; diff --git a/src/main/java/com/yunhai/homework/model/v2/HomeworkV2Request.java b/src/main/java/com/yunhai/homework/model/v2/HomeworkV2Request.java index 9464910..671ebd7 100644 --- a/src/main/java/com/yunhai/homework/model/v2/HomeworkV2Request.java +++ b/src/main/java/com/yunhai/homework/model/v2/HomeworkV2Request.java @@ -26,7 +26,7 @@ public class HomeworkV2Request { private String description; /** 参与班级 id 列表 */ - private List classIds; + private List classIds; /** 附件列表 */ private List attachments; diff --git a/src/main/java/com/yunhai/homework/model/v2/StudentMatrixQuery.java b/src/main/java/com/yunhai/homework/model/v2/StudentMatrixQuery.java index 49e3144..fcb531a 100644 --- a/src/main/java/com/yunhai/homework/model/v2/StudentMatrixQuery.java +++ b/src/main/java/com/yunhai/homework/model/v2/StudentMatrixQuery.java @@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode; public class StudentMatrixQuery extends BasePageQuery { /** 班级筛选(空 = 全部参与班级) */ - private String classId; + private Integer classId; /** 提交状态筛选:NOT_SUBMITTED/SUBMITTED/LATE_SUBMITTED/RETURNED/REVIEWED */ private String submitStatus; diff --git a/src/main/java/com/yunhai/homework/model/v2/StudentMatrixVo.java b/src/main/java/com/yunhai/homework/model/v2/StudentMatrixVo.java index 6257285..b80bb2c 100644 --- a/src/main/java/com/yunhai/homework/model/v2/StudentMatrixVo.java +++ b/src/main/java/com/yunhai/homework/model/v2/StudentMatrixVo.java @@ -21,7 +21,7 @@ public class StudentMatrixVo { /** 姓名 */ private String studentName; - private String classId; + private Integer classId; private String className; diff --git a/src/main/java/com/yunhai/homework/model/v2/TeachingClassVo.java b/src/main/java/com/yunhai/homework/model/v2/TeachingClassVo.java index d9fd64e..b675060 100644 --- a/src/main/java/com/yunhai/homework/model/v2/TeachingClassVo.java +++ b/src/main/java/com/yunhai/homework/model/v2/TeachingClassVo.java @@ -9,7 +9,7 @@ import lombok.Data; public class TeachingClassVo { /** 班级业务ID(bschclass sch_class.class_id) */ - private String classId; + private Integer classId; /** 班级名称(学校班级列表映射;缺失时回退为班级ID) */ private String className; diff --git a/src/main/java/com/yunhai/homework/repository/ClassStudentRepository.java b/src/main/java/com/yunhai/homework/repository/ClassStudentRepository.java deleted file mode 100644 index 0581e29..0000000 --- a/src/main/java/com/yunhai/homework/repository/ClassStudentRepository.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.yunhai.homework.repository; - -import com.yunhai.homework.entity.ClassStudent; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; - -/** - * 班级学生名册仓储。 - */ -public interface ClassStudentRepository extends JpaRepository { - - /** 按学生ID(用户中心数字ID)反查学生身份(学生端接口入口) */ - List findByStudentIdAndStatus(Integer studentId, Integer status); - - /** 班级在班学生 */ - List findByClassIdAndStatus(String classId, Integer status); - - /** 指定班级集合的全部在班学生(应交名单) */ - List findByClassIdInAndStatus(List classIds, Integer status); - - /** 指定学校的全部名册(同步任务全量刷新用) */ - List findBySchoolId(Integer schoolId); - - /** 年级→班级树:按学校去重班级(class_student 快照聚合),列序:classId, className, gradeName */ - @Query("select distinct c.classId, c.className, c.gradeName from ClassStudent c " + - "where c.schoolId = :schoolId and c.status = 1") - List findDistinctClasses(@Param("schoolId") Integer schoolId); -} diff --git a/src/main/java/com/yunhai/homework/repository/HomeworkClassRepository.java b/src/main/java/com/yunhai/homework/repository/HomeworkClassRepository.java index 8f651f5..80f3835 100644 --- a/src/main/java/com/yunhai/homework/repository/HomeworkClassRepository.java +++ b/src/main/java/com/yunhai/homework/repository/HomeworkClassRepository.java @@ -18,7 +18,7 @@ public interface HomeworkClassRepository extends JpaRepository findHomeworkIdsByClassIds(@Param("classIds") List classIds); + List findHomeworkIdsByClassIds(@Param("classIds") List classIds); /** 批量查 N 个作业的班级关联(列表展示避免 N+1) */ @Query("select c from HomeworkClass c where c.homeworkId in :homeworkIds") diff --git a/src/main/java/com/yunhai/homework/repository/SchClassTeachRepository.java b/src/main/java/com/yunhai/homework/repository/SchClassTeachRepository.java deleted file mode 100644 index 8e60f47..0000000 --- a/src/main/java/com/yunhai/homework/repository/SchClassTeachRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.yunhai.homework.repository; - -import com.yunhai.homework.entity.SchClassTeach; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; - -/** - * 班级任教关系快照仓储。 - */ -public interface SchClassTeachRepository extends JpaRepository { - - /** 指定学校指定教师的全部有效任教记录 */ - List findBySchoolIdAndTeaIdAndStatus(Integer schoolId, Integer teaId, Integer status); - - /** 指定学校指定教师去重学科编码(字典序由调用方保证) */ - @Query("select distinct t.subId from SchClassTeach t " + - "where t.schoolId = :schoolId and t.teaId = :teaId and t.status = 1") - List findDistinctSubIds(@Param("schoolId") Integer schoolId, @Param("teaId") Integer teaId); -} diff --git a/src/main/java/com/yunhai/homework/service/impl/ClassStudentService.java b/src/main/java/com/yunhai/homework/service/impl/ClassStudentService.java deleted file mode 100644 index 0785269..0000000 --- a/src/main/java/com/yunhai/homework/service/impl/ClassStudentService.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.yunhai.homework.service.impl; - -import com.yunhai.homework.entity.ClassStudent; -import com.yunhai.homework.repository.ClassStudentRepository; -import com.yunhai.homework.utils.UserContext; -import com.yunhai.platform.apistd.BizException; -import com.yunhai.platform.utils.exception.ErrorCode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -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.stream.Collectors; - -/** - * 班级学生名册服务:学生端身份映射 + 名册同步任务入口。 - *

- * 身份口径:当前登录人用户中心数字ID(UserContext.getUserId(),即 SchStudent.UserStuSerID) - * ↔ class_student.student_id(status=1 在班)。名册不再存登录账号。 - * bschclass 名册开放接口未就绪期间(计划 §13-1),联调用种子数据 - * (sql/v3_seed.sql)填充本表;syncAll() 预留同步实现位。 - */ -@Service -public class ClassStudentService { - - private static final Logger log = LoggerFactory.getLogger(ClassStudentService.class); - - @Autowired - private ClassStudentRepository classStudentRepository; - - /** - * 当前登录用户ID对应的学生名册行(在班)。 - * - * @throws BizException 未登录或用户ID未匹配名册 - */ - public List resolveMe() { - Integer userId = UserContext.getUserId(); - if (userId == null) { - throw new BizException(ErrorCode.FORBIDDEN, "未获取到登录身份"); - } - List me = classStudentRepository.findByStudentIdAndStatus(userId, 1); - if (me.isEmpty()) { - throw new BizException(ErrorCode.FORBIDDEN, "当前用户未匹配到学生名册,请联系管理员确认班级名册"); - } - return me; - } - - /** - * 学生 id(多班级重复时取第一个;学籍号一人一号,正常唯一)。 - */ - public Integer resolveMyStudentId() { - return resolveMe().get(0).getStudentId(); - } - - /** - * 我所在的班级 id 集合。 - */ - public List resolveMyClassIds() { - return resolveMe().stream().map(ClassStudent::getClassId).distinct().collect(Collectors.toList()); - } - - /** - * 名册全量同步(每日 Job / 手动触发)。 - * TODO bschclass「按学校查年级班级树+学生名册」开放接口就绪后接入 - * (参照 ClassService.getSchTeaList 的直连模式);未就绪时仅记录日志跳过。 - */ - @Transactional - public int syncAll() { - log.warn("[syncAll] bschclass 名册开放接口未就绪,本轮跳过(联调请执行 sql/v3_seed.sql 种子数据)"); - return 0; - } - - /** - * 班级在班学生(运维排查/种子校验用)。 - */ - public List findByClassId(String classId) { - return classStudentRepository.findByClassIdAndStatus(classId, 1); - } -} diff --git a/src/main/java/com/yunhai/homework/service/impl/HomeworkProgressCalculator.java b/src/main/java/com/yunhai/homework/service/impl/HomeworkProgressCalculator.java index 2e66e31..eac4203 100644 --- a/src/main/java/com/yunhai/homework/service/impl/HomeworkProgressCalculator.java +++ b/src/main/java/com/yunhai/homework/service/impl/HomeworkProgressCalculator.java @@ -1,19 +1,15 @@ package com.yunhai.homework.service.impl; -import com.yunhai.homework.entity.ClassStudent; import com.yunhai.homework.entity.HomeworkReadRecord; import com.yunhai.homework.entity.HomeworkSubmission; import com.yunhai.homework.enums.SubmitStatusEnum; import com.yunhai.homework.model.v2.ProgressVo; -import com.yunhai.homework.repository.ClassStudentRepository; import com.yunhai.homework.repository.HomeworkReadRecordRepository; import com.yunhai.homework.repository.HomeworkSubmissionRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; import java.util.ArrayList; -import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; @@ -27,40 +23,31 @@ import java.util.stream.Collectors; * 单作业量级 ≤ 数百人,全部实时聚合不落冗余字段: * should = 参与班级在班学生去重数;submitted = 当前版本 status ∈ 已交集合; * graded = REVIEWED;unreadUndone = should −(已读 ∪ 已交)。 + * 名册实时取 bschclass({@link RosterService},GetClaArrStulist),无本地快照。 */ @Service public class HomeworkProgressCalculator { - /** - * 名册条目(去重前):矩阵与提醒名单需要 班级×学生 维度。 - */ - public static class RosterEntry { - public Integer studentId; - public String studentName; - public String classId; - public String className; - } - /** * 聚合结果:总进度 + 分班进度 + 全量名册(班级×学生)。 */ public static class Result { public ProgressVo total; public List byClass = new ArrayList<>(); - public List roster = new ArrayList<>(); + public List roster = new ArrayList<>(); } /** * 分班进度条目。 */ public static class ClassProgress { - public String classId; + public Integer classId; public String className; public ProgressVo progress; } @Autowired - private ClassStudentRepository classStudentRepository; + private RosterService rosterService; @Autowired private HomeworkReadRecordRepository readRecordRepository; @@ -73,25 +60,18 @@ public class HomeworkProgressCalculator { * * @param classIds 参与班级 id(homework_class 解析结果) */ - public Result compute(Integer homeworkId, List classIds) { + public Result compute(Integer homeworkId, List classIds) { Result result = new Result(); - // 1. 名册:班级×学生(应交基数) - List roster = classIds == null || classIds.isEmpty() - ? new ArrayList<>() - : classStudentRepository.findByClassIdInAndStatus(classIds, 1); + // 1. 名册:班级×学生(应交基数,实时 bschclass) + List roster = rosterService.roster(classIds); Set distinctStudents = new HashSet<>(); - for (ClassStudent cs : roster) { - RosterEntry entry = new RosterEntry(); - entry.studentId = cs.getStudentId(); - entry.studentName = cs.getStudentName(); - entry.classId = cs.getClassId(); - entry.className = cs.getClassName(); - result.roster.add(entry); - distinctStudents.add(cs.getStudentId()); + for (RosterService.RosterEntry cs : roster) { + result.roster.add(cs); + distinctStudents.add(cs.studentId); } - result.roster.sort(Comparator - .comparing((RosterEntry e) -> nullSafe(e.className)) + result.roster.sort(java.util.Comparator + .comparing((RosterService.RosterEntry e) -> nullSafe(e.className)) .thenComparing(e -> nullSafe(e.studentName))); // 2. 已读集合 @@ -109,9 +89,9 @@ public class HomeworkProgressCalculator { result.total = aggregate(distinctStudents, readSet, latest); // 5. 分班进度(班级维度不去重,矩阵口径) - Map> byClassEntries = result.roster.stream() - .collect(Collectors.groupingBy(e -> nullSafe(e.classId), LinkedHashMap::new, Collectors.toList())); - for (Map.Entry> e : byClassEntries.entrySet()) { + Map> byClassEntries = result.roster.stream() + .collect(Collectors.groupingBy(e -> e.classId, LinkedHashMap::new, Collectors.toList())); + for (Map.Entry> e : byClassEntries.entrySet()) { Set classStudentIds = e.getValue().stream().map(r -> r.studentId).collect(Collectors.toSet()); ClassProgress cp = new ClassProgress(); cp.classId = e.getKey(); diff --git a/src/main/java/com/yunhai/homework/service/impl/HomeworkService.java b/src/main/java/com/yunhai/homework/service/impl/HomeworkService.java index 669dd8b..a828e0d 100644 --- a/src/main/java/com/yunhai/homework/service/impl/HomeworkService.java +++ b/src/main/java/com/yunhai/homework/service/impl/HomeworkService.java @@ -354,14 +354,14 @@ public class HomeworkService implements IHomeworkService { if (collectableIds.isEmpty()) { return; } - Map> classMap = homeworkClassRepository.findByHomeworkIds(collectableIds).stream() + Map> classMap = homeworkClassRepository.findByHomeworkIds(collectableIds).stream() .collect(Collectors.groupingBy(c -> c.getHomeworkId(), Collectors.mapping(c -> c.getClassId(), Collectors.toList()))); for (HomeworkVo vo : content) { if (!collectableIds.contains(vo.getId())) { continue; } - List classIds = classMap.getOrDefault(vo.getId(), Collections.emptyList()); + List classIds = classMap.getOrDefault(vo.getId(), Collections.emptyList()); ProgressVo progress = homeworkProgressCalculator.compute(vo.getId(), classIds).total; vo.setProgress(progress); } @@ -776,7 +776,7 @@ public class HomeworkService implements IHomeworkService { } List hwIds = collected.stream().map(Homework::getId).collect(Collectors.toList()); - Map> classMap = homeworkClassRepository.findByHomeworkIds(hwIds).stream() + Map> classMap = homeworkClassRepository.findByHomeworkIds(hwIds).stream() .collect(Collectors.groupingBy(HomeworkClass::getHomeworkId, Collectors.mapping(HomeworkClass::getClassId, Collectors.toList()))); @@ -787,7 +787,7 @@ public class HomeworkService implements IHomeworkService { long excellent = 0, good = 0, pass = 0, fail = 0; for (Homework h : collected) { - List classIds = classMap.getOrDefault(h.getId(), Collections.emptyList()); + List classIds = classMap.getOrDefault(h.getId(), Collections.emptyList()); ProgressVo p = homeworkProgressCalculator.compute(h.getId(), classIds).total; HomeworkStatisticsVo.HomeworkStat d = new HomeworkStatisticsVo.HomeworkStat(); @@ -898,8 +898,7 @@ public class HomeworkService implements IHomeworkService { return names; } return classes.stream() - .map(HomeworkClass::getClassId) - .filter(StringUtils::hasText) + .map(c -> String.valueOf(c.getClassId())) .collect(Collectors.joining("、")); } diff --git a/src/main/java/com/yunhai/homework/service/impl/StudentHomeworkService.java b/src/main/java/com/yunhai/homework/service/impl/StudentHomeworkService.java index 7cf7753..14f67bf 100644 --- a/src/main/java/com/yunhai/homework/service/impl/StudentHomeworkService.java +++ b/src/main/java/com/yunhai/homework/service/impl/StudentHomeworkService.java @@ -1,6 +1,5 @@ package com.yunhai.homework.service.impl; -import com.yunhai.homework.entity.ClassStudent; import com.yunhai.homework.entity.Homework; import com.yunhai.homework.entity.HomeworkAttachment; import com.yunhai.homework.entity.HomeworkClass; @@ -19,7 +18,6 @@ import com.yunhai.homework.model.v2.StudentResultVo; import com.yunhai.homework.model.v2.StudentSubmitRequest; import com.yunhai.homework.model.v2.SubmissionActionRequest; import com.yunhai.homework.model.v2.SubmissionVersionVo; -import com.yunhai.homework.repository.ClassStudentRepository; import com.yunhai.homework.repository.HomeworkAttachmentRepository; import com.yunhai.homework.repository.HomeworkClassRepository; import com.yunhai.homework.repository.HomeworkReadRecordRepository; @@ -46,8 +44,8 @@ import java.util.stream.Collectors; /** * 课堂作业 V2 学生端业务(PRD §18 学生页 1~3)。 *

- * 身份:登录平台用户ID ↔ class_student.student_id 名册(ClassStudentService);仅可见本人班级作业。 - * 提交多版本:提交/打回重交/撤回均新增行(version+1、is_latest 翻转),历史保留。 + * 身份:登录平台用户ID ↔ bschclass 学生名册({@link RosterService} 实时匹配,无本地快照); + * 仅可见本人班级作业。提交多版本:提交/打回重交/撤回均新增行(version+1、is_latest 翻转),历史保留。 */ @Service public class StudentHomeworkService { @@ -71,10 +69,7 @@ public class StudentHomeworkService { private SubmissionAttachmentRepository submissionAttachmentRepository; @Autowired - private ClassStudentRepository classStudentRepository; - - @Autowired - private ClassStudentService classStudentService; + private RosterService rosterService; // ============================ 页 1:作业列表 ============================ @@ -83,9 +78,9 @@ public class StudentHomeworkService { */ @Transactional(readOnly = true) public BasePageResult list(String tab, com.yunhai.homework.model.BasePageQuery query) { - List me = classStudentService.resolveMe(); - List myClassIds = me.stream().map(ClassStudent::getClassId).distinct().collect(Collectors.toList()); - Integer myStudentId = me.get(0).getStudentId(); + List me = rosterService.mine(); + List myClassIds = me.stream().map(e -> e.classId).distinct().collect(Collectors.toList()); + Integer myStudentId = me.get(0).studentId; List homeworkIds = homeworkClassRepository.findHomeworkIdsByClassIds(myClassIds); if (homeworkIds.isEmpty()) { @@ -182,16 +177,16 @@ public class StudentHomeworkService { if (status != HwStatusEnum.PUBLISHED && status != HwStatusEnum.CLOSED) { return; } - ClassStudent mine = classStudentService.resolveMe().get(0); + RosterService.RosterEntry mine = rosterService.mine().get(0); LocalDateTime now = LocalDateTime.now(); - HomeworkReadRecord record = readRecordRepository.findByHomeworkIdAndStudentId(id, mine.getStudentId()) + HomeworkReadRecord record = readRecordRepository.findByHomeworkIdAndStudentId(id, mine.studentId) .orElse(null); if (record == null) { record = new HomeworkReadRecord(); record.setHomeworkId(id); - record.setStudentId(mine.getStudentId()); - record.setStudentName(mine.getStudentName()); - record.setClassId(mine.getClassId()); + record.setStudentId(mine.studentId); + record.setStudentName(mine.studentName); + record.setClassId(mine.classId); record.setIsRead(1); record.setFirstReadAt(now); record.setLastReadAt(now); @@ -210,9 +205,9 @@ public class StudentHomeworkService { @Transactional(readOnly = true) public StudentResultVo result(Integer id) { Homework homework = requireVisible(id); - ClassStudent mine = classStudentService.resolveMe().get(0); + RosterService.RosterEntry mine = rosterService.mine().get(0); List versions = - submissionRepository.findByHomeworkIdAndStudentIdOrderByVersionDesc(id, mine.getStudentId()); + submissionRepository.findByHomeworkIdAndStudentIdOrderByVersionDesc(id, mine.studentId); StudentResultVo vo = new StudentResultVo(); vo.setHomeworkId(id); vo.setHomeworkTitle(homework.getTitle()); @@ -281,7 +276,7 @@ public class StudentHomeworkService { // ============================ 提交内核 ============================ private Integer doSubmit(Homework homework, String text, List attachments) { - ClassStudent mine = classStudentService.resolveMe().get(0); + RosterService.RosterEntry mine = rosterService.mine().get(0); HwStatusEnum hwStatus = HwStatusEnum.of(homework.getHwStatus()); if (hwStatus == HwStatusEnum.ARCHIVED) { throw new BizException(ErrorCode.FORBIDDEN, "作业已归档,不可提交"); @@ -320,9 +315,9 @@ public class StudentHomeworkService { } HomeworkSubmission submission = new HomeworkSubmission(); fillSnapshot(submission, homework); - submission.setStudentId(mine.getStudentId()); - submission.setStudentName(mine.getStudentName()); - submission.setVersion(nextVersion(homework.getId(), mine.getStudentId())); + submission.setStudentId(mine.studentId); + submission.setStudentName(mine.studentName); + submission.setVersion(nextVersion(homework.getId(), mine.studentId)); submission.setIsLatest(1); submission.setStatus(late ? SubmitStatusEnum.LATE_SUBMITTED.getCode() : SubmitStatusEnum.SUBMITTED.getCode()); submission.setIsLate(late ? 1 : 0); @@ -333,10 +328,10 @@ public class StudentHomeworkService { int sort = 0; for (AttachmentItem item : items) { - SubmissionAttachment sa = new SubmissionAttachment(); - sa.setSubmissionId(submission.getId()); - sa.setHomeworkId(homework.getId()); - sa.setStudentId(mine.getStudentId()); + SubmissionAttachment sa = new SubmissionAttachment(); + sa.setSubmissionId(submission.getId()); + sa.setHomeworkId(homework.getId()); + sa.setStudentId(mine.studentId); sa.setFileId(item.getFileId()); sa.setFileUrl(item.getFileUrl()); sa.setFileType(item.getFileType()); @@ -355,15 +350,15 @@ public class StudentHomeworkService { private void fillSnapshot(HomeworkSubmission submission, Homework homework) { submission.setHomeworkId(homework.getId()); - ClassStudent mine = classStudentService.resolveMe().get(0); - submission.setClassId(mine.getClassId()); - submission.setClassName(mine.getClassName() == null ? mine.getClassId() : mine.getClassName()); + RosterService.RosterEntry mine = rosterService.mine().get(0); + submission.setClassId(mine.classId); + submission.setClassName(mine.className == null ? String.valueOf(mine.classId) : mine.className); // studentId/studentName 由调用方覆盖(fillSnapshot 先行填充默认) if (submission.getStudentId() == null) { - submission.setStudentId(mine.getStudentId()); + submission.setStudentId(mine.studentId); } if (submission.getStudentName() == null) { - submission.setStudentName(mine.getStudentName()); + submission.setStudentName(mine.studentName); } } @@ -378,7 +373,8 @@ public class StudentHomeworkService { if (!visibleStatus(HwStatusEnum.of(homework.getHwStatus()))) { throw new BizException(ErrorCode.FORBIDDEN, "作业不在可见范围"); } - List myClassIds = classStudentService.resolveMyClassIds(); + List myClassIds = rosterService.mine().stream() + .map(e -> e.classId).distinct().collect(Collectors.toList()); boolean hit = homeworkClassRepository.findByHomeworkId(homeworkId).stream() .map(HomeworkClass::getClassId) .anyMatch(myClassIds::contains); @@ -397,7 +393,7 @@ public class StudentHomeworkService { } private HomeworkSubmission myLatest(Integer homeworkId) { - Integer studentId = classStudentService.resolveMyStudentId(); + Integer studentId = rosterService.mine().get(0).studentId; return submissionRepository.findByHomeworkIdAndStudentIdAndIsLatest(homeworkId, studentId, 1) .orElse(null); } diff --git a/src/main/java/com/yunhai/homework/service/impl/TeacherHomeworkV2Service.java b/src/main/java/com/yunhai/homework/service/impl/TeacherHomeworkV2Service.java index 035270f..91df264 100644 --- a/src/main/java/com/yunhai/homework/service/impl/TeacherHomeworkV2Service.java +++ b/src/main/java/com/yunhai/homework/service/impl/TeacherHomeworkV2Service.java @@ -2,7 +2,6 @@ package com.yunhai.homework.service.impl; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.annotation.ExcelProperty; -import com.yunhai.homework.entity.ClassStudent; import com.yunhai.homework.entity.Homework; import com.yunhai.homework.entity.HomeworkAttachment; import com.yunhai.homework.entity.HomeworkClass; @@ -15,6 +14,7 @@ import com.yunhai.homework.enums.ReviewStatusEnum; import com.yunhai.homework.enums.SubmitStatusEnum; import com.yunhai.homework.model.BasePageResult; import com.yunhai.homework.model.bsch.SchClassDto; +import com.yunhai.homework.model.bsch.SchGradeDto; import com.yunhai.homework.model.bsch.SchInfoDto; import com.yunhai.homework.model.bsch.SchSubjectDto; import com.yunhai.homework.model.bsch.SchTeachDto; @@ -35,14 +35,12 @@ import com.yunhai.homework.model.v2.SubmissionVersionVo; import com.yunhai.homework.model.v2.SubjectDto; import com.yunhai.homework.model.v2.TeacherHomeworkQuery; import com.yunhai.homework.model.v2.TeachingClassVo; -import com.yunhai.homework.repository.ClassStudentRepository; import com.yunhai.homework.repository.HomeworkAttachmentRepository; import com.yunhai.homework.repository.HomeworkClassRepository; import com.yunhai.homework.repository.HomeworkReadRecordRepository; import com.yunhai.homework.repository.HomeworkRepository; import com.yunhai.homework.repository.HomeworkSubmissionRepository; import com.yunhai.homework.repository.NotificationRepository; -import com.yunhai.homework.repository.SchClassTeachRepository; import com.yunhai.homework.repository.SubmissionAttachmentRepository; import com.yunhai.homework.service.IClassService; import com.yunhai.homework.utils.PageUtils; @@ -110,10 +108,7 @@ public class TeacherHomeworkV2Service { private SubmissionAttachmentRepository submissionAttachmentRepository; @Autowired - private ClassStudentRepository classStudentRepository; - - @Autowired - private SchClassTeachRepository schClassTeachRepository; + private RosterService rosterService; @Autowired private NotificationRepository notificationRepository; @@ -197,21 +192,22 @@ public class TeacherHomeworkV2Service { homework.setRemind1d(request.getRemind1d() == null ? 1 : request.getRemind1d()); homework.setRemind1h(request.getRemind1h() == null ? 1 : request.getRemind1h()); if (request.getClassIds() != null && !request.getClassIds().isEmpty()) { - homework.setReceiveList(String.join(",", request.getClassIds())); + homework.setReceiveList(request.getClassIds().stream() + .map(String::valueOf).collect(Collectors.joining(","))); } } - private void saveChildren(Homework homework, List classIds, List attachments) { + private void saveChildren(Homework homework, List classIds, List attachments) { saveClasses(homework, classIds); saveAttachments(homework, attachments); } - private void saveClasses(Homework homework, List classIds) { + private void saveClasses(Homework homework, List classIds) { if (classIds == null || classIds.isEmpty()) { throw new BizException(ErrorCode.FORBIDDEN, "请至少选择一个参与班级"); } - List distinct = classIds.stream().filter(StringUtils::hasText).distinct().collect(Collectors.toList()); - for (String classId : distinct) { + List distinct = classIds.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList()); + for (Integer classId : distinct) { HomeworkClass hc = new HomeworkClass(); hc.setHomeworkId(homework.getId()); hc.setClassId(classId); @@ -241,13 +237,9 @@ public class TeacherHomeworkV2Service { } } - /** 班级名快照:优先取名册,无名册时回退班级 id */ - private String resolveClassName(String classId) { - return classStudentRepository.findByClassIdAndStatus(classId, 1).stream() - .map(ClassStudent::getClassName) - .filter(StringUtils::hasText) - .findFirst() - .orElse(classId); + /** 班级名快照:实时取 bschclass 班级列表映射,缺失时回退班级 id */ + private String resolveClassName(Integer classId) { + return rosterService.className(classId); } // ============================ 页 2:草稿箱 ============================ @@ -437,15 +429,13 @@ public class TeacherHomeworkV2Service { public BasePageResult students(Integer id, StudentMatrixQuery query) { Homework homework = stateService.requireOwned(id, UserContext.getUserId()); List classes = homeworkClassRepository.findByHomeworkId(id); - List classIds = classIds(classes); - if (StringUtils.hasText(query.getClassId())) { + List classIds = classIds(classes); + if (query.getClassId() != null) { classIds = classIds.stream().filter(c -> c.equals(query.getClassId())).collect(Collectors.toList()); } - // 名册(班级×学生) - List roster = classIds.isEmpty() - ? new ArrayList<>() - : classStudentRepository.findByClassIdInAndStatus(classIds, 1); + // 名册(班级×学生,实时 bschclass) + List roster = rosterService.roster(classIds); Map readMap = readRecordRepository.findByHomeworkId(id).stream() .collect(Collectors.toMap(HomeworkReadRecord::getStudentId, r -> r, (a, b) -> a)); Map latestMap = submissionRepository.findByHomeworkIdAndIsLatest(id, 1).stream() @@ -457,17 +447,17 @@ public class TeacherHomeworkV2Service { .collect(Collectors.groupingBy(SubmissionAttachment::getSubmissionId)); List rows = new ArrayList<>(); - for (ClassStudent cs : roster) { + for (RosterService.RosterEntry cs : roster) { StudentMatrixVo row = new StudentMatrixVo(); - row.setStudentId(cs.getStudentId()); - row.setStudentName(cs.getStudentName()); - row.setClassId(cs.getClassId()); - row.setClassName(cs.getClassName()); - HomeworkReadRecord read = readMap.get(cs.getStudentId()); + row.setStudentId(cs.studentId); + row.setStudentName(cs.studentName); + row.setClassId(cs.classId); + row.setClassName(cs.className); + HomeworkReadRecord read = readMap.get(cs.studentId); row.setIsRead(read != null && read.getIsRead() != null && read.getIsRead() == 1 ? 1 : 0); row.setFirstReadAt(read == null ? null : read.getFirstReadAt()); row.setLastReadAt(read == null ? null : read.getLastReadAt()); - HomeworkSubmission sub = latestMap.get(cs.getStudentId()); + HomeworkSubmission sub = latestMap.get(cs.studentId); if (sub == null) { row.setSubmissionId(0); row.setSubmitStatus(SubmitStatusEnum.NOT_SUBMITTED.getCode()); @@ -854,31 +844,66 @@ public class TeacherHomeworkV2Service { // ============================ 班级树 / 名册 ============================ /** - * 年级→班级树(发布选班;来自名册快照聚合)。 + * 年级→班级树(发布选班;全校班级,不按学科过滤)。 */ @Transactional(readOnly = true) public List classTree() { - Integer schId = UserContext.getSchId(); - if (schId == null) { + return classTree(null); + } + + /** + * 年级→班级树(发布选班)。数据源 bschclass 实时接口:班级 GetVClassList、 + * 年级 GetSchLenLevellist、在班人数 GetClaArrStulist(一次批量外呼); + * subId 非空时仅保留当前教师该学科的任教班级(GetSchTeachlist),空年级组不保留。 + */ + @Transactional(readOnly = true) + public List classTree(String subId) { + // subId=null 为无参全校树;显式传入空白串视为参数错误 + if (subId != null && !StringUtils.hasText(subId.trim())) { + throw new BizException(ErrorCode.PARAM_ERROR, "学科编码(subId)不得为空"); + } + String schSerId = currentSchSerId(); + if (schSerId == null) { return new ArrayList<>(); } - List rows = classStudentRepository.findDistinctClasses(schId); - Map> byGrade = rows.stream() - .collect(Collectors.groupingBy(r -> r[2] == null || !StringUtils.hasText(r[2].toString()) - ? "未分组" : r[2].toString(), java.util.LinkedHashMap::new, Collectors.toList())); + Set scope = null; + if (StringUtils.hasText(subId)) { + scope = teachingClassIds(schSerId, subId.trim()); + if (scope.isEmpty()) { + return new ArrayList<>(); + } + } + List classes = classService.getSchClassList(schSerId); + Map gradeNames = gradeNames(schSerId); + Map> byGrade = new java.util.LinkedHashMap<>(); + List scopeIds = new ArrayList<>(); + for (SchClassDto c : classes) { + if (c == null || c.getClassId() == null || (scope != null && !scope.contains(c.getClassId()))) { + continue; + } + byGrade.computeIfAbsent(c.getGradeId(), k -> new ArrayList<>()).add(c); + scopeIds.add(c.getClassId()); + } + if (scopeIds.isEmpty()) { + return new ArrayList<>(); + } + Map counts = rosterService.studentCounts(scopeIds); List tree = new ArrayList<>(); - for (Map.Entry> entry : byGrade.entrySet()) { + for (Map.Entry> entry : byGrade.entrySet()) { + Integer gradeId = entry.getKey(); + String gradeName = gradeId != null && gradeNames.containsKey(gradeId) + ? gradeNames.get(gradeId) : "未分组"; ClassTreeNode grade = new ClassTreeNode(); - grade.setId(entry.getKey()); - grade.setName(entry.getKey()); + grade.setId(gradeId == null ? gradeName : String.valueOf(gradeId)); + grade.setName(gradeName); grade.setIsParent(true); - for (Object[] r : entry.getValue()) { - String classId = String.valueOf(r[0]); + for (SchClassDto c : entry.getValue()) { ClassTreeNode leaf = new ClassTreeNode(); - leaf.setId(classId); - leaf.setName(r[1] == null || !StringUtils.hasText(r[1].toString()) ? classId : r[1].toString()); + leaf.setId(String.valueOf(c.getClassId())); + leaf.setName(StringUtils.hasText(c.getClassName()) + ? c.getClassName() : String.valueOf(c.getClassId())); leaf.setIsParent(false); - leaf.setStudentCount(classStudentRepository.findByClassIdAndStatus(classId, 1).size()); + leaf.setStudentCount(counts.getOrDefault(c.getClassId(), 0)); grade.getChildren().add(leaf); } tree.add(grade); @@ -886,6 +911,39 @@ public class TeacherHomeworkV2Service { return tree; } + /** + * 当前教师在 bschclass 的 subId 学科任教班级ID集合(实时 GetSchTeachlist, + * sch_class.class_id 取值域);远端不可用时异常向上抛,登录身份缺失时返回空集合。 + */ + private Set teachingClassIds(String schSerId, String subId) { + Set ids = new LinkedHashSet<>(); + Integer userId = UserContext.getUserId(); + if (schSerId == null || userId == null) { + return ids; + } + for (SchTeachDto teach : classService.getSchTeachList(schSerId, userId)) { + if (subId.equals(teach.getSubId()) && teach.getClassId() != null) { + ids.add(teach.getClassId()); + } + } + return ids; + } + + /** 学校年级ID → 年级名(bschclass GetSchLenLevellist;远端失败降级空映射,班级归入「未分组」) */ + private Map gradeNames(String schSerId) { + Map names = new java.util.LinkedHashMap<>(); + try { + for (SchGradeDto g : classService.getSchGradeList(schSerId)) { + if (g != null && g.getId() != null && StringUtils.hasText(g.getName())) { + names.put(g.getId(), g.getName()); + } + } + } catch (BizException e) { + log.warn("[classTree] 年级列表拉取失败, 降级「未分组」展示: {}", e.getMessage()); + } + return names; + } + // ============================ 学科(我布置的 / 我任教的) ============================ /** @@ -909,49 +967,27 @@ public class TeacherHomeworkV2Service { } /** - * 我的任教学科:bschclass 任教关系(sch_class_teach)当前教师去重学科, - * 名称经本校学科字典解析。 + * 我的任教学科:bschclass 任教关系当前教师去重学科,名称经本校学科字典解析。 */ public List teachingSubjects() { return toSubjectDtos(teachingSubjectCodes(), subjectDictionary()); } /** - * 我的任教去重学科编码:bschclass 任教关系(sch_class_teach)当前教师。 - * 登录身份缺学校/教师信息时返回空集合;远端不可用时降级读本地任教快照 - * (sch_class_teach,同 class_student 口径),快照也无记录则保持原语义向上抛出。 + * 我的任教去重学科编码:bschclass 任教关系(GetSchTeachlist)当前教师,实时获取。 + * 登录身份缺学校/教师信息时返回空集合;远端不可用时异常向上抛 + * (assignedSubjects 捕获后仅返回布置学科)。 */ private Set teachingSubjectCodes() { Set codes = new LinkedHashSet<>(); - try { - for (SchTeachDto teach : currentTeachList()) { - if (StringUtils.hasText(teach.getSubId())) { - codes.add(teach.getSubId()); - } + for (SchTeachDto teach : currentTeachList()) { + if (StringUtils.hasText(teach.getSubId())) { + codes.add(teach.getSubId()); } - } catch (BizException e) { - codes.addAll(localTeachingSubIds()); - if (codes.isEmpty()) { - throw e; - } - log.warn("[teachingSubjectCodes] bschclass 任教拉取失败, 降级本地任教快照: {}", e.getMessage()); } return codes; } - /** - * 当前教师在本地任教快照(sch_class_teach)中的去重学科编码; - * 缺学校/教师身份时返回空集合。 - */ - private Set localTeachingSubIds() { - Integer schId = UserContext.getSchId(); - Integer userId = UserContext.getUserId(); - if (schId == null || userId == null) { - return Collections.emptySet(); - } - return new LinkedHashSet<>(schClassTeachRepository.findDistinctSubIds(schId, userId)); - } - /** * 按学科筛选我的任教班级:任教关系当前教师该学科的班级去重, * 班级名称取学校班级列表(bschclass GetVClassList)映射并按其排序输出, @@ -966,12 +1002,7 @@ public class TeacherHomeworkV2Service { if (schSerId == null || userId == null) { return new ArrayList<>(); } - Set classIds = new LinkedHashSet<>(); - for (SchTeachDto teach : classService.getSchTeachList(schSerId, userId)) { - if (subId.equals(teach.getSubId()) && teach.getClassId() != null) { - classIds.add(teach.getClassId()); - } - } + Set classIds = teachingClassIds(schSerId, subId); if (classIds.isEmpty()) { return new ArrayList<>(); } @@ -994,7 +1025,7 @@ public class TeacherHomeworkV2Service { private static TeachingClassVo teachingClassVo(Integer classId, String className) { TeachingClassVo vo = new TeachingClassVo(); - vo.setClassId(String.valueOf(classId)); + vo.setClassId(classId); vo.setClassName(StringUtils.hasText(className) ? className : String.valueOf(classId)); return vo; } @@ -1012,7 +1043,7 @@ public class TeacherHomeworkV2Service { } /** - * 当前教师在 bschclass 的任教关系明细(sch_class_teach)。 + * 当前教师在 bschclass 的任教关系明细(GetSchTeachlist 实时)。 * 登录身份缺学校/教师信息时返回空列表;远端不可用时抛 BizException,由调用方决定是否降级。 */ private List currentTeachList() { @@ -1132,20 +1163,13 @@ public class TeacherHomeworkV2Service { // ============================ 名册辅助 ============================ - /** 参与班级在班学生 id 集合 */ + /** 参与班级在班学生 id 集合(实时 bschclass 名册) */ private List rosterStudentIds(Integer homeworkId) { - return roster(homeworkId).stream().map(ClassStudent::getStudentId).collect(Collectors.toList()); + return rosterService.roster(classIds(homeworkClassRepository.findByHomeworkId(homeworkId))) + .stream().map(e -> e.studentId).collect(Collectors.toList()); } - private List roster(Integer homeworkId) { - List classIds = classIds(homeworkClassRepository.findByHomeworkId(homeworkId)); - if (classIds.isEmpty()) { - return new ArrayList<>(); - } - return classStudentRepository.findByClassIdInAndStatus(classIds, 1); - } - - private static List classIds(List classes) { + private static List classIds(List classes) { return classes.stream().map(HomeworkClass::getClassId).collect(Collectors.toList()); }