@@ -25,7 +25,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* 课堂作业 V2 学生端接口(PRD §18 路径一字对齐:/student/homeworks…)。
|
* 课堂作业 V2 学生端接口(PRD §18 路径一字对齐:/student/homeworks…)。
|
||||||
* <p>
|
* <p>
|
||||||
* 身份:当前登录用户ID ↔ class_student 名册;仅可见本人班级作业,禁 IDOR。
|
* 身份:当前登录用户ID ↔ bschclass 学生名册(实时匹配);仅可见本人班级作业,禁 IDOR。
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = Config.API_PATH + "/student/homeworks")
|
@RequestMapping(value = Config.API_PATH + "/student/homeworks")
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import com.yunhai.homework.model.v2.SubmissionVersionVo;
|
|||||||
import com.yunhai.homework.model.v2.SubjectDto;
|
import com.yunhai.homework.model.v2.SubjectDto;
|
||||||
import com.yunhai.homework.model.v2.TeacherHomeworkQuery;
|
import com.yunhai.homework.model.v2.TeacherHomeworkQuery;
|
||||||
import com.yunhai.homework.model.v2.TeachingClassVo;
|
import com.yunhai.homework.model.v2.TeachingClassVo;
|
||||||
import com.yunhai.homework.service.impl.ClassStudentService;
|
|
||||||
import com.yunhai.homework.service.impl.TeacherHomeworkV2Service;
|
import com.yunhai.homework.service.impl.TeacherHomeworkV2Service;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
@@ -51,9 +50,6 @@ public class TeacherHomeworkV2Controller {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TeacherHomeworkV2Service teacherHomeworkV2Service;
|
private TeacherHomeworkV2Service teacherHomeworkV2Service;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ClassStudentService classStudentService;
|
|
||||||
|
|
||||||
// ============================ 页 1:发布作业 ============================
|
// ============================ 页 1:发布作业 ============================
|
||||||
|
|
||||||
/** 创建作业(落草稿) */
|
/** 创建作业(落草稿) */
|
||||||
@@ -198,22 +194,15 @@ public class TeacherHomeworkV2Controller {
|
|||||||
|
|
||||||
/** 按学科筛选我的任教班级(subId=学科编码;班级名称取学校班级列表) */
|
/** 按学科筛选我的任教班级(subId=学科编码;班级名称取学校班级列表) */
|
||||||
@GetMapping("/subjects/classes")
|
@GetMapping("/subjects/classes")
|
||||||
public List<TeachingClassVo> teachingClasses(@RequestParam("subId") String subId) {
|
public List<TeachingClassVo> teachingClasses(@RequestParam("subject") String subject) {
|
||||||
return teacherHomeworkV2Service.teachingClasses(subId);
|
return teacherHomeworkV2Service.teachingClasses(subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================ 辅助:班级树 / 名册同步 ============================
|
// ============================ 辅助:班级树 / 名册同步 ============================
|
||||||
|
|
||||||
/** 年级→班级树(发布选班;名册快照聚合) */
|
/** 年级→班级树(发布选班;subId 传学科编码时仅返回该学科任教班级) */
|
||||||
@GetMapping("/classes")
|
@GetMapping("/classes")
|
||||||
public List<ClassTreeNode> classTree() {
|
public List<ClassTreeNode> classTree(@RequestParam(value = "subject", required = false) String subject) {
|
||||||
return teacherHomeworkV2Service.classTree();
|
return teacherHomeworkV2Service.classTree(subject);
|
||||||
}
|
|
||||||
|
|
||||||
/** 手动触发名册同步(bschclass 接口就绪前为空操作) */
|
|
||||||
@PostMapping("/classes/sync")
|
|
||||||
public Map<String, Integer> syncClasses() {
|
|
||||||
int synced = classStudentService.syncAll();
|
|
||||||
return java.util.Collections.singletonMap("synced", synced);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)。
|
|
||||||
* <p>
|
|
||||||
* 由同步任务从 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;
|
|
||||||
}
|
|
||||||
@@ -26,8 +26,8 @@ public class HomeworkClass extends BaseEntity {
|
|||||||
private Integer homeworkId;
|
private Integer homeworkId;
|
||||||
|
|
||||||
/** 班级ID */
|
/** 班级ID */
|
||||||
@Column(name = "class_id", nullable = false, length = 64)
|
@Column(name = "class_id", nullable = false)
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
/** 班级名快照 */
|
/** 班级名快照 */
|
||||||
@Column(name = "class_name", length = 50)
|
@Column(name = "class_name", length = 50)
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ public class HomeworkReadRecord extends BaseEntity {
|
|||||||
private String studentName;
|
private String studentName;
|
||||||
|
|
||||||
/** 班级ID */
|
/** 班级ID */
|
||||||
@Column(name = "class_id", length = 64)
|
@Column(name = "class_id")
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
/** 阅读状态:0 UNREAD / 1 READ */
|
/** 阅读状态:0 UNREAD / 1 READ */
|
||||||
@Column(name = "is_read", nullable = false)
|
@Column(name = "is_read", nullable = false)
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ public class HomeworkSubmission extends BaseEntity {
|
|||||||
private String studentName;
|
private String studentName;
|
||||||
|
|
||||||
/** 班级ID */
|
/** 班级ID */
|
||||||
@Column(name = "class_id", nullable = false, length = 64)
|
@Column(name = "class_id", nullable = false)
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
/** 班级名快照 */
|
/** 班级名快照 */
|
||||||
@Column(name = "class_name", nullable = false, length = 50)
|
@Column(name = "class_name", nullable = false, length = 50)
|
||||||
|
|||||||
@@ -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)。
|
|
||||||
* <p>
|
|
||||||
* 由同步任务从 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;
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,7 @@ package com.yunhai.homework.job;
|
|||||||
import com.yunhai.homework.entity.Homework;
|
import com.yunhai.homework.entity.Homework;
|
||||||
import com.yunhai.homework.enums.HwStatusEnum;
|
import com.yunhai.homework.enums.HwStatusEnum;
|
||||||
import com.yunhai.homework.enums.NotificationTypeEnum;
|
import com.yunhai.homework.enums.NotificationTypeEnum;
|
||||||
import com.yunhai.homework.repository.HomeworkClassRepository;
|
|
||||||
import com.yunhai.homework.repository.HomeworkRepository;
|
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.HomeworkStateService;
|
||||||
import com.yunhai.homework.service.impl.NotificationService;
|
import com.yunhai.homework.service.impl.NotificationService;
|
||||||
import com.yunhai.homework.service.impl.TeacherHomeworkV2Service;
|
import com.yunhai.homework.service.impl.TeacherHomeworkV2Service;
|
||||||
@@ -33,9 +31,6 @@ public class HomeworkScheduledJobs {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private HomeworkRepository homeworkRepository;
|
private HomeworkRepository homeworkRepository;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HomeworkClassRepository homeworkClassRepository;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HomeworkStateService stateService;
|
private HomeworkStateService stateService;
|
||||||
|
|
||||||
@@ -45,9 +40,6 @@ public class HomeworkScheduledJobs {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TeacherHomeworkV2Service teacherHomeworkV2Service;
|
private TeacherHomeworkV2Service teacherHomeworkV2Service;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ClassStudentService classStudentService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时发布:每分钟扫描到点的 DRAFT_SCHEDULED 作业 → PUBLISHED + 作业发布通知;
|
* 定时发布:每分钟扫描到点的 DRAFT_SCHEDULED 作业 → PUBLISHED + 作业发布通知;
|
||||||
* 失败回退 DRAFT_UNPUBLISHED 并站内通知教师。
|
* 失败回退 DRAFT_UNPUBLISHED 并站内通知教师。
|
||||||
@@ -146,16 +138,4 @@ public class HomeworkScheduledJobs {
|
|||||||
NotificationService.deadlineReminderContent(homework) + "(剩余不足 " + slotDesc + ")");
|
NotificationService.deadlineReminderContent(homework) + "(剩余不足 " + slotDesc + ")");
|
||||||
log.info("[deadlineReminder] homeworkId={}, slot={}, sent={}", homework.getId(), slot, sent);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ClassItem {
|
public class ClassItem {
|
||||||
|
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
private String className;
|
private String className;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 年级→班级树(发布作业选班 + 应交名单基数来源)。
|
* 年级→班级树(发布作业选班 + 应交名单基数来源)。
|
||||||
* 叶子节点 id = 班级 id(class_student 快照聚合)。
|
* 叶子节点 id = 班级 id(bschclass 班级/年级实时组装)。
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class ClassTreeNode {
|
public class ClassTreeNode {
|
||||||
|
|
||||||
/** 年级节点为 gradeName,班级叶子为 classId */
|
/** 年级节点为年级ID(无年级归属时为「未分组」文案),班级叶子为 classId */
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
/** 展示名 */
|
/** 展示名 */
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class HomeworkStatsVo {
|
|||||||
@Data
|
@Data
|
||||||
public static class ByClass {
|
public static class ByClass {
|
||||||
|
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
private String className;
|
private String className;
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class HomeworkV2Request {
|
|||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
/** 参与班级 id 列表 */
|
/** 参与班级 id 列表 */
|
||||||
private List<String> classIds;
|
private List<Integer> classIds;
|
||||||
|
|
||||||
/** 附件列表 */
|
/** 附件列表 */
|
||||||
private List<AttachmentItem> attachments;
|
private List<AttachmentItem> attachments;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
public class StudentMatrixQuery extends BasePageQuery {
|
public class StudentMatrixQuery extends BasePageQuery {
|
||||||
|
|
||||||
/** 班级筛选(空 = 全部参与班级) */
|
/** 班级筛选(空 = 全部参与班级) */
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
/** 提交状态筛选:NOT_SUBMITTED/SUBMITTED/LATE_SUBMITTED/RETURNED/REVIEWED */
|
/** 提交状态筛选:NOT_SUBMITTED/SUBMITTED/LATE_SUBMITTED/RETURNED/REVIEWED */
|
||||||
private String submitStatus;
|
private String submitStatus;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class StudentMatrixVo {
|
|||||||
/** 姓名 */
|
/** 姓名 */
|
||||||
private String studentName;
|
private String studentName;
|
||||||
|
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
private String className;
|
private String className;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import lombok.Data;
|
|||||||
public class TeachingClassVo {
|
public class TeachingClassVo {
|
||||||
|
|
||||||
/** 班级业务ID(bschclass sch_class.class_id) */
|
/** 班级业务ID(bschclass sch_class.class_id) */
|
||||||
private String classId;
|
private Integer classId;
|
||||||
|
|
||||||
/** 班级名称(学校班级列表映射;缺失时回退为班级ID) */
|
/** 班级名称(学校班级列表映射;缺失时回退为班级ID) */
|
||||||
private String className;
|
private String className;
|
||||||
|
|||||||
@@ -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<ClassStudent, Integer> {
|
|
||||||
|
|
||||||
/** 按学生ID(用户中心数字ID)反查学生身份(学生端接口入口) */
|
|
||||||
List<ClassStudent> findByStudentIdAndStatus(Integer studentId, Integer status);
|
|
||||||
|
|
||||||
/** 班级在班学生 */
|
|
||||||
List<ClassStudent> findByClassIdAndStatus(String classId, Integer status);
|
|
||||||
|
|
||||||
/** 指定班级集合的全部在班学生(应交名单) */
|
|
||||||
List<ClassStudent> findByClassIdInAndStatus(List<String> classIds, Integer status);
|
|
||||||
|
|
||||||
/** 指定学校的全部名册(同步任务全量刷新用) */
|
|
||||||
List<ClassStudent> 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<Object[]> findDistinctClasses(@Param("schoolId") Integer schoolId);
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,7 @@ public interface HomeworkClassRepository extends JpaRepository<HomeworkClass, In
|
|||||||
|
|
||||||
/** 指定班级的全部作业ID(学生端列表倒查用) */
|
/** 指定班级的全部作业ID(学生端列表倒查用) */
|
||||||
@Query("select c.homeworkId from HomeworkClass c where c.classId in :classIds")
|
@Query("select c.homeworkId from HomeworkClass c where c.classId in :classIds")
|
||||||
List<Integer> findHomeworkIdsByClassIds(@Param("classIds") List<String> classIds);
|
List<Integer> findHomeworkIdsByClassIds(@Param("classIds") List<Integer> classIds);
|
||||||
|
|
||||||
/** 批量查 N 个作业的班级关联(列表展示避免 N+1) */
|
/** 批量查 N 个作业的班级关联(列表展示避免 N+1) */
|
||||||
@Query("select c from HomeworkClass c where c.homeworkId in :homeworkIds")
|
@Query("select c from HomeworkClass c where c.homeworkId in :homeworkIds")
|
||||||
|
|||||||
@@ -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<SchClassTeach, Integer> {
|
|
||||||
|
|
||||||
/** 指定学校指定教师的全部有效任教记录 */
|
|
||||||
List<SchClassTeach> 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<String> findDistinctSubIds(@Param("schoolId") Integer schoolId, @Param("teaId") Integer teaId);
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 班级学生名册服务:学生端身份映射 + 名册同步任务入口。
|
|
||||||
* <p>
|
|
||||||
* 身份口径:当前登录人用户中心数字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<ClassStudent> resolveMe() {
|
|
||||||
Integer userId = UserContext.getUserId();
|
|
||||||
if (userId == null) {
|
|
||||||
throw new BizException(ErrorCode.FORBIDDEN, "未获取到登录身份");
|
|
||||||
}
|
|
||||||
List<ClassStudent> 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<String> 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<ClassStudent> findByClassId(String classId) {
|
|
||||||
return classStudentRepository.findByClassIdAndStatus(classId, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,15 @@
|
|||||||
package com.yunhai.homework.service.impl;
|
package com.yunhai.homework.service.impl;
|
||||||
|
|
||||||
import com.yunhai.homework.entity.ClassStudent;
|
|
||||||
import com.yunhai.homework.entity.HomeworkReadRecord;
|
import com.yunhai.homework.entity.HomeworkReadRecord;
|
||||||
import com.yunhai.homework.entity.HomeworkSubmission;
|
import com.yunhai.homework.entity.HomeworkSubmission;
|
||||||
import com.yunhai.homework.enums.SubmitStatusEnum;
|
import com.yunhai.homework.enums.SubmitStatusEnum;
|
||||||
import com.yunhai.homework.model.v2.ProgressVo;
|
import com.yunhai.homework.model.v2.ProgressVo;
|
||||||
import com.yunhai.homework.repository.ClassStudentRepository;
|
|
||||||
import com.yunhai.homework.repository.HomeworkReadRecordRepository;
|
import com.yunhai.homework.repository.HomeworkReadRecordRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkSubmissionRepository;
|
import com.yunhai.homework.repository.HomeworkSubmissionRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -27,40 +23,31 @@ import java.util.stream.Collectors;
|
|||||||
* 单作业量级 ≤ 数百人,全部实时聚合不落冗余字段:
|
* 单作业量级 ≤ 数百人,全部实时聚合不落冗余字段:
|
||||||
* should = 参与班级在班学生去重数;submitted = 当前版本 status ∈ 已交集合;
|
* should = 参与班级在班学生去重数;submitted = 当前版本 status ∈ 已交集合;
|
||||||
* graded = REVIEWED;unreadUndone = should −(已读 ∪ 已交)。
|
* graded = REVIEWED;unreadUndone = should −(已读 ∪ 已交)。
|
||||||
|
* 名册实时取 bschclass({@link RosterService},GetClaArrStulist),无本地快照。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class HomeworkProgressCalculator {
|
public class HomeworkProgressCalculator {
|
||||||
|
|
||||||
/**
|
|
||||||
* 名册条目(去重前):矩阵与提醒名单需要 班级×学生 维度。
|
|
||||||
*/
|
|
||||||
public static class RosterEntry {
|
|
||||||
public Integer studentId;
|
|
||||||
public String studentName;
|
|
||||||
public String classId;
|
|
||||||
public String className;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 聚合结果:总进度 + 分班进度 + 全量名册(班级×学生)。
|
* 聚合结果:总进度 + 分班进度 + 全量名册(班级×学生)。
|
||||||
*/
|
*/
|
||||||
public static class Result {
|
public static class Result {
|
||||||
public ProgressVo total;
|
public ProgressVo total;
|
||||||
public List<ClassProgress> byClass = new ArrayList<>();
|
public List<ClassProgress> byClass = new ArrayList<>();
|
||||||
public List<RosterEntry> roster = new ArrayList<>();
|
public List<RosterService.RosterEntry> roster = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分班进度条目。
|
* 分班进度条目。
|
||||||
*/
|
*/
|
||||||
public static class ClassProgress {
|
public static class ClassProgress {
|
||||||
public String classId;
|
public Integer classId;
|
||||||
public String className;
|
public String className;
|
||||||
public ProgressVo progress;
|
public ProgressVo progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClassStudentRepository classStudentRepository;
|
private RosterService rosterService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HomeworkReadRecordRepository readRecordRepository;
|
private HomeworkReadRecordRepository readRecordRepository;
|
||||||
@@ -73,25 +60,18 @@ public class HomeworkProgressCalculator {
|
|||||||
*
|
*
|
||||||
* @param classIds 参与班级 id(homework_class 解析结果)
|
* @param classIds 参与班级 id(homework_class 解析结果)
|
||||||
*/
|
*/
|
||||||
public Result compute(Integer homeworkId, List<String> classIds) {
|
public Result compute(Integer homeworkId, List<Integer> classIds) {
|
||||||
Result result = new Result();
|
Result result = new Result();
|
||||||
|
|
||||||
// 1. 名册:班级×学生(应交基数)
|
// 1. 名册:班级×学生(应交基数,实时 bschclass)
|
||||||
List<ClassStudent> roster = classIds == null || classIds.isEmpty()
|
List<RosterService.RosterEntry> roster = rosterService.roster(classIds);
|
||||||
? new ArrayList<>()
|
|
||||||
: classStudentRepository.findByClassIdInAndStatus(classIds, 1);
|
|
||||||
Set<Integer> distinctStudents = new HashSet<>();
|
Set<Integer> distinctStudents = new HashSet<>();
|
||||||
for (ClassStudent cs : roster) {
|
for (RosterService.RosterEntry cs : roster) {
|
||||||
RosterEntry entry = new RosterEntry();
|
result.roster.add(cs);
|
||||||
entry.studentId = cs.getStudentId();
|
distinctStudents.add(cs.studentId);
|
||||||
entry.studentName = cs.getStudentName();
|
|
||||||
entry.classId = cs.getClassId();
|
|
||||||
entry.className = cs.getClassName();
|
|
||||||
result.roster.add(entry);
|
|
||||||
distinctStudents.add(cs.getStudentId());
|
|
||||||
}
|
}
|
||||||
result.roster.sort(Comparator
|
result.roster.sort(java.util.Comparator
|
||||||
.comparing((RosterEntry e) -> nullSafe(e.className))
|
.comparing((RosterService.RosterEntry e) -> nullSafe(e.className))
|
||||||
.thenComparing(e -> nullSafe(e.studentName)));
|
.thenComparing(e -> nullSafe(e.studentName)));
|
||||||
|
|
||||||
// 2. 已读集合
|
// 2. 已读集合
|
||||||
@@ -109,9 +89,9 @@ public class HomeworkProgressCalculator {
|
|||||||
result.total = aggregate(distinctStudents, readSet, latest);
|
result.total = aggregate(distinctStudents, readSet, latest);
|
||||||
|
|
||||||
// 5. 分班进度(班级维度不去重,矩阵口径)
|
// 5. 分班进度(班级维度不去重,矩阵口径)
|
||||||
Map<String, List<RosterEntry>> byClassEntries = result.roster.stream()
|
Map<Integer, List<RosterService.RosterEntry>> byClassEntries = result.roster.stream()
|
||||||
.collect(Collectors.groupingBy(e -> nullSafe(e.classId), LinkedHashMap::new, Collectors.toList()));
|
.collect(Collectors.groupingBy(e -> e.classId, LinkedHashMap::new, Collectors.toList()));
|
||||||
for (Map.Entry<String, List<RosterEntry>> e : byClassEntries.entrySet()) {
|
for (Map.Entry<Integer, List<RosterService.RosterEntry>> e : byClassEntries.entrySet()) {
|
||||||
Set<Integer> classStudentIds = e.getValue().stream().map(r -> r.studentId).collect(Collectors.toSet());
|
Set<Integer> classStudentIds = e.getValue().stream().map(r -> r.studentId).collect(Collectors.toSet());
|
||||||
ClassProgress cp = new ClassProgress();
|
ClassProgress cp = new ClassProgress();
|
||||||
cp.classId = e.getKey();
|
cp.classId = e.getKey();
|
||||||
|
|||||||
@@ -354,14 +354,14 @@ public class HomeworkService implements IHomeworkService {
|
|||||||
if (collectableIds.isEmpty()) {
|
if (collectableIds.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<Integer, List<String>> classMap = homeworkClassRepository.findByHomeworkIds(collectableIds).stream()
|
Map<Integer, List<Integer>> classMap = homeworkClassRepository.findByHomeworkIds(collectableIds).stream()
|
||||||
.collect(Collectors.groupingBy(c -> c.getHomeworkId(),
|
.collect(Collectors.groupingBy(c -> c.getHomeworkId(),
|
||||||
Collectors.mapping(c -> c.getClassId(), Collectors.toList())));
|
Collectors.mapping(c -> c.getClassId(), Collectors.toList())));
|
||||||
for (HomeworkVo vo : content) {
|
for (HomeworkVo vo : content) {
|
||||||
if (!collectableIds.contains(vo.getId())) {
|
if (!collectableIds.contains(vo.getId())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
List<String> classIds = classMap.getOrDefault(vo.getId(), Collections.emptyList());
|
List<Integer> classIds = classMap.getOrDefault(vo.getId(), Collections.emptyList());
|
||||||
ProgressVo progress = homeworkProgressCalculator.compute(vo.getId(), classIds).total;
|
ProgressVo progress = homeworkProgressCalculator.compute(vo.getId(), classIds).total;
|
||||||
vo.setProgress(progress);
|
vo.setProgress(progress);
|
||||||
}
|
}
|
||||||
@@ -776,7 +776,7 @@ public class HomeworkService implements IHomeworkService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Integer> hwIds = collected.stream().map(Homework::getId).collect(Collectors.toList());
|
List<Integer> hwIds = collected.stream().map(Homework::getId).collect(Collectors.toList());
|
||||||
Map<Integer, List<String>> classMap = homeworkClassRepository.findByHomeworkIds(hwIds).stream()
|
Map<Integer, List<Integer>> classMap = homeworkClassRepository.findByHomeworkIds(hwIds).stream()
|
||||||
.collect(Collectors.groupingBy(HomeworkClass::getHomeworkId,
|
.collect(Collectors.groupingBy(HomeworkClass::getHomeworkId,
|
||||||
Collectors.mapping(HomeworkClass::getClassId, Collectors.toList())));
|
Collectors.mapping(HomeworkClass::getClassId, Collectors.toList())));
|
||||||
|
|
||||||
@@ -787,7 +787,7 @@ public class HomeworkService implements IHomeworkService {
|
|||||||
long excellent = 0, good = 0, pass = 0, fail = 0;
|
long excellent = 0, good = 0, pass = 0, fail = 0;
|
||||||
|
|
||||||
for (Homework h : collected) {
|
for (Homework h : collected) {
|
||||||
List<String> classIds = classMap.getOrDefault(h.getId(), Collections.emptyList());
|
List<Integer> classIds = classMap.getOrDefault(h.getId(), Collections.emptyList());
|
||||||
ProgressVo p = homeworkProgressCalculator.compute(h.getId(), classIds).total;
|
ProgressVo p = homeworkProgressCalculator.compute(h.getId(), classIds).total;
|
||||||
|
|
||||||
HomeworkStatisticsVo.HomeworkStat d = new HomeworkStatisticsVo.HomeworkStat();
|
HomeworkStatisticsVo.HomeworkStat d = new HomeworkStatisticsVo.HomeworkStat();
|
||||||
@@ -898,8 +898,7 @@ public class HomeworkService implements IHomeworkService {
|
|||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
return classes.stream()
|
return classes.stream()
|
||||||
.map(HomeworkClass::getClassId)
|
.map(c -> String.valueOf(c.getClassId()))
|
||||||
.filter(StringUtils::hasText)
|
|
||||||
.collect(Collectors.joining("、"));
|
.collect(Collectors.joining("、"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.yunhai.homework.service.impl;
|
package com.yunhai.homework.service.impl;
|
||||||
|
|
||||||
import com.yunhai.homework.entity.ClassStudent;
|
|
||||||
import com.yunhai.homework.entity.Homework;
|
import com.yunhai.homework.entity.Homework;
|
||||||
import com.yunhai.homework.entity.HomeworkAttachment;
|
import com.yunhai.homework.entity.HomeworkAttachment;
|
||||||
import com.yunhai.homework.entity.HomeworkClass;
|
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.StudentSubmitRequest;
|
||||||
import com.yunhai.homework.model.v2.SubmissionActionRequest;
|
import com.yunhai.homework.model.v2.SubmissionActionRequest;
|
||||||
import com.yunhai.homework.model.v2.SubmissionVersionVo;
|
import com.yunhai.homework.model.v2.SubmissionVersionVo;
|
||||||
import com.yunhai.homework.repository.ClassStudentRepository;
|
|
||||||
import com.yunhai.homework.repository.HomeworkAttachmentRepository;
|
import com.yunhai.homework.repository.HomeworkAttachmentRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkClassRepository;
|
import com.yunhai.homework.repository.HomeworkClassRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkReadRecordRepository;
|
import com.yunhai.homework.repository.HomeworkReadRecordRepository;
|
||||||
@@ -46,8 +44,8 @@ import java.util.stream.Collectors;
|
|||||||
/**
|
/**
|
||||||
* 课堂作业 V2 学生端业务(PRD §18 学生页 1~3)。
|
* 课堂作业 V2 学生端业务(PRD §18 学生页 1~3)。
|
||||||
* <p>
|
* <p>
|
||||||
* 身份:登录平台用户ID ↔ class_student.student_id 名册(ClassStudentService);仅可见本人班级作业。
|
* 身份:登录平台用户ID ↔ bschclass 学生名册({@link RosterService} 实时匹配,无本地快照);
|
||||||
* 提交多版本:提交/打回重交/撤回均新增行(version+1、is_latest 翻转),历史保留。
|
* 仅可见本人班级作业。提交多版本:提交/打回重交/撤回均新增行(version+1、is_latest 翻转),历史保留。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class StudentHomeworkService {
|
public class StudentHomeworkService {
|
||||||
@@ -71,10 +69,7 @@ public class StudentHomeworkService {
|
|||||||
private SubmissionAttachmentRepository submissionAttachmentRepository;
|
private SubmissionAttachmentRepository submissionAttachmentRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClassStudentRepository classStudentRepository;
|
private RosterService rosterService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ClassStudentService classStudentService;
|
|
||||||
|
|
||||||
// ============================ 页 1:作业列表 ============================
|
// ============================ 页 1:作业列表 ============================
|
||||||
|
|
||||||
@@ -83,9 +78,9 @@ public class StudentHomeworkService {
|
|||||||
*/
|
*/
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public BasePageResult<StudentHomeworkVo> list(String tab, com.yunhai.homework.model.BasePageQuery query) {
|
public BasePageResult<StudentHomeworkVo> list(String tab, com.yunhai.homework.model.BasePageQuery query) {
|
||||||
List<ClassStudent> me = classStudentService.resolveMe();
|
List<RosterService.RosterEntry> me = rosterService.mine();
|
||||||
List<String> myClassIds = me.stream().map(ClassStudent::getClassId).distinct().collect(Collectors.toList());
|
List<Integer> myClassIds = me.stream().map(e -> e.classId).distinct().collect(Collectors.toList());
|
||||||
Integer myStudentId = me.get(0).getStudentId();
|
Integer myStudentId = me.get(0).studentId;
|
||||||
|
|
||||||
List<Integer> homeworkIds = homeworkClassRepository.findHomeworkIdsByClassIds(myClassIds);
|
List<Integer> homeworkIds = homeworkClassRepository.findHomeworkIdsByClassIds(myClassIds);
|
||||||
if (homeworkIds.isEmpty()) {
|
if (homeworkIds.isEmpty()) {
|
||||||
@@ -182,16 +177,16 @@ public class StudentHomeworkService {
|
|||||||
if (status != HwStatusEnum.PUBLISHED && status != HwStatusEnum.CLOSED) {
|
if (status != HwStatusEnum.PUBLISHED && status != HwStatusEnum.CLOSED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ClassStudent mine = classStudentService.resolveMe().get(0);
|
RosterService.RosterEntry mine = rosterService.mine().get(0);
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
HomeworkReadRecord record = readRecordRepository.findByHomeworkIdAndStudentId(id, mine.getStudentId())
|
HomeworkReadRecord record = readRecordRepository.findByHomeworkIdAndStudentId(id, mine.studentId)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
if (record == null) {
|
if (record == null) {
|
||||||
record = new HomeworkReadRecord();
|
record = new HomeworkReadRecord();
|
||||||
record.setHomeworkId(id);
|
record.setHomeworkId(id);
|
||||||
record.setStudentId(mine.getStudentId());
|
record.setStudentId(mine.studentId);
|
||||||
record.setStudentName(mine.getStudentName());
|
record.setStudentName(mine.studentName);
|
||||||
record.setClassId(mine.getClassId());
|
record.setClassId(mine.classId);
|
||||||
record.setIsRead(1);
|
record.setIsRead(1);
|
||||||
record.setFirstReadAt(now);
|
record.setFirstReadAt(now);
|
||||||
record.setLastReadAt(now);
|
record.setLastReadAt(now);
|
||||||
@@ -210,9 +205,9 @@ public class StudentHomeworkService {
|
|||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public StudentResultVo result(Integer id) {
|
public StudentResultVo result(Integer id) {
|
||||||
Homework homework = requireVisible(id);
|
Homework homework = requireVisible(id);
|
||||||
ClassStudent mine = classStudentService.resolveMe().get(0);
|
RosterService.RosterEntry mine = rosterService.mine().get(0);
|
||||||
List<HomeworkSubmission> versions =
|
List<HomeworkSubmission> versions =
|
||||||
submissionRepository.findByHomeworkIdAndStudentIdOrderByVersionDesc(id, mine.getStudentId());
|
submissionRepository.findByHomeworkIdAndStudentIdOrderByVersionDesc(id, mine.studentId);
|
||||||
StudentResultVo vo = new StudentResultVo();
|
StudentResultVo vo = new StudentResultVo();
|
||||||
vo.setHomeworkId(id);
|
vo.setHomeworkId(id);
|
||||||
vo.setHomeworkTitle(homework.getTitle());
|
vo.setHomeworkTitle(homework.getTitle());
|
||||||
@@ -281,7 +276,7 @@ public class StudentHomeworkService {
|
|||||||
// ============================ 提交内核 ============================
|
// ============================ 提交内核 ============================
|
||||||
|
|
||||||
private Integer doSubmit(Homework homework, String text, List<AttachmentItem> attachments) {
|
private Integer doSubmit(Homework homework, String text, List<AttachmentItem> attachments) {
|
||||||
ClassStudent mine = classStudentService.resolveMe().get(0);
|
RosterService.RosterEntry mine = rosterService.mine().get(0);
|
||||||
HwStatusEnum hwStatus = HwStatusEnum.of(homework.getHwStatus());
|
HwStatusEnum hwStatus = HwStatusEnum.of(homework.getHwStatus());
|
||||||
if (hwStatus == HwStatusEnum.ARCHIVED) {
|
if (hwStatus == HwStatusEnum.ARCHIVED) {
|
||||||
throw new BizException(ErrorCode.FORBIDDEN, "作业已归档,不可提交");
|
throw new BizException(ErrorCode.FORBIDDEN, "作业已归档,不可提交");
|
||||||
@@ -320,9 +315,9 @@ public class StudentHomeworkService {
|
|||||||
}
|
}
|
||||||
HomeworkSubmission submission = new HomeworkSubmission();
|
HomeworkSubmission submission = new HomeworkSubmission();
|
||||||
fillSnapshot(submission, homework);
|
fillSnapshot(submission, homework);
|
||||||
submission.setStudentId(mine.getStudentId());
|
submission.setStudentId(mine.studentId);
|
||||||
submission.setStudentName(mine.getStudentName());
|
submission.setStudentName(mine.studentName);
|
||||||
submission.setVersion(nextVersion(homework.getId(), mine.getStudentId()));
|
submission.setVersion(nextVersion(homework.getId(), mine.studentId));
|
||||||
submission.setIsLatest(1);
|
submission.setIsLatest(1);
|
||||||
submission.setStatus(late ? SubmitStatusEnum.LATE_SUBMITTED.getCode() : SubmitStatusEnum.SUBMITTED.getCode());
|
submission.setStatus(late ? SubmitStatusEnum.LATE_SUBMITTED.getCode() : SubmitStatusEnum.SUBMITTED.getCode());
|
||||||
submission.setIsLate(late ? 1 : 0);
|
submission.setIsLate(late ? 1 : 0);
|
||||||
@@ -333,10 +328,10 @@ public class StudentHomeworkService {
|
|||||||
|
|
||||||
int sort = 0;
|
int sort = 0;
|
||||||
for (AttachmentItem item : items) {
|
for (AttachmentItem item : items) {
|
||||||
SubmissionAttachment sa = new SubmissionAttachment();
|
SubmissionAttachment sa = new SubmissionAttachment();
|
||||||
sa.setSubmissionId(submission.getId());
|
sa.setSubmissionId(submission.getId());
|
||||||
sa.setHomeworkId(homework.getId());
|
sa.setHomeworkId(homework.getId());
|
||||||
sa.setStudentId(mine.getStudentId());
|
sa.setStudentId(mine.studentId);
|
||||||
sa.setFileId(item.getFileId());
|
sa.setFileId(item.getFileId());
|
||||||
sa.setFileUrl(item.getFileUrl());
|
sa.setFileUrl(item.getFileUrl());
|
||||||
sa.setFileType(item.getFileType());
|
sa.setFileType(item.getFileType());
|
||||||
@@ -355,15 +350,15 @@ public class StudentHomeworkService {
|
|||||||
|
|
||||||
private void fillSnapshot(HomeworkSubmission submission, Homework homework) {
|
private void fillSnapshot(HomeworkSubmission submission, Homework homework) {
|
||||||
submission.setHomeworkId(homework.getId());
|
submission.setHomeworkId(homework.getId());
|
||||||
ClassStudent mine = classStudentService.resolveMe().get(0);
|
RosterService.RosterEntry mine = rosterService.mine().get(0);
|
||||||
submission.setClassId(mine.getClassId());
|
submission.setClassId(mine.classId);
|
||||||
submission.setClassName(mine.getClassName() == null ? mine.getClassId() : mine.getClassName());
|
submission.setClassName(mine.className == null ? String.valueOf(mine.classId) : mine.className);
|
||||||
// studentId/studentName 由调用方覆盖(fillSnapshot 先行填充默认)
|
// studentId/studentName 由调用方覆盖(fillSnapshot 先行填充默认)
|
||||||
if (submission.getStudentId() == null) {
|
if (submission.getStudentId() == null) {
|
||||||
submission.setStudentId(mine.getStudentId());
|
submission.setStudentId(mine.studentId);
|
||||||
}
|
}
|
||||||
if (submission.getStudentName() == null) {
|
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()))) {
|
if (!visibleStatus(HwStatusEnum.of(homework.getHwStatus()))) {
|
||||||
throw new BizException(ErrorCode.FORBIDDEN, "作业不在可见范围");
|
throw new BizException(ErrorCode.FORBIDDEN, "作业不在可见范围");
|
||||||
}
|
}
|
||||||
List<String> myClassIds = classStudentService.resolveMyClassIds();
|
List<Integer> myClassIds = rosterService.mine().stream()
|
||||||
|
.map(e -> e.classId).distinct().collect(Collectors.toList());
|
||||||
boolean hit = homeworkClassRepository.findByHomeworkId(homeworkId).stream()
|
boolean hit = homeworkClassRepository.findByHomeworkId(homeworkId).stream()
|
||||||
.map(HomeworkClass::getClassId)
|
.map(HomeworkClass::getClassId)
|
||||||
.anyMatch(myClassIds::contains);
|
.anyMatch(myClassIds::contains);
|
||||||
@@ -397,7 +393,7 @@ public class StudentHomeworkService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private HomeworkSubmission myLatest(Integer homeworkId) {
|
private HomeworkSubmission myLatest(Integer homeworkId) {
|
||||||
Integer studentId = classStudentService.resolveMyStudentId();
|
Integer studentId = rosterService.mine().get(0).studentId;
|
||||||
return submissionRepository.findByHomeworkIdAndStudentIdAndIsLatest(homeworkId, studentId, 1)
|
return submissionRepository.findByHomeworkIdAndStudentIdAndIsLatest(homeworkId, studentId, 1)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.yunhai.homework.service.impl;
|
|||||||
|
|
||||||
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.EasyExcel;
|
||||||
import com.alibaba.excel.annotation.ExcelProperty;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import com.yunhai.homework.entity.ClassStudent;
|
|
||||||
import com.yunhai.homework.entity.Homework;
|
import com.yunhai.homework.entity.Homework;
|
||||||
import com.yunhai.homework.entity.HomeworkAttachment;
|
import com.yunhai.homework.entity.HomeworkAttachment;
|
||||||
import com.yunhai.homework.entity.HomeworkClass;
|
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.enums.SubmitStatusEnum;
|
||||||
import com.yunhai.homework.model.BasePageResult;
|
import com.yunhai.homework.model.BasePageResult;
|
||||||
import com.yunhai.homework.model.bsch.SchClassDto;
|
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.SchInfoDto;
|
||||||
import com.yunhai.homework.model.bsch.SchSubjectDto;
|
import com.yunhai.homework.model.bsch.SchSubjectDto;
|
||||||
import com.yunhai.homework.model.bsch.SchTeachDto;
|
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.SubjectDto;
|
||||||
import com.yunhai.homework.model.v2.TeacherHomeworkQuery;
|
import com.yunhai.homework.model.v2.TeacherHomeworkQuery;
|
||||||
import com.yunhai.homework.model.v2.TeachingClassVo;
|
import com.yunhai.homework.model.v2.TeachingClassVo;
|
||||||
import com.yunhai.homework.repository.ClassStudentRepository;
|
|
||||||
import com.yunhai.homework.repository.HomeworkAttachmentRepository;
|
import com.yunhai.homework.repository.HomeworkAttachmentRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkClassRepository;
|
import com.yunhai.homework.repository.HomeworkClassRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkReadRecordRepository;
|
import com.yunhai.homework.repository.HomeworkReadRecordRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkRepository;
|
import com.yunhai.homework.repository.HomeworkRepository;
|
||||||
import com.yunhai.homework.repository.HomeworkSubmissionRepository;
|
import com.yunhai.homework.repository.HomeworkSubmissionRepository;
|
||||||
import com.yunhai.homework.repository.NotificationRepository;
|
import com.yunhai.homework.repository.NotificationRepository;
|
||||||
import com.yunhai.homework.repository.SchClassTeachRepository;
|
|
||||||
import com.yunhai.homework.repository.SubmissionAttachmentRepository;
|
import com.yunhai.homework.repository.SubmissionAttachmentRepository;
|
||||||
import com.yunhai.homework.service.IClassService;
|
import com.yunhai.homework.service.IClassService;
|
||||||
import com.yunhai.homework.utils.PageUtils;
|
import com.yunhai.homework.utils.PageUtils;
|
||||||
@@ -110,10 +108,7 @@ public class TeacherHomeworkV2Service {
|
|||||||
private SubmissionAttachmentRepository submissionAttachmentRepository;
|
private SubmissionAttachmentRepository submissionAttachmentRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClassStudentRepository classStudentRepository;
|
private RosterService rosterService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SchClassTeachRepository schClassTeachRepository;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private NotificationRepository notificationRepository;
|
private NotificationRepository notificationRepository;
|
||||||
@@ -197,21 +192,22 @@ public class TeacherHomeworkV2Service {
|
|||||||
homework.setRemind1d(request.getRemind1d() == null ? 1 : request.getRemind1d());
|
homework.setRemind1d(request.getRemind1d() == null ? 1 : request.getRemind1d());
|
||||||
homework.setRemind1h(request.getRemind1h() == null ? 1 : request.getRemind1h());
|
homework.setRemind1h(request.getRemind1h() == null ? 1 : request.getRemind1h());
|
||||||
if (request.getClassIds() != null && !request.getClassIds().isEmpty()) {
|
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<String> classIds, List<AttachmentItem> attachments) {
|
private void saveChildren(Homework homework, List<Integer> classIds, List<AttachmentItem> attachments) {
|
||||||
saveClasses(homework, classIds);
|
saveClasses(homework, classIds);
|
||||||
saveAttachments(homework, attachments);
|
saveAttachments(homework, attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveClasses(Homework homework, List<String> classIds) {
|
private void saveClasses(Homework homework, List<Integer> classIds) {
|
||||||
if (classIds == null || classIds.isEmpty()) {
|
if (classIds == null || classIds.isEmpty()) {
|
||||||
throw new BizException(ErrorCode.FORBIDDEN, "请至少选择一个参与班级");
|
throw new BizException(ErrorCode.FORBIDDEN, "请至少选择一个参与班级");
|
||||||
}
|
}
|
||||||
List<String> distinct = classIds.stream().filter(StringUtils::hasText).distinct().collect(Collectors.toList());
|
List<Integer> distinct = classIds.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
||||||
for (String classId : distinct) {
|
for (Integer classId : distinct) {
|
||||||
HomeworkClass hc = new HomeworkClass();
|
HomeworkClass hc = new HomeworkClass();
|
||||||
hc.setHomeworkId(homework.getId());
|
hc.setHomeworkId(homework.getId());
|
||||||
hc.setClassId(classId);
|
hc.setClassId(classId);
|
||||||
@@ -241,13 +237,9 @@ public class TeacherHomeworkV2Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 班级名快照:优先取名册,无名册时回退班级 id */
|
/** 班级名快照:实时取 bschclass 班级列表映射,缺失时回退班级 id */
|
||||||
private String resolveClassName(String classId) {
|
private String resolveClassName(Integer classId) {
|
||||||
return classStudentRepository.findByClassIdAndStatus(classId, 1).stream()
|
return rosterService.className(classId);
|
||||||
.map(ClassStudent::getClassName)
|
|
||||||
.filter(StringUtils::hasText)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(classId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================ 页 2:草稿箱 ============================
|
// ============================ 页 2:草稿箱 ============================
|
||||||
@@ -437,15 +429,13 @@ public class TeacherHomeworkV2Service {
|
|||||||
public BasePageResult<StudentMatrixVo> students(Integer id, StudentMatrixQuery query) {
|
public BasePageResult<StudentMatrixVo> students(Integer id, StudentMatrixQuery query) {
|
||||||
Homework homework = stateService.requireOwned(id, UserContext.getUserId());
|
Homework homework = stateService.requireOwned(id, UserContext.getUserId());
|
||||||
List<HomeworkClass> classes = homeworkClassRepository.findByHomeworkId(id);
|
List<HomeworkClass> classes = homeworkClassRepository.findByHomeworkId(id);
|
||||||
List<String> classIds = classIds(classes);
|
List<Integer> classIds = classIds(classes);
|
||||||
if (StringUtils.hasText(query.getClassId())) {
|
if (query.getClassId() != null) {
|
||||||
classIds = classIds.stream().filter(c -> c.equals(query.getClassId())).collect(Collectors.toList());
|
classIds = classIds.stream().filter(c -> c.equals(query.getClassId())).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 名册(班级×学生)
|
// 名册(班级×学生,实时 bschclass)
|
||||||
List<ClassStudent> roster = classIds.isEmpty()
|
List<RosterService.RosterEntry> roster = rosterService.roster(classIds);
|
||||||
? new ArrayList<>()
|
|
||||||
: classStudentRepository.findByClassIdInAndStatus(classIds, 1);
|
|
||||||
Map<Integer, HomeworkReadRecord> readMap = readRecordRepository.findByHomeworkId(id).stream()
|
Map<Integer, HomeworkReadRecord> readMap = readRecordRepository.findByHomeworkId(id).stream()
|
||||||
.collect(Collectors.toMap(HomeworkReadRecord::getStudentId, r -> r, (a, b) -> a));
|
.collect(Collectors.toMap(HomeworkReadRecord::getStudentId, r -> r, (a, b) -> a));
|
||||||
Map<Integer, HomeworkSubmission> latestMap = submissionRepository.findByHomeworkIdAndIsLatest(id, 1).stream()
|
Map<Integer, HomeworkSubmission> latestMap = submissionRepository.findByHomeworkIdAndIsLatest(id, 1).stream()
|
||||||
@@ -457,17 +447,17 @@ public class TeacherHomeworkV2Service {
|
|||||||
.collect(Collectors.groupingBy(SubmissionAttachment::getSubmissionId));
|
.collect(Collectors.groupingBy(SubmissionAttachment::getSubmissionId));
|
||||||
|
|
||||||
List<StudentMatrixVo> rows = new ArrayList<>();
|
List<StudentMatrixVo> rows = new ArrayList<>();
|
||||||
for (ClassStudent cs : roster) {
|
for (RosterService.RosterEntry cs : roster) {
|
||||||
StudentMatrixVo row = new StudentMatrixVo();
|
StudentMatrixVo row = new StudentMatrixVo();
|
||||||
row.setStudentId(cs.getStudentId());
|
row.setStudentId(cs.studentId);
|
||||||
row.setStudentName(cs.getStudentName());
|
row.setStudentName(cs.studentName);
|
||||||
row.setClassId(cs.getClassId());
|
row.setClassId(cs.classId);
|
||||||
row.setClassName(cs.getClassName());
|
row.setClassName(cs.className);
|
||||||
HomeworkReadRecord read = readMap.get(cs.getStudentId());
|
HomeworkReadRecord read = readMap.get(cs.studentId);
|
||||||
row.setIsRead(read != null && read.getIsRead() != null && read.getIsRead() == 1 ? 1 : 0);
|
row.setIsRead(read != null && read.getIsRead() != null && read.getIsRead() == 1 ? 1 : 0);
|
||||||
row.setFirstReadAt(read == null ? null : read.getFirstReadAt());
|
row.setFirstReadAt(read == null ? null : read.getFirstReadAt());
|
||||||
row.setLastReadAt(read == null ? null : read.getLastReadAt());
|
row.setLastReadAt(read == null ? null : read.getLastReadAt());
|
||||||
HomeworkSubmission sub = latestMap.get(cs.getStudentId());
|
HomeworkSubmission sub = latestMap.get(cs.studentId);
|
||||||
if (sub == null) {
|
if (sub == null) {
|
||||||
row.setSubmissionId(0);
|
row.setSubmissionId(0);
|
||||||
row.setSubmitStatus(SubmitStatusEnum.NOT_SUBMITTED.getCode());
|
row.setSubmitStatus(SubmitStatusEnum.NOT_SUBMITTED.getCode());
|
||||||
@@ -854,31 +844,66 @@ public class TeacherHomeworkV2Service {
|
|||||||
// ============================ 班级树 / 名册 ============================
|
// ============================ 班级树 / 名册 ============================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 年级→班级树(发布选班;来自名册快照聚合)。
|
* 年级→班级树(发布选班;全校班级,不按学科过滤)。
|
||||||
*/
|
*/
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public List<ClassTreeNode> classTree() {
|
public List<ClassTreeNode> classTree() {
|
||||||
Integer schId = UserContext.getSchId();
|
return classTree(null);
|
||||||
if (schId == null) {
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年级→班级树(发布选班)。数据源 bschclass 实时接口:班级 GetVClassList、
|
||||||
|
* 年级 GetSchLenLevellist、在班人数 GetClaArrStulist(一次批量外呼);
|
||||||
|
* subId 非空时仅保留当前教师该学科的任教班级(GetSchTeachlist),空年级组不保留。
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<ClassTreeNode> 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<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
List<Object[]> rows = classStudentRepository.findDistinctClasses(schId);
|
Set<Integer> scope = null;
|
||||||
Map<String, List<Object[]>> byGrade = rows.stream()
|
if (StringUtils.hasText(subId)) {
|
||||||
.collect(Collectors.groupingBy(r -> r[2] == null || !StringUtils.hasText(r[2].toString())
|
scope = teachingClassIds(schSerId, subId.trim());
|
||||||
? "未分组" : r[2].toString(), java.util.LinkedHashMap::new, Collectors.toList()));
|
if (scope.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<SchClassDto> classes = classService.getSchClassList(schSerId);
|
||||||
|
Map<Integer, String> gradeNames = gradeNames(schSerId);
|
||||||
|
Map<Integer, List<SchClassDto>> byGrade = new java.util.LinkedHashMap<>();
|
||||||
|
List<Integer> 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<Integer, Integer> counts = rosterService.studentCounts(scopeIds);
|
||||||
List<ClassTreeNode> tree = new ArrayList<>();
|
List<ClassTreeNode> tree = new ArrayList<>();
|
||||||
for (Map.Entry<String, List<Object[]>> entry : byGrade.entrySet()) {
|
for (Map.Entry<Integer, List<SchClassDto>> entry : byGrade.entrySet()) {
|
||||||
|
Integer gradeId = entry.getKey();
|
||||||
|
String gradeName = gradeId != null && gradeNames.containsKey(gradeId)
|
||||||
|
? gradeNames.get(gradeId) : "未分组";
|
||||||
ClassTreeNode grade = new ClassTreeNode();
|
ClassTreeNode grade = new ClassTreeNode();
|
||||||
grade.setId(entry.getKey());
|
grade.setId(gradeId == null ? gradeName : String.valueOf(gradeId));
|
||||||
grade.setName(entry.getKey());
|
grade.setName(gradeName);
|
||||||
grade.setIsParent(true);
|
grade.setIsParent(true);
|
||||||
for (Object[] r : entry.getValue()) {
|
for (SchClassDto c : entry.getValue()) {
|
||||||
String classId = String.valueOf(r[0]);
|
|
||||||
ClassTreeNode leaf = new ClassTreeNode();
|
ClassTreeNode leaf = new ClassTreeNode();
|
||||||
leaf.setId(classId);
|
leaf.setId(String.valueOf(c.getClassId()));
|
||||||
leaf.setName(r[1] == null || !StringUtils.hasText(r[1].toString()) ? classId : r[1].toString());
|
leaf.setName(StringUtils.hasText(c.getClassName())
|
||||||
|
? c.getClassName() : String.valueOf(c.getClassId()));
|
||||||
leaf.setIsParent(false);
|
leaf.setIsParent(false);
|
||||||
leaf.setStudentCount(classStudentRepository.findByClassIdAndStatus(classId, 1).size());
|
leaf.setStudentCount(counts.getOrDefault(c.getClassId(), 0));
|
||||||
grade.getChildren().add(leaf);
|
grade.getChildren().add(leaf);
|
||||||
}
|
}
|
||||||
tree.add(grade);
|
tree.add(grade);
|
||||||
@@ -886,6 +911,39 @@ public class TeacherHomeworkV2Service {
|
|||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前教师在 bschclass 的 subId 学科任教班级ID集合(实时 GetSchTeachlist,
|
||||||
|
* sch_class.class_id 取值域);远端不可用时异常向上抛,登录身份缺失时返回空集合。
|
||||||
|
*/
|
||||||
|
private Set<Integer> teachingClassIds(String schSerId, String subId) {
|
||||||
|
Set<Integer> 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<Integer, String> gradeNames(String schSerId) {
|
||||||
|
Map<Integer, String> 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<SubjectDto> teachingSubjects() {
|
public List<SubjectDto> teachingSubjects() {
|
||||||
return toSubjectDtos(teachingSubjectCodes(), subjectDictionary());
|
return toSubjectDtos(teachingSubjectCodes(), subjectDictionary());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 我的任教去重学科编码:bschclass 任教关系(sch_class_teach)当前教师。
|
* 我的任教去重学科编码:bschclass 任教关系(GetSchTeachlist)当前教师,实时获取。
|
||||||
* 登录身份缺学校/教师信息时返回空集合;远端不可用时降级读本地任教快照
|
* 登录身份缺学校/教师信息时返回空集合;远端不可用时异常向上抛
|
||||||
* (sch_class_teach,同 class_student 口径),快照也无记录则保持原语义向上抛出。
|
* (assignedSubjects 捕获后仅返回布置学科)。
|
||||||
*/
|
*/
|
||||||
private Set<String> teachingSubjectCodes() {
|
private Set<String> teachingSubjectCodes() {
|
||||||
Set<String> codes = new LinkedHashSet<>();
|
Set<String> codes = new LinkedHashSet<>();
|
||||||
try {
|
for (SchTeachDto teach : currentTeachList()) {
|
||||||
for (SchTeachDto teach : currentTeachList()) {
|
if (StringUtils.hasText(teach.getSubId())) {
|
||||||
if (StringUtils.hasText(teach.getSubId())) {
|
codes.add(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;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前教师在本地任教快照(sch_class_teach)中的去重学科编码;
|
|
||||||
* 缺学校/教师身份时返回空集合。
|
|
||||||
*/
|
|
||||||
private Set<String> 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)映射并按其排序输出,
|
* 班级名称取学校班级列表(bschclass GetVClassList)映射并按其排序输出,
|
||||||
@@ -966,12 +1002,7 @@ public class TeacherHomeworkV2Service {
|
|||||||
if (schSerId == null || userId == null) {
|
if (schSerId == null || userId == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
Set<Integer> classIds = new LinkedHashSet<>();
|
Set<Integer> classIds = teachingClassIds(schSerId, subId);
|
||||||
for (SchTeachDto teach : classService.getSchTeachList(schSerId, userId)) {
|
|
||||||
if (subId.equals(teach.getSubId()) && teach.getClassId() != null) {
|
|
||||||
classIds.add(teach.getClassId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (classIds.isEmpty()) {
|
if (classIds.isEmpty()) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
@@ -994,7 +1025,7 @@ public class TeacherHomeworkV2Service {
|
|||||||
|
|
||||||
private static TeachingClassVo teachingClassVo(Integer classId, String className) {
|
private static TeachingClassVo teachingClassVo(Integer classId, String className) {
|
||||||
TeachingClassVo vo = new TeachingClassVo();
|
TeachingClassVo vo = new TeachingClassVo();
|
||||||
vo.setClassId(String.valueOf(classId));
|
vo.setClassId(classId);
|
||||||
vo.setClassName(StringUtils.hasText(className) ? className : String.valueOf(classId));
|
vo.setClassName(StringUtils.hasText(className) ? className : String.valueOf(classId));
|
||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1043,7 @@ public class TeacherHomeworkV2Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前教师在 bschclass 的任教关系明细(sch_class_teach)。
|
* 当前教师在 bschclass 的任教关系明细(GetSchTeachlist 实时)。
|
||||||
* 登录身份缺学校/教师信息时返回空列表;远端不可用时抛 BizException,由调用方决定是否降级。
|
* 登录身份缺学校/教师信息时返回空列表;远端不可用时抛 BizException,由调用方决定是否降级。
|
||||||
*/
|
*/
|
||||||
private List<SchTeachDto> currentTeachList() {
|
private List<SchTeachDto> currentTeachList() {
|
||||||
@@ -1132,20 +1163,13 @@ public class TeacherHomeworkV2Service {
|
|||||||
|
|
||||||
// ============================ 名册辅助 ============================
|
// ============================ 名册辅助 ============================
|
||||||
|
|
||||||
/** 参与班级在班学生 id 集合 */
|
/** 参与班级在班学生 id 集合(实时 bschclass 名册) */
|
||||||
private List<Integer> rosterStudentIds(Integer homeworkId) {
|
private List<Integer> 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<ClassStudent> roster(Integer homeworkId) {
|
private static List<Integer> classIds(List<HomeworkClass> classes) {
|
||||||
List<String> classIds = classIds(homeworkClassRepository.findByHomeworkId(homeworkId));
|
|
||||||
if (classIds.isEmpty()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
return classStudentRepository.findByClassIdInAndStatus(classIds, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<String> classIds(List<HomeworkClass> classes) {
|
|
||||||
return classes.stream().map(HomeworkClass::getClassId).collect(Collectors.toList());
|
return classes.stream().map(HomeworkClass::getClassId).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user