目录
部分
首先是课程信息
我们课程信息在前端展示的数据肯定不能是数据库中的课程表那些数据,应该是=课程表+描述表
添加课程
1.需要展示的课程实体类
- package com.guli.edu.form;
-
- @ApiModel(value = "课程基本信息", description = "编辑课程基本信息的表单对象")
- @Data
- public class CourseInfoForm implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @ApiModelProperty(value = "课程ID")
- private String id;
-
- @ApiModelProperty(value = "课程讲师ID")
- private String teacherId;
-
- @ApiModelProperty(value = "课程专业ID")
- private String subjectId;
-
- @ApiModelProperty(value = "课程标题")
- private String title;
-
- @ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")
- private BigDecimal price;
-
- @ApiModelProperty(value = "总课时")
- private Integer lessonNum;
-
- @ApiModelProperty(value = "课程封面图片路径")
- private String cover;
-
- @ApiModelProperty(value = "课程简介")
- private String description;
- }
2.控制层
成功返回课程id
- package com.guli.edu.controller.admin;
-
- @Api(description="课程管理")
- @CrossOrigin //跨域
- @RestController
- @RequestMapping("/admin/edu/course")
- public class CourseAdminController {
-
- @Autowired
- private CourseService courseService;
-
- @ApiOperation(value = "新增课程")
- @PostMapping("save-course-info")
- public R saveCourseInfo(
- @ApiParam(name = "CourseInfoForm", value = "课程基本信息", required = true)
- @RequestBody CourseInfoForm courseInfoForm){
-
- String courseId = courseService.saveCourseInfo(courseInfoForm);
- if(!StringUtils.isEmpty(courseId)){
- return R.ok().data("courseId", courseId);
- }else{
- return R.error().message("保存失败");
- }
- }
- }
3.业务层
思路:1.将我们传入的课程类转为课程表educourse,然后进行插入——>2.插入后,得到对应课程的id——>3.因为我们描述表和课程表是一对一关系,new一个描述类,从传入的课程类取出描述信息封装到对应描述表中,并且给这个描述传入id保证一对一关系
- /**
- * 1.添加课程基本信息
- * @param courseInfoVo
- */
- @Override
- public String saveCourseInfo(CourseInfoVo courseInfoVo) {
-
- /**
- * 1.向课程表添加课程基本信息
- * 将CourseInfoVo对象转为EduCourse,然后插入
- */
- EduCourse eduCourse = new EduCourse();
- BeanUtils.copyProperties(courseInfoVo,eduCourse);
- int insert = baseMapper.insert(eduCourse);
-
- if(insert==0){
- throw new GuliException(20001,"添加课程信息失败");
- }
- //获取添加后的课程id
- String cid = eduCourse.getId();
-
- /**
- * 2.向课程描述表中添加课程简介
- */
- EduCourseDescription courseDescription = new EduCourseDescription();
- courseDescription.setDescription(courseInfoVo.getDescription());
-
- //设置的描述id就是==我们的课程id,来保证我们的描述信息与课程是一对一的关系
- courseDescription.setId(cid);
- courseDescriptionService.save(courseDescription);
-
- //返回课程id
- return cid;
- }
获取课程信息
思路:和上面一样 ,通过id得到课程表信息后,因为我们展示的字段有限,所以是一个新的类(只是说结合了课程表和描述表)——>2.然后再利用BeanUtils直接将课程信息copy到这个类上——>3.因为描述表和课程表是一对一关系,所以也类似,直接查询对应描述信息,然后封装即可
- /**
- * 2.根据courseId获取课程信息
- * 需要查两张表,一张课程表一张描述表,然后总结一起返回
- * @param courseId
- * @return
- */
- @Override
- public CourseInfoVo getCourseInfo(String courseId) {
- //1.查询课程表
- EduCourse eduCourse = baseMapper.selectById(courseId);
- CourseInfoVo courseInfoVo = new CourseInfoVo();
- BeanUtils.copyProperties(eduCourse,courseInfoVo);
-
- //2.查询描述表
- EduCourseDescription courseDescription = courseDescriptionService.getById(courseId);
- courseInfoVo.setDescription(courseDescription.getDescription());
-
- return courseInfoVo;
- }
多字段条件分页
思路:wrapper根据字段是否为空然后决定是否封装这些字段——>2.然后baseMapper调用selectPage进行查询,封装wrapper和Page得到分页信息——>3.然后将分页信息封装到map中返回
- /**
- * 6.条件查询分页
- * @param coursePage
- * @param courseFrontVo
- * @return
- */
- @Override
- public Map
getCourseFrontList(Page coursePage, CourseFrontVo courseFrontVo) { -
- QueryWrapper
wrapper = new QueryWrapper<>(); - //1.根据条件判断查询内容
- if(!StringUtils.isEmpty(courseFrontVo.getSubjectParentId())){
- wrapper.eq("subject_parent_id",courseFrontVo.getSubjectParentId());
- }
- if(!StringUtils.isEmpty(courseFrontVo.getSubjectId())){
- wrapper.eq("subject_id",courseFrontVo.getSubjectId());
- }
- if(!StringUtils.isEmpty(courseFrontVo.getBuyCountSort())){//销量
- wrapper.orderByDesc("buy_count");
- }
- if(!StringUtils.isEmpty(courseFrontVo.getGmtCreateSort())){//时间最新
- wrapper.orderByDesc("gmt_create");
- }
- if(!StringUtils.isEmpty(courseFrontVo.getPriceSort())){//价格
- wrapper.orderByDesc("price");
- }
- //2.调用mybatisplus的api分页查询
- baseMapper.selectPage(coursePage,wrapper);
-
- //3.得到查询的数据,封装到map中
- List
records = coursePage.getRecords(); - long current = coursePage.getCurrent();
- long pages = coursePage.getPages();
- long size = coursePage.getSize();
- long total = coursePage.getTotal();
- boolean hasNext = coursePage.hasNext();
- boolean hasPrevious = coursePage.hasPrevious();
-
- Map
map = new HashMap(); - map.put("items", records);
- map.put("current", current);
- map.put("pages", pages);
- map.put("size", size);
- map.put("total", total);
- map.put("hasNext", hasNext);
- map.put("hasPrevious", hasPrevious);
-
- return map;
- }
课程列表
按照时间排序
- /**
- * 6.课程列表
- */
- @GetMapping
- public R etCourseList(){
- List
list = courseService.list(null); - list.stream().sorted(Comparator.comparing(EduCourse::getGmtCreate));
- return R.ok().data("list",list);
- }
删除课程
思路:1.首先明确删除课程需要连着章节小节,描述一起删除——>2.删除课程后,然后通过courseId删除小节——>3.并且删除章节和描述信息和课程本身
- /**
- * 5.根据课程id删除课程
- * 先删除小节,再删除章节,如果章节中含有小节就不能删除上章节
- * @param courseId
- */
- @Override
- public void removeCourse(String courseId) {
- //1.根据课程id删除小节
- eduVideoService.removeVideoByCourseId(courseId);
-
- //2.删除章节
- eduChapterService.removeChapterByCourseId(courseId);
-
- //3.删除描述信息,这里课程id与描述信息表的id是一样的,保证了一对一关系
- courseDescriptionService.removeById(courseId);
-
- //4.删除课程本身
- int res = baseMapper.deleteById(courseId);
- if(res==0){
- throw new GuliException(20001,"删除失败");
- }
- }
删除小节
思路:1.通过courseId从小节表中进行查询,指定select字段video_source_id,目的是删除视频——>2.然后因为查询出来的List泛型是小节,但是里面字段只有视频id,我们利用流操作转换一下——>3.然后删除小节视频,再根据课程id删除所有小节
- /**
- * 1.根据课程id删除小节,还需要删除视频(先删除视频再删除小节)
- * 一个课程中可能有多个小节,也就是多个视频
- * @param courseId
- */
- @Override
- public void removeVideoByCourseId(String courseId) {
- // 1.根据课程id查看里面的所有小节中的视频->得到eduVideoList里面是video_source_id
- QueryWrapper
wrapperVideo = new QueryWrapper<>(); - wrapperVideo.eq("course_id",courseId).select("video_source_id");
- List
eduVideoList = baseMapper.selectList(wrapperVideo); -
- //2.将List
转为List - List
videoIds = eduVideoList.stream() - .map(EduVideo::getVideoSourceId)
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
-
- //3.删除课程里面的所有视频
- if(videoIds.size()>0){
- vodClient.deleteBatch(videoIds);
- }
-
- //4.再根据课程id删除所有小节
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("course_id",courseId);
- baseMapper.delete(wrapper);
- }
课程大纲(简单级联封装思路)
1.控制层
- /**
- * 1.课程大纲列表
- * 根据course的id字段查得chapter字段内容
- */
- @GetMapping("getChapterVideo/{courseId}")
- public R getChapterVideo(@PathVariable String courseId) {
- List
list = chapterService.getChapterVideoByCourseId(courseId); - return R.ok().data("allChapterVoList", list);
- }
2.业务层
思路:1.根据课程id得到所有Chapter数据,然后再根据courseId得到所有的小节数据——>2.最关键的是对章节的封装,遍历章节数据将其转为前端要展示的新章节类,并且将新章节添加到集合中——>3.接着对小节封装,遍历每个小节数据,比较每个小节和章节的父子id,如果符合就将小节数据转为新小节类,并且添加到小节集合中——>4.最后章节添加这些小节
- /**
- * 1.根据课程id查询课程大纲
- *
- * @param courseId
- * @return
- */
- @Override
- public List
getChapterVideoByCourseId(String courseId) { - //最终要得到的数据列表
- ArrayList
chapterVoList = new ArrayList<>(); -
- /**
- *1.根据课程id查询里面所有的章节
- */
- QueryWrapper
wrapperChapter = new QueryWrapper<>(); - wrapperChapter.eq("course_id", courseId);
- List
eduChapterList = baseMapper.selectList(wrapperChapter); -
- /**
- *2.根据课程id查询课程里面所有的小节
- */
- QueryWrapper
wrapperVideo = new QueryWrapper<>(); - wrapperVideo.eq("course_id",courseId)
- .orderByAsc("sort","id");
- List
videoList = videoService.list(wrapperVideo); -
- /**
- * 3.对章节进行封装
- */
- int count = eduChapterList.size();
- for (int i = 0; i < count; i++) {
- //获取每个章节然后对vo进行填充
- EduChapter chapter = eduChapterList.get(i);
- ChapterVo chapterVo = new ChapterVo();
- BeanUtils.copyProperties(chapter,chapterVo);
-
- chapterVoList.add(chapterVo);
-
- /**
- *4.对小节进行封装
- */
- ArrayList
videoVoList = new ArrayList<>(); - int countVo = videoList.size();
-
- for (int j = 0; j < countVo; j++) {
- EduVideo video = videoList.get(j);
- //进行判断,如果这个小节的chapterId==章节id,就进行添加至videoVoList
- if(chapter.getId().equals(video.getChapterId())){
- VideoVo videoVo = new VideoVo();
- BeanUtils.copyProperties(video,videoVo);
- videoVoList.add(videoVo);
- }
- }
- /**
- * 5.ChapterVo封装他的孩子们videoVoList
- */
- chapterVo.setChildren(videoVoList);
- }
-
- return chapterVoList;
- }