课程列表管理端新版

This commit is contained in:
liu.zixi
2025-11-19 21:54:30 +08:00
parent e419b9cd0c
commit 74c8a1383d
6 changed files with 521 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ import com.xboe.api.ThirdApi;
import com.xboe.module.course.dto.*;
import com.xboe.module.course.entity.*;
import com.xboe.module.course.service.*;
import com.xboe.module.course.vo.CoursePageVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -55,6 +56,9 @@ public class CourseManageApi extends ApiBaseController{
@Resource
private ICourseService courseService;
@Autowired
private ICoursePageService coursePageService;
@Autowired
IOutSideDataService outsideService;
@@ -99,6 +103,23 @@ public class CourseManageApi extends ApiBaseController{
// PageList<Course> coursePageList = courseService.findPage(pager.getPageIndex(), pager.getPageSize(),dto);
// return success(coursePageList);
// }
/**
* 新-管理端 课程列表
* @return
*/
@PostMapping("/page")
public JsonResponse<PageList<CoursePageVo>> managePage(@RequestBody CoursePageQueryDTO coursePageQueryDTO) {
// 处理入参逻辑
if (coursePageQueryDTO.getLearningTimeStart() == null || coursePageQueryDTO.getLearningTimeEnd() == null) {
return badRequest("请指定正确的培训时间选择范围");
}
// 管理端查询时不需要传入当前用户信息
return success(coursePageService.pageQuery(null, coursePageQueryDTO));
}
@GetMapping("/export")
public void manageExport() {}
/**
* 管理列表的查询

View File

@@ -0,0 +1,75 @@
package com.xboe.module.course.dto;
import lombok.Data;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
@Data
public class CoursePageQueryDTO {
/**课程名称*/
private String name;
/**资源归属一级*/
private String resOwner1;
/**资源归属二级*/
private String resOwner2;
/**资源归属三级*/
private String resOwner3;
/**是否发布,无就是全部*/
private Boolean publish;
/**创建人*/
private String createUser;
/**课程分类的一级*/
private String sysType1;
/**课程分类的二级*/
private String sysType2;
/**课程分类的三级*/
private String sysType3;
/**授课教师*/
private String teacherName;
/**培训时间筛选类型*/
private String learningTimeType;
/**培训时间-左区间*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime learningTimeStart;
/**培训时间-右区间*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime learningTimeEnd;
/**审核状态*/
private String status;
/**启用状态*/
private Boolean enabled;
/**是否公开课*/
private Integer openCourse;
/**创建来源*/
private String createFrom;
/**页码*/
private Integer pageIndex;
/**每页数量*/
private Integer pageSize;
/**排序字段*/
private String orderField;
/**排序顺序*/
private Boolean orderAsc;
}

View File

@@ -406,6 +406,26 @@ public class Course extends BaseEntity {
@Transient
private Boolean isTip;
/**
* 课程时长(秒)
*/
@Column(name = "course_duration")
private Long courseDuration;
/**
* 排序权重
*/
@Column(name = "sort_weight")
private Integer sortWeight;
/**
* 创建来源
* teacher-教师端
* admin-管理员端
*/
@Column(name = "create_from")
private String createFrom;
public Course(String id,String name,String summary,String coverImg,String sysCreateAid,String sysCreateBy,Integer type,LocalDateTime publishTime){
super.setId(id);
this.name=name;

View File

@@ -0,0 +1,17 @@
package com.xboe.module.course.service;
import com.xboe.common.PageList;
import com.xboe.core.CurrentUser;
import com.xboe.module.course.dto.CoursePageQueryDTO;
import com.xboe.module.course.vo.CoursePageVo;
public interface ICoursePageService {
/**
* 分页查询
* @param currentUser 教师端传入此选项
* @param coursePageQueryDTO
* @return
*/
PageList<CoursePageVo> pageQuery(CurrentUser currentUser, CoursePageQueryDTO coursePageQueryDTO);
}

View File

@@ -0,0 +1,257 @@
package com.xboe.module.course.service.impl;
import com.xboe.common.OrderCondition;
import com.xboe.common.PageList;
import com.xboe.core.CurrentUser;
import com.xboe.core.orm.FieldFilters;
import com.xboe.core.orm.IFieldFilter;
import com.xboe.core.orm.QueryBuilder;
import com.xboe.data.dto.UserOrgIds;
import com.xboe.data.outside.IOutSideDataService;
import com.xboe.module.course.dao.CourseDao;
import com.xboe.module.course.dao.CourseTeacherDao;
import com.xboe.module.course.dto.CoursePageQueryDTO;
import com.xboe.module.course.entity.Course;
import com.xboe.module.course.entity.CourseTeacher;
import com.xboe.module.course.service.ICoursePageService;
import com.xboe.module.course.vo.CoursePageVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class CoursePageServiceImpl implements ICoursePageService {
@Resource
private CourseDao courseDao;
@Resource
private CourseTeacherDao courseTeacherDao;
@Autowired
private IOutSideDataService outSideDataService;
@Override
public PageList<CoursePageVo> pageQuery(CurrentUser currentUser, CoursePageQueryDTO coursePageQueryDTO) {
/*
* 1. 前置权限过滤
* 权限说明:管理员登录后当前页面只可查看本人创建的课程及被授权的课程,其他课程不可见,被赋予查看权的用户可直接引用可查看的课程
*/
UserOrgIds userOrgIds = outSideDataService.getOrgIds();
List<String> orgIds = userOrgIds.getIds();
boolean isSystemAdmin = userOrgIds.getPermissions().containsKey(UserOrgIds.IsSystemAdminKey)
&& userOrgIds.getPermissions().get(UserOrgIds.IsSystemAdminKey);
String currentAccountId = currentUser == null ? null : currentUser.getAccountId();
// 构建查询条件
List<IFieldFilter> filters = createFilters(coursePageQueryDTO);
// 自动添加过滤已删除
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));
}
}
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;
}
/**
* 生成过滤条件
*
* @param dto
* @return
*/
private List<IFieldFilter> createFilters(CoursePageQueryDTO dto) {
List<IFieldFilter> filters = new ArrayList<>();
if (StringUtils.isNotBlank(dto.getName())) {
filters.add(FieldFilters.like("c.name", dto.getName()));
}
if (StringUtils.isNotBlank(dto.getCreateUser())) {
filters.add(FieldFilters.like("c.sysCreateBy", dto.getCreateUser()));
}
if (StringUtils.isNotBlank(dto.getResOwner3())) {
filters.add(FieldFilters.eq("c.resOwner3", dto.getResOwner3()));
}
if (StringUtils.isNotBlank(dto.getResOwner2())) {
filters.add(FieldFilters.eq("c.resOwner2", dto.getResOwner2()));
}
if (StringUtils.isNotBlank(dto.getResOwner1())) {
filters.add(FieldFilters.eq("c.resOwner1", dto.getResOwner1()));
}
if (dto.getPublish() != null) {
filters.add(FieldFilters.eq("c.published", dto.getPublish()));
}
// 状态查询
if (StringUtils.isNotBlank(dto.getStatus())) {
filters.add(FieldFilters.eq("c.status", Integer.valueOf(dto.getStatus())));
}
// 系统分类查询
if (StringUtils.isNotBlank(dto.getSysType3())) {
filters.add(FieldFilters.eq("c.sysType3", dto.getSysType3()));
}
if (StringUtils.isNotBlank(dto.getSysType2())) {
filters.add(FieldFilters.eq("c.sysType2", dto.getSysType2()));
}
if (StringUtils.isNotBlank(dto.getSysType1())) {
filters.add(FieldFilters.eq("c.sysType1", dto.getSysType1()));
}
// 是否启用
if (dto.getEnabled() != null) {
filters.add(FieldFilters.eq("c.enabled", dto.getEnabled()));
}
// 时间范围查询(待定)
return filters;
}
private List<CourseTeacher> getCourseTeacherList(List<String> courseIds) {
return courseTeacherDao.findList(OrderCondition.desc("courseId"), FieldFilters.in("courseId", courseIds));
}
/**
* 将Course转换为CoursePageVo
* @param course
* @return
*/
private CoursePageVo convertToVo(Course course, List<CourseTeacher> courseTeacherList) {
CoursePageVo vo = new CoursePageVo();
vo.setId(course.getId());
vo.setName(course.getName());
vo.setCoverImg(course.getCoverImg());
vo.setSysType1(course.getSysType1());
vo.setSysType2(course.getSysType2());
vo.setSysType3(course.getSysType3());
vo.setResOwner1(course.getResOwner1());
vo.setResOwner2(course.getResOwner2());
vo.setResOwner3(course.getResOwner3());
vo.setSysCreateBy(course.getSysCreateBy());
vo.setCreateFrom(course.getCreateFrom());
vo.setSysCreateTime(course.getSysCreateTime());
vo.setForUsers(course.getForUsers());
vo.setStatus(course.getStatus());
// auditType 需要从其他地方获取,这里暂时设置为默认值
vo.setAuditType(1);
vo.setPublished(course.getPublished());
vo.setStudys(course.getStudys());
vo.setScore(course.getScore());
// courseDuration 需要计算,这里暂时设置为默认值
vo.setCourseDuration(course.getCourseDuration());
vo.setEnabled(course.getEnabled());
// 获取教师名称
List<String> teacherNames = courseTeacherList.stream()
.filter(ct -> StringUtils.equals(ct.getCourseId(), course.getId()))
.map(CourseTeacher::getTeacherName)
.collect(Collectors.toList());
if (!teacherNames.isEmpty()) {
vo.setTeacherName(String.join(",", teacherNames));
}
return vo;
}
private void handleOrder(QueryBuilder query, String orderField, Boolean orderAsc) {
if (StringUtils.isNotBlank(orderField)) {
boolean isAsc = orderAsc == null || orderAsc;
// 1. 多字段排序
if (StringUtils.equals(orderField, "sysType")) {
if (isAsc) {
query.addOrder(OrderCondition.asc("c.sysType1"));
query.addOrder(OrderCondition.asc("c.sysType2"));
query.addOrder(OrderCondition.asc("c.sysType3"));
} else {
query.addOrder(OrderCondition.desc("c.sysType1"));
query.addOrder(OrderCondition.desc("c.sysType2"));
query.addOrder(OrderCondition.desc("c.sysType3"));
}
} else if (StringUtils.equals(orderField, "resOwner")) {
if (isAsc) {
query.addOrder(OrderCondition.asc("c.resOwner1"));
query.addOrder(OrderCondition.asc("c.resOwner2"));
query.addOrder(OrderCondition.asc("c.resOwner3"));
} else {
query.addOrder(OrderCondition.desc("c.resOwner1"));
query.addOrder(OrderCondition.desc("c.resOwner2"));
query.addOrder(OrderCondition.desc("c.resOwner3"));
}
} else {
if (isAsc) {
query.addOrder(OrderCondition.asc("c." + orderField));
} else {
query.addOrder(OrderCondition.desc("c." + orderField));
}
}
} else {
OrderCondition isTop = OrderCondition.desc("c.isTop");
query.addOrder(isTop);
OrderCondition sortWeightOc = OrderCondition.asc("c.sortWeight");
query.addOrder(sortWeightOc);
}
}
}

