mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/per-boe/java-servers.git
synced 2025-12-17 06:46:53 +08:00
feat:
1.【FCJDFDXTXS-120】导出学习记录学习完成时间为空时,学习结束时间应为学生最后一次学习时间 2.【FCJDFDXTXS-115、138、140】修改课程名称的展示逻辑,修改为章名称+节名称,详细逻辑如下:默认取sectionName-contentName,如果sectionName不存在,就用courseName-contentName
This commit is contained in:
@@ -1,16 +1,15 @@
|
||||
package com.xboe.module.course.entity;
|
||||
|
||||
import com.xboe.core.SysConstant;
|
||||
import com.xboe.core.orm.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.xboe.core.SysConstant;
|
||||
import com.xboe.core.orm.BaseEntity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 课程内容表
|
||||
* */
|
||||
@@ -93,6 +92,13 @@ public class CourseContent extends BaseEntity {
|
||||
/**用于学习时的状态显示,非存储字段*/
|
||||
@Transient
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 展示名称(章名+节名,如果没有章节,则为课程名+节名)
|
||||
* 25.12.15新增
|
||||
*/
|
||||
@Transient
|
||||
private String displayName;
|
||||
|
||||
public CourseContent() {
|
||||
|
||||
|
||||
@@ -56,6 +56,14 @@ public interface ICourseContentService{
|
||||
*/
|
||||
List<CourseContent> getByCourseId(String courseId);
|
||||
|
||||
/**
|
||||
* 根据id集合得到内容
|
||||
*
|
||||
* @param ids id集合
|
||||
* @return 课程内容集合
|
||||
*/
|
||||
List<CourseContent> getByIds(List<String> ids);
|
||||
|
||||
/**
|
||||
* 根据课程id、章节id得到课程所有目录(即章节,分页),顺序按orderIndex 从小到大的顺序
|
||||
* 25.11.26新增
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.xboe.module.course.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.xboe.module.course.entity.CourseSection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 课程章节目录
|
||||
* */
|
||||
@@ -27,4 +27,13 @@ public interface ICourseSectionService {
|
||||
*/
|
||||
List<CourseSection> getByCourseId(String courseId);
|
||||
|
||||
/**
|
||||
* 根据id批量查询课程章节目录
|
||||
*
|
||||
* @param ids id集合
|
||||
* @return 课程章节目录集合
|
||||
*/
|
||||
List<CourseSection> getByIds(List<String> ids);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -142,6 +142,14 @@ public class CourseContentServiceImpl implements ICourseContentService {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CourseContent> getByIds(List<String> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return ccDao.findList(OrderCondition.asc("sortIndex"), FieldFilters.in("id", ids), FieldFilters.eq("deleted", false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据课程id、章节id得到课程所有目录(即章节,分页),顺序按orderIndex 从小到大的顺序
|
||||
* 25.11.26新增
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.xboe.module.course.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.xboe.common.OrderCondition;
|
||||
import com.xboe.core.orm.FieldFilters;
|
||||
import com.xboe.module.course.dao.CourseSectionDao;
|
||||
import com.xboe.module.course.entity.CourseSection;
|
||||
import com.xboe.module.course.service.ICourseSectionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -35,6 +34,20 @@ public class CourseSectionServiceImpl implements ICourseSectionService {
|
||||
return courseSectionDao.findList(OrderCondition.asc("orderIndex"), FieldFilters.eq("courseId", courseId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id批量查询课程章节目录
|
||||
*
|
||||
* @param ids id集合
|
||||
* @return 课程章节目录集合
|
||||
*/
|
||||
@Override
|
||||
public List<CourseSection> getByIds(List<String> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return courseSectionDao.findList(OrderCondition.asc("orderIndex"), FieldFilters.in("id", ids));
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void copyCourseSection(String id) {
|
||||
// String sql="insert into boe_course_section(course_id,description,name," +
|
||||
|
||||
@@ -452,7 +452,8 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
// 这个开始时间已经弃置了,不过先用再说(有值)
|
||||
map.put("学习开始时间", studyCourse1.getStartTime());
|
||||
// 结束时间为空的,说明还没学习结束(有值)
|
||||
map.put("学习结束时间", studyCourse1.getFinishTime());
|
||||
// 25.12.15修改,需求调整:如果结束时间为空,改为获取最后一次学习时间
|
||||
map.put("学习结束时间", studyCourse1.getFinishTime() == null ? studyCourse1.getLastTime() : studyCourse1.getFinishTime());
|
||||
// 学习时长(保留两位小数):
|
||||
map.put("学习时长", studyCourse1.getTotalDuration() == null ? null : String.format("%.2f", studyCourse1.getTotalDuration() / 60.0));
|
||||
// 学习状态需要转换
|
||||
@@ -1356,11 +1357,14 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
courseName = studyCourses.get(0).getCourseName();
|
||||
// 查询资源名称
|
||||
List<CourseContent> courseContents = contentService.getByCourseId(courseId);
|
||||
String contentName = "";
|
||||
String displayName = "";
|
||||
if (courseContents != null && !courseContents.isEmpty()) {
|
||||
// 25.12.15新增,修改课程名称的展示逻辑,修改为章名称+节名称
|
||||
// 详细逻辑如下:默认取sectionName-contentName,如果sectionName不存在,就用courseName-contentName
|
||||
studyService.setContentDisplayName(courseContents);
|
||||
for (CourseContent cc : courseContents) {
|
||||
if (contentId.equals(cc.getId())) {
|
||||
contentName = cc.getContentName();
|
||||
displayName = cc.getDisplayName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1398,7 +1402,7 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
}
|
||||
}
|
||||
// 将考试信息与用户信息拼接为map
|
||||
String finalContentName = contentName;
|
||||
String finalContentName = displayName;
|
||||
List<Map<String, Object>> dataList = studyExams.stream().map(exam -> {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
// 拼接基本信息
|
||||
@@ -1494,11 +1498,14 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
}
|
||||
// 查询资源名称
|
||||
List<CourseContent> courseContents = contentService.getByCourseId(courseId);
|
||||
String contentName = "";
|
||||
String displayName = "";
|
||||
if (courseContents != null && !courseContents.isEmpty()) {
|
||||
for (CourseContent cc : courseContents) {
|
||||
// 25.12.15新增,修改课程名称的展示逻辑,修改为章名称+节名称
|
||||
// 详细逻辑如下:默认取sectionName-contentName,如果sectionName不存在,就用courseName-contentName
|
||||
studyService.setContentDisplayName(courseContents);
|
||||
if (contentId.equals(cc.getId())) {
|
||||
contentName = cc.getContentName();
|
||||
displayName = cc.getDisplayName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1536,7 +1543,7 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
}
|
||||
}
|
||||
// 3.将作业信息与用户信息拼接为map
|
||||
String finalContentName = contentName;
|
||||
String finalContentName = displayName;
|
||||
List<Map<String, Object>> dataList = studyHomeWorks.stream().map(hw -> {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
// 拼接基本信息
|
||||
|
||||
@@ -137,6 +137,13 @@ public class StudyCourseItem extends IdEntity {
|
||||
@Transient
|
||||
private BigDecimal progressVideo;
|
||||
|
||||
/**
|
||||
* 展示名称(章名+节名,如果没有章节,则为课程名+节名)
|
||||
* 25.12.15新增
|
||||
*/
|
||||
@Transient
|
||||
private String displayName;
|
||||
|
||||
/**
|
||||
* 考试记录集合
|
||||
* 仅在资源学习情况分页查询-考试信息接口使用
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xboe.school.study.service;
|
||||
|
||||
import com.xboe.common.PageList;
|
||||
import com.xboe.module.course.entity.CourseContent;
|
||||
import com.xboe.school.study.dto.StudyContentDto;
|
||||
import com.xboe.school.study.entity.StudyCourseItem;
|
||||
import com.xboe.school.study.entity.StudyTime;
|
||||
@@ -101,6 +102,14 @@ public interface IStudyService {
|
||||
*/
|
||||
PageList<StudyCourseItem> findItemPage(int pageIndex, int pageSize, List<String> ids, String contentId, String courseId, String name, Integer status);
|
||||
|
||||
/**
|
||||
* 为courseContents列表设置展示名称(章名+节名 或 课程名+节名)
|
||||
* 25.12.15新增
|
||||
*
|
||||
* @param courseContents 课程内容集合
|
||||
*/
|
||||
void setContentDisplayName(List<CourseContent> courseContents);
|
||||
|
||||
List<StudyCourseItem> getList(String courseId, String contentId, String name, Integer status);
|
||||
|
||||
void updateStudyCourseItemLastTime(String studyContentId, int lastStudyTime, LocalDateTime timestamp);
|
||||
|
||||
@@ -8,12 +8,17 @@ import com.xboe.core.orm.QueryBuilder;
|
||||
import com.xboe.core.orm.UpdateBuilder;
|
||||
import com.xboe.module.course.entity.Course;
|
||||
import com.xboe.module.course.entity.CourseContent;
|
||||
import com.xboe.module.course.entity.CourseSection;
|
||||
import com.xboe.module.course.service.ICourseContentService;
|
||||
import com.xboe.module.course.service.ICourseSectionService;
|
||||
import com.xboe.school.study.dao.StudyCourseDao;
|
||||
import com.xboe.school.study.dao.StudyCourseItemDao;
|
||||
import com.xboe.school.study.dao.StudyTimeDao;
|
||||
import com.xboe.school.study.dto.StudyContentDto;
|
||||
import com.xboe.school.study.entity.StudyCourse;
|
||||
import com.xboe.school.study.entity.StudyCourseItem;
|
||||
import com.xboe.school.study.entity.StudyTime;
|
||||
import com.xboe.school.study.service.IStudyCourseService;
|
||||
import com.xboe.school.study.service.IStudyService;
|
||||
import com.xboe.standard.enums.BoedxContentType;
|
||||
import com.xboe.system.user.dao.UserDao;
|
||||
@@ -27,10 +32,10 @@ import javax.transaction.Transactional;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class StudyServiceImpl implements IStudyService{
|
||||
@@ -46,6 +51,16 @@ public class StudyServiceImpl implements IStudyService{
|
||||
|
||||
@Autowired
|
||||
UserDao userDao;
|
||||
|
||||
@Autowired
|
||||
IStudyCourseService studyCourseService;
|
||||
|
||||
@Autowired
|
||||
ICourseContentService courseContentService;
|
||||
|
||||
@Autowired
|
||||
ICourseSectionService courseSectionService;
|
||||
|
||||
@Autowired
|
||||
StringRedisTemplate redisTemplate;
|
||||
|
||||
@@ -272,7 +287,7 @@ public class StudyServiceImpl implements IStudyService{
|
||||
}
|
||||
}
|
||||
// 未传输status的情况,查询所有资源学习情况数据
|
||||
String sql = "select a.id, a.course_id, a.course_name, a.aname, " + "IFNULL(b.finish_time, '0') as finish_time, IFNULL(b.progress, 0) as progress, IFNULL(b.status, 1) as status " + ",b.score,b.item_id,b.aid " + "from (select id, course_id, course_name, aname, 0, 1 from boe_study_course where course_id = '" + courseId + "'" + (StringUtils.isBlank(name) ? "" : "and aname like '%" + name + "%'") + ") a " + "inner join " + "(select bsc.id, bsc.course_id, bsc.course_name, bsc.aname, item.id as item_id,item.finish_time, item.progress, item.status,MAX(item.score) score,item.aid " + "from boe_study_course bsc left join boe_study_course_item item on item.course_id = bsc.course_id and item.study_id = bsc.id " + "where bsc.course_id = '" + courseId + "'" +
|
||||
String sql = "select a.id, a.course_id, a.course_name, a.aname, " + "IFNULL(b.finish_time, '0') as finish_time, IFNULL(b.progress, 0) as progress, IFNULL(b.status, 1) as status " + ",b.score,b.item_id,b.aid,b.content_id " + "from (select id, course_id, course_name, aname, 0, 1 from boe_study_course where course_id = '" + courseId + "'" + (StringUtils.isBlank(name) ? "" : "and aname like '%" + name + "%'") + ") a " + "inner join " + "(select bsc.id, bsc.course_id, bsc.course_name, bsc.aname, item.id as item_id,item.finish_time, item.progress, item.status,MAX(item.score) score,item.aid,item.content_id " + "from boe_study_course bsc left join boe_study_course_item item on item.course_id = bsc.course_id and item.study_id = bsc.id " + "where bsc.course_id = '" + courseId + "'" +
|
||||
(StringUtils.isBlank(contentId) ? "" : "and item.content_id = '" + contentId + "'") +
|
||||
(StringUtils.isBlank(name) ? "" : "and item.aname like '%" + name +"%'") + " group by bsc.id) b " +
|
||||
"on a.course_id = b.course_id and a.id = b.id " +
|
||||
@@ -306,17 +321,102 @@ public class StudyServiceImpl implements IStudyService{
|
||||
sc.setScore(Float.valueOf(objs[7].toString()));
|
||||
}
|
||||
// 25.12.5新增,补全aid查询
|
||||
if (objs[8] != null) {
|
||||
sc.setAid(String.valueOf(objs[8].toString()));
|
||||
if (objs[9] != null) {
|
||||
sc.setAid(String.valueOf(objs[9].toString()));
|
||||
}
|
||||
// 25.12.15新增,补全contentId查询
|
||||
if (objs[10] != null) {
|
||||
sc.setContentId(String.valueOf(objs[10].toString()));
|
||||
}
|
||||
item.add(sc);
|
||||
}
|
||||
// 25.12.15新增,修改课程名称的展示逻辑,修改为章名称+节名称
|
||||
// 详细逻辑如下:默认取sectionName-contentName,如果sectionName不存在,就用courseName-contentName
|
||||
List<String> contentIds = item.stream().map(StudyCourseItem::getContentId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
||||
if (!contentIds.isEmpty()) {
|
||||
List<CourseContent> contentList = courseContentService.getByIds(contentIds);
|
||||
if (contentList != null) {
|
||||
setContentDisplayName(contentList);
|
||||
// 根据contentId将展示名称映射到item
|
||||
for (StudyCourseItem studyCourseItem : item) {
|
||||
studyCourseItem.setDisplayName(contentList.stream().filter(content -> content.getId().equals(studyCourseItem.getContentId())).findFirst().map(CourseContent::getDisplayName).orElse(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 查询当前
|
||||
PageList<StudyCourseItem> pageList = new PageList<>(item);
|
||||
pageList.setCount(totalCount);
|
||||
pageList.setPageSize(pageSize);
|
||||
pageList.setList(item);
|
||||
return pageList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 CourseContent 列表设置展示名称(章名+节名 或 课程名+节名)
|
||||
* 基于 25.12.15 的展示逻辑:优先使用 章名+节名,章不存在则退化为 课程名+节名
|
||||
*
|
||||
* @param courseContents 节内容列表(即“节”)
|
||||
*/
|
||||
@Override
|
||||
public void setContentDisplayName(List<CourseContent> courseContents) {
|
||||
if (courseContents == null || courseContents.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 1. 提取唯一 sectionId 和 courseId
|
||||
Set<String> sectionIds = new HashSet<>();
|
||||
Set<String> courseIds = new HashSet<>();
|
||||
for (CourseContent content : courseContents) {
|
||||
if (content.getCsectionId() != null) {
|
||||
sectionIds.add(content.getCsectionId());
|
||||
}
|
||||
if (content.getCourseId() != null) {
|
||||
courseIds.add(content.getCourseId());
|
||||
}
|
||||
}
|
||||
// 2. 批量查询 CourseSection
|
||||
Map<String, CourseSection> sectionMap = new HashMap<>();
|
||||
if (!sectionIds.isEmpty()) {
|
||||
List<CourseSection> sections = courseSectionService.getByIds(new ArrayList<>(sectionIds));
|
||||
if (sections != null) {
|
||||
sectionMap = sections.stream().collect(Collectors.toMap(CourseSection::getId, Function.identity(), (e1, e2) -> e1));
|
||||
}
|
||||
}
|
||||
// 3. 批量查询 StudyCourse
|
||||
Map<String, StudyCourse> courseMap = new HashMap<>();
|
||||
if (!courseIds.isEmpty()) {
|
||||
List<StudyCourse> courses = studyCourseService.findByIds(new ArrayList<>(courseIds));
|
||||
if (courses != null) {
|
||||
courseMap = courses.stream().collect(Collectors.toMap(StudyCourse::getId, Function.identity(), (e1, e2) -> e1));
|
||||
}
|
||||
}
|
||||
// 4. 为每个 CourseContent 设置 displayName
|
||||
for (CourseContent courseContent : courseContents) {
|
||||
String sectionName = null;
|
||||
String courseName = "空课程名称";
|
||||
String contentName = (courseContent.getContentName() != null) ? courseContent.getContentName() : "空内容名称";
|
||||
// 尝试获取章名
|
||||
if (courseContent.getCsectionId() != null) {
|
||||
CourseSection section = sectionMap.get(courseContent.getCsectionId());
|
||||
if (section != null && section.getName() != null) {
|
||||
sectionName = section.getName();
|
||||
}
|
||||
}
|
||||
// 设置 displayName:优先章+节,否则课程+节
|
||||
String displayName;
|
||||
if (sectionName != null) {
|
||||
displayName = sectionName + "-" + contentName;
|
||||
} else {
|
||||
// 获取课程名
|
||||
if (courseContent.getCourseId() != null) {
|
||||
StudyCourse course = courseMap.get(courseContent.getCourseId());
|
||||
if (course != null && course.getCourseName() != null) {
|
||||
courseName = course.getCourseName();
|
||||
}
|
||||
}
|
||||
displayName = courseName + "-" + contentName;
|
||||
}
|
||||
courseContent.setDisplayName(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user