视图修改、接口修改
This commit is contained in:
@@ -37,7 +37,8 @@ CREATE TABLE `tb_resource` (
|
||||
-- Banner管理表
|
||||
DROP TABLE IF EXISTS `tb_banner`;
|
||||
CREATE TABLE `tb_banner` (
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'Banner ID',
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'ID',
|
||||
`banner_id` VARCHAR(50) NOT NULL COMMENT 'Banner ID',
|
||||
`title` VARCHAR(255) NOT NULL COMMENT 'Banner标题',
|
||||
`image_url` VARCHAR(500) NOT NULL COMMENT 'Banner图片URL',
|
||||
`link_type` INT(4) DEFAULT 1 COMMENT '链接类型(1资源 2课程 3外部链接)',
|
||||
@@ -52,6 +53,7 @@ CREATE TABLE `tb_banner` (
|
||||
`delete_time` TIMESTAMP NULL DEFAULT NULL COMMENT '删除时间',
|
||||
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_banner_id` (`banner_id`),
|
||||
KEY `idx_order` (`order_num`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Banner表';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.xyzh.api.news.banner;
|
||||
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.dto.resource.TbBanner;
|
||||
|
||||
import java.util.List;
|
||||
@@ -21,7 +22,7 @@ public interface BannerService {
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<TbBanner> getBannerList(Integer status);
|
||||
ResultDomain<TbBanner> getBannerList(TbBanner filter);
|
||||
|
||||
/**
|
||||
* @description 根据ID获取Banner详情
|
||||
@@ -30,7 +31,7 @@ public interface BannerService {
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<TbBanner> getBannerById(String bannerID);
|
||||
ResultDomain<TbBanner> getBannerPage(PageParam pageParam,TbBanner filter);
|
||||
|
||||
/**
|
||||
* @description 创建Banner
|
||||
@@ -96,4 +97,12 @@ public interface BannerService {
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<Boolean> batchUpdateBannerOrder(java.util.Map<String, Integer> bannerOrders);
|
||||
|
||||
/**
|
||||
* @description 获取首页横幅列表
|
||||
* @return ResultDomain<TbBanner> 首页横幅列表
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<TbBanner> selectHomeBanners();
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package org.xyzh.api.study.course;
|
||||
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.core.page.PageRequest;
|
||||
import org.xyzh.common.dto.study.TbCourse;
|
||||
import org.xyzh.common.dto.study.TbCourseChapter;
|
||||
import org.xyzh.common.dto.study.TbCourseNode;
|
||||
import org.xyzh.common.dto.study.TbLearningRecord;
|
||||
import org.xyzh.common.vo.CourseVO;
|
||||
|
||||
import java.util.List;
|
||||
import org.xyzh.common.vo.CourseItemVO;
|
||||
|
||||
/**
|
||||
* @description 课程服务接口
|
||||
@@ -41,29 +37,29 @@ public interface CourseService {
|
||||
/**
|
||||
* @description 根据ID获取课程详情
|
||||
* @param courseID 课程ID
|
||||
* @return ResultDomain<TbCourse> 课程详情
|
||||
* @return ResultDomain<CourseItemVO> 课程详情
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<CourseVO> getCourseById(String courseID);
|
||||
ResultDomain<CourseItemVO> getCourseById(String courseID);
|
||||
|
||||
/**
|
||||
* @description 创建课程
|
||||
* @param course 课程信息
|
||||
* @return ResultDomain<TbCourse> 创建结果
|
||||
* @param courseItemVO 课程信息
|
||||
* @return ResultDomain<CourseItemVO> 创建结果
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<CourseVO> createCourse(CourseVO courseVO);
|
||||
ResultDomain<CourseItemVO> createCourse(CourseItemVO courseItemVO);
|
||||
|
||||
/**
|
||||
* @description 更新课程
|
||||
* @param courseVO 课程信息
|
||||
* @return ResultDomain<CourseVO> 更新结果
|
||||
* @param courseItemVO 课程信息
|
||||
* @return ResultDomain<CourseItemVO> 更新结果
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
ResultDomain<CourseVO> updateCourse(CourseVO courseVO);
|
||||
ResultDomain<CourseItemVO> updateCourse(CourseItemVO courseItemVO);
|
||||
|
||||
/**
|
||||
* @description 删除课程
|
||||
@@ -185,4 +181,13 @@ public interface CourseService {
|
||||
* @since 2025-10-22
|
||||
*/
|
||||
ResultDomain<Boolean> deleteChapterNode(String nodeID);
|
||||
|
||||
/**
|
||||
* @description 获取课程进度
|
||||
* @param courseID 课程ID
|
||||
* @return ResultDomain<CourseItemVO> 课程进度
|
||||
* @author yslg
|
||||
* @since 2025-10-28
|
||||
*/
|
||||
ResultDomain<CourseItemVO> getCourseProgress(String courseID);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import org.xyzh.common.dto.BaseDTO;
|
||||
public class TbBanner extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String bannerID;
|
||||
|
||||
/**
|
||||
* @description Banner标题
|
||||
@@ -58,6 +60,14 @@ public class TbBanner extends BaseDTO {
|
||||
*/
|
||||
private String updater;
|
||||
|
||||
public String getBannerID() {
|
||||
return bannerID;
|
||||
}
|
||||
|
||||
public void setBannerID(String bannerID) {
|
||||
this.bannerID = bannerID;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
@@ -134,6 +144,7 @@ public class TbBanner extends BaseDTO {
|
||||
public String toString() {
|
||||
return "TbBanner{" +
|
||||
"id=" + getID() +
|
||||
", bannerID='" + bannerID + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", imageUrl='" + imageUrl + '\'' +
|
||||
", linkType=" + linkType +
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package org.xyzh.common.vo;
|
||||
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
import org.xyzh.common.dto.study.TbCourseNode;
|
||||
import org.xyzh.common.dto.study.TbCourseChapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChapterVO extends BaseDTO{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private TbCourseChapter chapter;
|
||||
private List<TbCourseNode> nodes;
|
||||
|
||||
public TbCourseChapter getChapter() {
|
||||
return chapter;
|
||||
}
|
||||
public void setChapter(TbCourseChapter chapter) {
|
||||
this.chapter = chapter;
|
||||
}
|
||||
public List<TbCourseNode> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
public void setNodes(List<TbCourseNode> nodes) {
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void addNode(TbCourseNode node) {
|
||||
if (nodes == null) {
|
||||
nodes = new ArrayList<>();
|
||||
}
|
||||
nodes.add(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,589 @@
|
||||
package org.xyzh.common.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
import org.xyzh.common.dto.study.TbCourse;
|
||||
import org.xyzh.common.dto.study.TbCourseChapter;
|
||||
import org.xyzh.common.dto.study.TbCourseNode;
|
||||
import org.xyzh.common.dto.study.TbLearningRecord;
|
||||
|
||||
/**
|
||||
* @description 课程项目VO - 包含课程和学习记录的关键信息
|
||||
* @filename CourseItemVO.java
|
||||
* @author yslg
|
||||
* @copyright xyzh
|
||||
* @since 2025-10-28
|
||||
*/
|
||||
public class CourseItemVO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// ========== 课程基本信息 ==========
|
||||
/**
|
||||
* @description 课程ID
|
||||
*/
|
||||
private String courseID;
|
||||
|
||||
/**
|
||||
* @description 课程名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @description 课程封面图片
|
||||
*/
|
||||
private String coverImage;
|
||||
|
||||
/**
|
||||
* @description 课程描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @description 课程时长(分钟)
|
||||
*/
|
||||
private Integer duration;
|
||||
|
||||
/**
|
||||
* @description 授课老师
|
||||
*/
|
||||
private String teacher;
|
||||
|
||||
/**
|
||||
* @description 课程状态(0未上线 1已上线 2已下架)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* @description 浏览次数
|
||||
*/
|
||||
private Integer viewCount;
|
||||
|
||||
/**
|
||||
* @description 学习人数
|
||||
*/
|
||||
private Integer learnCount;
|
||||
|
||||
/**
|
||||
* @description 课程创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
// ========== 学习记录信息 ==========
|
||||
/**
|
||||
* @description 学习记录ID
|
||||
*/
|
||||
private String recordID;
|
||||
|
||||
/**
|
||||
* @description 学习进度(0-100)
|
||||
*/
|
||||
private BigDecimal progress;
|
||||
|
||||
/**
|
||||
* @description 是否完成
|
||||
*/
|
||||
private Boolean isComplete;
|
||||
|
||||
/**
|
||||
* @description 学习时长(秒)
|
||||
*/
|
||||
private Integer learningDuration;
|
||||
|
||||
/**
|
||||
* @description 最后学习时间
|
||||
*/
|
||||
private Date lastLearnTime;
|
||||
|
||||
/**
|
||||
* @description 完成时间
|
||||
*/
|
||||
private Date completeTime;
|
||||
|
||||
// ========== 章节节点信息 ==========
|
||||
/**
|
||||
* @description 章节ID(当此对象代表章节或节点时使用)
|
||||
*/
|
||||
private String chapterID;
|
||||
|
||||
/**
|
||||
* @description 节点ID(当此对象代表节点时使用)
|
||||
*/
|
||||
private String nodeID;
|
||||
|
||||
/**
|
||||
* @description 父级ID(章节的父章节ID)
|
||||
*/
|
||||
private String parentID;
|
||||
|
||||
/**
|
||||
* @description 节点类型(1视频 2文档 3音频 4图片 5链接)
|
||||
*/
|
||||
private Integer nodeType;
|
||||
|
||||
/**
|
||||
* @description 节点内容(富文本内容)
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* @description 视频URL
|
||||
*/
|
||||
private String videoUrl;
|
||||
|
||||
/**
|
||||
* @description 资源ID
|
||||
*/
|
||||
private String resourceID;
|
||||
|
||||
/**
|
||||
* @description 排序号
|
||||
*/
|
||||
private Integer orderNum;
|
||||
|
||||
/**
|
||||
* @description 是否必修(1必修 0选修)
|
||||
*/
|
||||
private Integer isRequired;
|
||||
|
||||
// ========== 层级结构 ==========
|
||||
/**
|
||||
* @description 章节列表(课程的章节列表)
|
||||
*/
|
||||
private List<CourseItemVO> chapters;
|
||||
|
||||
/**
|
||||
* @description 章节节点映射(key: chapterID, value: 该章节下的节点列表)
|
||||
*/
|
||||
private Map<String, List<CourseItemVO>> chapterNodes;
|
||||
|
||||
// ========== Getters and Setters ==========
|
||||
|
||||
public String getCourseID() {
|
||||
return courseID;
|
||||
}
|
||||
|
||||
public void setCourseID(String courseID) {
|
||||
this.courseID = courseID;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCoverImage() {
|
||||
return coverImage;
|
||||
}
|
||||
|
||||
public void setCoverImage(String coverImage) {
|
||||
this.coverImage = coverImage;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(Integer duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getTeacher() {
|
||||
return teacher;
|
||||
}
|
||||
|
||||
public void setTeacher(String teacher) {
|
||||
this.teacher = teacher;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Integer getViewCount() {
|
||||
return viewCount;
|
||||
}
|
||||
|
||||
public void setViewCount(Integer viewCount) {
|
||||
this.viewCount = viewCount;
|
||||
}
|
||||
|
||||
public Integer getLearnCount() {
|
||||
return learnCount;
|
||||
}
|
||||
|
||||
public void setLearnCount(Integer learnCount) {
|
||||
this.learnCount = learnCount;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getRecordID() {
|
||||
return recordID;
|
||||
}
|
||||
|
||||
public void setRecordID(String recordID) {
|
||||
this.recordID = recordID;
|
||||
}
|
||||
|
||||
public BigDecimal getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(BigDecimal progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public Boolean getIsComplete() {
|
||||
return isComplete;
|
||||
}
|
||||
|
||||
public void setIsComplete(Boolean isComplete) {
|
||||
this.isComplete = isComplete;
|
||||
}
|
||||
|
||||
public Integer getLearningDuration() {
|
||||
return learningDuration;
|
||||
}
|
||||
|
||||
public void setLearningDuration(Integer learningDuration) {
|
||||
this.learningDuration = learningDuration;
|
||||
}
|
||||
|
||||
public Date getLastLearnTime() {
|
||||
return lastLearnTime;
|
||||
}
|
||||
|
||||
public void setLastLearnTime(Date lastLearnTime) {
|
||||
this.lastLearnTime = lastLearnTime;
|
||||
}
|
||||
|
||||
public Date getCompleteTime() {
|
||||
return completeTime;
|
||||
}
|
||||
|
||||
public void setCompleteTime(Date completeTime) {
|
||||
this.completeTime = completeTime;
|
||||
}
|
||||
|
||||
public String getChapterID() {
|
||||
return chapterID;
|
||||
}
|
||||
|
||||
public void setChapterID(String chapterID) {
|
||||
this.chapterID = chapterID;
|
||||
}
|
||||
|
||||
public String getNodeID() {
|
||||
return nodeID;
|
||||
}
|
||||
|
||||
public void setNodeID(String nodeID) {
|
||||
this.nodeID = nodeID;
|
||||
}
|
||||
|
||||
public String getParentID() {
|
||||
return parentID;
|
||||
}
|
||||
|
||||
public void setParentID(String parentID) {
|
||||
this.parentID = parentID;
|
||||
}
|
||||
|
||||
public Integer getNodeType() {
|
||||
return nodeType;
|
||||
}
|
||||
|
||||
public void setNodeType(Integer nodeType) {
|
||||
this.nodeType = nodeType;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getVideoUrl() {
|
||||
return videoUrl;
|
||||
}
|
||||
|
||||
public void setVideoUrl(String videoUrl) {
|
||||
this.videoUrl = videoUrl;
|
||||
}
|
||||
|
||||
public String getResourceID() {
|
||||
return resourceID;
|
||||
}
|
||||
|
||||
public void setResourceID(String resourceID) {
|
||||
this.resourceID = resourceID;
|
||||
}
|
||||
|
||||
public Integer getOrderNum() {
|
||||
return orderNum;
|
||||
}
|
||||
|
||||
public void setOrderNum(Integer orderNum) {
|
||||
this.orderNum = orderNum;
|
||||
}
|
||||
|
||||
public Integer getIsRequired() {
|
||||
return isRequired;
|
||||
}
|
||||
|
||||
public void setIsRequired(Integer isRequired) {
|
||||
this.isRequired = isRequired;
|
||||
}
|
||||
|
||||
public List<CourseItemVO> getChapters() {
|
||||
return chapters;
|
||||
}
|
||||
|
||||
public void setChapters(List<CourseItemVO> chapters) {
|
||||
this.chapters = chapters;
|
||||
}
|
||||
|
||||
public Map<String, List<CourseItemVO>> getChapterNodes() {
|
||||
return chapterNodes;
|
||||
}
|
||||
|
||||
public void setChapterNodes(Map<String, List<CourseItemVO>> chapterNodes) {
|
||||
this.chapterNodes = chapterNodes;
|
||||
}
|
||||
|
||||
// ========== 类型转换方法 ==========
|
||||
|
||||
/**
|
||||
* @description 转换为课程实体对象
|
||||
* @return TbCourse 课程实体
|
||||
*/
|
||||
public TbCourse toCourse() {
|
||||
TbCourse course = new TbCourse();
|
||||
course.setID(this.getID());
|
||||
course.setCourseID(this.courseID);
|
||||
course.setName(this.name);
|
||||
course.setCoverImage(this.coverImage);
|
||||
course.setDescription(this.description);
|
||||
course.setDuration(this.duration);
|
||||
course.setTeacher(this.teacher);
|
||||
course.setStatus(this.status);
|
||||
course.setViewCount(this.viewCount);
|
||||
course.setLearnCount(this.learnCount);
|
||||
course.setCreateTime(this.createTime);
|
||||
return course;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 从课程实体创建CourseItemVO
|
||||
* @param course 课程实体
|
||||
* @return CourseItemVO
|
||||
*/
|
||||
public static CourseItemVO fromCourse(TbCourse course) {
|
||||
if (course == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CourseItemVO vo = new CourseItemVO();
|
||||
vo.setID(course.getID());
|
||||
vo.setCourseID(course.getCourseID());
|
||||
vo.setName(course.getName());
|
||||
vo.setCoverImage(course.getCoverImage());
|
||||
vo.setDescription(course.getDescription());
|
||||
vo.setDuration(course.getDuration());
|
||||
vo.setTeacher(course.getTeacher());
|
||||
vo.setStatus(course.getStatus());
|
||||
vo.setViewCount(course.getViewCount());
|
||||
vo.setLearnCount(course.getLearnCount());
|
||||
vo.setCreateTime(course.getCreateTime());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 转换为学习记录实体对象
|
||||
* @return TbLearningRecord 学习记录实体
|
||||
*/
|
||||
public TbLearningRecord toLearningRecord() {
|
||||
TbLearningRecord record = new TbLearningRecord();
|
||||
if (this.recordID != null) {
|
||||
// 如果有recordID,说明是从已有记录转换的,需要设置ID
|
||||
record.setID(this.recordID);
|
||||
}
|
||||
record.setCourseID(this.courseID);
|
||||
record.setDuration(this.learningDuration);
|
||||
record.setProgress(this.progress);
|
||||
record.setIsComplete(this.isComplete);
|
||||
record.setCompleteTime(this.completeTime);
|
||||
record.setLastLearnTime(this.lastLearnTime);
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 设置学习记录信息
|
||||
* @param record 学习记录实体
|
||||
*/
|
||||
public void setLearningRecordInfo(TbLearningRecord record) {
|
||||
if (record == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.recordID = record.getID();
|
||||
this.progress = record.getProgress();
|
||||
this.isComplete = record.getIsComplete();
|
||||
this.learningDuration = record.getDuration();
|
||||
this.lastLearnTime = record.getLastLearnTime();
|
||||
this.completeTime = record.getCompleteTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 从课程和学习记录创建CourseItemVO
|
||||
* @param course 课程实体
|
||||
* @param record 学习记录实体
|
||||
* @return CourseItemVO
|
||||
*/
|
||||
public static CourseItemVO fromCourseAndRecord(TbCourse course, TbLearningRecord record) {
|
||||
CourseItemVO vo = fromCourse(course);
|
||||
if (vo != null && record != null) {
|
||||
vo.setLearningRecordInfo(record);
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 从章节创建CourseItemVO
|
||||
* @param chapter 章节实体
|
||||
* @return CourseItemVO
|
||||
*/
|
||||
public static CourseItemVO fromChapter(TbCourseChapter chapter) {
|
||||
if (chapter == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CourseItemVO vo = new CourseItemVO();
|
||||
vo.setID(chapter.getID());
|
||||
vo.setChapterID(chapter.getChapterID());
|
||||
vo.setCourseID(chapter.getCourseID());
|
||||
vo.setParentID(chapter.getParentID());
|
||||
vo.setName(chapter.getName());
|
||||
vo.setDescription(chapter.getContent());
|
||||
vo.setDuration(chapter.getDuration());
|
||||
vo.setVideoUrl(chapter.getVideoUrl());
|
||||
vo.setResourceID(chapter.getResourceID());
|
||||
vo.setNodeType(chapter.getChapterType());
|
||||
vo.setOrderNum(chapter.getOrderNum());
|
||||
vo.setCreateTime(chapter.getCreateTime());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 从节点创建CourseItemVO
|
||||
* @param node 节点实体
|
||||
* @return CourseItemVO
|
||||
*/
|
||||
public static CourseItemVO fromNode(TbCourseNode node) {
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CourseItemVO vo = new CourseItemVO();
|
||||
vo.setID(node.getID());
|
||||
vo.setNodeID(node.getNodeID());
|
||||
vo.setChapterID(node.getChapterID());
|
||||
vo.setName(node.getName());
|
||||
|
||||
vo.setContent(node.getContent());
|
||||
vo.setDuration(node.getDuration());
|
||||
vo.setVideoUrl(node.getVideoUrl());
|
||||
vo.setResourceID(node.getResourceID());
|
||||
vo.setNodeType(node.getNodeType());
|
||||
vo.setOrderNum(node.getOrderNum());
|
||||
vo.setIsRequired(node.getIsRequired());
|
||||
vo.setCreateTime(node.getCreateTime());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 转换为章节实体对象
|
||||
* @return TbCourseChapter 章节实体
|
||||
*/
|
||||
public TbCourseChapter toChapter() {
|
||||
TbCourseChapter chapter = new TbCourseChapter();
|
||||
chapter.setID(this.getID());
|
||||
chapter.setChapterID(this.chapterID);
|
||||
chapter.setCourseID(this.courseID);
|
||||
chapter.setParentID(this.parentID);
|
||||
chapter.setName(this.name);
|
||||
chapter.setContent(this.description);
|
||||
chapter.setDuration(this.duration);
|
||||
chapter.setVideoUrl(this.videoUrl);
|
||||
chapter.setResourceID(this.resourceID);
|
||||
chapter.setChapterType(this.nodeType);
|
||||
chapter.setOrderNum(this.orderNum);
|
||||
return chapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 转换为节点实体对象
|
||||
* @return TbCourseNode 节点实体
|
||||
*/
|
||||
public TbCourseNode toNode() {
|
||||
TbCourseNode node = new TbCourseNode();
|
||||
node.setID(this.getID());
|
||||
node.setNodeID(this.nodeID);
|
||||
node.setChapterID(this.chapterID);
|
||||
node.setName(this.name);
|
||||
node.setContent(this.content);
|
||||
node.setDuration(this.duration);
|
||||
node.setVideoUrl(this.videoUrl);
|
||||
node.setResourceID(this.resourceID);
|
||||
node.setNodeType(this.nodeType);
|
||||
node.setOrderNum(this.orderNum);
|
||||
node.setIsRequired(this.isRequired);
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CourseItemVO{" +
|
||||
"courseID='" + courseID + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", coverImage='" + coverImage + '\'' +
|
||||
", teacher='" + teacher + '\'' +
|
||||
", duration=" + duration +
|
||||
", status=" + status +
|
||||
", progress=" + progress +
|
||||
", isComplete=" + isComplete +
|
||||
", learningDuration=" + learningDuration +
|
||||
", lastLearnTime=" + lastLearnTime +
|
||||
", viewCount=" + viewCount +
|
||||
", learnCount=" + learnCount +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package org.xyzh.common.vo;
|
||||
|
||||
import org.xyzh.common.dto.BaseDTO;
|
||||
import org.xyzh.common.dto.study.TbCourse;
|
||||
import org.xyzh.common.dto.study.TbCourseTag;
|
||||
import org.xyzh.common.vo.ChapterVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CourseVO extends BaseDTO{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private TbCourse course;
|
||||
private List<ChapterVO> courseChapters;
|
||||
private List<TbCourseTag> courseTags;
|
||||
|
||||
|
||||
public TbCourse getCourse() {
|
||||
return course;
|
||||
}
|
||||
public void setCourse(TbCourse course) {
|
||||
this.course = course;
|
||||
}
|
||||
public List<ChapterVO> getCourseChapters() {
|
||||
return courseChapters;
|
||||
}
|
||||
public void setCourseChapters(List<ChapterVO> courseChapters) {
|
||||
this.courseChapters = courseChapters;
|
||||
}
|
||||
public List<TbCourseTag> getCourseTags() {
|
||||
return courseTags;
|
||||
}
|
||||
public void setCourseTags(List<TbCourseTag> courseTags) {
|
||||
this.courseTags = courseTags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.xyzh.crontab.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.xyzh.crontab.task.DataBackupTask;
|
||||
import org.xyzh.crontab.task.LogCleanTask;
|
||||
import org.xyzh.crontab.task.SystemStatisticsTask;
|
||||
|
||||
public enum TaskEnums {
|
||||
DATA_BACKUP("dataBackup", DataBackupTask.class),
|
||||
LOG_CLEAN("logClean", LogCleanTask.class),
|
||||
SystemStatistics("systemStatistics", SystemStatisticsTask.class);
|
||||
|
||||
|
||||
private String name;
|
||||
private Class<?> clazz;
|
||||
|
||||
TaskEnums(String name, Class<?> clazz) {
|
||||
this.name = name;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public static TaskEnums getByName(String name) {
|
||||
return Arrays.stream(TaskEnums.values())
|
||||
.filter(task -> task.getName().equals(name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.xyzh.crontab.task.newsTask;
|
||||
|
||||
|
||||
abstract public class NewsTask {
|
||||
|
||||
// 爬取网站目标
|
||||
private String target;
|
||||
// 爬取标题
|
||||
private String title;
|
||||
|
||||
|
||||
}
|
||||
@@ -6,7 +6,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.xyzh.api.news.banner.BannerService;
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageRequest;
|
||||
import org.xyzh.common.dto.resource.TbBanner;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
|
||||
/**
|
||||
* @description 横幅控制器
|
||||
@@ -27,16 +31,16 @@ public class BannerController {
|
||||
* 获取横幅列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ResultDomain<TbBanner> getBannerList() {
|
||||
return bannerService.getBannerList(null);
|
||||
public ResultDomain<TbBanner> getBannerList(TbBanner filter) {
|
||||
return bannerService.getBannerList(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取横幅详情
|
||||
*/
|
||||
@GetMapping("/banner/{bannerID}")
|
||||
public ResultDomain<TbBanner> getBannerById(@PathVariable String bannerID) {
|
||||
return bannerService.getBannerById(bannerID);
|
||||
@PostMapping("/banner/page")
|
||||
public ResultDomain<TbBanner> getBannerPage(@RequestBody PageRequest<TbBanner> pageRequest) {
|
||||
return bannerService.getBannerPage(pageRequest.getPageParam(), pageRequest.getFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,36 +62,27 @@ public class BannerController {
|
||||
/**
|
||||
* 删除横幅
|
||||
*/
|
||||
@DeleteMapping("/banner/{bannerID}")
|
||||
public ResultDomain<Boolean> deleteBanner(@PathVariable String bannerID) {
|
||||
return bannerService.deleteBanner(bannerID);
|
||||
@DeleteMapping("/banner")
|
||||
public ResultDomain<Boolean> deleteBanner(@RequestBody TbBanner banner) {
|
||||
return bannerService.deleteBanner(banner.getBannerID());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新横幅状态
|
||||
*/
|
||||
@PutMapping("/banner/{bannerID}/status")
|
||||
public ResultDomain<TbBanner> updateBannerStatus(
|
||||
@PathVariable String bannerID,
|
||||
@RequestParam Integer status) {
|
||||
return bannerService.updateBannerStatus(bannerID, status);
|
||||
@PutMapping("/banner/status")
|
||||
public ResultDomain<TbBanner> updateBannerStatus(@RequestBody TbBanner banner) {
|
||||
return bannerService.updateBannerStatus(banner.getBannerID(), banner.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新横幅排序
|
||||
* 获取首页横幅列表
|
||||
*/
|
||||
@PutMapping("/banner/{bannerID}/order")
|
||||
public ResultDomain<TbBanner> updateBannerOrder(
|
||||
@PathVariable String bannerID,
|
||||
@RequestParam Integer orderNum) {
|
||||
return bannerService.updateBannerOrder(bannerID, orderNum);
|
||||
@GetMapping("/home")
|
||||
public ResultDomain<TbBanner> getHomeBannerList() {
|
||||
return bannerService.selectHomeBanners();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取活跃横幅
|
||||
*/
|
||||
@GetMapping("/active")
|
||||
public ResultDomain<TbBanner> getActiveBanners(@RequestParam(required = false) Integer limit) {
|
||||
return bannerService.getActiveBanners(limit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,19 @@ public interface BannerMapper extends BaseMapper<TbBanner> {
|
||||
*/
|
||||
List<TbBanner> selectBanners(TbBanner filter);
|
||||
|
||||
List<TbBanner> selectBannersLimit(@Param("filter") TbBanner filter, @Param("limit") Integer limit);
|
||||
|
||||
|
||||
/**
|
||||
* @description 分页查询Banner
|
||||
* @param filter 过滤条件
|
||||
* @param pageParam 分页参数
|
||||
* @return List<TbBanner> Banner列表
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
List<TbBanner> selectBannersPage(@Param("filter") TbBanner filter, @Param("pageParam") PageParam pageParam);
|
||||
|
||||
/**
|
||||
* @description 根据Banner ID查询Banner信息
|
||||
* @param bannerId Banner ID
|
||||
@@ -117,16 +130,6 @@ public interface BannerMapper extends BaseMapper<TbBanner> {
|
||||
*/
|
||||
int batchDeleteBanners(@Param("ids") List<String> ids);
|
||||
|
||||
/**
|
||||
* @description 分页查询Banner
|
||||
* @param filter 过滤条件
|
||||
* @param pageParam 分页参数
|
||||
* @return List<TbBanner> Banner列表
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
List<TbBanner> selectBannersPage(@Param("filter") TbBanner filter, @Param("pageParam") PageParam pageParam);
|
||||
|
||||
/**
|
||||
* @description 统计Banner总数
|
||||
* @param filter 过滤条件
|
||||
|
||||
@@ -11,6 +11,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageDomain;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.dto.resource.TbBanner;
|
||||
import org.xyzh.common.utils.IDUtils;
|
||||
import org.xyzh.news.mapper.BannerMapper;
|
||||
@@ -32,49 +34,27 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
private BannerMapper bannerMapper;
|
||||
|
||||
@Override
|
||||
public ResultDomain<TbBanner> getBannerList(Integer status) {
|
||||
public ResultDomain<TbBanner> getBannerList(TbBanner filter) {
|
||||
ResultDomain<TbBanner> resultDomain = new ResultDomain<>();
|
||||
try {
|
||||
List<TbBanner> list;
|
||||
if (status != null) {
|
||||
list = bannerMapper.selectByStatus(status);
|
||||
} else {
|
||||
TbBanner filter = new TbBanner();
|
||||
list = bannerMapper.selectBanners(filter);
|
||||
}
|
||||
resultDomain.success("获取横幅列表成功", list);
|
||||
return resultDomain;
|
||||
} catch (Exception e) {
|
||||
logger.error("获取横幅列表异常: {}", e.getMessage(), e);
|
||||
resultDomain.fail("获取横幅列表失败: " + e.getMessage());
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
List<TbBanner> list = bannerMapper.selectBanners(filter);
|
||||
resultDomain.success("获取横幅列表成功", list);
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<TbBanner> getBannerById(String bannerID) {
|
||||
public ResultDomain<TbBanner> getBannerPage(PageParam pageParam,TbBanner filter) {
|
||||
ResultDomain<TbBanner> resultDomain = new ResultDomain<>();
|
||||
try {
|
||||
// 参数验证
|
||||
if (!StringUtils.hasText(bannerID)) {
|
||||
resultDomain.fail("横幅ID不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
List<TbBanner> list = bannerMapper.selectBannersPage(filter, pageParam);
|
||||
PageDomain<TbBanner> pageDomain = new PageDomain<>();
|
||||
int total = (int)bannerMapper.countBanners(filter);
|
||||
pageParam.setTotalElements(total);
|
||||
pageParam.setTotalPages( (int)Math.ceil((double)total / pageParam.getPageSize()));
|
||||
pageDomain.setDataList(list);
|
||||
pageDomain.setPageParam(pageParam);
|
||||
|
||||
// 查询横幅
|
||||
TbBanner banner = bannerMapper.selectByBannerId(bannerID);
|
||||
if (banner == null || banner.getDeleted()) {
|
||||
resultDomain.fail("横幅不存在");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
resultDomain.success("获取横幅详情成功", banner);
|
||||
return resultDomain;
|
||||
} catch (Exception e) {
|
||||
logger.error("获取横幅详情异常: {}", e.getMessage(), e);
|
||||
resultDomain.fail("获取横幅详情失败: " + e.getMessage());
|
||||
return resultDomain;
|
||||
}
|
||||
resultDomain.success("获取横幅列表成功", pageDomain);
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,7 +83,7 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
if (banner.getID() == null) {
|
||||
banner.setID(IDUtils.generateID());
|
||||
}
|
||||
|
||||
banner.setBannerID(IDUtils.generateID());
|
||||
banner.setCreateTime(new Date());
|
||||
banner.setUpdateTime(new Date());
|
||||
banner.setDeleted(false);
|
||||
@@ -139,13 +119,13 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
ResultDomain<TbBanner> resultDomain = new ResultDomain<>();
|
||||
try {
|
||||
// 参数验证
|
||||
if (banner == null || !StringUtils.hasText(banner.getID())) {
|
||||
if (banner == null || !StringUtils.hasText(banner.getBannerID())) {
|
||||
resultDomain.fail("横幅ID不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 检查横幅是否存在
|
||||
TbBanner existing = bannerMapper.selectById(banner.getID());
|
||||
TbBanner existing = bannerMapper.selectByBannerId(banner.getBannerID());
|
||||
if (existing == null || existing.getDeleted()) {
|
||||
resultDomain.fail("横幅不存在");
|
||||
return resultDomain;
|
||||
@@ -153,7 +133,7 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
|
||||
// 如果修改了标题,检查标题是否已被使用
|
||||
if (StringUtils.hasText(banner.getTitle()) && !banner.getTitle().equals(existing.getTitle())) {
|
||||
int count = bannerMapper.countByTitle(banner.getTitle(), banner.getID());
|
||||
int count = bannerMapper.countByTitle(banner.getTitle(), banner.getBannerID());
|
||||
if (count > 0) {
|
||||
resultDomain.fail("横幅标题已存在");
|
||||
return resultDomain;
|
||||
@@ -166,9 +146,9 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
// 更新数据库
|
||||
int result = bannerMapper.updateBanner(banner);
|
||||
if (result > 0) {
|
||||
logger.info("更新横幅成功: {}", banner.getID());
|
||||
logger.info("更新横幅成功: {}", banner.getBannerID());
|
||||
// 重新查询返回完整数据
|
||||
TbBanner updated = bannerMapper.selectById(banner.getID());
|
||||
TbBanner updated = bannerMapper.selectByBannerId(banner.getBannerID());
|
||||
resultDomain.success("更新横幅成功", updated);
|
||||
return resultDomain;
|
||||
} else {
|
||||
@@ -247,7 +227,7 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
if (result > 0) {
|
||||
logger.info("更新横幅状态成功: {}", bannerID);
|
||||
// 重新查询返回完整数据
|
||||
TbBanner updated = bannerMapper.selectById(banner.getID());
|
||||
TbBanner updated = bannerMapper.selectByBannerId(banner.getBannerID());
|
||||
resultDomain.success("更新横幅状态成功", updated);
|
||||
return resultDomain;
|
||||
} else {
|
||||
@@ -291,7 +271,7 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
if (result > 0) {
|
||||
logger.info("更新横幅排序成功: {}", bannerID);
|
||||
// 重新查询返回完整数据
|
||||
TbBanner updated = bannerMapper.selectById(banner.getID());
|
||||
TbBanner updated = bannerMapper.selectByBannerId(banner.getBannerID());
|
||||
resultDomain.success("更新横幅排序成功", updated);
|
||||
return resultDomain;
|
||||
} else {
|
||||
@@ -377,4 +357,15 @@ public class NCBannerServiceImpl implements BannerService {
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<TbBanner> selectHomeBanners() {
|
||||
ResultDomain<TbBanner> resultDomain = new ResultDomain<>();
|
||||
TbBanner filter = new TbBanner();
|
||||
filter.setStatus(1);
|
||||
|
||||
List<TbBanner> list = bannerMapper.selectBannersLimit(filter, 5);
|
||||
resultDomain.success("获取首页横幅列表成功", list);
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,11 @@ import org.springframework.util.StringUtils;
|
||||
import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.dto.resource.TbResourceTag;
|
||||
import org.xyzh.common.dto.resource.TbTag;
|
||||
import org.xyzh.common.dto.user.TbSysUser;
|
||||
import org.xyzh.common.utils.IDUtils;
|
||||
import org.xyzh.news.mapper.ResourceTagMapper;
|
||||
import org.xyzh.news.mapper.TagMapper;
|
||||
import org.xyzh.system.utils.LoginUtil;
|
||||
import org.xyzh.api.news.tag.TagService;
|
||||
|
||||
/**
|
||||
@@ -89,39 +91,27 @@ public class NCTagServiceImpl implements TagService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResultDomain<TbTag> updateTag(TbTag tag) {
|
||||
ResultDomain<TbTag> resultDomain = new ResultDomain<>();
|
||||
TbSysUser user = LoginUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
resultDomain.fail("用户未登录");
|
||||
return resultDomain;
|
||||
}
|
||||
try {
|
||||
// 参数验证
|
||||
if (tag == null || !StringUtils.hasText(tag.getID())) {
|
||||
if (tag == null || !StringUtils.hasText(tag.getTagID())) {
|
||||
resultDomain.fail("标签ID不能为空");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 检查标签是否存在
|
||||
TbTag existingTag = tagMapper.selectById(tag.getID());
|
||||
if (existingTag == null || existingTag.getDeleted()) {
|
||||
resultDomain.fail("标签不存在");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 检查标签名称是否重复(排除自身,同类型下)
|
||||
if (StringUtils.hasText(tag.getName())) {
|
||||
Integer tagType = tag.getTagType() != null ? tag.getTagType() : existingTag.getTagType();
|
||||
int count = tagMapper.countByNameAndType(tag.getName(), tagType, tag.getID());
|
||||
if (count > 0) {
|
||||
resultDomain.fail("该类型下标签名称已存在");
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新时间
|
||||
tag.setUpdater(user.getID());
|
||||
tag.setUpdateTime(new Date());
|
||||
|
||||
// 更新数据库
|
||||
int result = tagMapper.updateTag(tag);
|
||||
if (result > 0) {
|
||||
logger.info("更新标签成功: {}", tag.getID());
|
||||
logger.info("更新标签成功: {}", tag.getTagID());
|
||||
// 重新查询返回完整数据
|
||||
TbTag updated = tagMapper.selectById(tag.getID());
|
||||
TbTag updated = tagMapper.selectByTagId(tag.getTagID());
|
||||
resultDomain.success("更新标签成功", updated);
|
||||
return resultDomain;
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<!-- 基础结果映射 -->
|
||||
<resultMap id="BaseResultMap" type="org.xyzh.common.dto.resource.TbBanner">
|
||||
<id column="id" property="id" jdbcType="VARCHAR"/>
|
||||
<result column="banner_id" property="bannerID" jdbcType="VARCHAR"/>
|
||||
<result column="title" property="title" jdbcType="VARCHAR"/>
|
||||
<result column="image_url" property="imageUrl" jdbcType="VARCHAR"/>
|
||||
<result column="link_type" property="linkType" jdbcType="INTEGER"/>
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
<!-- 基础字段 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, title, image_url, link_type, link_id, link_url, order_num, status,
|
||||
id, banner_id, title, image_url, link_type, link_id, link_url, order_num, status,
|
||||
creator, updater, create_time, update_time, delete_time, deleted
|
||||
</sql>
|
||||
|
||||
@@ -30,6 +31,9 @@
|
||||
<sql id="Where_Clause">
|
||||
<where>
|
||||
deleted = 0
|
||||
<if test="bannerID != null and bannerID != ''">
|
||||
AND banner_id = #{bannerID}
|
||||
</if>
|
||||
<if test="title != null and title != ''">
|
||||
AND title LIKE CONCAT('%', #{title}, '%')
|
||||
</if>
|
||||
@@ -44,6 +48,26 @@
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Filter_Clause">
|
||||
<where>
|
||||
deleted = 0
|
||||
<if test="filter.bannerID != null and filter.bannerID != ''">
|
||||
AND banner_id = #{filter.bannerID}
|
||||
</if>
|
||||
<if test="filter.title != null and filter.title != ''">
|
||||
AND title LIKE CONCAT('%', #{filter.title}, '%')
|
||||
</if>
|
||||
<if test="filter.linkType != null">
|
||||
AND link_type = #{filter.linkType}
|
||||
</if>
|
||||
<if test="filter.linkID != null and filter.linkID != ''">
|
||||
AND link_id = #{filter.linkID}
|
||||
</if>
|
||||
<if test="filter.status != null">
|
||||
AND status = #{filter.status}
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!-- selectBanners -->
|
||||
<select id="selectBanners" resultMap="BaseResultMap">
|
||||
@@ -54,12 +78,21 @@
|
||||
ORDER BY order_num ASC, create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectBannersLimit" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM tb_banner
|
||||
<include refid="Filter_Clause"/>
|
||||
ORDER BY order_num ASC, create_time DESC
|
||||
LIMIT #{limit}
|
||||
</select>
|
||||
|
||||
<!-- 根据Banner ID查询Banner信息 -->
|
||||
<select id="selectByBannerId" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List" />
|
||||
FROM tb_banner
|
||||
WHERE id = #{bannerId} AND deleted = 0
|
||||
WHERE banner_id = #{bannerID} AND deleted = 0
|
||||
</select>
|
||||
|
||||
<!-- 根据状态查询Banner列表 -->
|
||||
@@ -95,18 +128,18 @@
|
||||
FROM tb_banner
|
||||
WHERE title = #{title} AND deleted = 0
|
||||
<if test="excludeId != null and excludeId != ''">
|
||||
AND id != #{excludeId}
|
||||
AND banner_id != #{excludeId}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 插入Banner -->
|
||||
<insert id="insertBanner" parameterType="org.xyzh.common.dto.resource.TbBanner">
|
||||
INSERT INTO tb_banner (
|
||||
id, title, image_url, link_type, link_id, link_url, order_num, status,
|
||||
creator, updater, create_time, update_time, delete_time, deleted
|
||||
id, banner_id, title, image_url, link_type, link_id, link_url, order_num, status,
|
||||
creator, create_time
|
||||
) VALUES (
|
||||
#{id}, #{title}, #{imageUrl}, #{linkType}, #{linkID}, #{linkUrl}, #{orderNum}, #{status},
|
||||
#{creator}, #{updater}, #{createTime}, #{updateTime}, #{deleteTime}, #{deleted}
|
||||
#{id}, #{bannerID}, #{title}, #{imageUrl}, #{linkType}, #{linkID}, #{linkUrl}, #{orderNum}, #{status},
|
||||
#{creator}, #{createTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -114,6 +147,9 @@
|
||||
<update id="updateBanner" parameterType="org.xyzh.common.dto.resource.TbBanner">
|
||||
UPDATE tb_banner
|
||||
<set>
|
||||
<if test="bannerID != null and bannerID != ''">
|
||||
banner_id = #{bannerID},
|
||||
</if>
|
||||
<if test="title != null and title != ''">
|
||||
title = #{title},
|
||||
</if>
|
||||
@@ -148,24 +184,24 @@
|
||||
deleted = #{deleted},
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{id}
|
||||
WHERE banner_id = #{bannerID}
|
||||
</update>
|
||||
|
||||
<!-- 删除Banner -->
|
||||
<delete id="deleteBanner" parameterType="org.xyzh.common.dto.resource.TbBanner">
|
||||
DELETE FROM tb_banner
|
||||
WHERE id = #{id}
|
||||
WHERE banner_id = #{bannerID}
|
||||
</delete>
|
||||
|
||||
<!-- 批量插入Banner -->
|
||||
<insert id="batchInsertBanners" parameterType="java.util.List">
|
||||
INSERT INTO tb_banner (
|
||||
id, title, image_url, link_type, link_id, link_url, order_num, status,
|
||||
id, banner_id, title, image_url, link_type, link_id, link_url, order_num, status,
|
||||
creator, updater, create_time, update_time, delete_time, deleted
|
||||
) VALUES
|
||||
<foreach collection="bannerList" item="item" separator=",">
|
||||
(
|
||||
#{item.id}, #{item.title}, #{item.imageUrl}, #{item.linkType}, #{item.linkID},
|
||||
#{item.id}, #{item.bannerID}, #{item.title}, #{item.imageUrl}, #{item.linkType}, #{item.linkID},
|
||||
#{item.linkUrl}, #{item.orderNum}, #{item.status}, #{item.creator}, #{item.updater},
|
||||
#{item.createTime}, #{item.updateTime}, #{item.deleteTime}, #{item.deleted}
|
||||
)
|
||||
@@ -175,9 +211,9 @@
|
||||
<!-- 批量删除Banner -->
|
||||
<delete id="batchDeleteBanners">
|
||||
DELETE FROM tb_banner
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
WHERE banner_id IN
|
||||
<foreach collection="ids" item="bannerID" open="(" separator="," close=")">
|
||||
#{bannerID}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
@@ -186,7 +222,7 @@
|
||||
SELECT
|
||||
<include refid="Base_Column_List" />
|
||||
FROM tb_banner
|
||||
<include refid="Where_Clause" />
|
||||
<include refid="Filter_Clause" />
|
||||
ORDER BY order_num ASC, create_time DESC
|
||||
LIMIT #{pageParam.pageSize} OFFSET #{pageParam.offset}
|
||||
</select>
|
||||
@@ -195,7 +231,7 @@
|
||||
<select id="countBanners" resultType="long">
|
||||
SELECT COUNT(1)
|
||||
FROM tb_banner
|
||||
<include refid="Where_Clause" />
|
||||
<include refid="Filter_Clause" />
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -10,11 +10,11 @@ import org.xyzh.common.core.page.PageRequest;
|
||||
import org.xyzh.common.dto.study.TbCourse;
|
||||
import org.xyzh.common.dto.study.TbCourseChapter;
|
||||
import org.xyzh.common.dto.study.TbCourseNode;
|
||||
import org.xyzh.common.dto.study.TbLearningRecord;
|
||||
import org.xyzh.common.vo.ChapterVO;
|
||||
import org.xyzh.common.vo.CourseVO;
|
||||
import org.xyzh.common.vo.CourseItemVO;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -52,24 +52,30 @@ public class CourseController {
|
||||
* 根据ID获取课程详情
|
||||
*/
|
||||
@GetMapping("/{courseID}")
|
||||
public ResultDomain<CourseVO> getCourseById(@PathVariable("courseID") String courseID) {
|
||||
public ResultDomain<CourseItemVO> getCourseById(@PathVariable("courseID") String courseID) {
|
||||
return courseService.getCourseById(courseID);
|
||||
}
|
||||
|
||||
@GetMapping("/{courseID}/progress")
|
||||
public ResultDomain<CourseItemVO> getCourseProgress(@PathVariable("courseID") String courseID) {
|
||||
return courseService.getCourseProgress(courseID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建课程
|
||||
*/
|
||||
@PostMapping("/course")
|
||||
public ResultDomain<CourseVO> createCourse(@RequestBody CourseVO courseVO) {
|
||||
return courseService.createCourse(courseVO);
|
||||
public ResultDomain<CourseItemVO> createCourse(@RequestBody CourseItemVO courseItemVO) {
|
||||
return courseService.createCourse(courseItemVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新课程基本信息
|
||||
*/
|
||||
@PutMapping("/course")
|
||||
public ResultDomain<CourseVO> updateCourse(@RequestBody CourseVO courseVO) {
|
||||
return courseService.updateCourse(courseVO);
|
||||
public ResultDomain<CourseItemVO> updateCourse(@RequestBody CourseItemVO courseItemVO) {
|
||||
return courseService.updateCourse(courseItemVO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -88,8 +88,8 @@ public class LearningTaskController {
|
||||
* 删除任务
|
||||
*/
|
||||
@DeleteMapping("/task")
|
||||
public ResultDomain<Boolean> deleteTask(@PathVariable("taskID") String taskID) {
|
||||
return learningTaskService.deleteTask(taskID);
|
||||
public ResultDomain<Boolean> deleteTask(@RequestBody TbLearningTask task) {
|
||||
return learningTaskService.deleteTask(task.getTaskID());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.dto.study.TbCourse;
|
||||
import org.xyzh.common.vo.CourseItemVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -181,4 +182,14 @@ public interface CourseMapper extends BaseMapper<TbCourse> {
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
int incrementViewCount(@Param("courseID") String courseID);
|
||||
|
||||
/**
|
||||
* @description 增加课程学习人数
|
||||
* @param courseID 课程ID
|
||||
* @param count 增加人数
|
||||
* @return int 影响行数
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
int incrementLearnCount(@Param("courseID") String courseID, @Param("count") int count);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.dto.study.TbCourseNode;
|
||||
import org.xyzh.common.vo.CourseItemVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -35,6 +36,16 @@ public interface CourseNodeMapper extends BaseMapper<TbCourseNode> {
|
||||
* @since 2025-10-21
|
||||
*/
|
||||
List<TbCourseNode> selectCourseNodesByChapterIDs(@Param("chapterIDs") List<String> chapterIDs);
|
||||
|
||||
/**
|
||||
* @description 查询节点进度
|
||||
* @param chapterIDs 章节ID列表
|
||||
* @param userID 用户ID(可选,传null则不关联学习记录)
|
||||
* @return List<CourseItemVO> 节点进度列表
|
||||
* @author yslg
|
||||
* @since 2025-10-28
|
||||
*/
|
||||
List<CourseItemVO> selectNodesProgress(@Param("chapterIDs") List<String> chapterIDs, @Param("userID") String userID);
|
||||
/**
|
||||
* @description 根据节点ID查询节点信息
|
||||
* @param nodeId 节点ID
|
||||
|
||||
@@ -20,14 +20,10 @@ import org.xyzh.common.core.page.PageRequest;
|
||||
import org.xyzh.common.dto.study.TbCourse;
|
||||
import org.xyzh.common.dto.study.TbCourseChapter;
|
||||
import org.xyzh.common.dto.study.TbCourseNode;
|
||||
import org.xyzh.common.dto.study.TbCourseTag;
|
||||
import org.xyzh.common.dto.study.TbLearningRecord;
|
||||
import org.xyzh.common.dto.user.TbSysUser;
|
||||
import org.xyzh.common.utils.IDUtils;
|
||||
import org.xyzh.common.vo.ChapterVO;
|
||||
import org.xyzh.common.vo.CourseVO;
|
||||
import org.xyzh.common.vo.CourseItemVO;
|
||||
import org.xyzh.study.mapper.CourseMapper;
|
||||
import org.xyzh.study.mapper.CourseTagMapper;
|
||||
import org.xyzh.study.mapper.CourseChapterMapper;
|
||||
import org.xyzh.study.mapper.CourseNodeMapper;
|
||||
import org.xyzh.study.service.SCCourseService;
|
||||
@@ -51,9 +47,6 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
@Autowired
|
||||
private CourseChapterMapper courseChapterMapper;
|
||||
|
||||
@Autowired
|
||||
private CourseTagMapper courseTagMapper;
|
||||
|
||||
@Autowired
|
||||
private CourseNodeMapper courseNodeMapper;
|
||||
|
||||
@@ -81,108 +74,133 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<CourseVO> getCourseById(String courseID) {
|
||||
ResultDomain<CourseVO> resultDomain = new ResultDomain<>();
|
||||
public ResultDomain<CourseItemVO> getCourseById(String courseID) {
|
||||
ResultDomain<CourseItemVO> resultDomain = new ResultDomain<>();
|
||||
// 查询课程
|
||||
TbCourse course = courseMapper.selectByCourseId(courseID);
|
||||
// 查询标签
|
||||
List<TbCourseTag> tags = courseTagMapper.selectByCourseId(courseID);
|
||||
CourseVO courseVO = new CourseVO();
|
||||
courseVO.setCourse(course);
|
||||
courseVO.setCourseTags(tags);
|
||||
if (course == null) {
|
||||
resultDomain.fail("课程不存在");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 从课程实体创建CourseItemVO
|
||||
CourseItemVO courseItemVO = CourseItemVO.fromCourse(course);
|
||||
|
||||
// 查询课程章节
|
||||
TbCourseChapter filter = new TbCourseChapter();
|
||||
filter.setCourseID(courseID);
|
||||
List<TbCourseChapter> chapters = courseChapterMapper.selectCourseChapters(filter);
|
||||
// 查询子节点
|
||||
if (chapters.size() > 0) {
|
||||
List<String> chapterIDs = chapters.stream().map(TbCourseChapter::getChapterID).collect(Collectors.toList());
|
||||
|
||||
// 查询并构建章节及节点结构
|
||||
if (!chapters.isEmpty()) {
|
||||
List<String> chapterIDs = chapters.stream()
|
||||
.map(TbCourseChapter::getChapterID)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 查询所有节点
|
||||
List<TbCourseNode> nodes = courseNodeMapper.selectCourseNodesByChapterIDs(chapterIDs);
|
||||
Map<String, List<TbCourseNode>> nodesMap = nodes.stream().collect(Collectors.groupingBy(TbCourseNode::getChapterID));
|
||||
List<ChapterVO> chapterVOs = chapters.stream().map(chapter -> {
|
||||
ChapterVO chapterVO = new ChapterVO();
|
||||
chapterVO.setChapter(chapter);
|
||||
chapterVO.setNodes(nodesMap.get(chapter.getChapterID()));
|
||||
return chapterVO;
|
||||
}).collect(Collectors.toList());
|
||||
courseVO.setCourseChapters(chapterVOs);
|
||||
|
||||
// 转换章节为CourseItemVO列表
|
||||
List<CourseItemVO> chapterVOs = chapters.stream()
|
||||
.map(CourseItemVO::fromChapter)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 转换节点为CourseItemVO,并按章节ID分组
|
||||
Map<String, List<CourseItemVO>> nodesMap = nodes.stream()
|
||||
.map(CourseItemVO::fromNode)
|
||||
.collect(Collectors.groupingBy(CourseItemVO::getChapterID));
|
||||
|
||||
// 设置章节列表和章节节点映射
|
||||
courseItemVO.setChapters(chapterVOs);
|
||||
courseItemVO.setChapterNodes(nodesMap);
|
||||
}
|
||||
|
||||
resultDomain.success("获取课程详情成功", courseVO);
|
||||
resultDomain.success("获取课程详情成功", courseItemVO);
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<CourseVO> createCourse(CourseVO courseVO) {
|
||||
ResultDomain<CourseVO> resultDomain = new ResultDomain<>();
|
||||
public ResultDomain<CourseItemVO> createCourse(CourseItemVO courseItemVO) {
|
||||
ResultDomain<CourseItemVO> resultDomain = new ResultDomain<>();
|
||||
TbSysUser user = LoginUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
resultDomain.fail("请先登录");
|
||||
return resultDomain;
|
||||
}
|
||||
TbCourse course = courseVO.getCourse();
|
||||
|
||||
// 转换为课程实体并保存
|
||||
TbCourse course = courseItemVO.toCourse();
|
||||
String courseID = IDUtils.generateID();
|
||||
course.setID(IDUtils.generateID());
|
||||
course.setCreator(user.getID());
|
||||
course.setCourseID(courseID);
|
||||
Date now = new Date();
|
||||
course.setCreateTime(now);
|
||||
course.setStatus(0);
|
||||
|
||||
|
||||
if (course.getStatus() == null) {
|
||||
course.setStatus(0);
|
||||
}
|
||||
courseMapper.insertCourse(course);
|
||||
courseItemVO.setCourseID(courseID);
|
||||
|
||||
List<ChapterVO> courseChapters = courseVO.getCourseChapters();
|
||||
List<TbCourseChapter> chapters = new ArrayList<>();
|
||||
List<TbCourseNode> nodes = new ArrayList<>();
|
||||
int length = courseChapters.size();
|
||||
for (int i=0; i<length; i++) {
|
||||
ChapterVO chapterVO = courseChapters.get(i);
|
||||
TbCourseChapter chapter = chapterVO.getChapter();
|
||||
List<TbCourseNode> nodesList = chapterVO.getNodes();
|
||||
// 处理章节和节点
|
||||
List<CourseItemVO> chapterVOs = courseItemVO.getChapters();
|
||||
if (chapterVOs != null && !chapterVOs.isEmpty()) {
|
||||
List<TbCourseChapter> chapters = new ArrayList<>();
|
||||
List<TbCourseNode> allNodes = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < chapterVOs.size(); i++) {
|
||||
CourseItemVO chapterVO = chapterVOs.get(i);
|
||||
TbCourseChapter chapter = chapterVO.toChapter();
|
||||
|
||||
String chapterID = IDUtils.generateID();
|
||||
chapter.setID(IDUtils.generateID());
|
||||
chapter.setChapterID(chapterID);
|
||||
chapter.setCourseID(courseID);
|
||||
chapter.setCreator(user.getID());
|
||||
chapter.setCreateTime(now);
|
||||
chapter.setOrderNum(i);
|
||||
chapters.add(chapter);
|
||||
|
||||
// 更新chapterVO中的ID
|
||||
chapterVO.setChapterID(chapterID);
|
||||
|
||||
chapter.setCourseID(courseID);
|
||||
String chapterID = IDUtils.generateID();
|
||||
chapter.setID(IDUtils.generateID());
|
||||
chapter.setChapterID(chapterID);
|
||||
chapter.setCreator(user.getID());
|
||||
chapter.setCreateTime(now);
|
||||
chapter.setOrderNum(i);
|
||||
chapters.add(chapter);
|
||||
|
||||
for (int j=0; j<nodesList.size(); j++) {
|
||||
TbCourseNode node = nodesList.get(j);
|
||||
node.setNodeID(IDUtils.generateID());
|
||||
node.setChapterID(chapterID);
|
||||
node.setCreator(user.getID());
|
||||
node.setCreateTime(now);
|
||||
nodes.add(node);
|
||||
// 处理该章节的节点
|
||||
List<CourseItemVO> nodeVOs = chapterVO.getChapters(); // 节点存储在chapters字段中
|
||||
if (nodeVOs != null && !nodeVOs.isEmpty()) {
|
||||
for (int j = 0; j < nodeVOs.size(); j++) {
|
||||
CourseItemVO nodeVO = nodeVOs.get(j);
|
||||
TbCourseNode node = nodeVO.toNode();
|
||||
|
||||
String nodeID = IDUtils.generateID();
|
||||
node.setID(IDUtils.generateID());
|
||||
node.setNodeID(nodeID);
|
||||
node.setChapterID(chapterID);
|
||||
node.setCreator(user.getID());
|
||||
node.setCreateTime(now);
|
||||
node.setOrderNum(j);
|
||||
allNodes.add(node);
|
||||
|
||||
// 更新nodeVO中的ID
|
||||
nodeVO.setNodeID(nodeID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!chapters.isEmpty()) {
|
||||
courseChapterMapper.batchInsertCourseChapters(chapters);
|
||||
}
|
||||
if (!allNodes.isEmpty()) {
|
||||
courseNodeMapper.batchInsertCourseNodes(allNodes);
|
||||
}
|
||||
}
|
||||
courseChapterMapper.batchInsertCourseChapters(chapters);
|
||||
courseNodeMapper.batchInsertCourseNodes(nodes);
|
||||
|
||||
List<TbCourseTag> courseTags = courseVO.getCourseTags();
|
||||
length = courseTags.size();
|
||||
if (length > 0) {
|
||||
for (int i=0; i<length; i++) {
|
||||
TbCourseTag tag = courseTags.get(i);
|
||||
tag.setCourseID(courseID);
|
||||
tag.setTagID(IDUtils.generateID());
|
||||
tag.setCreator(user.getID());
|
||||
tag.setCreateTime(now);
|
||||
}
|
||||
courseTagMapper.batchInsertCourseTags(courseTags);
|
||||
}
|
||||
|
||||
|
||||
resultDomain.success("创建课程成功",courseVO);
|
||||
resultDomain.success("创建课程成功", courseItemVO);
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<CourseVO> updateCourse(CourseVO courseVO) {
|
||||
ResultDomain<CourseVO> resultDomain = new ResultDomain<>();
|
||||
public ResultDomain<CourseItemVO> updateCourse(CourseItemVO courseItemVO) {
|
||||
ResultDomain<CourseItemVO> resultDomain = new ResultDomain<>();
|
||||
|
||||
TbSysUser user = LoginUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
@@ -190,8 +208,7 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
TbCourse course = courseVO.getCourse();
|
||||
String courseID = course.getCourseID();
|
||||
String courseID = courseItemVO.getCourseID();
|
||||
|
||||
if (courseID == null || courseID.isEmpty()) {
|
||||
resultDomain.fail("课程ID不能为空");
|
||||
@@ -199,12 +216,14 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
}
|
||||
|
||||
// 1. 更新课程基本信息
|
||||
TbCourse course = courseItemVO.toCourse();
|
||||
course.setUpdater(user.getID());
|
||||
course.setUpdateTime(new Date());
|
||||
Date now = new Date();
|
||||
course.setUpdateTime(now);
|
||||
courseMapper.updateCourse(course);
|
||||
|
||||
// 2. 处理章节和节点
|
||||
List<ChapterVO> newChapterVOs = courseVO.getCourseChapters();
|
||||
List<CourseItemVO> newChapterVOs = courseItemVO.getChapters();
|
||||
if (newChapterVOs == null) {
|
||||
newChapterVOs = new ArrayList<>();
|
||||
}
|
||||
@@ -235,12 +254,11 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
List<TbCourseNode> nodesToUpdate = new ArrayList<>();
|
||||
|
||||
Set<String> newChapterIDs = new HashSet<>();
|
||||
Date now = new Date();
|
||||
|
||||
// 遍历新的章节
|
||||
for (int i = 0; i < newChapterVOs.size(); i++) {
|
||||
ChapterVO chapterVO = newChapterVOs.get(i);
|
||||
TbCourseChapter chapter = chapterVO.getChapter();
|
||||
CourseItemVO chapterVO = newChapterVOs.get(i);
|
||||
TbCourseChapter chapter = chapterVO.toChapter();
|
||||
String chapterID = chapter.getChapterID();
|
||||
|
||||
chapter.setCourseID(courseID);
|
||||
@@ -266,9 +284,9 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
newChapterIDs.add(chapterID);
|
||||
|
||||
// 处理该章节的节点
|
||||
List<TbCourseNode> newNodes = chapterVO.getNodes();
|
||||
if (newNodes == null) {
|
||||
newNodes = new ArrayList<>();
|
||||
List<CourseItemVO> newNodeVOs = chapterVO.getChapters(); // 节点存储在chapters字段中
|
||||
if (newNodeVOs == null) {
|
||||
newNodeVOs = new ArrayList<>();
|
||||
}
|
||||
|
||||
List<TbCourseNode> existingNodesForChapter = existingNodesMap.getOrDefault(chapterID, new ArrayList<>());
|
||||
@@ -278,8 +296,9 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
Set<String> newNodeIDs = new HashSet<>();
|
||||
|
||||
// 遍历新的节点
|
||||
for (int j = 0; j < newNodes.size(); j++) {
|
||||
TbCourseNode node = newNodes.get(j);
|
||||
for (int j = 0; j < newNodeVOs.size(); j++) {
|
||||
CourseItemVO nodeVO = newNodeVOs.get(j);
|
||||
TbCourseNode node = nodeVO.toNode();
|
||||
String nodeID = node.getNodeID();
|
||||
|
||||
node.setChapterID(chapterID);
|
||||
@@ -349,50 +368,7 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 处理标签
|
||||
List<TbCourseTag> newTags = courseVO.getCourseTags();
|
||||
if (newTags == null) {
|
||||
newTags = new ArrayList<>();
|
||||
}
|
||||
|
||||
// 获取现有标签
|
||||
List<TbCourseTag> existingTags = courseTagMapper.selectByCourseId(courseID);
|
||||
Map<String, TbCourseTag> existingTagMap = existingTags.stream()
|
||||
.collect(Collectors.toMap(TbCourseTag::getTagID, tag -> tag));
|
||||
|
||||
Set<String> newTagIDs = new HashSet<>();
|
||||
List<TbCourseTag> tagsToInsert = new ArrayList<>();
|
||||
|
||||
// 处理新标签
|
||||
for (TbCourseTag tag : newTags) {
|
||||
String tagID = tag.getTagID();
|
||||
|
||||
if (tagID == null || tagID.isEmpty() || !existingTagMap.containsKey(tagID)) {
|
||||
// 新增标签
|
||||
tag.setID(IDUtils.generateID());
|
||||
tag.setCourseID(courseID);
|
||||
tag.setCreator(user.getID());
|
||||
tag.setCreateTime(now);
|
||||
tagsToInsert.add(tag);
|
||||
} else {
|
||||
newTagIDs.add(tagID);
|
||||
}
|
||||
}
|
||||
|
||||
// 找出要删除的标签
|
||||
List<String> tagIDsToDelete = existingTagMap.keySet().stream()
|
||||
.filter(id -> !newTagIDs.contains(id))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!tagIDsToDelete.isEmpty()) {
|
||||
courseTagMapper.batchDeleteCourseTags(tagIDsToDelete);
|
||||
}
|
||||
|
||||
if (!tagsToInsert.isEmpty()) {
|
||||
courseTagMapper.batchInsertCourseTags(tagsToInsert);
|
||||
}
|
||||
|
||||
resultDomain.success("更新课程成功", courseVO);
|
||||
resultDomain.success("更新课程成功", courseItemVO);
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
@@ -544,4 +520,57 @@ public class SCCourseServiceImpl implements SCCourseService {
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultDomain<CourseItemVO> getCourseProgress(String courseID) {
|
||||
ResultDomain<CourseItemVO> resultDomain = new ResultDomain<>();
|
||||
|
||||
// 获取当前用户
|
||||
TbSysUser user = LoginUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
resultDomain.fail("用户未登录");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 查询课程
|
||||
TbCourse course = courseMapper.selectByCourseId(courseID);
|
||||
if (course == null) {
|
||||
resultDomain.fail("课程不存在");
|
||||
return resultDomain;
|
||||
}
|
||||
|
||||
// 从课程实体创建CourseItemVO
|
||||
CourseItemVO courseItemVO = CourseItemVO.fromCourse(course);
|
||||
|
||||
// 查询课程章节
|
||||
TbCourseChapter filter = new TbCourseChapter();
|
||||
filter.setCourseID(courseID);
|
||||
List<TbCourseChapter> chapters = courseChapterMapper.selectCourseChapters(filter);
|
||||
|
||||
// 查询并构建章节及节点结构(带进度)
|
||||
if (!chapters.isEmpty()) {
|
||||
List<String> chapterIDs = chapters.stream()
|
||||
.map(TbCourseChapter::getChapterID)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 查询带进度的节点(传入用户ID)
|
||||
List<CourseItemVO> nodesWithProgress = courseNodeMapper.selectNodesProgress(chapterIDs, user.getID());
|
||||
|
||||
// 转换章节为CourseItemVO列表
|
||||
List<CourseItemVO> chapterVOs = chapters.stream()
|
||||
.map(CourseItemVO::fromChapter)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 按章节ID分组节点
|
||||
Map<String, List<CourseItemVO>> nodesMap = nodesWithProgress.stream()
|
||||
.collect(Collectors.groupingBy(CourseItemVO::getChapterID));
|
||||
|
||||
// 设置章节列表和章节节点映射
|
||||
courseItemVO.setChapters(chapterVOs);
|
||||
courseItemVO.setChapterNodes(nodesMap);
|
||||
}
|
||||
|
||||
resultDomain.success("获取课程进度成功", courseItemVO);
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.xyzh.common.vo.TaskItemVO;
|
||||
import org.xyzh.common.vo.TaskVO;
|
||||
import org.xyzh.study.mapper.LearningTaskMapper;
|
||||
import org.xyzh.study.mapper.TaskUserMapper;
|
||||
import org.xyzh.study.mapper.CourseMapper;
|
||||
import org.xyzh.system.utils.LoginUtil;
|
||||
import org.xyzh.study.mapper.TaskItemMapper;
|
||||
import org.xyzh.api.study.task.LearningTaskService;
|
||||
@@ -48,6 +49,9 @@ public class SCLearningTaskServiceImpl implements LearningTaskService {
|
||||
@Autowired
|
||||
private TaskUserMapper taskUserMapper;
|
||||
|
||||
@Autowired
|
||||
private CourseMapper courseMapper;
|
||||
|
||||
@Autowired
|
||||
private TaskItemMapper taskItemMapper;
|
||||
|
||||
@@ -82,7 +86,8 @@ public class SCLearningTaskServiceImpl implements LearningTaskService {
|
||||
taskUsers.add(taskUser);
|
||||
}
|
||||
int result = taskUserMapper.batchInsertTaskUsers(taskUsers);
|
||||
if (result > 0) {
|
||||
int learnCount = courseMapper.incrementLearnCount(taskID, userIDs.size());
|
||||
if (result > 0 && learnCount > 0) {
|
||||
resultDomain.success("添加任务用户成功", taskUsers);
|
||||
return resultDomain;
|
||||
} else {
|
||||
@@ -181,6 +186,10 @@ public class SCLearningTaskServiceImpl implements LearningTaskService {
|
||||
item.setCreateTime(now);
|
||||
});
|
||||
taskUserMapper.batchInsertTaskUsers(taskUsers);
|
||||
for(TbTaskItem item : taskCourses) {
|
||||
int learnCount = courseMapper.incrementLearnCount(item.getItemID(), taskUsers.size());
|
||||
|
||||
}
|
||||
|
||||
resultDomain.success("创建任务成功", taskVO);
|
||||
return resultDomain;
|
||||
@@ -349,6 +358,7 @@ public class SCLearningTaskServiceImpl implements LearningTaskService {
|
||||
|
||||
if (!usersToInsert.isEmpty()) {
|
||||
taskUserMapper.batchInsertTaskUsers(usersToInsert);
|
||||
int learnCount = courseMapper.incrementLearnCount(taskID, usersToInsert.size());
|
||||
}
|
||||
|
||||
resultDomain.success("更新任务成功", taskVO);
|
||||
@@ -357,8 +367,17 @@ public class SCLearningTaskServiceImpl implements LearningTaskService {
|
||||
|
||||
@Override
|
||||
public ResultDomain<Boolean> deleteTask(String taskID) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
ResultDomain<Boolean> resultDomain = new ResultDomain<>();
|
||||
TbLearningTask filter = new TbLearningTask();
|
||||
filter.setTaskID(taskID);
|
||||
int result = learningTaskMapper.deleteLearningTask(filter);
|
||||
if (result > 0) {
|
||||
resultDomain.success("删除任务成功", true);
|
||||
return resultDomain;
|
||||
} else {
|
||||
resultDomain.fail("删除任务失败");
|
||||
return resultDomain;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
teacher, status, view_count, learn_count, order_num, creator, create_time
|
||||
) VALUES (
|
||||
#{id}, #{courseID}, #{name}, #{coverImage}, #{description}, #{content}, #{duration},
|
||||
#{teacher}, #{status}, #{viewCount}, #{learnCount}, #{orderNum}, #{creator},#{createTime}
|
||||
#{teacher}, #{status}, 0, 0, #{orderNum}, #{creator},#{createTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -248,15 +248,14 @@
|
||||
<insert id="batchInsertCourses" parameterType="java.util.List">
|
||||
INSERT INTO tb_course (
|
||||
id, course_id, name, cover_image, description, content, duration,
|
||||
teacher, status, view_count, learn_count, order_num, creator, updater,
|
||||
create_time, update_time, delete_time, deleted
|
||||
teacher, status, view_count, learn_count, order_num, creator,
|
||||
create_time, delete_time, deleted
|
||||
) VALUES
|
||||
<foreach collection="courseList" item="item" separator=",">
|
||||
(
|
||||
#{item.id}, #{item.courseID}, #{item.name}, #{item.coverImage}, #{item.description},
|
||||
#{item.content}, #{item.duration}, #{item.teacher}, #{item.status}, #{item.viewCount},
|
||||
#{item.learnCount}, #{item.orderNum}, #{item.creator}, #{item.updater},
|
||||
#{item.createTime}, #{item.updateTime}, #{item.deleteTime}, #{item.deleted}
|
||||
#{item.content}, #{item.duration}, #{item.teacher}, #{item.status}, 0,
|
||||
0, #{item.orderNum}, #{item.creator}, #{item.createTime}, #{item.deleteTime}, #{item.deleted}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
@@ -292,4 +291,14 @@
|
||||
SET view_count = view_count + 1
|
||||
WHERE course_id = #{courseID} AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- incrementLearnCount -->
|
||||
|
||||
<update id="incrementLearnCount">
|
||||
UPDATE tb_course
|
||||
SET learn_count = learn_count + #{count}
|
||||
WHERE course_id = #{courseID} AND deleted = 0
|
||||
</update>
|
||||
|
||||
|
||||
</mapper>
|
||||
@@ -23,6 +23,27 @@
|
||||
<result column="deleted" property="deleted" jdbcType="BOOLEAN"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="CourseItemResultMap" type="org.xyzh.common.vo.CourseItemVO">
|
||||
<id column="id" property="id" jdbcType="VARCHAR"/>
|
||||
<result column="node_id" property="nodeID" jdbcType="VARCHAR"/>
|
||||
<result column="chapter_id" property="chapterID" jdbcType="VARCHAR"/>
|
||||
<result column="name" property="name" jdbcType="VARCHAR"/>
|
||||
<result column="content" property="content" jdbcType="LONGVARCHAR"/>
|
||||
<result column="node_type" property="nodeType" jdbcType="INTEGER"/>
|
||||
<result column="resource_id" property="resourceID" jdbcType="VARCHAR"/>
|
||||
<result column="video_url" property="videoUrl" jdbcType="VARCHAR"/>
|
||||
<result column="duration" property="duration" jdbcType="INTEGER"/>
|
||||
<result column="order_num" property="orderNum" jdbcType="INTEGER"/>
|
||||
<result column="is_required" property="isRequired" jdbcType="INTEGER"/>
|
||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<!-- 学习记录相关字段 -->
|
||||
<result column="progress" property="progress" jdbcType="DECIMAL"/>
|
||||
<result column="is_complete" property="isComplete" jdbcType="BOOLEAN"/>
|
||||
<result column="learning_duration" property="learningDuration" jdbcType="INTEGER"/>
|
||||
<result column="last_learn_time" property="lastLearnTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="complete_time" property="completeTime" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 基础字段 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, node_id, chapter_id, name, content, node_type, resource_id, video_url, duration, order_num, is_required,
|
||||
@@ -236,4 +257,41 @@
|
||||
AND deleted = 0
|
||||
ORDER BY order_num ASC, create_time ASC
|
||||
</select>
|
||||
<!-- selectNodesProgress -->
|
||||
|
||||
<select id="selectNodesProgress" resultMap="CourseItemResultMap">
|
||||
SELECT
|
||||
tcn.id,
|
||||
tcn.node_id,
|
||||
tcn.chapter_id,
|
||||
tcn.`name`,
|
||||
tcn.content,
|
||||
tcn.node_type,
|
||||
tcn.resource_id,
|
||||
tcn.video_url,
|
||||
tcn.duration,
|
||||
tcn.order_num,
|
||||
tcn.is_required,
|
||||
tcn.create_time,
|
||||
tlr.duration as learning_duration,
|
||||
tlr.progress,
|
||||
tlr.is_complete,
|
||||
tlr.last_learn_time,
|
||||
tlr.complete_time
|
||||
FROM
|
||||
tb_course_node tcn
|
||||
LEFT JOIN tb_learning_record tlr ON tcn.node_id = tlr.node_id
|
||||
<if test="userID != null and userID != ''">
|
||||
AND tlr.user_id = #{userID}
|
||||
</if>
|
||||
WHERE
|
||||
tcn.chapter_id IN
|
||||
<foreach collection="chapterIDs" item="chapterID" open="(" separator="," close=")">
|
||||
#{chapterID}
|
||||
</foreach>
|
||||
AND tcn.deleted = 0
|
||||
ORDER BY
|
||||
tcn.order_num ASC,
|
||||
tcn.create_time ASC
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
@@ -125,11 +125,9 @@
|
||||
<!-- 插入学习记录 -->
|
||||
<insert id="insertLearningRecord" parameterType="org.xyzh.common.dto.study.TbLearningRecord">
|
||||
INSERT INTO tb_learning_record (
|
||||
id, user_id, task_id, resource_type, resource_id, course_id, chapter_id, node_id, duration, progress,
|
||||
is_complete, complete_time, last_learn_time, create_time
|
||||
id, user_id, task_id, resource_type, resource_id, course_id, chapter_id, node_id, create_time
|
||||
) VALUES (
|
||||
#{id}, #{userID}, #{taskID}, #{resourceType}, #{resourceID}, #{courseID}, #{chapterID}, #{nodeID}, #{duration}, #{progress},
|
||||
#{isComplete}, #{completeTime}, #{lastLearnTime}, #{createTime}
|
||||
#{id}, #{userID}, #{taskID}, #{resourceType}, #{resourceID}, #{courseID}, #{chapterID}, #{nodeID}, #{createTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -171,14 +169,11 @@
|
||||
<!-- 批量插入学习记录 -->
|
||||
<insert id="batchInsertLearningRecords" parameterType="java.util.List">
|
||||
INSERT INTO tb_learning_record (
|
||||
id, user_id, resource_type, resource_id, task_id, duration, progress,
|
||||
is_complete, complete_time, last_learn_time, create_time, update_time
|
||||
id, user_id, resource_type, resource_id, task_id, course_id, chapter_id, node_id, create_time
|
||||
) VALUES
|
||||
<foreach collection="learningRecordList" item="item" separator=",">
|
||||
(
|
||||
#{item.id}, #{item.userID}, #{item.resourceType}, #{item.resourceID}, #{item.taskID},
|
||||
#{item.duration}, #{item.progress}, #{item.isComplete}, #{item.completeTime},
|
||||
#{item.lastLearnTime}, #{item.createTime}, #{item.updateTime}
|
||||
#{item.id}, #{item.userID}, #{item.resourceType}, #{item.resourceID}, #{item.taskID}, #{item.courseID}, #{item.chapterID}, #{item.nodeID}, #{item.createTime}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
@@ -152,9 +152,9 @@
|
||||
<!-- 插入任务用户关联 -->
|
||||
<insert id="insertTaskUser" parameterType="org.xyzh.common.dto.study.TbTaskUser">
|
||||
INSERT INTO tb_task_user (
|
||||
id, task_id, user_id, dept_id,creator, create_time
|
||||
id, task_id, user_id, dept_id,creator, status, progress, create_time
|
||||
) VALUES (
|
||||
#{id}, #{taskID}, #{userID}, #{deptID}, #{creator}, #{createTime}
|
||||
#{id}, #{taskID}, #{userID}, #{deptID}, #{creator}, 0, 0, #{createTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -193,8 +193,8 @@
|
||||
) VALUES
|
||||
<foreach collection="taskUserList" item="item" separator=",">
|
||||
(
|
||||
#{item.id}, #{item.taskID}, #{item.userID}, #{item.deptID}, #{item.status},
|
||||
#{item.progress}, #{item.completeTime}, #{item.creator}, #{item.createTime}
|
||||
#{item.id}, #{item.taskID}, #{item.userID}, #{item.deptID}, 0,
|
||||
0, #{item.completeTime}, #{item.creator}, #{item.createTime}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
Reference in New Issue
Block a user