feat(student-plan): 实现学生学案查询功能

- 新增FindStudentPlansReqVO和FindStudentPlansRspVO定义请求和响应数据结构
- 新增LessonPlanItem用于描述单个学案项
- StudentLessonPlansDO模型新增isFinished属性
- 扩展StudentLessonPlansDOMapper,添加分页及按姓名查询学生学案列表方法及统计总数方法
- 扩展LessonPlansDOMapper,新增按学案ID列表批量查询方法
- 实现StudentLessonPlansService及LessonPlansService接口对应查询方法
- 新增StudentLessonPlansController,提供学生学案分页查询接口
- 在前端LearningPlan.vue添加学案查询界面及分页、搜索功能
- 封装studentLessonPlans接口axios方法,支持分页按姓名查询学生学案数据
- 添加单元测试更新验证数据库查询正确性
This commit is contained in:
lbw
2025-12-17 15:23:40 +08:00
parent 49cd146bc3
commit dbe7312633
16 changed files with 335 additions and 6 deletions

View File

@@ -0,0 +1,77 @@
package com.yinlihupo.enlish.service.controller;
import com.yinlihupo.enlish.service.domain.dataobject.LessonPlansDO;
import com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO;
import com.yinlihupo.enlish.service.model.bo.StudentDetail;
import com.yinlihupo.enlish.service.model.vo.plan.FindStudentPlansReqVO;
import com.yinlihupo.enlish.service.model.vo.plan.FindStudentPlansRspVO;
import com.yinlihupo.enlish.service.model.vo.plan.LessonPlanItem;
import com.yinlihupo.enlish.service.service.LessonPlansService;
import com.yinlihupo.enlish.service.service.StudentLessonPlansService;
import com.yinlihupo.enlish.service.service.StudentService;
import com.yinlihupo.framework.biz.operationlog.aspect.ApiOperationLog;
import com.yinlihupo.framework.common.response.PageResponse;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RequestMapping("/studentLessonPlans/")
@RestController
public class StudentLessonPlansController {
@Resource
private StudentLessonPlansService studentLessonPlansService;
@Resource
private StudentService studentService;
@Resource
private LessonPlansService lessonPlansService;
@PostMapping("/list")
@ApiOperationLog(description = "查询学生学案")
public PageResponse<FindStudentPlansRspVO> findStudentPlans(@RequestBody FindStudentPlansReqVO findStudentPlansReqVO) {
Integer studentLessonPlanTotal = studentLessonPlansService.findStudentLessonPlanTotal();
String name = findStudentPlansReqVO.getName();
Integer page = findStudentPlansReqVO.getPage();
Integer size = findStudentPlansReqVO.getSize();
List<StudentLessonPlansDO> studentLessonPlansDOListPageSize = studentLessonPlansService.findStudentLessonPlansDOList(page, size, name);
Map<Integer, List<StudentLessonPlansDO>> studentId2StudentLessonPlansDOListMap = studentLessonPlansDOListPageSize.stream().collect(
Collectors.groupingBy(StudentLessonPlansDO::getStudentId)
);
List<Integer> planIds = studentLessonPlansDOListPageSize.stream().map(StudentLessonPlansDO::getPlanId).toList();
List<LessonPlansDO> lessonPlans = lessonPlansService.findLessonPlans(planIds);
Map<Integer, LessonPlansDO> id2LessonPlansDO = lessonPlans.stream().collect(Collectors.toMap(
LessonPlansDO::getId,
lessonPlansDO -> lessonPlansDO
));
List<StudentDetail> studentDetailList = studentService.getStudentDetailList(new ArrayList<>(studentId2StudentLessonPlansDOListMap.keySet()));
List<FindStudentPlansRspVO> findStudentPlansRspVOList = studentDetailList.stream().map(studentDetail -> {
List<StudentLessonPlansDO> studentLessonPlansDOList = studentId2StudentLessonPlansDOListMap.get(studentDetail.getId());
return FindStudentPlansRspVO.builder()
.name(studentDetail.getName())
.id(studentDetail.getId())
.classId(studentDetail.getClassId())
.gradeId(studentDetail.getGradeId())
.gradeName(studentDetail.getGradeName())
.className(studentDetail.getClassName())
.plans(studentLessonPlansDOList.stream().map(studentLessonPlansDO ->
LessonPlanItem.builder().title(id2LessonPlansDO.get(studentLessonPlansDO.getPlanId()).getTitle()).id(studentLessonPlansDO.getPlanId()).isFinished(studentLessonPlansDO.getIsFinished()).build()
).toList())
.build();
}).toList();
return PageResponse.success(findStudentPlansRspVOList, page, studentLessonPlanTotal, size);
}
}

View File

