个人学习记录

This commit is contained in:
2025-11-17 16:07:30 +08:00
parent 6e9057f6ee
commit d2e554c715
9 changed files with 529 additions and 40 deletions

View File

@@ -1,7 +1,9 @@
package org.xyzh.api.study.record;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.dto.study.TbLearningRecord;
import org.xyzh.common.vo.LearningStatisticsDetailVO;
import java.math.BigDecimal;
import java.util.List;
@@ -129,4 +131,23 @@ public interface LearningRecordService {
* @since 2025-10-30
*/
ResultDomain<Map<String, Object>> getStudyRecordsRankings();
/**
* @description 获取时间范围内每天的学习时长
* @param startTime 开始时间
* @param endTime 结束时间
* @return ResultDomain<Map<String, Object>> 用户学习记录统计
* @author yslg
* @since 2025-10-30
*/
ResultDomain<Map<String, Object>> getUserRecordRange(String startTime, String endTime);
/**
* @description 获取用户学习记录统计
* @param learningRecord 学习记录
* @return ResultDomain<Map<String, Object>> 用户学习记录统计
* @author yslg
* @since 2025-10-30
*/
ResultDomain<LearningStatisticsDetailVO> getUserRecordRangePage(PageRequest<TbLearningRecord> learningRecord);
}

View File

@@ -6,10 +6,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.xyzh.api.study.record.LearningRecordService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.dto.study.TbLearningRecord;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.PathVariable;
import org.xyzh.common.vo.LearningStatisticsDetailVO;
import java.util.Map;
@@ -92,4 +91,28 @@ public class LearningRecordController {
public ResultDomain<Map<String, Object>> getStudyRecordsRankings() {
return learningRecordService.getStudyRecordsRankings();
}
/**
* 获取用户学习记录统计
* @param startTime 开始时间
* @param endTime 结束时间
* @return 用户学习记录统计
*/
@GetMapping("/user/record/range")
public ResultDomain<Map<String, Object>> getUserRecordRange(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime) {
return learningRecordService.getUserRecordRange(startTime, endTime);
}
/**
* 获取用户学习记录统计
* @param startTime 开始时间
* @param endTime 结束时间
* @return 用户学习记录统计
*/
@PostMapping("/user/record/range")
public ResultDomain<LearningStatisticsDetailVO> getUserRecordRangePage(@RequestBody PageRequest<TbLearningRecord> learningRecord) {
return learningRecordService.getUserRecordRangePage(learningRecord);
}
}

View File

@@ -6,6 +6,7 @@ import org.apache.ibatis.annotations.Param;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.dto.study.TbLearningRecord;
import org.xyzh.common.dto.study.TbLearningTask;
import org.xyzh.common.vo.LearningStatisticsDetailVO;
import org.xyzh.common.vo.UserDeptRoleVO;
import java.util.List;
@@ -138,7 +139,7 @@ public interface LearningRecordMapper extends BaseMapper<TbLearningRecord> {
* @author yslg
* @since 2025-10-15
*/
List<TbLearningRecord> selectLearningRecordsPage(@Param("filter") TbLearningRecord filter, @Param("pageParam") PageParam pageParam);
List<LearningStatisticsDetailVO> selectLearningRecordsPage(@Param("filter") TbLearningRecord filter, @Param("pageParam") PageParam pageParam);
/**
* @description 统计学习记录总数
@@ -195,4 +196,16 @@ public interface LearningRecordMapper extends BaseMapper<TbLearningRecord> {
* @since 2025-10-30
*/
List<Map<String, Object>> getWeeklyTaskCompletionRanking(@Param("userDeptRoles") List<UserDeptRoleVO> userDeptRoles);
/**
* @description 获取用户时间范围内每天的学习时长
* @param userId 用户ID
* @param startTime 开始时间
* @param endTime 结束时间
* @return List<Map<String, Object>> 每天学习时长数据
* @author yslg
* @since 2025-11-17
*/
List<Map<String, Object>> getUserDailyDuration(@Param("userId") String userId, @Param("startTime") String startTime, @Param("endTime") String endTime);
}

View File

