fix: 新增学生导入模板接口及修复阅读任务日期筛选

- 新增 GET /api/v1/school/students/import/template 接口,返回导入模板配置
- 实现阅读任务 startDate/endDate 日期范围查询(按任务日期交集筛选)
- 支持阅读任务按 startDate/endDate 排序

Made-with: Cursor
This commit is contained in:
zhonghua 2026-03-24 10:05:28 +08:00
parent bf03bc30af
commit 1e73b480a0
3 changed files with 82 additions and 11 deletions

View File

@ -13,6 +13,7 @@ import com.reading.platform.common.security.SecurityUtils;
import com.reading.platform.dto.request.StudentCreateRequest;
import com.reading.platform.dto.request.StudentUpdateRequest;
import com.reading.platform.dto.request.TransferStudentRequest;
import com.reading.platform.dto.response.StudentImportTemplateResponse;
import com.reading.platform.dto.response.StudentResponse;
import com.reading.platform.dto.response.StudentTransferHistoryItemResponse;
import com.reading.platform.entity.Student;
@ -24,6 +25,7 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -137,6 +139,22 @@ public class SchoolStudentController {
return Result.success();
}
@Operation(summary = "Get student import template")
@GetMapping("/import/template")
public Result<StudentImportTemplateResponse> getImportTemplate() {
return Result.success(new StudentImportTemplateResponse(
Arrays.asList("姓名", "性别", "出生日期", "班级ID", "家长姓名", "家长电话"),
Arrays.asList("张小明", "", "2020-01-15", "1", "张三", "13800138000"),
Arrays.asList(
"姓名为必填项",
"性别可选:男/女,默认为男",
"出生日期格式YYYY-MM-DD",
"班级ID为必填项可在班级管理中查看",
"家长姓名和家长电话为选填项"
)
));
}
@Operation(summary = "Get student class transfer history")
@GetMapping("/{id}/history")
public Result<List<StudentTransferHistoryItemResponse>> getStudentClassHistory(@PathVariable Long id) {

View File

@ -0,0 +1,27 @@
package com.reading.platform.dto.response;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 学生导入模板响应
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "学生导入模板")
public class StudentImportTemplateResponse {
@Schema(description = "表头列表")
private List<String> headers;
@Schema(description = "示例行")
private List<String> example;
@Schema(description = "说明事项")
private List<String> notes;
}

View File

@ -712,19 +712,45 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task>
wrapper.eq(Task::getStatus, status);
}
// TODO: 实现更多筛选条件
// - classIds: 班级筛选需要关联 task_target
// - teacherIds: 教师筛选
// - dateType/startDate/endDate: 时间筛选
// - completionRate: 完成率筛选
// - sortBy/sortOrder: 排序
// 时间筛选任务的 startDate~dueDate 与查询范围有交集的纳入结果
// 交集条件task.startDate <= endDate AND task.dueDate >= startDate
if (StringUtils.hasText(startDate) && StringUtils.hasText(endDate)) {
try {
LocalDate rangeStart = LocalDate.parse(startDate);
LocalDate rangeEnd = LocalDate.parse(endDate);
// 任务开始日期 <= 查询结束日期任务不能完全在查询范围之后
wrapper.le(Task::getStartDate, rangeEnd);
// 任务截止日期 >= 查询开始日期任务不能完全在查询范围之前
wrapper.and(w -> w.ge(Task::getDueDate, rangeStart).or().isNull(Task::getDueDate));
} catch (Exception e) {
log.warn("解析日期参数失败 startDate={}, endDate={}", startDate, endDate, e);
}
} else if (StringUtils.hasText(startDate)) {
try {
LocalDate rangeStart = LocalDate.parse(startDate);
wrapper.ge(Task::getDueDate, rangeStart);
} catch (Exception e) {
log.warn("解析 startDate 参数失败: {}", startDate, e);
}
} else if (StringUtils.hasText(endDate)) {
try {
LocalDate rangeEnd = LocalDate.parse(endDate);
wrapper.le(Task::getStartDate, rangeEnd);
} catch (Exception e) {
log.warn("解析 endDate 参数失败: {}", endDate, e);
}
}
// 默认排序
if ("completionRate".equals(sortBy)) {
// 完成率排序需要特殊处理暂时使用创建时间
wrapper.orderByDesc(Task::getCreatedAt);
// TODO: classIdsteacherIdscompletionRate 筛选待实现
// 排序
boolean asc = "asc".equalsIgnoreCase(sortOrder);
if ("startDate".equals(sortBy)) {
wrapper.orderBy(true, asc, Task::getStartDate);
} else if ("endDate".equals(sortBy) || "dueDate".equals(sortBy)) {
wrapper.orderBy(true, asc, Task::getDueDate);
} else {
wrapper.orderByDesc(Task::getCreatedAt);
wrapper.orderBy(true, asc, Task::getCreatedAt);
}
Page<Task> taskPage = taskMapper.selectPage(page, wrapper);