@@ -25,6 +25,8 @@ public class StudentLessonPlansDO {
private Integer totalCount;
private Integer isFinished;
private String memorizedWordsJson;
private String unmemorizedWordsJson;

View File

@@ -1,10 +1,15 @@
package com.yinlihupo.enlish.service.domain.mapper;
import com.yinlihupo.enlish.service.domain.dataobject.LessonPlansDO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface LessonPlansDOMapper {
void insert(LessonPlansDO lessonPlansDO);
LessonPlansDO selectById(Integer id);
List<LessonPlansDO> findLessonPlansByStudentId(@Param("ids") List<Integer> ids);
}

View File

@@ -1,8 +1,15 @@
package com.yinlihupo.enlish.service.domain.mapper;
import com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface StudentLessonPlansDOMapper {
void insert(StudentLessonPlansDO studentLessonPlansDO);
List<StudentLessonPlansDO> selectStudentLessonPlanList(@Param("startIndex") Integer startIndex, @Param("pageSize") Integer pageSize, @Param("name") String name);
Integer selectStudentPlanTotal();
}

View File

@@ -0,0 +1,17 @@
package com.yinlihupo.enlish.service.model.vo.plan;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class FindStudentPlansReqVO {
String name;
Integer page;
Integer size;
}

View File

@@ -0,0 +1,24 @@
package com.yinlihupo.enlish.service.model.vo.plan;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class FindStudentPlansRspVO {
private Integer id;
private String name;
private Integer classId;
private String className;
private Integer gradeId;
private String gradeName;
List<LessonPlanItem> plans;
}

View File

@@ -0,0 +1,19 @@
package com.yinlihupo.enlish.service.model.vo.plan;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class LessonPlanItem {
private Integer id;
private String title;
private Integer isFinished;
}

View File

@@ -1,5 +1,11 @@
package com.yinlihupo.enlish.service.service;
import com.yinlihupo.enlish.service.domain.dataobject.LessonPlansDO;
import java.util.List;
public interface LessonPlansService {
void generateLessonPlans(Integer studentId, Integer unitId);
List<LessonPlansDO> findLessonPlans(List<Integer> ids);
}

View File

@@ -0,0 +1,12 @@
package com.yinlihupo.enlish.service.service;
import com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO;
import java.util.List;
public interface StudentLessonPlansService {
List<StudentLessonPlansDO> findStudentLessonPlansDOList(Integer page, Integer size, String name);
Integer findStudentLessonPlanTotal();
}

View File

@@ -8,7 +8,6 @@ import com.yinlihupo.enlish.service.utils.DifyArticleClient;
import com.yinlihupo.enlish.service.utils.StringToPlanMapUtil;
import com.yinlihupo.framework.common.util.JsonUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.factory.annotation.Value;
@@ -150,6 +149,10 @@ public class LessonPlansServiceImpl implements LessonPlansService {
}
}
@Override
public List<LessonPlansDO> findLessonPlans(List<Integer> ids) {
return lessonPlansDOMapper.findLessonPlansByStudentId(ids);
}
private Map<String, Object> generateWeekendPlans(List<VocabularyBankDO> checkList,

View File

@@ -0,0 +1,33 @@
package com.yinlihupo.enlish.service.service.plan;
import com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO;
import com.yinlihupo.enlish.service.domain.mapper.StudentLessonPlansDOMapper;
import com.yinlihupo.enlish.service.service.StudentLessonPlansService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class StudentLessonPlansServiceImpl implements StudentLessonPlansService {
@Resource
private StudentLessonPlansDOMapper studentLessonPlansDOMapper;
@Override
public List<StudentLessonPlansDO> findStudentLessonPlansDOList(Integer page, Integer size, String name) {
log.info("查询学生学案");
if (name.isEmpty()) {
return studentLessonPlansDOMapper.selectStudentLessonPlanList((page - 1) * size, size, null);
}
return studentLessonPlansDOMapper.selectStudentLessonPlanList((page - 1) * size, size, name);
}
@Override
public Integer findStudentLessonPlanTotal() {
return studentLessonPlansDOMapper.selectStudentPlanTotal();
}
}

View File

@@ -22,4 +22,15 @@
where id = #{id}
</select>
<select id="findLessonPlansByStudentId" resultMap="BaseResultMap">
select *
from lesson_plans
<if test="ids != null">
where id in
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
#{id}
</foreach>
</if>
</select>
</mapper>

View File

@@ -8,6 +8,7 @@
<result column="start_time" jdbcType="TIMESTAMP" property="startTime" />
<result column="mastery_rat" jdbcType="DECIMAL" property="masteryRat" />
<result column="total_count" jdbcType="INTEGER" property="totalCount" />
<result column="is_finished" jdbcType="INTEGER" property="isFinished" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO">
@@ -22,4 +23,26 @@
)
</insert>
<select id="selectStudentLessonPlanList" resultMap="BaseResultMap">
SELECT slp.*
FROM student_lesson_plans slp
LEFT JOIN student s ON slp.student_id = s.id
JOIN (
SELECT DISTINCT slp_in.student_id
FROM student_lesson_plans slp_in
LEFT JOIN student s_in ON slp_in.student_id = s_in.id
<if test="name != null and name != ''">
WHERE s_in.name LIKE CONCAT('%', #{name}, '%')
</if>
ORDER BY slp_in.student_id
LIMIT #{startIndex}, #{pageSize}
) AS temp ON slp.student_id = temp.student_id
ORDER BY slp.id
</select>
<select id="selectStudentPlanTotal">
SELECT count(DISTINCT student_id) AS total
FROM student_lesson_plans;
</select>
</mapper>

View File

@@ -17,7 +17,7 @@ public class PlanTest {
@Test
public void test() throws Exception {
LessonPlansDO lessonPlansDO = lessonPlansDOMapper.selectById(21);
LessonPlansDO lessonPlansDO = lessonPlansDOMapper.selectById(58);
Map<String, Object> stringObjectMap = JsonUtils.parseMap(lessonPlansDO.getContentDetails(), String.class, Object.class);
for (Map.Entry<String, Object> entry : stringObjectMap.entrySet()) {
System.out.println(entry.getKey());