@@ -13,11 +13,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.enums.TaskItemType;
import org.xyzh.common.core.page.PageRequest;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.dto.study.TbLearningRecord;
import org.xyzh.common.dto.study.TbLearningTask;
import org.xyzh.common.dto.study.TbTaskItem;
import org.xyzh.common.dto.study.TbTaskUser;
import org.xyzh.common.dto.user.TbSysUser;
import org.xyzh.common.vo.LearningStatisticsDetailVO;
import org.xyzh.common.vo.TaskItemVO;
import org.xyzh.common.vo.UserDeptRoleVO;
import org.xyzh.api.study.record.LearningRecordService;
@@ -328,4 +332,71 @@ public class SCLearningRecordServiceImpl implements LearningRecordService {
}
return resultDomain;
}
@Override
public ResultDomain<Map<String, Object>> getUserRecordRange(String startTime, String endTime) {
ResultDomain<Map<String, Object>> resultDomain = new ResultDomain<>();
try {
// 获取当前用户ID
String userId = LoginUtil.getCurrentUserId();
if (userId == null) {
resultDomain.fail("用户未登录");
return resultDomain;
}
// 查询时间范围内每天的学习时长
List<Map<String, Object>> dailyData = learningRecordMapper.getUserDailyDuration(userId, startTime, endTime);
Map<String, Object> chartData = new HashMap<>();
chartData.put("dailyDuration", dailyData);
resultDomain.success("获取学习时长统计成功", chartData);
} catch (Exception e) {
logger.error("获取学习时长统计失败", e);
resultDomain.fail("获取学习时长统计失败:" + e.getMessage());
}
return resultDomain;
}
@Override
public ResultDomain<LearningStatisticsDetailVO> getUserRecordRangePage(PageRequest<TbLearningRecord> pageRequest) {
ResultDomain<LearningStatisticsDetailVO> resultDomain = new ResultDomain<>();
try {
// 获取当前用户ID
String userId = LoginUtil.getCurrentUserId();
if (userId == null) {
resultDomain.fail("用户未登录");
return resultDomain;
}
TbLearningRecord filter = pageRequest.getFilter();
if (filter == null) {
filter = new TbLearningRecord();
}
PageParam pageParam = pageRequest.getPageParam();
if (pageParam == null) {
pageParam = new PageParam();
}
// 设置当前用户ID用于筛选
filter.setUserID(userId);
// 查询分页数据
List<LearningStatisticsDetailVO> list = learningRecordMapper.selectLearningRecordsPage(filter, pageParam);
long total = learningRecordMapper.countLearningRecords(filter);
// 构建分页结果
PageDomain<LearningStatisticsDetailVO> pageDomain = new PageDomain<>();
pageDomain.setDataList(list);
pageParam.setTotalElements((int) total);
pageParam.setTotalPages((int) Math.ceil((double) total / pageParam.getPageSize()));
pageDomain.setPageParam(pageParam);
resultDomain.success("查询学习记录成功", pageDomain);
} catch (Exception e) {
logger.error("查询学习记录失败", e);
resultDomain.fail("查询学习记录失败:" + e.getMessage());
}
return resultDomain;
}
}

View File