View File

@@ -0,0 +1,131 @@
package com.xboe.module.course.vo;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class CoursePageVo {
/**
* 课程ID
*/
private String id;
/**
* 课程名称
*/
private String name;
/**
* 课程封面图片地址
*/
private String coverImg;
/**
* 课程分类一级
*/
private String sysType1;
/**
* 课程分类二级
*/
private String sysType2;
/**
* 课程分类三级
*/
private String sysType3;
/**
* 资源归属一级
*/
private String resOwner1;
/**
* 资源归属二级
*/
private String resOwner2;
/**
* 资源归属三级
*/
private String resOwner3;
/**
* 创建人
*/
private String sysCreateBy;
/**
* 创建来源
* teacher-教师端
* admin-管理员端
*/
private String createFrom;
/**
* 创建时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime sysCreateTime;
/**
* 目标人群
*/
private String forUsers;
/**
* 审核状态
* 1-无审核状态
* 2-审核中
* 3-审核驳回
* 5-审核通过
*/
private Integer status;
/**
* 课程审核类型
* 1-课程创建
* 2-课程编辑
* 3-课程启用
* 4-课程停用
* 5-撤回申请
*/
private Integer auditType;
/**
* 发布状态
* false-未发布
* true-已发布
*/
private Boolean published;
/**
* 学习人数
*/
private Integer studys;
/**
* 课程评分
*/
private Float score;
/**
* 课程时长(秒)
*/
private Long courseDuration;
/**
* 启用状态
* false-停用
* true-启用
*/
private Boolean enabled;
/**
* 授课教师
*/
private String teacherName;
}