mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/per-boe/java-servers.git
synced 2025-12-16 14:26:49 +08:00
Compare commits
56 Commits
9f26b991a0
...
251114-fea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e642924caa | ||
|
|
7756edf122 | ||
|
|
eedaf13711 | ||
|
|
8a9690379a | ||
|
|
6a25c3c94a | ||
|
|
eb684e5fed | ||
|
|
4e0afbb19c | ||
|
|
05e3f55510 | ||
|
|
7f19cfa81d | ||
|
|
a9e0b87b95 | ||
|
|
5f160f9516 | ||
|
|
7d7a2c40c7 | ||
|
|
4260930295 | ||
|
|
5ea2a12a67 | ||
|
|
3e98719b3b | ||
|
|
e82bfc4ba3 | ||
|
|
2ac77e7cc9 | ||
|
|
efb3b49603 | ||
|
|
e7706a7319 | ||
|
|
ce88a297f9 | ||
|
|
4d79c8c51d | ||
|
|
21aa360d2a | ||
|
|
4a92af0432 | ||
|
|
c8f74526ea | ||
|
|
e49b62b05d | ||
|
|
a9cfc7898c | ||
|
|
fd9899fb05 | ||
|
|
cbebcc6da8 | ||
|
|
3ba06fd16e | ||
|
|
f99b7f0336 | ||
|
|
13e1a3fd02 | ||
|
|
1d567f6a0d | ||
|
|
38e9eed3a4 | ||
|
|
0612ca8b88 | ||
|
|
edd6540a76 | ||
|
|
63bcd9d11e | ||
|
|
ad1f02c8ab | ||
|
|
eba13bb602 | ||
|
|
240d4725e6 | ||
|
|
0b5716ed7d | ||
|
|
a1121e8700 | ||
|
|
5f42139407 | ||
|
|
3d35519615 | ||
|
|
e76833a3c2 | ||
|
|
c3027517c5 | ||
|
|
ce2524fdcb | ||
|
|
4f53a268ba | ||
|
|
8e1a68d416 | ||
|
|
4e6d1a6b04 | ||
|
|
f506fe49f2 | ||
|
|
3c582e9ade | ||
|
|
716ba91c2e | ||
|
|
f39562ffc9 | ||
|
|
2b7d0ef35a | ||
|
|
7e21784a74 | ||
|
|
4b064171e6 |
@@ -0,0 +1,54 @@
|
||||
package com.xboe.module.course.api;
|
||||
|
||||
import com.xboe.core.JsonResponse;
|
||||
import com.xboe.core.api.ApiBaseController;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.index.query.WrapperQueryBuilder;
|
||||
import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
||||
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/xboe/m/course/manage")
|
||||
@Slf4j
|
||||
public class CourseEsApi extends ApiBaseController {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RestHighLevelClient restHighLevelClient;
|
||||
|
||||
@GetMapping("/es/sort")
|
||||
public JsonResponse updateSortWeight() {
|
||||
UpdateByQueryRequest request = new UpdateByQueryRequest("new_resource_list");
|
||||
|
||||
// 使用 Painless 脚本为文档添加 sortWeight 字段
|
||||
Script script = new Script(
|
||||
ScriptType.INLINE,
|
||||
"painless",
|
||||
"ctx._source.sortWeight = 9999",
|
||||
Collections.emptyMap()
|
||||
);
|
||||
request.setScript(script);
|
||||
|
||||
// 可选:只更新那些还没有 sortWeight 字段的文档(避免覆盖已有值)
|
||||
String query = "{ \"bool\": { \"must_not\": { \"exists\": { \"field\": \"sortWeight\" } } } }";
|
||||
request.setQuery(new WrapperQueryBuilder(query));
|
||||
|
||||
try {
|
||||
BulkByScrollResponse response = restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
|
||||
return success(response.getUpdated());
|
||||
} catch (IOException e) {
|
||||
log.error("更新索引失败", e);
|
||||
return error("更新索引失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,6 +131,16 @@ public class CourseManageApi extends ApiBaseController{
|
||||
return success(coursePageService.pageQuery(null, coursePageQueryDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新-教师端 我开发的课程
|
||||
* @param coursePageQueryDTO
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/develop_page")
|
||||
public JsonResponse<PageList<CoursePageVo>> teacherPage(@RequestBody CoursePageQueryDTO coursePageQueryDTO) {
|
||||
return success(coursePageService.pageQuery(getCurrent(), coursePageQueryDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前用户是否在管理端显示置顶相关功能
|
||||
* @return
|
||||
@@ -420,9 +430,10 @@ public class CourseManageApi extends ApiBaseController{
|
||||
fillCourseData(dto.getCourse());
|
||||
courseService.save(dto);
|
||||
}else {
|
||||
// 20251215lzx:编辑基本信息不提交状态,让前端课程可以继续查看
|
||||
//修改后重置,重新提交审核,重新发布
|
||||
dto.getCourse().setPublished(false);
|
||||
dto.getCourse().setStatus(Course.STATUS_NONE);
|
||||
// dto.getCourse().setPublished(false);
|
||||
// dto.getCourse().setStatus(Course.STATUS_NONE);
|
||||
courseService.update(dto);
|
||||
}
|
||||
String token = request.getHeader("Xboe-Access-Token");
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.xboe.module.course.dto.CoursePageQueryDTO;
|
||||
@@ -101,6 +102,7 @@ public class CourseDao extends BaseDao<Course> {
|
||||
StringBuilder builder = new StringBuilder("select ");
|
||||
builder.append("c.id,");
|
||||
builder.append("c.name,");
|
||||
builder.append("c.type,");
|
||||
builder.append("c.cover_img AS coverImg,");
|
||||
builder.append("c.sys_type1 AS sysType1,");
|
||||
builder.append("c.sys_type2 AS sysType2,");
|
||||
@@ -122,7 +124,8 @@ public class CourseDao extends BaseDao<Course> {
|
||||
builder.append("c.open_course AS openCourse,");
|
||||
builder.append("c.is_top AS isTop,");
|
||||
builder.append("COALESCE(tch.teacher_names, '') AS teacherName,");
|
||||
builder.append("c.sort_weight AS sortWeight");
|
||||
builder.append("c.sort_weight AS sortWeight,");
|
||||
builder.append("c.sys_update_time AS sysUpdateTime");
|
||||
// 拼接FROM及查询条件语句
|
||||
appendFrom(builder, queryDTO, isSystemAdmin, orgIds, currentAccountId, userCenterSchema);
|
||||
// 排序语句
|
||||
@@ -142,59 +145,65 @@ public class CourseDao extends BaseDao<Course> {
|
||||
}
|
||||
|
||||
vo.setName((String) row[1]);
|
||||
vo.setCoverImg((String) row[2]);
|
||||
vo.setSysType1((String) row[3]);
|
||||
vo.setSysType2((String) row[4]);
|
||||
vo.setSysType3((String) row[5]);
|
||||
vo.setOrgId((String) row[6]);
|
||||
vo.setOrgName((String) row[7]);
|
||||
vo.setOrgFullName((String) row[8]);
|
||||
vo.setSysCreateBy((String) row[9]);
|
||||
vo.setCreateFrom((String) row[10]);
|
||||
vo.setType((Integer) row[2]);
|
||||
vo.setCoverImg((String) row[3]);
|
||||
vo.setSysType1((String) row[4]);
|
||||
vo.setSysType2((String) row[5]);
|
||||
vo.setSysType3((String) row[6]);
|
||||
vo.setOrgId((String) row[7]);
|
||||
vo.setOrgName((String) row[8]);
|
||||
vo.setOrgFullName((String) row[9]);
|
||||
vo.setSysCreateBy((String) row[10]);
|
||||
vo.setCreateFrom((String) row[11]);
|
||||
|
||||
// 增加对Timestamp和LocalDateTime的兼容性,防止Timestamp为null的情况
|
||||
Timestamp sysCreateTimestamp = (Timestamp) row[11];
|
||||
Timestamp sysCreateTimestamp = (Timestamp) row[12];
|
||||
if (sysCreateTimestamp != null) {
|
||||
vo.setSysCreateTime(sysCreateTimestamp.toLocalDateTime());
|
||||
}
|
||||
|
||||
vo.setForUsers((String) row[12]);
|
||||
vo.setStatus((Integer) row[13]);
|
||||
vo.setPublished((Boolean) row[14]);
|
||||
vo.setForUsers((String) row[13]);
|
||||
vo.setStatus((Integer) row[14]);
|
||||
vo.setPublished((Boolean) row[15]);
|
||||
|
||||
// 增加对Timestamp和LocalDateTime的兼容性,防止Timestamp为null的情况
|
||||
Timestamp publishTimestamp = (Timestamp) row[15];
|
||||
Timestamp publishTimestamp = (Timestamp) row[16];
|
||||
if (publishTimestamp != null) {
|
||||
vo.setPublishTime(publishTimestamp.toLocalDateTime());
|
||||
}
|
||||
|
||||
// 防止Number为null的情况
|
||||
Number studysNum = (Number) row[16];
|
||||
Number studysNum = (Number) row[17];
|
||||
if (studysNum != null) {
|
||||
vo.setStudys(studysNum.intValue());
|
||||
} else {
|
||||
vo.setStudys(0);
|
||||
}
|
||||
|
||||
Number scoreNum = (Number) row[17];
|
||||
Number scoreNum = (Number) row[18];
|
||||
if (scoreNum != null) {
|
||||
vo.setScore(scoreNum.floatValue());
|
||||
} else {
|
||||
vo.setScore(0.0f);
|
||||
}
|
||||
|
||||
Number durationNum = (Number) row[18];
|
||||
Number durationNum = (Number) row[19];
|
||||
if (durationNum != null) {
|
||||
vo.setCourseDuration(durationNum.longValue());
|
||||
} else {
|
||||
vo.setCourseDuration(0L);
|
||||
}
|
||||
|
||||
vo.setEnabled((Boolean) row[19]);
|
||||
vo.setOpenCourse((Integer) row[20]);
|
||||
vo.setIsTop((Boolean) row[21]);
|
||||
vo.setTeacherName((String) row[22]);
|
||||
vo.setSortWeight((Integer) row[23]);
|
||||
vo.setEnabled((Boolean) row[20]);
|
||||
vo.setOpenCourse((Integer) row[21]);
|
||||
vo.setIsTop((Boolean) row[22]);
|
||||
vo.setTeacherName((String) row[23]);
|
||||
vo.setSortWeight((Integer) row[24]);
|
||||
// 增加对Timestamp和LocalDateTime的兼容性,防止Timestamp为null的情况
|
||||
Timestamp sysUpdateTimestamp = (Timestamp) row[25];
|
||||
if (sysUpdateTimestamp != null) {
|
||||
vo.setSysUpdateTime(sysUpdateTimestamp.toLocalDateTime());
|
||||
}
|
||||
coursePageVos.add(vo);
|
||||
}
|
||||
return coursePageVos;
|
||||
@@ -215,6 +224,19 @@ public class CourseDao extends BaseDao<Course> {
|
||||
return count.longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询课程名称
|
||||
* @param courseName
|
||||
* @return
|
||||
*/
|
||||
public List<String> queryCourseNames(String courseName) {
|
||||
String sql = "SELECT name FROM boe_course WHERE deleted = 0 AND (name = :courseName OR name LIKE CONCAT(:courseName,'(%)'))";
|
||||
Query query = entityManager.createNativeQuery(sql);
|
||||
query.setParameter("courseName", courseName);
|
||||
|
||||
return (List<String>) query.getResultList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接FROM及查询条件语句
|
||||
*
|
||||
@@ -229,14 +251,14 @@ public class CourseDao extends BaseDao<Course> {
|
||||
// 开头判断:课程培训时间的两个参数是否不为null
|
||||
boolean filterLearningTime = queryDTO.getLearningTimeStart() != null && queryDTO.getLearningTimeEnd() != null;
|
||||
builder.append(" FROM boe_course c");
|
||||
// 聚合教师姓名(仅未删除的教师)
|
||||
// 聚合教师姓名
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("LEFT JOIN (SELECT course_id, GROUP_CONCAT(teacher_name ORDER BY id SEPARATOR ',') AS teacher_names FROM boe_course_teacher GROUP BY course_id) tch ON c.id = tch.course_id");
|
||||
builder.append("LEFT JOIN (SELECT course_id, GROUP_CONCAT(teacher_name ORDER BY id SEPARATOR '、') AS teacher_names FROM boe_course_teacher GROUP BY course_id) tch ON c.id = tch.course_id");
|
||||
// 学习人数聚合(满足时间条件的学习记录,且学习记录有效)
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("LEFT JOIN (SELECT course_id, COUNT(*) AS studys FROM boe_study_course");
|
||||
builder.append("LEFT JOIN (SELECT course_id, COUNT(*) AS studys FROM boe_study_course WHERE status > 1");
|
||||
if (filterLearningTime) {
|
||||
builder.append(" WHERE (add_time >= :learningTimeStart AND add_time <= :learningTimeEnd) OR (finish_time >= :learningTimeStart AND finish_time <= :learningTimeEnd)");
|
||||
builder.append(" AND (add_time >= :learningTimeStart AND add_time <= :learningTimeEnd) OR (finish_time >= :learningTimeStart AND finish_time <= :learningTimeEnd)");
|
||||
}
|
||||
builder.append(" GROUP BY course_id) stu ON c.id = stu.course_id");
|
||||
// 评分聚合(在时间区间内的有效打分)
|
||||
@@ -253,6 +275,20 @@ public class CourseDao extends BaseDao<Course> {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("LEFT JOIN ").append(userCenterSchema)
|
||||
.append(".organization org ON c.org_id = org.organization_id AND org.deleted = 0");
|
||||
// 教师联查 - 移除原来的条件性JOIN,改用EXISTS子查询方式避免数据重复
|
||||
// 注意:由于上方已通过GROUP_CONCAT聚合教师姓名,此处不再需要JOIN教师表
|
||||
/*
|
||||
if (StringUtils.isNotBlank(queryDTO.getTeacherId())) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("LEFT JOIN boe_course_teacher ct ON c.id = ct.course_id");
|
||||
}
|
||||
*/
|
||||
// 排序字段是否为sysType
|
||||
if (StringUtils.equals(queryDTO.getOrderField(), "sysType")) {
|
||||
builder.append(System.lineSeparator()).append("LEFT JOIN boe_sys_type st1 ON c.sys_type1 = st1.id");
|
||||
builder.append(System.lineSeparator()).append("LEFT JOIN boe_sys_type st2 ON c.sys_type2 = st2.id");
|
||||
builder.append(System.lineSeparator()).append("LEFT JOIN boe_sys_type st3 ON c.sys_type3 = st3.id");
|
||||
}
|
||||
|
||||
// where条件
|
||||
// 第一个条件:deleted = 0
|
||||
@@ -297,14 +333,21 @@ public class CourseDao extends BaseDao<Course> {
|
||||
builder.append("AND c.published = :publish");
|
||||
}
|
||||
// 时间筛选逻辑:只有当两个时间参数都提供时才启用学习记录存在性校验
|
||||
if (filterLearningTime) {
|
||||
// 注释掉原有的WHERE条件中的时间筛选逻辑,因为时间筛选应只影响聚合字段的计算,不应过滤课程记录
|
||||
/*if (filterLearningTime) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("AND (:learningTimeStart IS NULL OR :learningTimeEnd IS NULL OR EXISTS (SELECT 1 FROM boe_study_course sc WHERE sc.course_id = c.id AND sc.finish_time IS NOT NULL AND sc.add_time >= :learningTimeStart AND sc.finish_time <= :learningTimeEnd))");
|
||||
}
|
||||
// 授课教师
|
||||
if (StringUtils.isNotBlank(queryDTO.getTeacherName())) {
|
||||
}*/
|
||||
// 授课教师筛选 - 使用EXISTS子查询替代JOIN以避免数据重复
|
||||
// 注意:由于上方已通过GROUP_CONCAT聚合教师姓名,此处仅用于教师筛选条件
|
||||
if (StringUtils.isNotBlank(queryDTO.getTeacherId())) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("AND tch.teacher_names LIKE CONCAT('%', :teacherName, '%')");
|
||||
// 判断teacherId是一个还是多个
|
||||
if (queryDTO.getTeacherId().contains(",")) {
|
||||
builder.append("AND EXISTS (SELECT 1 FROM boe_course_teacher ct WHERE ct.course_id = c.id AND ct.teacher_id IN (:teacherIdList))");
|
||||
} else {
|
||||
builder.append("AND EXISTS (SELECT 1 FROM boe_course_teacher ct WHERE ct.course_id = c.id AND ct.teacher_id = :teacherId)");
|
||||
}
|
||||
}
|
||||
// 展开后条件
|
||||
if (queryDTO.getEnabled() != null) {
|
||||
@@ -313,15 +356,24 @@ public class CourseDao extends BaseDao<Course> {
|
||||
}
|
||||
if (queryDTO.getOpenCourse() != null) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("AND c.open_course = :openCourse");
|
||||
// 兼容null数据
|
||||
if (queryDTO.getOpenCourse() == 0) {
|
||||
builder.append("AND (c.open_course IS NULL or c.open_course = 0)");
|
||||
} else {
|
||||
builder.append("AND c.open_course = 1");
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getOrgId())) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("AND c.org_id = :orgId");
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getCreateUser())) {
|
||||
if (StringUtils.isNotBlank(queryDTO.getCreateUserId())) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("AND c.sys_create_by LIKE CONCAT('%', :createUser, '%')");
|
||||
if (queryDTO.getCreateUserId().contains(",")) {
|
||||
builder.append("AND c.sys_create_aid IN (:createUserIdList)");
|
||||
} else {
|
||||
builder.append("AND c.sys_create_aid = :createUserId");
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getCreateFrom())) {
|
||||
builder.append(System.lineSeparator());
|
||||
@@ -348,16 +400,19 @@ public class CourseDao extends BaseDao<Course> {
|
||||
// 多字段排序: sysType resOwner
|
||||
if (StringUtils.equals(orderField, "sysType")) {
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
builder.append("c.").append(orderFieldSql).append(i).append(" ").append(orderAscStr).append(", ");
|
||||
builder.append("CONVERT(st1.name USING gbk) ").append(orderAscStr).append(", CONVERT(st2.name USING gbk) ").append(orderAscStr).append(", CONVERT(st3.name USING gbk) ").append(orderAscStr).append(", ");
|
||||
// builder.append("c.").append(orderFieldSql).append(i).append(" ").append(orderAscStr).append(", ");
|
||||
}
|
||||
} else if (StringUtils.equals(orderField, "resOwner")) {
|
||||
builder.append("org.org_name ").append(orderAscStr).append(", ");
|
||||
} else if (StringUtils.equals(orderField, "orgName")) {
|
||||
builder.append("CONVERT(org.org_name USING gbk) ").append(orderAscStr).append(", ");
|
||||
} else if (StringUtils.equals(orderField, "studys")) {
|
||||
builder.append("COALESCE(stu.studys, 0) ").append(orderAscStr).append(", ");
|
||||
} else if (StringUtils.equals(orderField, "score")) {
|
||||
builder.append("COALESCE(grd.score, 0) ").append(orderAscStr).append(", ");
|
||||
} else if (StringUtils.equals(orderField, "courseDuration")) {
|
||||
builder.append("COALESCE(cc.duration_sum, 0) ").append(orderAscStr).append(", ");
|
||||
} else if (StringUtils.equals(orderField, "name") || StringUtils.equals(orderField, "sysCreateBy")) {
|
||||
builder.append("CONVERT(c.").append(orderFieldSql).append(" USING gbk) ").append(orderAscStr).append(", ");
|
||||
} else {
|
||||
builder.append("c.").append(orderFieldSql).append(" ").append(orderAscStr).append(", ");
|
||||
}
|
||||
@@ -399,23 +454,36 @@ public class CourseDao extends BaseDao<Course> {
|
||||
query.setParameter("publish", queryDTO.getPublish());
|
||||
}
|
||||
if (filterLearningTime) {
|
||||
query.setParameter("learningTimeStart", queryDTO.getLearningTimeStart());
|
||||
query.setParameter("learningTimeEnd", queryDTO.getLearningTimeEnd());
|
||||
query.setParameter("learningTimeStart", queryDTO.getLearningTimeStart().withHour(0).withMinute(0).withSecond(0));
|
||||
query.setParameter("learningTimeEnd", queryDTO.getLearningTimeEnd().withHour(23).withMinute(59).withSecond(59));
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getTeacherName())) {
|
||||
query.setParameter("teacherName", queryDTO.getTeacherName());
|
||||
if (StringUtils.isNotBlank(queryDTO.getTeacherId())) {
|
||||
String teacherIdStr = queryDTO.getTeacherId();
|
||||
if (teacherIdStr.contains(",")) {
|
||||
List<String> teacherIdList = Arrays.asList(teacherIdStr.split(","));
|
||||
query.setParameter("teacherIdList", teacherIdList);
|
||||
} else {
|
||||
query.setParameter("teacherId", queryDTO.getTeacherId());
|
||||
}
|
||||
}
|
||||
if (queryDTO.getEnabled() != null) {
|
||||
query.setParameter("enabled", queryDTO.getEnabled());
|
||||
}
|
||||
if (queryDTO.getOpenCourse() != null) {
|
||||
query.setParameter("openCourse", queryDTO.getOpenCourse());
|
||||
// 这部分在where条件消化掉了,故去掉
|
||||
// if (queryDTO.getOpenCourse() != null) {
|
||||
// query.setParameter("openCourse", queryDTO.getOpenCourse());
|
||||
// }
|
||||
if (StringUtils.isNotBlank(queryDTO.getOrgId())) {
|
||||
query.setParameter("orgId", queryDTO.getOrgId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getResOwner1())) {
|
||||
query.setParameter("orgId", queryDTO.getResOwner1());
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getCreateUser())) {
|
||||
query.setParameter("createUser", queryDTO.getCreateUser());
|
||||
if (StringUtils.isNotBlank(queryDTO.getCreateUserId())) {
|
||||
String createUserIdStr = queryDTO.getCreateUserId();
|
||||
if (createUserIdStr.contains(",")) {
|
||||
List<String> createUserIdList = Arrays.asList(createUserIdStr.split(","));
|
||||
query.setParameter("createUserIdList", createUserIdList);
|
||||
} else {
|
||||
query.setParameter("createUserId", queryDTO.getCreateUserId());
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotBlank(queryDTO.getCreateFrom())) {
|
||||
query.setParameter("createFrom", queryDTO.getCreateFrom());
|
||||
|
||||
@@ -31,6 +31,11 @@ public class CoursePageQueryDTO {
|
||||
/**创建人*/
|
||||
private String createUser;
|
||||
|
||||
/**
|
||||
* 创建人id
|
||||
*/
|
||||
private String createUserId;
|
||||
|
||||
/**课程分类的一级*/
|
||||
private String sysType1;
|
||||
|
||||
@@ -43,6 +48,11 @@ public class CoursePageQueryDTO {
|
||||
/**授课教师*/
|
||||
private String teacherName;
|
||||
|
||||
/**
|
||||
* 授课教师id
|
||||
*/
|
||||
private String teacherId;
|
||||
|
||||
/**培训时间筛选类型*/
|
||||
private String learningTimeType;
|
||||
|
||||
@@ -77,4 +87,11 @@ public class CoursePageQueryDTO {
|
||||
|
||||
/**排序顺序*/
|
||||
private Boolean orderAsc;
|
||||
|
||||
/**
|
||||
* 是否是新建在线课程页面
|
||||
* false时,代表是在管理端的“在线管理”、“我开发的课程”
|
||||
* true时,代表是在学习路径图/项目管理 中,创建在线课程的选择页面
|
||||
*/
|
||||
private Boolean isCreateCourse;
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@ public class CourseToCourseFullText {
|
||||
cft.setDevice(c.getDevice());
|
||||
|
||||
cft.setIsTop(c.getIsTop()? 1:0);
|
||||
if (c.getSortWeight() != null) {
|
||||
cft.setSortWeight(c.getSortWeight());
|
||||
} else {
|
||||
cft.setSortWeight(9999);
|
||||
}
|
||||
cft.setKeywords(c.getKeywords());
|
||||
//DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
//Long second = c.getPublishTime().toEpochSecond(ZoneOffset.of("+8"));
|
||||
|
||||
@@ -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新增
|
||||
|
||||
@@ -82,67 +82,41 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
|
||||
String currentAccountId = currentUser == null ? null : currentUser.getAccountId();
|
||||
|
||||
// 第一版废弃
|
||||
// // 构建查询条件
|
||||
// List<IFieldFilter> filters = new ArrayList<>();
|
||||
//
|
||||
// // 自动添加过滤已删除
|
||||
// filters.add(FieldFilters.eq("c.deleted", false));
|
||||
//
|
||||
// // 添加权限过滤条件
|
||||
// if (!isSystemAdmin) {
|
||||
// // 非系统管理员需要进行权限过滤
|
||||
// List<IFieldFilter> permissionFilters = new ArrayList<>();
|
||||
//
|
||||
// // 添加组织权限过滤
|
||||
// if (orgIds != null && !orgIds.isEmpty()) {
|
||||
// permissionFilters.add(FieldFilters.in("c.orgId", orgIds));
|
||||
// }
|
||||
//
|
||||
// // 添加创建人过滤(可以看到自己创建的课程)
|
||||
// if (StringUtils.isNotBlank(currentAccountId)) {
|
||||
// permissionFilters.add(FieldFilters.eq("c.sysCreateAid", currentAccountId));
|
||||
// }
|
||||
//
|
||||
// // 如果有权限条件,则添加OR条件
|
||||
// if (!permissionFilters.isEmpty()) {
|
||||
// filters.add(FieldFilters.or(permissionFilters));
|
||||
// }
|
||||
// }
|
||||
// filters.addAll(createFilters(coursePageQueryDTO));
|
||||
//
|
||||
// QueryBuilder query = QueryBuilder.from(Course.class.getSimpleName() + " c").addFilters(filters);
|
||||
// // 处理排序
|
||||
// handleOrder(query, coursePageQueryDTO.getOrderField(), coursePageQueryDTO.getOrderAsc());
|
||||
//
|
||||
// // 设置分页参数
|
||||
// int pageIndex = coursePageQueryDTO.getPageIndex() != null ? coursePageQueryDTO.getPageIndex() : 0;
|
||||
// int pageSize = coursePageQueryDTO.getPageSize() != null ? coursePageQueryDTO.getPageSize() : 10;
|
||||
// query.setPageIndex(pageIndex);
|
||||
// query.setPageSize(pageSize);
|
||||
//
|
||||
// // 执行查询
|
||||
// PageList<Course> coursePageList = courseDao.findPage(query.builder());
|
||||
//
|
||||
// // 转换为CoursePageVo
|
||||
// PageList<CoursePageVo> result = new PageList<>();
|
||||
// result.setCount(coursePageList.getCount());
|
||||
// result.setPageSize(coursePageList.getPageSize());
|
||||
//
|
||||
// // 子查询:根据课程id查询课程下的教师
|
||||
// List<String> courseIds = coursePageList.getList().stream()
|
||||
// .map(Course::getId)
|
||||
// .collect(Collectors.toList());
|
||||
// List<CourseTeacher> courseTeacherList = getCourseTeacherList(courseIds);
|
||||
// List<CoursePageVo> voList = coursePageList.getList().stream()
|
||||
// .map(c -> convertToVo(c, courseTeacherList))
|
||||
// .collect(Collectors.toList());
|
||||
// result.setList(voList);
|
||||
//
|
||||
// return result;
|
||||
// 第二版
|
||||
List<String> readIds = userOrgIds.getReadIds();
|
||||
orgIds.addAll(readIds);
|
||||
|
||||
long total = courseDao.countCourse(coursePageQueryDTO, isSystemAdmin, orgIds, currentAccountId, mySqlSchemaProperties.getUserCenterSchema());
|
||||
List<CoursePageVo> voList = courseDao.queryCourse(coursePageQueryDTO, isSystemAdmin, orgIds, currentAccountId, true, mySqlSchemaProperties.getUserCenterSchema());
|
||||
// 整理数据
|
||||
if (voList != null && !voList.isEmpty()) {
|
||||
for (CoursePageVo vo : voList) {
|
||||
// status为null的给默认值
|
||||
if (vo.getStatus() == null) {
|
||||
vo.setStatus(Course.STATUS_NONE);
|
||||
}
|
||||
// createFrom为空的
|
||||
if (StringUtils.isBlank(vo.getCreateFrom())) {
|
||||
vo.setCreateFrom(CourseCreateFromEnum.ADMIN.getCode());
|
||||
}
|
||||
// openCourse
|
||||
if (vo.getOpenCourse() == null) {
|
||||
vo.setOpenCourse(0);
|
||||
}
|
||||
// published
|
||||
if (vo.getPublished() == null) {
|
||||
vo.setPublished(false);
|
||||
}
|
||||
// enabled
|
||||
if (vo.getEnabled() == null) {
|
||||
vo.setEnabled(true);
|
||||
}
|
||||
// isTop
|
||||
if (vo.getIsTop() == null) {
|
||||
vo.setIsTop(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PageList<CoursePageVo> result = new PageList<>();
|
||||
result.setCount((int) total);
|
||||
result.setPageSize(coursePageQueryDTO.getPageSize());
|
||||
@@ -175,7 +149,8 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
}
|
||||
return courseList.stream()
|
||||
.map(c -> convertToVo(c, courseTeacherList))
|
||||
.sorted(Comparator.comparing(CoursePageVo::getSortWeight)) // 按照sortWeight字段进行排序
|
||||
.sorted(Comparator.comparing(CoursePageVo::getSortWeight, Comparator.nullsLast(Comparator.naturalOrder()))
|
||||
.thenComparing(CoursePageVo::getTopTime, Comparator.nullsLast(Comparator.reverseOrder())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -183,6 +158,7 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
public ServiceResponse<Boolean> top(String courseId, boolean top) {
|
||||
// 1. 查询课程数据
|
||||
Course course = courseDao.get(courseId);
|
||||
Map<String, Object> fieldMap = new HashMap<>();
|
||||
if (top) {
|
||||
// 2. 执行置顶操作
|
||||
// 2.1 目前课程是否已置顶
|
||||
@@ -197,9 +173,14 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
return ServiceResponse.failure("最多只能置顶10个课程");
|
||||
}
|
||||
// 2.3 设置置顶
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
courseDao.updateMultiFieldById(courseId,
|
||||
UpdateBuilder.create("isTop", top),
|
||||
UpdateBuilder.create("topTime", LocalDateTime.now()));
|
||||
UpdateBuilder.create("topTime", now),
|
||||
UpdateBuilder.create("sortWeight", 0));
|
||||
fieldMap.put("isTop", 1);
|
||||
fieldMap.put("topTime", now);
|
||||
fieldMap.put("sortWeight", 0);
|
||||
} else {
|
||||
// 3. 取消置顶
|
||||
// 3.1 课程是否已置顶
|
||||
@@ -213,12 +194,14 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
UpdateBuilder.create("isTop", top),
|
||||
UpdateBuilder.create("topTime", null),
|
||||
UpdateBuilder.create("sortWeight", 9999));
|
||||
fieldMap.put("isTop", 0);
|
||||
fieldMap.put("sortWeight", 9999);
|
||||
}
|
||||
// ES同步
|
||||
if (this.fullTextSearch != null) {
|
||||
Object fullId = courseDao.findField("fullTextId", FieldFilters.eq("id", courseId));
|
||||
if (fullId != null) {
|
||||
publishUtil.updateFieldByDocId((String) fullId, "isTop", top ? 1 : 0);
|
||||
publishUtil.updateFieldByDocId((String) fullId, fieldMap);
|
||||
}
|
||||
}
|
||||
return ServiceResponse.success(true);
|
||||
@@ -229,9 +212,21 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
// 1. 按sortWeight升序排序
|
||||
topList.sort(Comparator.comparingInt(CoursePageVo::getSortWeight));
|
||||
// 2. 更新
|
||||
for (CoursePageVo vo : topList) {
|
||||
courseDao.updateMultiFieldById(vo.getId(),
|
||||
UpdateBuilder.create("sortWeight", vo.getSortWeight()));
|
||||
for (int i = 0, len = topList.size(); i < len; i++) {
|
||||
CoursePageVo vo = topList.get(i);
|
||||
String id = vo.getId();
|
||||
Map<String, Object> fieldMap = new HashMap<>();
|
||||
courseDao.updateMultiFieldById(id,
|
||||
UpdateBuilder.create("isTop", true),
|
||||
UpdateBuilder.create("sortWeight", i));
|
||||
fieldMap.put("isTop", 1);
|
||||
fieldMap.put("sortWeight", i);
|
||||
if (this.fullTextSearch != null) {
|
||||
Object fullId = courseDao.findField("fullTextId", FieldFilters.eq("id", id));
|
||||
if (fullId != null) {
|
||||
publishUtil.updateFieldByDocId((String) fullId, fieldMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ServiceResponse.success(topList);
|
||||
}
|
||||
@@ -301,15 +296,16 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
// 课程时长:秒转分
|
||||
map.put("courseDuration", coursePageVo.getCourseDuration() / 60);
|
||||
map.put("studys", coursePageVo.getStudys());
|
||||
map.put("score", coursePageVo.getScore());
|
||||
// 课程评分显示1位小数,四舍五入
|
||||
map.put("score", coursePageVo.getScore() == null ? "0.0" : String.format("%.1f", coursePageVo.getScore()));
|
||||
map.put("status", CourseStatusEnum.getByCode(coursePageVo.getStatus()).getLabel());
|
||||
map.put("published", coursePageVo.getPublished() == null || !coursePageVo.getPublished() ? "未发布" : "已发布");
|
||||
map.put("enabled", coursePageVo.getEnabled() == null || coursePageVo.getEnabled() ? "停用" : "启用");
|
||||
map.put("enabled", coursePageVo.getEnabled() == null || !coursePageVo.getEnabled() ? "停用" : "启用");
|
||||
map.put("openCourse", coursePageVo.getOpenCourse() == null || coursePageVo.getOpenCourse() == 0 ? "否" : "是");
|
||||
map.put("orgName", coursePageVo.getOrgName());
|
||||
map.put("orgName", coursePageVo.getOrgFullName()); // 修改为组织全名
|
||||
map.put("sysCreateBy", coursePageVo.getSysCreateBy());
|
||||
map.put("createFrom", CourseCreateFromEnum.getByCode(coursePageVo.getCreateFrom()).getLabel());
|
||||
map.put("sysCreateTime", formatter.format(coursePageVo.getSysCreateTime()));
|
||||
map.put("sysCreateTime", coursePageVo.getSysCreateTime() == null ? "" : formatter.format(coursePageVo.getSysCreateTime()));
|
||||
|
||||
dataList.add(map);
|
||||
}
|
||||
@@ -405,17 +401,21 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
vo.setSysCreateBy(course.getSysCreateBy());
|
||||
vo.setCreateFrom(course.getCreateFrom());
|
||||
vo.setSysCreateTime(course.getSysCreateTime());
|
||||
vo.setSysUpdateTime(course.getSysUpdateTime());
|
||||
vo.setForUsers(course.getForUsers());
|
||||
vo.setStatus(course.getStatus());
|
||||
// auditType 需要从其他地方获取,这里暂时设置为默认值
|
||||
vo.setAuditType(1);
|
||||
vo.setPublished(course.getPublished());
|
||||
vo.setPublishTime(course.getPublishTime());
|
||||
vo.setStudys(course.getStudys());
|
||||
vo.setScore(course.getScore());
|
||||
// courseDuration 需要计算,这里暂时设置为默认值
|
||||
vo.setCourseDuration(course.getCourseDuration());
|
||||
vo.setEnabled(course.getEnabled());
|
||||
vo.setSortWeight(course.getSortWeight());
|
||||
vo.setTopTime(course.getTopTime());
|
||||
vo.setIsTop(course.getIsTop());
|
||||
|
||||
// 获取教师名称
|
||||
List<String> teacherNames = courseTeacherList.stream()
|
||||
@@ -424,7 +424,7 @@ public class CoursePageServiceImpl implements ICoursePageService {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!teacherNames.isEmpty()) {
|
||||
vo.setTeacherName(String.join(",", teacherNames));
|
||||
vo.setTeacherName(String.join("、", teacherNames));
|
||||
}
|
||||
|
||||
return vo;
|
||||
|
||||
@@ -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," +
|
||||
|
||||
@@ -1882,6 +1882,29 @@ public class CourseServiceImpl implements ICourseService {
|
||||
return course.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成新的课程名称
|
||||
* @param originalName
|
||||
* @param existingNames
|
||||
* @return
|
||||
*/
|
||||
private String generateNewCourseName(String originalName, List<String> existingNames) {
|
||||
int maxNum = 0;
|
||||
String baseName = originalName.replaceAll("\\s*\\(\\d+\\)\\s*$", "").trim();
|
||||
|
||||
for (String name : existingNames) {
|
||||
// 匹配 "baseName (数字)"
|
||||
if (name.startsWith(baseName)) {
|
||||
String suffix = name.substring(baseName.length()).trim();
|
||||
if (suffix.matches("^\\(\\d+\\)$")) {
|
||||
int num = Integer.parseInt(suffix.substring(1, suffix.length() - 1));
|
||||
maxNum = Math.max(maxNum, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
return baseName + "(" + (maxNum + 1) + ")";
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public String copyCourse(String id, String refId, String refType, String aid, String aname) {
|
||||
@@ -1902,6 +1925,8 @@ public class CourseServiceImpl implements ICourseService {
|
||||
|
||||
String newId = IDGenerator.generate();
|
||||
String courseName = this.courseName(id);
|
||||
List<String> cpCourseNameList = courseDao.queryCourseNames(courseName);
|
||||
String newCourseName = generateNewCourseName(courseName, cpCourseNameList);
|
||||
LocalDateTime time = LocalDateTime.now();
|
||||
String mess = null;
|
||||
if (courseName.length() < 96) {
|
||||
@@ -1915,7 +1940,7 @@ public class CourseServiceImpl implements ICourseService {
|
||||
"order_study,status)" +
|
||||
"select '" + newId + "',org_id,'" + id + "','" + refId + "','" + refType + "'," + visible + ",'" + aid + "','" + aname + "','" + time + "',0,'" + aname + "'," +
|
||||
"'" + time + "',1,comments,cover_img,dead_time,device,enable_remark,enabled," +
|
||||
"erasable,0,for_scene,for_users,0,keywords,'" + courseName + "(1)" + "',open_object," +
|
||||
"erasable,0,for_scene,for_users,0,keywords,'" + newCourseName + "',open_object," +
|
||||
"overview,pass_formula,0,publish_time,0,res_owner1,res_owner2," +
|
||||
"res_owner3,score,score_formula,0,source,study_time,0,summary," +
|
||||
"sys_type1,sys_type2,sys_type3,tags,top_time,trample_count,type,value,0," +
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.xboe.module.course.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -122,6 +123,14 @@ public class PublishCourseUtil {
|
||||
log.error("更新全文索引字段错误",e);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFieldByDocId(String docId, Map<String, Object> fieldMap) {
|
||||
try {
|
||||
fullTextSearch.updateFields(ICourseFullTextSearch.DEFAULT_INDEX_NAME, fieldMap, docId);
|
||||
}catch(Exception e) {
|
||||
log.error("更新全文索引字段错误",e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeByDocId(String docId){
|
||||
if(fullTextSearch==null) {
|
||||
|
||||
@@ -18,6 +18,11 @@ public class CoursePageVo {
|
||||
* 课程名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 课程类型
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 课程封面图片地址
|
||||
@@ -87,6 +92,13 @@ public class CoursePageVo {
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime sysCreateTime;
|
||||
|
||||
/**
|
||||
* 最后修改时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime sysUpdateTime;
|
||||
|
||||
/**
|
||||
* 目标人群
|
||||
@@ -161,6 +173,13 @@ public class CoursePageVo {
|
||||
*/
|
||||
private Boolean isTop;
|
||||
|
||||
/**
|
||||
* 置顶时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime topTime;
|
||||
|
||||
/**
|
||||
* 排序权重
|
||||
*/
|
||||
@@ -172,4 +191,4 @@ public class CoursePageVo {
|
||||
* TODO 在线课优化二期会对此字段进行其他的赋值操作
|
||||
*/
|
||||
private Boolean isPermission = true;
|
||||
}
|
||||
}
|
||||
@@ -133,15 +133,15 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
*
|
||||
* @param pager 分页参数
|
||||
* @param courseId 25.11.25新增
|
||||
*
|
||||
* @param contentName 资源名称
|
||||
*/
|
||||
@RequestMapping(value = "/pagelist-resource", method = {RequestMethod.GET, RequestMethod.POST})
|
||||
public JsonResponse<PageList<CourseFinishCountDto>> findPageResource(Pagination pager, String courseId) {
|
||||
public JsonResponse<PageList<CourseFinishCountDto>> findPageResource(Pagination pager, String courseId, String contentName) {
|
||||
if (StringUtil.isBlank(courseId)) {
|
||||
return error("课程id不能为空");
|
||||
}
|
||||
try {
|
||||
PageList<CourseFinishCountDto> courseFinishCountDTOs = service.findPageResource(pager.getPageIndex(), pager.getPageSize(), courseId);
|
||||
PageList<CourseFinishCountDto> courseFinishCountDTOs = service.findPageResource(pager.getPageIndex(), pager.getPageSize(), courseId, contentName);
|
||||
return success(courseFinishCountDTOs);
|
||||
} catch (Exception e) {
|
||||
log.error("查询课程学习记录错误:{}", e.getMessage());
|
||||
@@ -230,6 +230,8 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
userInfoMap.put(user.getAid(), user);
|
||||
}
|
||||
}
|
||||
// 按报名时间倒序排序
|
||||
signRecordList.sort(Comparator.comparing(StudySignup::getSignTime).reversed());
|
||||
// 4. 原始数据→导出DTO(格式化处理:状态转中文、日期转字符串等)
|
||||
List<CourseSignDto> exportDtoList = new ArrayList<>();
|
||||
if (signRecordList != null) {
|
||||
@@ -343,7 +345,7 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
exportMap.put("部门", "部门");
|
||||
exportMap.put("学习开始时间", "学习开始时间");
|
||||
exportMap.put("学习结束时间", "学习结束时间");
|
||||
exportMap.put("学习时长(分)", "学习时长(分)");
|
||||
exportMap.put("学习时长", "学习时长");
|
||||
exportMap.put("学习状态", "学习状态");
|
||||
exportMap.put("学习进度", "学习进度");
|
||||
// 2.查询课程的所有考试答卷信息,拼接动态表头(XXX考试成绩)
|
||||
@@ -450,24 +452,25 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
// 这个开始时间已经弃置了,不过先用再说(有值)
|
||||
map.put("学习开始时间", studyCourse1.getStartTime());
|
||||
// 结束时间为空的,说明还没学习结束(有值)
|
||||
map.put("学习结束时间", studyCourse1.getFinishTime());
|
||||
// 学习时长:学习总时间是秒,现在要求的学习时间是分钟,向上取整,1秒算1分钟,60秒算1分钟,61秒算2分钟
|
||||
map.put("学习时长(分)", studyCourse1.getTotalDuration() == null ? null : (int) Math.ceil(studyCourse1.getTotalDuration() / 60.0));
|
||||
// 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));
|
||||
// 学习状态需要转换
|
||||
String statusText = "";
|
||||
if (studyCourse1.getStatus() != null) {
|
||||
switch (studyCourse1.getStatus()) {
|
||||
case StudyCourse.STATUS_NOSTUDY:
|
||||
statusText = "未开始学习";
|
||||
statusText = "未开始";
|
||||
break;
|
||||
case StudyCourse.STATUS_STUDYING:
|
||||
statusText = "学习中";
|
||||
statusText = "进行中";
|
||||
break;
|
||||
case StudyCourse.STATUS_ABORTED:
|
||||
statusText = "已终止";
|
||||
break;
|
||||
case StudyCourse.STATUS_FINISH:
|
||||
statusText = "学习完成";
|
||||
statusText = "已完成";
|
||||
break;
|
||||
default:
|
||||
statusText = "";
|
||||
@@ -493,7 +496,8 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
Optional<StudyCourseItem> studyCourseItemOptional = studyCourseItems.stream().filter(studyCourseItem -> Objects.equals(studyCourseItem.getContentId(), contentId) && Objects.equals(studyCourseItem.getAid(), studyCourse1.getAid())).findFirst();
|
||||
// 如果存在成绩,填写成绩,否则填入空值
|
||||
if (studyCourseItemOptional.isPresent()) {
|
||||
map.put(examName, studyCourseItemOptional.get().getScore());
|
||||
// 25.12.16修改:考试成绩修改为整数
|
||||
map.put(examName, studyCourseItemOptional.get().getScore() != null ? Math.round(studyCourseItemOptional.get().getScore()) : null);
|
||||
} else {
|
||||
map.put(examName, "");
|
||||
}
|
||||
@@ -1217,12 +1221,12 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
* @return 资源学习情况分页集合
|
||||
*/
|
||||
@RequestMapping(value="/contents",method = {RequestMethod.GET,RequestMethod.POST})
|
||||
public JsonResponse<PageList<StudyCourseItem>> findPage(Pagination pager,String courseId,String contentId,String name,Integer status){
|
||||
public JsonResponse<PageList<StudyCourseItem>> findPage(Pagination pager,String courseId,String contentId,String name,Integer status,String aid){
|
||||
if(StringUtils.isBlank(courseId)){
|
||||
return error("无课程信息");
|
||||
}
|
||||
try {
|
||||
PageList<StudyCourseItem> rs = studyService.findItemPage(pager.getPageIndex(), pager.getPageSize(), null, contentId, courseId, name, status);
|
||||
PageList<StudyCourseItem> rs = studyService.findItemPage(pager.getPageIndex(), pager.getPageSize(), null, contentId, courseId, name, status,aid);
|
||||
return success(rs);
|
||||
}catch(Exception e) {
|
||||
log.error("【资源学习情况分页查询】错误:{}", e.getMessage());
|
||||
@@ -1238,11 +1242,11 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
* @param courseId 课程id
|
||||
* @param contentId 内容id
|
||||
* @param name 用户名称
|
||||
* @param status 用户学习状态(1-未开始,2-已完成,3-进行中)
|
||||
* @param status 考试状态(2-考试已通过,4-考试未通过)
|
||||
* @return 资源学习情况分页集合
|
||||
*/
|
||||
@RequestMapping(value = "/contents-exam", method = {RequestMethod.GET, RequestMethod.POST})
|
||||
public JsonResponse<PageList<StudyCourseItem>> findPageExam(Pagination pager, String courseId, String contentId, String name, Integer status) {
|
||||
public JsonResponse<PageList<StudyCourseItem>> findPageExam(Pagination pager, String courseId, String contentId, String name, Integer status,String aid) {
|
||||
if (StringUtils.isBlank(courseId)) {
|
||||
return error("无课程信息");
|
||||
}
|
||||
@@ -1253,9 +1257,8 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
if (studyExams == null || studyExams.isEmpty()) {
|
||||
return success(new PageList<>());
|
||||
}
|
||||
List<String> studyCourseItemIds = studyExams.stream().map(StudyExam::getStudyItemId).collect(Collectors.toList());
|
||||
// 分页查询资源学习信息(只查询有考试信息的部分)
|
||||
PageList<StudyCourseItem> rs = studyService.findItemPage(pager.getPageIndex(), pager.getPageSize(), null, contentId, courseId, name, status);
|
||||
PageList<StudyCourseItem> rs = studyService.findItemPage(pager.getPageIndex(), pager.getPageSize(), null, contentId, courseId, name, status,aid);
|
||||
// 拼接考试信息
|
||||
List<StudyCourseItem> studyCourseItems = rs.getList();
|
||||
if (studyCourseItems != null && !studyCourseItems.isEmpty() && !studyExams.isEmpty()) {
|
||||
@@ -1283,7 +1286,7 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
* @return 资源学习情况分页集合
|
||||
*/
|
||||
@RequestMapping(value = "/contents-assess", method = {RequestMethod.GET, RequestMethod.POST})
|
||||
public JsonResponse<PageList<StudyCourseItem>> findPageAssess(Pagination pager, String courseId, String contentId, String name, Integer status) {
|
||||
public JsonResponse<PageList<StudyCourseItem>> findPageAssess(Pagination pager, String courseId, String contentId, String name, Integer status,String aid) {
|
||||
if (StringUtils.isBlank(courseId)) {
|
||||
return error("无课程信息");
|
||||
}
|
||||
@@ -1298,7 +1301,7 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
return success(new PageList<>());
|
||||
}
|
||||
// 分页查询资源学习信息(只查询有评估信息的部分)
|
||||
PageList<StudyCourseItem> rs = studyService.findItemPage(pager.getPageIndex(), pager.getPageSize(), null, contentId, courseId, name, status);
|
||||
PageList<StudyCourseItem> rs = studyService.findItemPage(pager.getPageIndex(), pager.getPageSize(), null, contentId, courseId, name, status,aid);
|
||||
// 拼接评估信息
|
||||
List<StudyCourseItem> studyCourseItems = rs.getList();
|
||||
if (studyCourseItems != null && !studyCourseItems.isEmpty() && !studyAssesses.isEmpty()) {
|
||||
@@ -1354,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;
|
||||
}
|
||||
}
|
||||
@@ -1396,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<>();
|
||||
// 拼接基本信息
|
||||
@@ -1418,11 +1424,12 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
// 考试状态需要转换(根据成绩和及格线判断)
|
||||
String examStatus = "";
|
||||
if (exam.getScore() != null && exam.getPassLine() != null) {
|
||||
examStatus = exam.getScore() >= exam.getPassLine() ? "通过" : "未通过";
|
||||
examStatus = exam.getScore() >= exam.getPassLine() ? "已通过" : "未通过";
|
||||
}
|
||||
map.put("考试状态", examStatus);
|
||||
// 考试成绩
|
||||
map.put("考试成绩", exam.getScore());
|
||||
// 25.12.16修改:考试成绩修改为整数
|
||||
map.put("考试成绩", exam.getScore() != null ? Math.round(exam.getScore()) : null);
|
||||
// 完成时间
|
||||
map.put("完成时间", exam.getEndTime());
|
||||
return map;
|
||||
@@ -1476,9 +1483,8 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
exportMap.put("姓名", "姓名");
|
||||
exportMap.put("工号", "工号");
|
||||
exportMap.put("部门", "部门");
|
||||
exportMap.put("作业状态", "作业状态");
|
||||
exportMap.put("作业成绩", "作业成绩");
|
||||
exportMap.put("完成时间", "完成时间");
|
||||
exportMap.put("完成状态", "完成状态");
|
||||
exportMap.put("作业内容", "作业内容");
|
||||
// 2.整理导出数据
|
||||
// 查询课程名称
|
||||
StudyCourse studyCourse = new StudyCourse();
|
||||
@@ -1492,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;
|
||||
}
|
||||
}
|
||||
@@ -1534,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<>();
|
||||
// 拼接基本信息
|
||||
@@ -1555,11 +1564,9 @@ public class StudyCourseApi extends ApiBaseController{
|
||||
map.put("部门", orgInfo);
|
||||
// 作业状态(如果有成绩则为已完成,否则为未完成)
|
||||
String hwStatus = (hw.getScore() != null) ? "已完成" : "未完成";
|
||||
map.put("作业状态", hwStatus);
|
||||
// 作业成绩
|
||||
map.put("作业成绩", hw.getScore());
|
||||
// 完成时间
|
||||
map.put("完成时间", hw.getEndTime());
|
||||
map.put("完成状态", hwStatus);
|
||||
// 作业内容
|
||||
map.put("作业内容", hw.getHwContent());
|
||||
return map;
|
||||
}).collect(Collectors.toList());
|
||||
// 先将Excel数据写入临时文件
|
||||
|
||||
@@ -65,13 +65,15 @@ public class StudySignupApi extends ApiBaseController{
|
||||
* @return 返回课程报名表的集合
|
||||
*/
|
||||
@PostMapping("/pagelist")
|
||||
public JsonResponse<PageList<StudySignup>> findPage(Pagination pager, String courseId, String name, Integer signType) {
|
||||
public JsonResponse<PageList<StudySignup>> findPage(Pagination pager, String courseId, String name, Integer signType,String aid) {
|
||||
// if(StringUtils.isBlank(courseId)){
|
||||
// return error("无课程信息");
|
||||
// }
|
||||
StudySignup ss=new StudySignup();
|
||||
ss.setCourseId(courseId);
|
||||
ss.setName(name);
|
||||
//25.12.11 新增aid筛选
|
||||
ss.setAid(aid);
|
||||
//2025.11.28 新增signType筛选
|
||||
ss.setSignType(signType);
|
||||
//CurrentUser cuser=getCurrent();
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.xboe.school.study.dto.CourseFinishCountDto;
|
||||
import com.xboe.school.study.entity.StudyCourse;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,33 +19,41 @@ public class CourseStatDao extends BaseDao<StudyCourse> {
|
||||
* @param startIndex 分页开始索引
|
||||
* @param pageSize 分页大小
|
||||
* @param courseId 课程ID
|
||||
* @param contentName 资源名称
|
||||
* @return 课程完成人数统计DTO集合
|
||||
*/
|
||||
public List<CourseFinishCountDto> findFinishCountPage(int startIndex, int pageSize, String courseId) {
|
||||
public List<CourseFinishCountDto> findFinishCountPage(int startIndex, int pageSize, String courseId, String contentName) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
// 课程名(和DTO字段对应)
|
||||
.append("c.content_name AS contentName, ")
|
||||
// 资源名
|
||||
.append("cc.content_name AS contentName, ")
|
||||
// 资源ID
|
||||
.append("cc.id AS contentId, ")
|
||||
// 完成人数(去重统计)
|
||||
.append("COUNT(DISTINCT c.aid) AS finishCount, ")
|
||||
//2025.11.27新增:资源类型
|
||||
.append("cc.content_type AS contentType ")
|
||||
// 你的课程表名
|
||||
.append("FROM boe_study_course_item c ")
|
||||
.append("FROM boe_course_content cc ")
|
||||
// 2025.11.27新增:连表 boe_course_content
|
||||
.append("LEFT JOIN boe_course_content cc ON cc.id = c.content_id ")
|
||||
.append("WHERE 1=1 ")
|
||||
// 条件:已完成
|
||||
.append("AND c.status = 9 ");
|
||||
.append("LEFT JOIN boe_study_course_item c ON cc.id = c.content_id AND c.status = 9 ")
|
||||
.append("WHERE 1=1 ");
|
||||
List<Object> params = new ArrayList<>();
|
||||
// courseId非空则过滤(参数化防注入)
|
||||
if (StringUtils.isNotBlank(courseId)) {
|
||||
sql.append("AND c.course_id = ? ");
|
||||
sql.append("AND cc.course_id = ? ");
|
||||
params.add(courseId);
|
||||
}
|
||||
// 25.12.1修改 新增:contentName模糊查询(粗略匹配)
|
||||
if (StringUtils.isNotBlank(contentName)) {
|
||||
// 实现“包含contentName”的模糊查询
|
||||
sql.append("AND cc.content_name LIKE ? ");
|
||||
// 通配符%拼接在参数上防注入,表示“前后任意字符包含contentName”
|
||||
params.add("%" + contentName + "%");
|
||||
}
|
||||
// 分组+排序+分页(聚合函数必须分组,排序参考第一个代码的desc id)
|
||||
sql.append("GROUP BY c.content_id, c.content_name, cc.content_type ")
|
||||
.append("ORDER BY c.content_id DESC ")
|
||||
sql.append("GROUP BY cc.id, cc.content_name, cc.content_type ")
|
||||
.append("ORDER BY cc.id DESC ")
|
||||
// MySQL分页:偏移量,每页条数
|
||||
.append("LIMIT ?, ?");
|
||||
// 补充分页参数(顺序:startIndex → pageSize)
|
||||
@@ -57,29 +66,41 @@ public class CourseStatDao extends BaseDao<StudyCourse> {
|
||||
for (Object[] objs : resultList) {
|
||||
CourseFinishCountDto dto = new CourseFinishCountDto();
|
||||
dto.setContentName(objs[0] != null ? (String) objs[0] : "");
|
||||
dto.setFinishCount(objs[1] != null ? ((Number) objs[1]).intValue() : 0);
|
||||
dto.setContentType((Integer) objs[2]);
|
||||
dto.setContentId(((BigInteger) objs[1]).toString());
|
||||
dto.setFinishCount(objs[2] != null ? ((Number) objs[2]).intValue() : 0);
|
||||
dto.setContentType((Integer) objs[3]);
|
||||
dtoList.add(dto);
|
||||
}
|
||||
return dtoList;
|
||||
}
|
||||
|
||||
// 查总条数(返回int类型,匹配PageList的count字段)
|
||||
public int findFinishCountTotal(String courseId) {
|
||||
/**
|
||||
* 查询课程完成人数
|
||||
*
|
||||
* @param courseId 课程ID
|
||||
* @param contentName 资源名称
|
||||
* @return 课程完成人数
|
||||
*/
|
||||
public int findFinishCountTotal(String courseId, String contentName) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
// 总条数=去重后的人数
|
||||
.append("COUNT(DISTINCT c.content_id) ")
|
||||
.append("FROM boe_study_course_item c ")
|
||||
.append("WHERE 1=1 ")
|
||||
// 条件:已完成
|
||||
.append("AND c.status = 9 ");
|
||||
.append("COUNT(DISTINCT c.id) ")
|
||||
.append("FROM boe_course_content c ")
|
||||
.append("WHERE 1=1 ");
|
||||
List<Object> params = new ArrayList<>();
|
||||
// courseId非空则过滤(参数化防注入)
|
||||
if (StringUtils.isNotBlank(courseId)) {
|
||||
sql.append("AND c.course_id = ? ");
|
||||
params.add(courseId);
|
||||
}
|
||||
// 25.12.1修改 新增:contentName模糊查询(粗略匹配)
|
||||
if (StringUtils.isNotBlank(contentName)) {
|
||||
// 实现“包含contentName”的模糊查询
|
||||
sql.append("AND c.content_name LIKE ? ");
|
||||
// 通配符%拼接在参数上防注入,表示“前后任意字符包含contentName”
|
||||
params.add("%" + contentName + "%");
|
||||
}
|
||||
// 用sqlCount替代sqlFindObject,直接返回int类型结果
|
||||
// sqlCount会执行SQL并返回COUNT的结果,无需手动转换Object
|
||||
return this.sqlCount(sql.toString(), params.toArray());
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.xboe.school.study.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* 课程完成人数统计DTO
|
||||
*/
|
||||
@@ -13,6 +15,11 @@ public class CourseFinishCountDto {
|
||||
*/
|
||||
private String contentName;
|
||||
|
||||
/**
|
||||
* 内容ID
|
||||
*/
|
||||
private String contentId;
|
||||
|
||||
/**
|
||||
* 完成人数(数据库 count 统计得出)
|
||||
*/
|
||||
@@ -24,4 +31,5 @@ public class CourseFinishCountDto {
|
||||
*/
|
||||
private Integer contentType;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -137,6 +137,13 @@ public class StudyCourseItem extends IdEntity {
|
||||
@Transient
|
||||
private BigDecimal progressVideo;
|
||||
|
||||
/**
|
||||
* 展示名称(章名+节名,如果没有章节,则为课程名+节名)
|
||||
* 25.12.15新增
|
||||
*/
|
||||
@Transient
|
||||
private String displayName;
|
||||
|
||||
/**
|
||||
* 考试记录集合
|
||||
* 仅在资源学习情况分页查询-考试信息接口使用
|
||||
|
||||
@@ -69,8 +69,9 @@ public interface IStudyCourseService {
|
||||
* @param pageIndex 页码
|
||||
* @param pageSize 每页数据条数
|
||||
* @param courseId 课程id
|
||||
* @param contentName 资源名称
|
||||
*/
|
||||
PageList<CourseFinishCountDto> findPageResource(int pageIndex, int pageSize, String courseId);
|
||||
PageList<CourseFinishCountDto> findPageResource(int pageIndex, int pageSize, String courseId, String contentName);
|
||||
|
||||
/**
|
||||
* 热度榜
|
||||
|
||||
@@ -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;
|
||||
@@ -99,7 +100,15 @@ public interface IStudyService {
|
||||
* @param status 用户学习状态(1-未开始,2-已完成,3-进行中)
|
||||
* @return 资源学习情况分页集合
|
||||
*/
|
||||
PageList<StudyCourseItem> findItemPage(int pageIndex, int pageSize, List<String> ids, String contentId, String courseId, String name, Integer status);
|
||||
PageList<StudyCourseItem> findItemPage(int pageIndex, int pageSize, List<String> ids, String contentId, String courseId, String name, Integer status,String aid);
|
||||
|
||||
/**
|
||||
* 为courseContents列表设置展示名称(章名+节名 或 课程名+节名)
|
||||
* 25.12.15新增
|
||||
*
|
||||
* @param courseContents 课程内容集合
|
||||
*/
|
||||
void setContentDisplayName(List<CourseContent> courseContents);
|
||||
|
||||
List<StudyCourseItem> getList(String courseId, String contentId, String name, Integer status);
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ package com.xboe.school.study.service.impl;
|
||||
|
||||
import com.xboe.common.OrderCondition;
|
||||
import com.xboe.common.PageList;
|
||||
import com.xboe.core.orm.*;
|
||||
import com.xboe.core.orm.FieldFilters;
|
||||
import com.xboe.core.orm.FieldUpdateType;
|
||||
import com.xboe.core.orm.QueryBuilder;
|
||||
import com.xboe.core.orm.UpdateBuilder;
|
||||
import com.xboe.core.utils.ConvertUtil;
|
||||
import com.xboe.data.outside.IOutSideDataService;
|
||||
import com.xboe.module.course.dao.CourseContentDao;
|
||||
@@ -24,15 +27,17 @@ import com.xboe.system.user.vo.UserSimpleVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.transaction.Transactional;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -56,6 +61,10 @@ public class StudyCourseServiceImpl implements IStudyCourseService{
|
||||
@Autowired
|
||||
IOrganizationService organizationService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
IStudyCourseService studyCourseService;
|
||||
|
||||
@Autowired
|
||||
StudyCourseDao studyCourseDao;
|
||||
|
||||
@@ -92,6 +101,13 @@ public class StudyCourseServiceImpl implements IStudyCourseService{
|
||||
@Autowired(required = false)
|
||||
ICourseStudySearch esSearch;//对ES的处理
|
||||
|
||||
/**
|
||||
* 用于避免JPA查询后修改entity实体字段,自动更新到数据库
|
||||
*/
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
|
||||
@Override
|
||||
public StudyCourse findByCourseIdAndAid(String courseId, String aid) {
|
||||
//加上排序,如果是多条学习记录,只会取最新的一条
|
||||
@@ -143,38 +159,10 @@ public class StudyCourseServiceImpl implements IStudyCourseService{
|
||||
if(sc.getStartTime()!=null){
|
||||
query.addFilter(FieldFilters.eq("startTime",sc.getStartTime()));
|
||||
}
|
||||
//25.12.11新增:添加根据用户aid通过逗号分隔查询
|
||||
if(StringUtils.isNotBlank(sc.getAid())) {
|
||||
query.addFilter(FieldFilters.eq("aid", sc.getAid()));
|
||||
}
|
||||
// 25.11.25新增:添加基于时间的查询条件
|
||||
if (StringUtils.isNotBlank(sc.getQueryStartTime()) && StringUtils.isNotBlank(sc.getQueryFinishTime())) {
|
||||
// 开始结束时间均传入的情况,实现筛选逻辑
|
||||
// (startTime >= 查询开始时间 AND startTime <= 查询结束时间) OR (finishTime >= 查询开始时间 AND finishTime <= 查询结束时间)
|
||||
// 这样兼容查询结束时间为空值的情况,因为学员课程未结束时没有结束时间
|
||||
LocalDate startDate = LocalDate.parse(sc.getQueryStartTime());
|
||||
LocalDateTime startDateTime = startDate.atStartOfDay();
|
||||
LocalDate finishDate = LocalDate.parse(sc.getQueryFinishTime());
|
||||
LocalDateTime finishDateTime = finishDate.atTime(LocalTime.MAX);
|
||||
// 筛选开始时间
|
||||
IFieldFilter startTimeInRange = FieldFilters.and(FieldFilters.ge("startTime", startDateTime), FieldFilters.le("startTime", finishDateTime));
|
||||
// 筛选结束时间
|
||||
IFieldFilter finishTimeInRange = FieldFilters.and(FieldFilters.ge("finishTime", startDateTime), FieldFilters.le("finishTime", finishDateTime));
|
||||
// OR条件查询
|
||||
query.addFilter(FieldFilters.or(startTimeInRange, finishTimeInRange));
|
||||
} else {
|
||||
// 只输出单个参数情况
|
||||
// 筛选开始时间
|
||||
if (StringUtils.isNotBlank(sc.getQueryStartTime())) {
|
||||
LocalDate startDate = LocalDate.parse(sc.getQueryStartTime());
|
||||
LocalDateTime startDateTime = startDate.atStartOfDay();
|
||||
query.addFilter(FieldFilters.ge("startTime", startDateTime));
|
||||
}
|
||||
// 筛选结束时间
|
||||
if (StringUtils.isNotBlank(sc.getQueryFinishTime())) {
|
||||
LocalDate finishDate = LocalDate.parse(sc.getQueryFinishTime());
|
||||
LocalDateTime finishDateTime = finishDate.atTime(LocalTime.MAX);
|
||||
query.addFilter(FieldFilters.le("finishTime", finishDateTime));
|
||||
}
|
||||
String userIdStr=sc.getAid();
|
||||
query.addFilter(FieldFilters.in("aid",userIdStr.split(",")));
|
||||
}
|
||||
}
|
||||
// 原有查询是否结束逻辑
|
||||
@@ -231,17 +219,73 @@ public class StudyCourseServiceImpl implements IStudyCourseService{
|
||||
}
|
||||
}
|
||||
}
|
||||
// 25.12.3新增,添加基于时间的查询条件,规则如下:
|
||||
if (sc != null && StringUtils.isNotBlank(sc.getCourseId()) && StringUtils.isNotBlank(sc.getQueryStartTime()) && StringUtils.isNotBlank(sc.getQueryFinishTime())) {
|
||||
List<StudyCourseItem> studyCourseItemList = studyCourseService.getStudyCourseItemByCourseId(sc.getCourseId());
|
||||
if (studyCourseItemList != null && !studyCourseItemList.isEmpty()) {
|
||||
// 将学习内容按照studyId进行分组,便于后续计算每个studyId下的总学习时长
|
||||
Map<String, List<StudyCourseItem>> itemsByStudyId = studyCourseItemList.stream().filter(item -> item.getFinishTime() != null).collect(Collectors.groupingBy(StudyCourseItem::getStudyId));
|
||||
// 获取查询的起止时间
|
||||
String queryStartTime = sc.getQueryStartTime();
|
||||
String queryFinishTime = sc.getQueryFinishTime();
|
||||
for (StudyCourse studyCourse : studyCourses) {
|
||||
// 实体类解耦
|
||||
entityManager.detach(studyCourse);
|
||||
// 解析查询时间范围
|
||||
LocalDate startDate = LocalDate.parse(queryStartTime);
|
||||
LocalDate endDate = LocalDate.parse(queryFinishTime);
|
||||
// 如果有查询时间范围,则计算筛选后的学习时长
|
||||
if (itemsByStudyId.containsKey(studyCourse.getId())) {
|
||||
List<StudyCourseItem> items = itemsByStudyId.get(studyCourse.getId());
|
||||
int filteredDuration = 0;
|
||||
for (StudyCourseItem item : items) {
|
||||
LocalDateTime finishTime = item.getFinishTime();
|
||||
LocalDate finishDate = finishTime.toLocalDate();
|
||||
// 判断结束时间是否在筛选范围内
|
||||
boolean inRange = true;
|
||||
if (finishDate.isBefore(startDate)) {
|
||||
inRange = false;
|
||||
}
|
||||
if (finishDate.isAfter(endDate)) {
|
||||
inRange = false;
|
||||
}
|
||||
// 如果在范围内,则累加学习时长
|
||||
if (inRange) {
|
||||
Integer duration = item.getStudyDuration();
|
||||
if (duration != null) {
|
||||
filteredDuration += duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新学习时长
|
||||
studyCourse.setTotalDuration(filteredDuration);
|
||||
} else {
|
||||
// 查询不到item的情况,默认置空
|
||||
studyCourse.setTotalDuration(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return studyCoursePageList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询课程的资源名称以及资源学习完成人数
|
||||
*
|
||||
* @param pageIndex 页码
|
||||
* @param pageSize 每页数据条数
|
||||
* @param courseId 课程id
|
||||
* @param contentName 资源名称
|
||||
*/
|
||||
@Override
|
||||
public PageList<CourseFinishCountDto> findPageResource(int pageIndex, int pageSize, String courseId) {
|
||||
public PageList<CourseFinishCountDto> findPageResource(int pageIndex, int pageSize, String courseId, String contentName) {
|
||||
// 1. 手动计算分页偏移量(数据库分页必需)
|
||||
// pageIndex<1时设为0,避免数据库LIMIT偏移量为负数
|
||||
int startIndex = (pageIndex < 1) ? 0 : (pageIndex - 1) * pageSize;
|
||||
// 2. 调用Dao层:查当前页数据(传入偏移量、每页条数、courseId条件)
|
||||
List<CourseFinishCountDto> dtoList = courseStatDao.findFinishCountPage(startIndex, pageSize, courseId);
|
||||
List<CourseFinishCountDto> dtoList = courseStatDao.findFinishCountPage(startIndex, pageSize, courseId,contentName);
|
||||
// 3. 调用Dao层:查总条数(对应PageList的count字段,用int类型,和PageList一致)
|
||||
int totalCount = courseStatDao.findFinishCountTotal(courseId);
|
||||
int totalCount = courseStatDao.findFinishCountTotal(courseId,contentName);
|
||||
// 4. 按PageList构造函数创建对象(只传list和count)
|
||||
PageList<CourseFinishCountDto> pageList = new PageList<>(dtoList, totalCount);
|
||||
// 5. 设置pageSize(覆盖默认10,确保总页数计算正确)
|
||||
@@ -809,36 +853,6 @@ public class StudyCourseServiceImpl implements IStudyCourseService{
|
||||
if (StringUtils.isNotBlank(sc.getAid())) {
|
||||
query.addFilter(FieldFilters.eq("aid", sc.getAid()));
|
||||
}
|
||||
// 25.11.25新增:添加基于时间的查询条件
|
||||
if (sc.getQueryStartTime() != null && sc.getQueryFinishTime() != null) {
|
||||
// 开始结束时间均传入的情况,实现筛选逻辑
|
||||
// (startTime >= 查询开始时间 AND startTime <= 查询结束时间) OR (finishTime >= 查询开始时间 AND finishTime <= 查询结束时间)
|
||||
// 这样兼容查询结束时间为空值的情况,因为学员课程未结束时没有结束时间
|
||||
LocalDate startDate = LocalDate.parse(sc.getQueryStartTime());
|
||||
LocalDateTime startDateTime = startDate.atStartOfDay();
|
||||
LocalDate finishDate = LocalDate.parse(sc.getQueryFinishTime());
|
||||
LocalDateTime finishDateTime = finishDate.atTime(LocalTime.MAX);
|
||||
// 筛选开始时间
|
||||
IFieldFilter startTimeInRange = FieldFilters.and(FieldFilters.ge("startTime", startDateTime), FieldFilters.le("startTime", finishDateTime));
|
||||
// 筛选结束时间
|
||||
IFieldFilter finishTimeInRange = FieldFilters.and(FieldFilters.ge("finishTime", startDateTime), FieldFilters.le("finishTime", finishDateTime));
|
||||
// OR条件查询
|
||||
query.addFilter(FieldFilters.or(startTimeInRange, finishTimeInRange));
|
||||
} else {
|
||||
// 只输出单个参数情况
|
||||
// 筛选开始时间
|
||||
if (sc.getQueryStartTime() != null) {
|
||||
LocalDate startDate = LocalDate.parse(sc.getQueryStartTime());
|
||||
LocalDateTime startDateTime = startDate.atStartOfDay();
|
||||
query.addFilter(FieldFilters.ge("startTime", startDateTime));
|
||||
}
|
||||
// 筛选结束时间
|
||||
if (sc.getQueryFinishTime() != null) {
|
||||
LocalDate finishDate = LocalDate.parse(sc.getQueryFinishTime());
|
||||
LocalDateTime finishDateTime = finishDate.atTime(LocalTime.MAX);
|
||||
query.addFilter(FieldFilters.le("finishTime", finishDateTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isFinish != null) {
|
||||
if (isFinish) {
|
||||
@@ -847,7 +861,55 @@ public class StudyCourseServiceImpl implements IStudyCourseService{
|
||||
query.addFilter(FieldFilters.lt("status", 9));
|
||||
}
|
||||
}
|
||||
return studyCourseDao.findList(query.builder());
|
||||
// 25.12.3新增,添加基于时间的查询条件,规则如下:
|
||||
List<StudyCourse> studyCourses = studyCourseDao.findList(query.builder());
|
||||
if (sc != null && StringUtils.isNotBlank(sc.getCourseId()) && StringUtils.isNotBlank(sc.getQueryStartTime()) && StringUtils.isNotBlank(sc.getQueryFinishTime())) {
|
||||
List<StudyCourseItem> studyCourseItemList = studyCourseService.getStudyCourseItemByCourseId(sc.getCourseId());
|
||||
if (studyCourseItemList != null && !studyCourseItemList.isEmpty()) {
|
||||
// 将学习内容按照studyId进行分组,便于后续计算每个studyId下的总学习时长
|
||||
Map<String, List<StudyCourseItem>> itemsByStudyId = studyCourseItemList.stream().filter(item -> item.getFinishTime() != null).collect(Collectors.groupingBy(StudyCourseItem::getStudyId));
|
||||
// 获取查询的起止时间
|
||||
String queryStartTime = sc.getQueryStartTime();
|
||||
String queryFinishTime = sc.getQueryFinishTime();
|
||||
for (StudyCourse studyCourse : studyCourses) {
|
||||
// 实体类解耦
|
||||
entityManager.detach(studyCourse);
|
||||
// 解析查询时间范围
|
||||
LocalDate startDate = LocalDate.parse(queryStartTime);
|
||||
LocalDate endDate = LocalDate.parse(queryFinishTime);
|
||||
// 如果有查询时间范围,则计算筛选后的学习时长
|
||||
if (itemsByStudyId.containsKey(studyCourse.getId())) {
|
||||
List<StudyCourseItem> items = itemsByStudyId.get(studyCourse.getId());
|
||||
int filteredDuration = 0;
|
||||
for (StudyCourseItem item : items) {
|
||||
LocalDateTime finishTime = item.getFinishTime();
|
||||
LocalDate finishDate = finishTime.toLocalDate();
|
||||
// 判断结束时间是否在筛选范围内
|
||||
boolean inRange = true;
|
||||
if (finishDate.isBefore(startDate)) {
|
||||
inRange = false;
|
||||
}
|
||||
if (finishDate.isAfter(endDate)) {
|
||||
inRange = false;
|
||||
}
|
||||
// 如果在范围内,则累加学习时长
|
||||
if (inRange) {
|
||||
Integer duration = item.getStudyDuration();
|
||||
if (duration != null) {
|
||||
filteredDuration += duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新学习时长
|
||||
studyCourse.setTotalDuration(filteredDuration);
|
||||
} else {
|
||||
// 查询不到item的情况,默认置空
|
||||
studyCourse.setTotalDuration(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return studyCourses;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -234,7 +249,7 @@ public class StudyServiceImpl implements IStudyService{
|
||||
* @return 资源学习情况分页集合
|
||||
*/
|
||||
@Override
|
||||
public PageList<StudyCourseItem> findItemPage(int pageIndex, int pageSize, List<String> ids, String contentId, String courseId,String name,Integer status) {
|
||||
public PageList<StudyCourseItem> findItemPage(int pageIndex, int pageSize, List<String> ids, String contentId, String courseId,String name,Integer status,String aid) {
|
||||
QueryBuilder query = QueryBuilder.from(StudyCourseItem.class);
|
||||
query.setPageIndex(pageIndex);
|
||||
query.setPageSize(pageSize);
|
||||
@@ -251,8 +266,13 @@ public class StudyServiceImpl implements IStudyService{
|
||||
query.addFilter(FieldFilters.eq("courseId",courseId));
|
||||
}
|
||||
if(StringUtils.isNotBlank(name)) {
|
||||
query.addFilter(FieldFilters.eq("aname", name));
|
||||
query.addFilter(FieldFilters.like("aname", name));
|
||||
}
|
||||
// 25.12.16新增 aid筛选
|
||||
if(StringUtils.isNotBlank(aid)){
|
||||
String aidList=aid;
|
||||
query.addFilter(FieldFilters.in("aid",aidList.split( ",")));
|
||||
}
|
||||
int pageIndex2 = (pageIndex-1)*10;
|
||||
if(status!=null) {
|
||||
if(status==3) {
|
||||
@@ -269,21 +289,36 @@ public class StudyServiceImpl implements IStudyService{
|
||||
// 未开始(结合现有数据,这里筛选状态为1及为null的数据)
|
||||
query.addFilter(FieldFilters.or(FieldFilters.eq("status", 1), FieldFilters.isNull("status")));
|
||||
return scItemDao.findPage(query.builder());
|
||||
} else if (status == 4) {
|
||||
// 25.12.16修改,添加筛选已完成数据之外的情况
|
||||
query.addFilter(FieldFilters.ne("status", 9));
|
||||
return scItemDao.findPage(query.builder());
|
||||
}
|
||||
}
|
||||
// 25.12.16新增:提前处理aid数组,供后续SQL拼接使用
|
||||
String aidSqlFilter = "";
|
||||
// 存储aid的SQL筛选片段
|
||||
if(StringUtils.isNotBlank(aid)){
|
||||
String[] aidArray = aid.split(",");
|
||||
// 拼接aid的in筛选
|
||||
aidSqlFilter = "and item.aid in ('" + String.join("','", aidArray) + "') ";
|
||||
}
|
||||
// 未传输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 " + "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 " + "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 " +
|
||||
//aidSqlFilter拼接aid筛选条件
|
||||
(StringUtils.isBlank(name) ? "" : "and item.aname like '%" + name +"%'") + aidSqlFilter+" group by bsc.id) b " +
|
||||
"on a.course_id = b.course_id and a.id = b.id " +
|
||||
"group by a.id limit "+ pageIndex2+","+ pageSize+";";
|
||||
String sql2 = "select count(*) as total from (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 " + "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.finish_time, item.progress, item.status " + "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 +"%'") +
|
||||
//aidSqlFilter拼接aid筛选条件
|
||||
(StringUtils.isBlank(name) ? "" : "and item.aname like '%" + name +"%'") +aidSqlFilter+
|
||||
" group by bsc.id) b " +
|
||||
"on a.course_id = b.course_id and a.id = b.id " +
|
||||
"group by a.id) as total";
|
||||
log.info("资源完成情况sql:{}", sql);
|
||||
log.info("数量查询sql:{}", sql2);
|
||||
List<Object[]> list = scDao.sqlFindList(sql);
|
||||
int totalCount = scDao.sqlCount(sql2);
|
||||
List<StudyCourseItem> item = new ArrayList<>();
|
||||
@@ -304,14 +339,103 @@ public class StudyServiceImpl implements IStudyService{
|
||||
if(objs[7] != null){
|
||||
sc.setScore(Float.valueOf(objs[7].toString()));
|
||||
}
|
||||
// 25.12.5新增,补全aid查询
|
||||
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
|
||||
|
||||
@@ -223,9 +223,11 @@ public class StudySignupServiceImpl implements IStudySignupService{
|
||||
if(ss.getCourseType()!=null) {
|
||||
query.addFilter(FieldFilters.eq("courseType", ss.getCourseType()));
|
||||
}
|
||||
if(StringUtils.isNotBlank(ss.getAid())) {
|
||||
query.addFilter(FieldFilters.eq("aid", ss.getAid()));
|
||||
}
|
||||
//25.12.11新增:添加根据用户aid通过逗号分隔查询
|
||||
if(StringUtils.isNotBlank(ss.getAid())){
|
||||
String userIdStr = ss.getAid();
|
||||
query.addFilter(FieldFilters.in("aid",userIdStr.split(",")));
|
||||
}
|
||||
// 25.11.26新增:添加根据报名方式查询(1自主报名,2管理代报)
|
||||
if (ss.getSignType() != null) {
|
||||
query.addFilter(FieldFilters.eq("signType", ss.getSignType()));
|
||||
|
||||
@@ -60,6 +60,7 @@ public class SysUploaderApi extends ApiBaseController{
|
||||
fileTypeSet.add("pptx");
|
||||
fileTypeSet.add("pdf");
|
||||
fileTypeSet.add("zip");
|
||||
fileTypeSet.add("txt");
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/file/upload", method = RequestMethod.POST, produces = "application/json")
|
||||
|
||||
Reference in New Issue
Block a user