@@ -156,6 +156,9 @@
<if test="updateTime != null">
update_time = #{updateTime},
</if>
<if test="startTime != null and endTime != null">
create_time BETWEEN #{startTime} AND #{endTime}
</if>
</set>
WHERE id = #{id}
</update>
@@ -187,21 +190,87 @@
</foreach>
</delete>
<!-- 分页查询学习记录 -->
<select id="selectLearningRecordsPage" resultMap="BaseResultMap">
<!-- LearningStatisticsDetailVO结果映射 -->
<resultMap id="StatisticsDetailResultMap" type="org.xyzh.common.vo.LearningStatisticsDetailVO">
<result column="stat_date" property="statDate" jdbcType="TIMESTAMP"/>
<result column="resource_type" property="resourceType" jdbcType="INTEGER"/>
<result column="resource_type_name" property="resourceTypeName" jdbcType="VARCHAR"/>
<result column="resource_id" property="resourceID" jdbcType="VARCHAR"/>
<result column="resource_title" property="resourceTitle" jdbcType="VARCHAR"/>
<result column="course_id" property="courseID" jdbcType="VARCHAR"/>
<result column="course_name" property="courseName" jdbcType="VARCHAR"/>
<result column="chapter_id" property="chapterID" jdbcType="VARCHAR"/>
<result column="chapter_name" property="chapterName" jdbcType="VARCHAR"/>
<result column="total_duration" property="totalDuration" jdbcType="INTEGER"/>
<result column="total_duration_formatted" property="totalDurationFormatted" jdbcType="VARCHAR"/>
<result column="learn_count" property="learnCount" jdbcType="INTEGER"/>
<result column="is_complete" property="isComplete" jdbcType="BOOLEAN"/>
<result column="complete_time" property="completeTime" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- 分页查询学习记录详情 -->
<select id="selectLearningRecordsPage" resultMap="StatisticsDetailResultMap">
SELECT
<include refid="Base_Column_List" />
FROM tb_learning_record
<include refid="Where_Clause" />
ORDER BY last_learn_time DESC, create_time DESC
COALESCE(lr.last_learn_time, lr.update_time, lr.create_time) AS stat_date,
lr.resource_type AS resource_type,
CASE lr.resource_type
WHEN 1 THEN '文章'
WHEN 2 THEN '课程'
WHEN 3 THEN '章节'
ELSE '未知'
END AS resource_type_name,
lr.resource_id AS resource_id,
CASE
WHEN lr.resource_type = 1 THEN COALESCE(r.title, CONCAT('文章-', lr.resource_id))
WHEN lr.resource_type = 2 THEN COALESCE(c.name, CONCAT('课程-', lr.course_id))
WHEN lr.resource_type = 3 THEN COALESCE(ch.name, CONCAT('章节-', lr.chapter_id))
ELSE '未知资源'
END AS resource_title,
COALESCE(lr.course_id, '') AS course_id,
COALESCE(c.name, '') AS course_name,
COALESCE(lr.chapter_id, '') AS chapter_id,
COALESCE(ch.name, '') AS chapter_name,
COALESCE(lr.duration, 0) AS total_duration,
'' AS total_duration_formatted,
1 AS learn_count,
COALESCE(lr.is_complete, 0) AS is_complete,
lr.complete_time AS complete_time
FROM tb_learning_record lr
LEFT JOIN tb_resource r ON lr.resource_type = 1 AND lr.resource_id = r.resource_id
LEFT JOIN tb_course c ON lr.resource_type = 2 AND lr.course_id = c.id
LEFT JOIN tb_course_chapter ch ON lr.resource_type = 3 AND lr.chapter_id = ch.id
<where>
<if test="filter.userID != null and filter.userID != ''">
AND lr.user_id = #{filter.userID}
</if>
<if test="filter.resourceType != null">
AND lr.resource_type = #{filter.resourceType}
</if>
<if test="filter.isComplete != null">
AND lr.is_complete = #{filter.isComplete}
</if>
</where>
ORDER BY lr.last_learn_time DESC, lr.create_time DESC
LIMIT #{pageParam.pageSize} OFFSET #{pageParam.offset}
</select>
<!-- 统计学习记录总数 -->
<select id="countLearningRecords" resultType="long">
SELECT COUNT(1)
FROM tb_learning_record
<include refid="Where_Clause" />
FROM tb_learning_record lr
<where>
<if test="filter != null">
<if test="filter.userID != null and filter.userID != ''">
AND lr.user_id = #{filter.userID}
</if>
<if test="filter.resourceType != null">
AND lr.resource_type = #{filter.resourceType}
</if>
<if test="filter.isComplete != null">
AND lr.is_complete = #{filter.isComplete}
</if>
</if>
</where>
</select>
<!-- 获取本周课程和文章的总学习时长统计 -->
@@ -362,4 +431,30 @@
<select id="getTaskStaticByTag">
</select>
<!-- 获取用户时间范围内每天的学习时长 -->
<select id="getUserDailyDuration" resultType="java.util.Map">
WITH RECURSIVE date_range AS (
-- 生成起始日期
SELECT DATE(#{startTime}) AS date
UNION ALL
-- 递归生成后续日期
SELECT DATE_ADD(date, INTERVAL 1 DAY)
FROM date_range
WHERE date &lt; DATE(#{endTime})
)
SELECT
dr.date AS date,
DATE_FORMAT(dr.date, '%Y-%m-%d') AS statDate,
COALESCE(SUM(lr.duration), 0) AS duration,
COALESCE(SUM(lr.duration), 0) AS totalDuration,
COUNT(lr.id) AS count
FROM date_range dr
LEFT JOIN tb_learning_record lr
ON DATE(lr.update_time) = dr.date
AND lr.user_id = #{userId}
GROUP BY dr.date
ORDER BY dr.date ASC
</select>
</mapper>