这一步是修改课程下一步展示的信息
"修改课程"中点击“保存并进行下一步”就会出现下图的页面
很简单的可以看出也是一个树形接口,一个大章节里面有许多的小章节
teachplan表
grade字段就是章节等级
parentid是课程计划的父级id
media_type字段是说明将来这个课程是视频的形式还是文档的形式,也就是媒体类型
/**
* <p>
* 课程计划
* </p>
*
* @author itcast
*/
@Data
@TableName("teachplan")
public class Teachplan implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 课程计划名称
*/
private String pname;
/**
* 课程计划父级Id
*/
private Long parentid;
/**
* 层级,分为1、2、3级
*/
private Integer grade;
/**
* 课程类型:1视频、2文档
*/
private String mediaType;
/**
* 开始直播时间
*/
private LocalDateTime startTime;
/**
* 直播结束时间
*/
private LocalDateTime endTime;
/**
* 章节及课程时介绍
*/
private String description;
/**
* 时长,单位时:分:秒
*/
private String timelength;
/**
* 排序字段
*/
private Integer orderby;
/**
* 课程标识
*/
private Long courseId;
/**
* 课程发布标识
*/
private Long coursePubId;
/**
* 状态(1正常 0删除)
*/
private Integer status;
/**
* 是否支持试学或预览(试看)
*/
private String isPreview;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createDate;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime changeDate;
}
课程计划如如果是关联视频的话有一张单独的表teachplan_media
media_id和teachplan_id是这张表的重点
为什么这样表中会有course_id课程id?
也很好理解,标识一下这段视频属于哪个课程的
/**
* <p>
*
* </p>
*
* @author itcast
*/
@Data
@TableName("teachplan_media")
public class TeachplanMedia implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 媒资文件id
*/
private String mediaId;
/**
* 课程计划标识
*/
private Long teachplanId;
/**
* 课程标识
*/
private Long courseId;
/**
* 媒资文件原始名称
*/
@TableField("media_fileName")
private String mediaFilename;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createDate;
/**
* 创建人
*/
private String createPeople;
/**
* 修改人
*/
private String changePeople;
}
我们最终要实现这种形式
要完成如下形式的数据
[
{
"id":268,
"pname":"1.配置管理",
"parentid":0,
"grade":1,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":1,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":null,
"teachPlanTreeNodes":[
{
"id":269,
"pname":"1.1 什么是配置中心",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":1,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":40,
"mediaId":"3a5a861d1c745d05166132c47b44f9e4",
"teachplanId":null,
"courseId":null,
"mediaFilename":"01-Nacos配置管理-内容介绍.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":270,
"pname":"1.2Nacos简介",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":2,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":41,
"mediaId":"23f83ae728bd1269eee7ea2236e79644",
"teachplanId":null,
"courseId":null,
"mediaFilename":"16-Nacos配置管理-课程总结.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":271,
"pname":"1.3安装Nacos Server",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":3,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":42,
"mediaId":"3a5a861d1c745d05166132c47b44f9e4",
"teachplanId":null,
"courseId":null,
"mediaFilename":"01-Nacos配置管理-内容介绍.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":272,
"pname":"1.4Nacos配置入门",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":4,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":43,
"mediaId":"3a5a861d1c745d05166132c47b44f9e4",
"teachplanId":null,
"courseId":null,
"mediaFilename":"01-Nacos配置管理-内容介绍.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":273,
"pname":"1.5命名空间管理",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":5,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":44,
"mediaId":"23f83ae728bd1269eee7ea2236e79644",
"teachplanId":null,
"courseId":null,
"mediaFilename":"16-Nacos配置管理-课程总结.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
}
]
},
{
"id":274,
"pname":"2.服务发现",
"parentid":0,
"grade":1,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":2,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":null,
"teachPlanTreeNodes":[
{
"id":275,
"pname":"2.1什么是服务发现",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":1,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":45,
"mediaId":"1f229319d6fed3431d2f9d06193a433b",
"teachplanId":null,
"courseId":null,
"mediaFilename":"01-分布式事务专题课程介绍.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":276,
"pname":"2.2服务发现快速入门",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":2,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":46,
"mediaId":"6ad24a762f67c18f61966c1b8c55abe6",
"teachplanId":null,
"courseId":null,
"mediaFilename":"07-分布式事务基础理论-BASE理论.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":277,
"pname":"2.3服务发现数据模型",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":3,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":47,
"mediaId":"1f229319d6fed3431d2f9d06193a433b",
"teachplanId":null,
"courseId":null,
"mediaFilename":"01-分布式事务专题课程介绍.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
},
{
"id":278,
"pname":"2.4服务列表管理",
"parentid":null,
"grade":2,
"mediaType":null,
"startTime":null,
"endTime":null,
"description":null,
"timelength":null,
"orderby":4,
"courseId":117,
"coursePubId":null,
"status":null,
"isPreview":null,
"createDate":null,
"changeDate":null,
"teachplanMedia":{
"id":48,
"mediaId":"6ad24a762f67c18f61966c1b8c55abe6",
"teachplanId":null,
"courseId":null,
"mediaFilename":"07-分布式事务基础理论-BASE理论.avi",
"createDate":null,
"createPeople":null,
"changePeople":null
},
"teachPlanTreeNodes":null
}
]
}
]
首先定义一个查询课程计划返回的Dto表
@Data
@ToString
public class TeachplanDto extends Teachplan {
private static final long serialVersionUID = 1586804545070538974L;
//课程计划关联的媒资信息
private TeachplanMedia teachplanMedia;
//子节点
private List<TeachplanDto> teachPlanTreeNodes;
}
完成课程计划查询的树状结构
我们在本篇文章中的“课程分类”有介绍树状结构查询,可以重新看看
public interface TeachplanMapper extends BaseMapper<Teachplan> {
//课程计划查询 - 树状结构
public List<TeachplanDto> selectTreeNodes(@Param("courseId") Long courseId);
}
<!--简单说明:把数据库查询结果中的column one_id字段映射到TeachplanDto类的id属性property-->
<!--<id>表示主键字段-->
<!--<result>表示普通字段-->
<resultMap id="treeNodeResultMap" type="com.xuecheng.content.model.dto.TeachplanDto">
<id column="one_id" property="id"/>
<result column="one_pname" property="pname"/>
<result column="one_parentid" property="parentid"/>
<result column="one_grade" property="grade"/>
<result column="one_mediaType" property="mediaType"/>
<result column="one_stratTime" property="startTime"/>
<result column="one_endTime" property="endTime"/>
<result column="one_orderby" property="orderby"/>
<result column="one_courseId" property="courseId"/>
<result column="one_coursePubId" property="coursePubId"/>
<!--映射子节点,一对多映射,ofType list中的对象类型-->
<collection property="teachPlanTreeNodes" ofType="com.xuecheng.content.model.dto.TeachplanDto">
<id column="two_id" property="id"/>
<result column="two_pname" property="pname"/>
<result column="two_parentid" property="parentid"/>
<result column="two_grade" property="grade"/>
<result column="two_mediaType" property="mediaType"/>
<result column="two_stratTime" property="startTime"/>
<result column="two_endTime" property="endTime"/>
<result column="two_orderby" property="orderby"/>
<result column="two_courseId" property="courseId"/>
<result column="two_coursePubId" property="coursePubId"/>
<!--javaType一对一映射 (小章节和视频直接的关系是一对一)-->
<association property="teachplanMedia" javaType="com.xuecheng.content.model.po.TeachplanMedia">
<id column="teachplanMeidaId" property="id"/>
<result column="mediaFilename" property="mediaFilename"/>
<result column="mediaId" property="mediaId"/>
</association>
</collection>
</resultMap>
<select id="selectTreeNodes" resultMap="treeNodeResultMap">
select one.id one_id,
one.pname one_pname,
one.parentid one_parentid,
one.grade one_grade,
one.media_type one_mediaType,
one.start_time one_startTime,
one.end_time one_endTime,
one.orderby one_orderby,
one.course_id one_courseId,
one.course_pub_id one_coursePubId,
two.id two_id,
two.pname two_pname,
two.grade two_grade,
two.media_type two_mediaType,
two.start_time two_startTime,
two.end_time two_endTime,
two.orderby two_orderby,
two.course_id two_courseId,
two.course_pub_id two_coursePubId,
m1.media_fileName mediaFilename,
m1.id teachplanMeidaId,
m1.media_id mediaId
FROM teachplan one
LEFT JOIN teachplan two on two.parentid = one.id
LEFT JOIN teachplan_media m1 on two.id = m1.teachplan_id
where one.parentid = 0
and one.course_id = #{courseId}
</select>
@Service
public class TeachplanServiceImpl implements TeachplanService {
@Autowired
private TeachplanMapper teachplanMapper;
/**
* 查询课程计划树形结构
* @param courseId 课程id
* @return 课程计划树形结构
*/
@Override
public List<TeachplanDto> findTeachplanTree(long courseId) {
return teachplanMapper.selectTreeNodes(courseId);
}
}
/**
* 课程计划相关接口
*/
@Api(value = "课程计划编辑接口",tags = "课程计划编辑接口")
@RestController
public class TeachPlanController {
@Autowired
private TeachplanServiceImpl teachplanService;
//查询课程计划
@ApiOperation("查询课程计划树形结构")
@GetMapping("/teachplan/{courseId}/tree-nodes")
//针对参数进行说明
@ApiImplicitParam(value = "courseId",name = "课程id",required = true,dataType = "Long",paramType = "path")
public List<TeachplanDto> getTreeNodes(@PathVariable Long courseId) {
return teachplanService.findTeachplanTree(courseId);
}
}
下面圈出来的地方“添加章”是一级章节
下面所示圈出来的地方是添加小章节,也就是二级
修改一二级章节只需要点击就可以修改,当鼠标点击其他位置(文本框失去焦点时)就可以将修改的内容保存
/**
* @description 新增大章节、小章节、修改章节信息
*/
@Data
public class SaveTeachplanDto {
/***
* 教学计划id
*/
private Long id;
/**
* 课程计划名称
*/
private String pname;
/**
* 课程计划父级Id
*/
private Long parentid;
/**
* 层级,分为1、2、3级
*/
private Integer grade;
/**
* 课程类型:1视频、2文档
*/
private String mediaType;
/**
* 课程标识
*/
private Long courseId;
/**
* 课程发布标识
*/
private Long coursePubId;
/**
* 是否支持试学或预览(试看)
*/
private String isPreview;
}
/**
* 新增/修改/保存课程计划
*
* @param saveTeachplanDto
*/
@Override
public void saveTeachplan(SaveTeachplanDto saveTeachplanDto) {
//通过课程计划id判断是新增还是修改(新增新增课程的时候不会有id)
//教学计划id
Long teachplanId = saveTeachplanDto.getId();
if (teachplanId == null) {
//新增
Teachplan teachplan = new Teachplan();
BeanUtils.copyProperties(saveTeachplanDto, teachplan);
//确定排序的字段
// 大章节的添加: 查询某个课程id下有多少个大章节即可
// select count(1) from teachplan where course_id = 117 and parentid = 0
// 小章节的添加:(我们只需要找到同级节点有几个即可,也就是parentId相同的就是同级的)
//select count(1) from teachplan where course_id = 117 and parentid = 父级id
Long parentId = saveTeachplanDto.getParentid();
Long courseId = saveTeachplanDto.getCourseId();
int count = this.getTeachplanCount(courseId, parentId);
// 确定排序字段
teachplan.setOrderby(count + 1);
teachplanMapper.insert(teachplan);
} else {
//修改
Teachplan teachplan = teachplanMapper.selectById(teachplanId);
//将要修改的参数复制到teachplan里
BeanUtils.copyProperties(saveTeachplanDto, teachplan);
teachplanMapper.updateById(teachplan);
}
}
}
private int getTeachplanCount(long courseId, long parentId) {
LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Teachplan::getCourseId, courseId)
.eq(Teachplan::getParentid, parentId);
return teachplanMapper.selectCount(queryWrapper);
}
@ApiOperation("课程计划创建或修改")
@PostMapping("/teachplan")
public void saveTeachplan(@RequestBody SaveTeachplanDto teachplanDto){
teachplanService.saveTeachplan(teachplanDto);
}
修改一级菜单、二级菜单、是否免费
初始时
修改后
新增一级菜单
新增二级菜单