一 vo
ChapterVo
@Data
public class ChapterVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 章节id
*/
private String id;
/**
* 章节标题
*/
private String title;
/**
* 排序
*/
private Integer sort;
/**
* 课时
*/
private List<VideoVo> children = new ArrayList<>();
}
VideoVo
@Data
public class VideoVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 课时id
*/
private String id;
/**
* 课时标题
*/
private String title;
/**
* 是否免费
*/
private Boolean free;
/**
* 排序
*/
private Integer sort;
/**
* 课时视频id
*/
private String videoSourceId;
}
二 控制器
@CrossOrigin //允许跨域
@Api(description = "章节管理")
@RestController
@RequestMapping("/admin/edu/chapter")
@Slf4j
public class ChapterController {
@Autowired
private ChapterService chapterService;
/**
* 功能描述:新增章节
*
* @param chapter 新增的章节
* @return R 返回给前端数据
* @author cakin
* @date 2020/12/7
*/
@ApiOperation("新增章节")
@PostMapping("save")
public R save(@ApiParam(value = "章节对象", required = true) @RequestBody Chapter chapter) {
boolean result = chapterService.save(chapter);
if (result) {
return R.ok().message("保存成功");
} else {
return R.error().message("保存失败");
}
}
/**
* 功能描述:根据id查询章节
*
* @param id 章节id
* @return R 返回给前端数据
* @author cakin
* @date 2020/12/7
*/
@ApiOperation("根据id查询章节")
@GetMapping("get/{id}")
public R getById(@ApiParam(value = "章节id", required = true) @PathVariable String id) {
Chapter chapter = chapterService.getById(id);
if (chapter != null) {
return R.ok().data("item", chapter);
} else {
return R.error().message("数据不存在");
}
}
/**
* 功能描述:根据id修改章节
*
* @param chapter 章节信息
* @return R 返回给前端数据
* @author cakin
* @date 2020/12/7
*/
@ApiOperation("根据id修改章节")
@PutMapping("update")
public R updateById(@ApiParam(value = "章节对象", required = true) @RequestBody Chapter chapter) {
boolean result = chapterService.updateById(chapter);
if (result) {
return R.ok().message("修改成功");
} else {
return R.error().message("数据不存在");
}
}
/**
* 功能描述:根据ID删除章节
*
* @param id 章节id
* @return R 返回给前端的数据
* @author cakin
* @date 2020/12/7
*/
@ApiOperation("根据ID删除章节")
@DeleteMapping("remove/{id}")
public R removeById(@ApiParam(value = "章节ID", required = true) @PathVariable String id) {
// TODO: 删除课程视频
// 此处调用vod中的删除视频文件的接口
// 删除章节
boolean result = chapterService.removeChapterById(id);
if (result) {
return R.ok().message("删除成功");
} else {
return R.error().message("数据不存在");
}
}
/**
* 功能描述:嵌套章节数据列表
*
* @param courseId 课程id
* @return R 返回给前端的数据
* @author cakin
* @date 2020/12/7
*/
@ApiOperation("嵌套章节数据列表")
@GetMapping("nested-list/{courseId}")
public R nestedListByCourseId(@ApiParam(value = "课程ID", required = true) @PathVariable String courseId) {
List<ChapterVo> chapterVoList = chapterService.nestedList(courseId);
return R.ok().data("items", chapterVoList);
}
三 Service层
1 接口
/**
* @className: ChapterService
* @description: 章节接口
* @date: 2020/12/7
* @author: cakin
*/
public interface ChapterService extends IService<Chapter> {
/**
* 功能描述:根据id删除章节
*
* @author cakin
* @date 2020/12/7
* @param id 章节id
* @return boolean 是否删除成功
*/
boolean removeChapterById(String id);
/**
* 功能描述:嵌套章节数据列表
*
* @author cakin
* @date 2020/12/7
* @param courseId 课程id
* @return List<ChapterVo> 嵌套课程列表
*/
List<ChapterVo> nestedList(String courseId);
}
2 实现
/**
* @className: ChapterServiceImpl
* @description: 章节服务类
* @date: 2020/12/7
* @author: cakin
*/
@Service
public class ChapterServiceImpl extends ServiceImpl<ChapterMapper, Chapter> implements ChapterService {
@Autowired
private VideoMapper videoMapper;
/**
* 功能描述:根据id删除章节
*
* @param id 章节id
* @return boolean 是否删除成功
* @author cakin
* @date 2020/12/7
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean removeChapterById(String id) {
// 根据courseId删除Video(课时)
QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
videoQueryWrapper.eq("chapter_id", id);
videoMapper.delete(videoQueryWrapper);
// 删除章节
return this.removeById(id);
}
/**
* 功能描述:嵌套章节数据列表
*
* @param courseId 课程id
* @return List<ChapterVo> 嵌套课程列表
* @author cakin
* @date 2020/12/7
*/
@Override
public List<ChapterVo> nestedList(String courseId) {
//方案1:效率低 1+n个sql
//通过course_id获取章节列表信息:List<Chapter> sql
//遍历List<Chapter>{ n
// 通过chapter_id查询List<Video> sql
// }
//方案2:效率高 1+1个sql
//通过course_id获取章节列表信息:List<Chapter> sql
//通过course_id查询List<Video> sql
// 获取章节信息列表
QueryWrapper<Chapter> chapterQueryWrapper = new QueryWrapper<>();
chapterQueryWrapper.eq("course_id", courseId);
chapterQueryWrapper.orderByAsc("sort", "id");
List<Chapter> chapterList = baseMapper.selectList(chapterQueryWrapper);
// 获取课时信息列表
QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
videoQueryWrapper.eq("course_id", courseId);
videoQueryWrapper.orderByAsc("sort", "id");
List<Video> videoList = videoMapper.selectList(videoQueryWrapper);
// 组装章节列表:List<ChapterVo>
List<ChapterVo> chapterVoList = new ArrayList<>();
for (int i = 0; i < chapterList.size(); i++) {
Chapter chapter = chapterList.get(i);
ChapterVo chapterVo = new ChapterVo();
BeanUtils.copyProperties(chapter, chapterVo);
chapterVoList.add(chapterVo);
// 组装课时列表:List<VideoVo>
List<VideoVo> videoVoList = new ArrayList<>();
for (int j = 0; j < videoList.size(); j++) {
Video video = videoList.get(j);
if (chapter.getId().equals(video.getChapterId())) {
VideoVo videoVo = new VideoVo();
BeanUtils.copyProperties(video, videoVo);
videoVoList.add(videoVo);
}
}
chapterVo.setChildren(videoVoList);
}
return chapterVoList;
}
}