diff --git a/docs/sql/2026-07-30-backfill-school-default-tasks.sql b/docs/sql/2026-07-30-backfill-school-default-tasks.sql new file mode 100644 index 0000000..08c13fa --- /dev/null +++ b/docs/sql/2026-07-30-backfill-school-default-tasks.sql @@ -0,0 +1,44 @@ +-- 为已有学校补齐学校级默认实训任务;不会覆盖任何学校管理员已保存的默认配置。 +START TRANSACTION; + +CREATE TABLE IF NOT EXISTS school_default_task_initialization ( + school_id varchar(64) NOT NULL, + status varchar(16) NOT NULL, + last_error varchar(1000) NULL, + attempt_count int NOT NULL DEFAULT 0, + create_time datetime NOT NULL, + update_time datetime NOT NULL, + PRIMARY KEY (school_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学校默认实训任务初始化状态'; + +INSERT INTO task_allocation (id, class_id, school_id, module, disabled_status, sort) +SELECT UUID(), CONCAT('SCHOOL_DEFAULT:', s.school_id), s.school_id, p.module, p.disabled_status, p.sort +FROM school s +JOIN task_allocation p ON p.class_id = '999999999' +WHERE s.school_id <> '999999999' + AND NOT EXISTS ( + SELECT 1 + FROM task_allocation existing_task + WHERE existing_task.class_id = CONCAT('SCHOOL_DEFAULT:', s.school_id) + ); + +INSERT INTO school_default_task_initialization ( + school_id, status, last_error, attempt_count, create_time, update_time +) +SELECT s.school_id, 'READY', NULL, 1, NOW(), NOW() +FROM school s +WHERE s.school_id <> '999999999' + AND EXISTS ( + SELECT 1 + FROM task_allocation default_task + WHERE default_task.class_id = CONCAT('SCHOOL_DEFAULT:', s.school_id) + ) +ON DUPLICATE KEY UPDATE + status = IF(status = 'READY', status, 'READY'), + update_time = NOW(); + +COMMIT; + +SELECT school_id, status, attempt_count, update_time +FROM school_default_task_initialization +ORDER BY update_time DESC; diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java index bdcd9d5..1ca3f8e 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreController.java @@ -12,6 +12,7 @@ import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper; import com.sztzjy.linkCommerce.mapper.TeachingClassStudentMapper; import com.sztzjy.linkCommerce.mapper.WeightMapper; import com.sztzjy.linkCommerce.service.ScoreRankService; +import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService; import com.sztzjy.linkCommerce.util.ResultEntity; import com.sztzjy.linkCommerce.util.excel.FilePortUtil; import io.swagger.annotations.Api; @@ -49,6 +50,8 @@ public class TeaScoreController { TeachingClassStudentMapper teachingClassStudentMapper; @Autowired TaskAllocationMapper taskAllocationMapper; + @Autowired(required = false) + SchoolDefaultTaskService schoolDefaultTaskService; @PostMapping("/selectStuRankAndScore") @ApiOperation("查询学生成绩和排名") @@ -279,12 +282,20 @@ public class TeaScoreController { } private Set resolveEnabledTaskModules(String classId) { - if (taskAllocationMapper == null || StringUtils.isBlank(classId)) { + if (StringUtils.isBlank(classId)) { return Collections.emptySet(); } - List allocations = selectTaskAllocations(classId); - if ((allocations == null || allocations.isEmpty()) && !"999999999".equals(classId)) { - allocations = selectTaskAllocations("999999999"); + List allocations; + if (schoolDefaultTaskService != null) { + allocations = schoolDefaultTaskService.resolveForTeachingClass(classId); + } else { + if (taskAllocationMapper == null) { + return Collections.emptySet(); + } + allocations = selectTaskAllocations(classId); + if ((allocations == null || allocations.isEmpty()) && !"999999999".equals(classId)) { + allocations = selectTaskAllocations("999999999"); + } } return (allocations == null ? Collections.emptyList() : allocations).stream() .filter(allocation -> allocation.getDisabledStatus() == null || allocation.getDisabledStatus() != 1) diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreControllerProgressTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreControllerProgressTest.java index 0030781..f6bdb8e 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreControllerProgressTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeaScoreControllerProgressTest.java @@ -9,6 +9,7 @@ import com.sztzjy.linkCommerce.mapper.StuRankMapper; import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper; import com.sztzjy.linkCommerce.mapper.SchoolClassMapper; import com.sztzjy.linkCommerce.service.ScoreRankService; +import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService; import com.sztzjy.linkCommerce.util.ResultEntity; import org.junit.jupiter.api.Test; import org.springframework.test.util.ReflectionTestUtils; @@ -62,6 +63,25 @@ class TeaScoreControllerProgressTest { assertNull(row.getTrainingProgress()); } + @Test + void scoreProgressUsesSchoolDefaultResolverWhenTeachingClassHasNoOwnTasks() { + TeaScoreController controller = controllerWithMocks(); + StuRankMapper rankMapper = field(controller, "stuRankMapper"); + StuGradeMapper gradeMapper = field(controller, "stuGradeMapper"); + SchoolDefaultTaskService defaultTaskService = mock(SchoolDefaultTaskService.class); + ReflectionTestUtils.setField(controller, "schoolDefaultTaskService", defaultTaskService); + StuRank rank = rank("student-1", "class-1"); + when(rankMapper.selectByExample(any())).thenReturn(Collections.singletonList(rank)); + when(defaultTaskService.resolveForTeachingClass("class-1")).thenReturn(Collections.singletonList(task("学校默认任务", (byte) 0))); + when(gradeMapper.selectByExample(any())).thenReturn(Collections.singletonList(grade("学校默认任务"))); + + ResultEntity> result = controller.selectStuRankAndScore("class-1", null, null, "school-1", 1, 10); + StuRank row = result.getBody().getData().getList().get(0); + + assertEquals(1, row.getTotalTaskCount()); + assertEquals(new BigDecimal("100.00"), row.getTrainingProgress()); + } + private TeaScoreController controllerWithMocks() { TeaScoreController controller = new TeaScoreController(); ReflectionTestUtils.setField(controller, "stuRankMapper", mock(StuRankMapper.class));