feat(review): 新增复习内容滚动展示与交互 API
- 新增 /review/feed 端点,合并报告和残片数据按时间倒序返回
- 新增 /review/report/{id} 和 /review/fragment/{id} 端点
- 支持复习内容在首页滚动展示及点击查看详情
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
package com.guo.learningprogresstracker.controller;
|
||||||
|
|
||||||
|
import com.guo.learningprogresstracker.dto.ReviewFeedItem;
|
||||||
|
import com.guo.learningprogresstracker.entity.CommonResult;
|
||||||
|
import com.guo.learningprogresstracker.entity.StudyReportFragmentsEntity;
|
||||||
|
import com.guo.learningprogresstracker.entity.StudyReportsEntity;
|
||||||
|
import com.guo.learningprogresstracker.exception.NotFindEntitiesException;
|
||||||
|
import com.guo.learningprogresstracker.service.impl.ReviewServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复习模块控制层 — 复习内容滚动展示与交互
|
||||||
|
*/
|
||||||
|
@RequestMapping("/review")
|
||||||
|
@RestController
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReviewController {
|
||||||
|
|
||||||
|
private final ReviewServiceImpl reviewService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取复习 feed,合并报告和残片按时间倒序
|
||||||
|
*/
|
||||||
|
@GetMapping("/feed")
|
||||||
|
public CommonResult<List<ReviewFeedItem>> getReviewFeed(
|
||||||
|
@RequestParam(defaultValue = "30") int limit) {
|
||||||
|
return CommonResult.success(reviewService.getReviewFeed(limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取报告详情
|
||||||
|
*/
|
||||||
|
@GetMapping("/report/{id}")
|
||||||
|
public CommonResult<StudyReportsEntity> getReportDetail(@PathVariable int id) throws NotFindEntitiesException {
|
||||||
|
return CommonResult.success(reviewService.getReportDetail(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取残片详情
|
||||||
|
*/
|
||||||
|
@GetMapping("/fragment/{id}")
|
||||||
|
public CommonResult<StudyReportFragmentsEntity> getFragmentDetail(@PathVariable int id) throws NotFindEntitiesException {
|
||||||
|
return CommonResult.success(reviewService.getFragmentDetail(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.guo.learningprogresstracker.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复习滚动 feed 条目,合并展示学习报告和残片
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ReviewFeedItem {
|
||||||
|
private Integer id;
|
||||||
|
private String sessionNum;
|
||||||
|
private String taskNum;
|
||||||
|
private String taskName;
|
||||||
|
private String sourceType; // REPORT | FRAGMENT
|
||||||
|
private String content;
|
||||||
|
private LocalDateTime createdTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.guo.learningprogresstracker.mapper;
|
||||||
|
|
||||||
|
import com.guo.learningprogresstracker.dto.ReviewFeedItem;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复习模块自定义查询 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ReviewMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取最近的学习报告和残片,合并排序后返回
|
||||||
|
*/
|
||||||
|
List<ReviewFeedItem> selectReviewFeed(@Param("limit") int limit);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.guo.learningprogresstracker.service;
|
||||||
|
|
||||||
|
import com.guo.learningprogresstracker.dto.ReviewFeedItem;
|
||||||
|
import com.guo.learningprogresstracker.entity.StudyReportFragmentsEntity;
|
||||||
|
import com.guo.learningprogresstracker.entity.StudyReportsEntity;
|
||||||
|
import com.guo.learningprogresstracker.exception.NotFindEntitiesException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复习模块 Service 接口
|
||||||
|
*/
|
||||||
|
public interface ReviewService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取复习 feed 列表,合并报告和残片按时间倒序
|
||||||
|
*/
|
||||||
|
List<ReviewFeedItem> getReviewFeed(int limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取报告详情
|
||||||
|
*/
|
||||||
|
StudyReportsEntity getReportDetail(int id) throws NotFindEntitiesException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取残片详情
|
||||||
|
*/
|
||||||
|
StudyReportFragmentsEntity getFragmentDetail(int id) throws NotFindEntitiesException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.guo.learningprogresstracker.service.impl;
|
||||||
|
|
||||||
|
import com.guo.learningprogresstracker.dto.ReviewFeedItem;
|
||||||
|
import com.guo.learningprogresstracker.entity.StudyReportFragmentsEntity;
|
||||||
|
import com.guo.learningprogresstracker.entity.StudyReportsEntity;
|
||||||
|
import com.guo.learningprogresstracker.exception.NotFindEntitiesException;
|
||||||
|
import com.guo.learningprogresstracker.mapper.ReviewMapper;
|
||||||
|
import com.guo.learningprogresstracker.mapper.StudyReportFragmentsMapper;
|
||||||
|
import com.guo.learningprogresstracker.mapper.StudyReportsMapper;
|
||||||
|
import com.guo.learningprogresstracker.service.ReviewService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复习模块 Service 实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReviewServiceImpl implements ReviewService {
|
||||||
|
|
||||||
|
private final ReviewMapper reviewMapper;
|
||||||
|
private final StudyReportsMapper studyReportsMapper;
|
||||||
|
private final StudyReportFragmentsMapper studyReportFragmentsMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ReviewFeedItem> getReviewFeed(int limit) {
|
||||||
|
return reviewMapper.selectReviewFeed(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StudyReportsEntity getReportDetail(int id) throws NotFindEntitiesException {
|
||||||
|
return Optional.ofNullable(studyReportsMapper.selectById(id))
|
||||||
|
.orElseThrow(() -> new NotFindEntitiesException("学习报告[" + id + "]不存在"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StudyReportFragmentsEntity getFragmentDetail(int id) throws NotFindEntitiesException {
|
||||||
|
return Optional.ofNullable(studyReportFragmentsMapper.selectById(id))
|
||||||
|
.orElseThrow(() -> new NotFindEntitiesException("学习残片[" + id + "]不存在"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis-org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.guo.learningprogresstracker.mapper.ReviewMapper">
|
||||||
|
|
||||||
|
<select id="selectReviewFeed" resultType="com.guo.learningprogresstracker.dto.ReviewFeedItem">
|
||||||
|
SELECT
|
||||||
|
combined.id,
|
||||||
|
combined.session_num AS sessionNum,
|
||||||
|
combined.source_type AS sourceType,
|
||||||
|
combined.content,
|
||||||
|
combined.created_time AS createdTime,
|
||||||
|
t.task_num AS taskNum,
|
||||||
|
t.task_name AS taskName
|
||||||
|
FROM (
|
||||||
|
SELECT r.id, r.session_num, r.content, r.created_time, 'REPORT' AS source_type
|
||||||
|
FROM study_reports r
|
||||||
|
WHERE r.deleted = 0
|
||||||
|
UNION ALL
|
||||||
|
SELECT f.id, f.session_num, f.content, f.created_time, 'FRAGMENT' AS source_type
|
||||||
|
FROM study_report_fragments f
|
||||||
|
WHERE f.deleted = 0
|
||||||
|
) combined
|
||||||
|
JOIN study_sessions ss ON combined.session_num = ss.session_num AND ss.deleted = 0
|
||||||
|
JOIN tasks t ON ss.task_num = t.task_num AND t.deleted = 0
|
||||||
|
ORDER BY combined.created_time DESC
|
||||||
|
LIMIT #{limit}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user