onlineSchool 项目课 五:动态的章节数据

一,动态章节表单的实现
章节的内容是拿出来且隐藏的,用触发事件点击添加时,才复制一份出来,复制到想复制的地方,复制的一份也是隐藏的,通过替换隐藏的样式才显示出来。 replaceAll替换隐藏的样式。
(如果章节的内容不拿出来,这个情况太复杂了,不好描述,可以选择不隐藏章节的内容试试看是什么情况。)

//添加章节数据的按钮
<button class="btn btn-primary" onclick="addCourseSection()">+添加章</button>
//点击添加时,复制一份章节的数据到这
<div class="tab-content" id="CourseSectionContent">

</div>
//隐藏的章节的内容,点击添加时复制一份到tabContent
<div id="CourseSection4Clone">
   <div sid="chapter-clone" class="chapter-section-clone" style="display:none;">
      <div class="form-group clearfix">
         <label class="control-label">章名称</label>
         <div class="col-md-8">
            <input type="text" name="chapterName" class="form-control" placeholder="请输入章名称">
         </div>
         <div class="col-md-1">
            <button class="btn btn-primary" onclick="deleteChapter(this)">-删除章</button>
         </div>
         <div class="col-md-1">
            <button class="btn btn-primary" onclick="addSection(this)">+添加节</button>
         </div>
      </div>

      <div id="section4Clone">
         <div sid="section-clone" class="form-group clearfix" style="margin-left: 10px">
            <label class="control-label">节信息</label>
            <div class="col-md-7">
               <input type="text" name="sectionName" class="form-control" placeholder="请输入节名称">
               <input type="text" name="videoUrl" class="form-control" style="margin: 10px 0px" placeholder="请输入视频链接">
               <input type="text" name="time" class="form-control" placeholder="请输入时长(分钟)">
            </div>
            <div class="col-md-1">
               <button class="btn btn-primary" onclick="deleteSection(this)">-删除节</button>
            </div>
         </div>
      </div>

   </div>
</div>

在这里插入图片描述
在这里插入图片描述

1,添加章节信息:通过包含章节样式的id,复制id 里面包含的章节的输入框,得到的是一个dom 对象,通过html 获取 dom 对象的内容,append 到 tabcontent中。通过样式替换显示出复制到 tabContent的章节输入框。

 function addCourseSection() {
      let divHtml = $('#CourseSection4Clone').clone().html()
      divHtml = divHtml.replaceAll("display:none","display:block")
      $('#CourseSectionContent').append(divHtml)
   }

2,添加节信息:通过 id 复制节信息,得到一个dom 对象,通过html 获取 dom 对象的内容,append到包含章节的样式中,接在节信息后面。

function addSection(el) {
      let divHtml = $('#section4Clone').clone().html()
      $(el).parent().parent().parent().append(divHtml)
   }

3,删除章节信息 节信息:点击时找到父节点,remove 删除章节信息,节信息。不用管id。

删除章节的信息在这里插入图片描述

function deleteChapter(el) {
      $(el).parent().parent().parent().remove()
   }

删除节信息删除

function deleteSection(el) {
      $(el).parent().parent().remove()
   }

二,动态章节表单的获取
1,创建章节的数组,可以返回章节的数组。
在 tabcontent 中找到所有章 sid 包含的div ,遍历这些div,找到input 中name=chapterName的值,判断有值创建章的对象,把chapter name属性与input值对应上,并创建章下节的数组。(要与章节数据结构的 bean 中的变量命名对应上。)
2,找一个个div 中节 sid 包含的div,遍历这些 div,找到input中name= sectionName的值。( videourl,time也是一样)判断有节的名称,创建节的对象,把属性与值对应上,如果获取的time是null就设置成0。
3,把节对象放到章下节的数组,把章节的对象放到章节的数组。

function getCourseSectionData() {
      let ChapterSection = []
      let chapterDivs = $('#CourseSectionContent').find("div[sid='chapter-clone']")
      $.each(chapterDivs,function (i,item) {
         let chapterName = $(item).find("input[name='chapterName']").val()
         if (!_os.isEmpty(chapterName)){
            let chapterObj = {}
            chapterObj.chapterName = chapterName
            chapterObj.sections = []

            let sectionDivs = $(item).find("div[sid='section-clone']")
            $.each(sectionDivs,function (i,item) {
               let sectionName = $(item).find("input[name='sectionName']").val()
               let videoUrl = $(item).find("input[name='videoUrl']").val()
               let time = $(item).find("input[name='time']").val()

               if (time == null){
                  time =0
               }
               if (!_os.isEmpty(sectionName)){
                  let sectionObj ={}
                  sectionObj.name = sectionName
                  sectionObj.videoUrl = videoUrl
                  sectionObj.time = time
                  chapterObj.sections.push(sectionObj)
               }
            })
            ChapterSection.push(chapterObj)
         }
      })
      return ChapterSection;
   }
   

二,动态章节表单数据的提交
在保存课程和章节的触发函数中,调用获取章节数据的函数,获取章节数据。通过 json把章节的数据转化成 String类型,作为ajax的参数提交到 controller,在controller中接收String类型的章节数据。

提交章节的数据在这里插入图片描述

 <button class="btn btn-primary" onclick="mergeCourseSection()">保存课程信息</button>
function mergeCourseSection() {
 		 let chapterSectionData = getCourseSectionData();
         let chapterSections = JSON.stringify(chapterSectionData)
         $('#courseForm').ajaxSubmit({
            dataType:'json',
            data:{'chapterSections':chapterSections},
            success:function (resp) {
               if (resp.errcode == 0){
                 Modal.alert('保存成功')
               }else {
                  Modal.alert('保存失败1')
               }
            },error:function (resp) {
               Modal.alert('保存失败2')
            }
         })
      }
 }     

三,动态章节数据的保存
1,controller中判断能接收到章节的数据,将数据转化成 list 格式,再调用保存章节数据的函数,返回课程的时长。
(这里以只添加和保存章节的数据做说明,那么返回的就是新增的课程时长。如果是保存课程和章节的数据,那么要在一个事务中,先保存课程的数据,再调用保存章节数据的函数。章节的数据是创建在一个课程之下的,所以还要把课程的id获取过来。)


    @RequestMapping("/mergeCourseSection")
    @ResponseBody
    public String mergeCourseSection(Course entity,String coursePicture,String chapterSections){
    	List<chapterSectionBean> sectionList = null;
        if (StringUtils.isNotEmpty(chapterSections)){
          sectionList = JSONArray.parseArray(chapterSections,chapterSectionBean.class);
	}
	}    
Integer CourseTotalTime = courseSectionService.createCourseSection(entity.getId(),sectionList);			

2,创建章节的数据到数据库。
a 声明课程的总时长,返回课程的总时长。(如果是只添加章节的数据,那么返回的就是新增的课程时长。只是命名成totalCourseTime而已。)

getMaxSort:获取章最大的sort,修改添加章节的数据时,在章最大的 sort 后面自增(对传入的参数的说明:一个课程下所有章的parentId都是0。一个课程一个章下所有节的parentId都是章的id,所以传入课程的id和parentId,结合sql ,就能获取一个课程下的所有章,获一个课程的章下所有节,最大的sort。)如果数据库中获取最大的sort,获取为空,sort就给个默认值,默认从0开始,先自增再设置到对应的字段中。(获取的sort 为空代表该课程下,原先是没有章节的数据的。)

//获取最大的sort,有两个参数传入一个对象
	public Integer getMaxSort(Long courseId, Long parentId){
		CourseSection entity = new CourseSection();
		entity.setCourseId(courseId);
		entity.setParentId(parentId);
		return entityDao.getMaxSort(entity);
	}

课程的章节表在这里插入图片描述
b 先创建章的数据:把章节的数据遍历到bean(因为courseSection表,没有chapterName)使用数据库的映射的类,创建数据库表的数据。
设置courseId,方法中带过来的。
parentId:章的parentId是0,节的parentId是章的id。
name:bean中有chapterName。
设置sort:先自增再设置进去。
在创建章的数据时声明章的时长,先把章的时长设为0,不要为了美观把章的时长变量的声明放到外面。
onsale:因为有课程的上下架功能,所以默认所有的章节都上架。
videoUrl:章没有videoUrl,所以设为空串。
当前时间设为创建和更新的时间。
create方法创建章的数据。

c创建节的数据:
获取节最大的sort,修改添加章节数据时在节最大的sort后面自增。
判断 bean 中有没有节的数据,有就遍历出来,遍历到CourseSection中,用StringUtils判断该有的 sectionName,time,videoUrl,有没有,没有就初始化一下。
章节共用一个表,设置一下其他的字段。

d 把章的总时长算出来。
foreach批量创建小节的数据。
和判断章的总时长不为0,把章的总时长设置进去,再更新章的数据清零变量。

//保存章节的数据到数据库
	public Integer createCourseSection(Long courseId,List<chapterSectionBean> sectionList){
		Integer CourseTotalTime = 0; //声明课程的时长

		//获取章最大的sort,修改时在章数据最大的sort后面自增
		Integer maxChapterSort = this.getMaxSort(courseId,0L);
		if (null == maxChapterSort)maxChapterSort=0;
		
		//先创建章的数据
		for (int i = 0; i < sectionList.size(); i++){ 
			chapterSectionBean chapterSectionBeans = sectionList.get(i); //遍历到bean courseSection表没有chapterName
			CourseSection chapter = new CourseSection(); 
			chapter.setCourseId(courseId);
			chapter.setParentId(0L);
			chapter.setName(chapterSectionBeans.getChapterName());
			maxChapterSort += 1;
			chapter.setSort(maxChapterSort);
			chapter.setTime(0);
			Integer ChapterTotalTime = 0; //在创建章的数据时声明章的时长
			chapter.setOnsale(1);
			chapter.setVideoUrl("");
			chapter.setCreateAt(new Date());
			chapter.setUpdateAt(new Date());
			this.create(chapter);

			//获取节最大的sort,修改时在节最大的sort后面自增
			Integer maxSectionSort = this.getMaxSort(courseId,chapter.getId());
			if (null == maxSectionSort)maxSectionSort=0;

			//判断章下有没有节的数据,有遍历出来
			if (!CollectionUtils.isEmpty(chapterSectionBeans.getSections())){
				for (int j = 0;j < chapterSectionBeans.getSections().size();j++){
					CourseSection sections = chapterSectionBeans.getSections().get(j);

					//创建节的数据
					sections.setCourseId(courseId);
					sections.setParentId(chapter.getId());
					maxSectionSort += 1;
					sections.setSort(maxSectionSort);
					sections.setOnsale(1);

					//判断如果提交的节的数据为空就初始化一下
					if (StringUtils.isEmpty(sections.getName())){
						sections.setName("");
					}
					if (sections.getTime()==null){
						sections.setTime(0);
					}
					if (StringUtils.isEmpty(sections.getVideoUrl())){
						sections.setVideoUrl("");
					}
					sections.setCreateAt(new Date());
					sections.setUpdateAt(new Date());

					ChapterTotalTime += sections.getTime();//计算章的时长

				}
				//foreach批量创建所有的小节
				this.entityDao.createSections(chapterSectionBeans.getSections()); //之后会在bean里面补充所有CourseSection的字段

				//更新章的时间
				if (ChapterTotalTime != 0){
					chapter.setTime(ChapterTotalTime);
					this.update(chapter);

					CourseTotalTime += ChapterTotalTime; //更新课程的时间
				}
			}
		}
		return  CourseTotalTime;
	}

批量创建所有小节数据的sql

<insert id="createSections" parameterType="java.util.List">
		INSERT INTO course_section
		( courseId,parentId,name,sort,time,onsale,videoUrl,createAt,updateAt )
		VALUES
		<foreach collection="list" item="item" index="index" separator=",">
		( #{item.courseId},#{item.parentId},#{item.name},#{item.sort},#{item.time},#{item.onsale},#{item.videoUrl},#{item.createAt},#{item.updateAt} )
		</foreach>
	</insert>

四,针对时长的处理
a 在修改时选择添加课程的章节数据,要更新对应的课程时长:
在这里插入图片描述
在这里插入图片描述
创建章节的数据会返回一个新增的课程时长,新增的章节数据创建在一个课程下。
通过课程的 id 获取课程的数据,获取课程的时长,加上传过来的新增的时长,更新课程的数据。(或者之后修改和删除时加上负的时长)获取时都可以加上判断避免空指针异常。

public void updateCourseTime (Long courseId, Integer chapterSectionTime){
		Course course = this.getById(courseId);
		if (course != null && chapterSectionTime != null){
			String time = course.getTime();
			
			if (!StringUtils.isEmpty(time)){
				Integer totalTime = Integer.parseInt(time);
				
				totalTime = chapterSectionTime + totalTime ;
				course.setTime(totalTime.toString());
				this.update(course);
			}
		}
	}

b 修改章节的数据:章只能修改章的名称,修改节信息包含修改小节的时长。

修该章的数据在这里插入图片描述在这里插入图片描述
修改节的信息在这里插入图片描述在这里插入图片描述
在这里插入图片描述

根据前端传过来的当前操作的数据的id,获取被修改的数据。
如果修改的是小节的数据,获取修改后的时长差,(也就是原时长减去修改后的时长)
判断如果修改了小节的时间,更新小节的时间,更新章的时间,更新课程的时间。
最后更新数据库中章名称数据。

@Transactional
	public void updateSection(CourseSection courseSection){
		CourseSection entity = this.getById(courseSection.getId()); //获取原修改的数据
		if (0 != entity.getParentId()){ //如果修改的是小节的数据,只有获取的数据才有parentId,courseId
			//获取修改后的时长差
			Integer time = courseSection.getTime() - entity.getTime();

			//如果修改了时间再做接下来的操作
			if (time != 0){
				//更新小节的时间
				entity.setTime(courseSection.getTime());

				//更新章的时间
				CourseSection chapter = this.getById(entity.getParentId()); //获取章
				chapter.setTime(chapter.getTime() + time); //设置章的时长
				this.update(chapter); //更新章的数据

				//更新课程的时间
				courseService.updateCourseTime(entity.getCourseId(),time);
			}
		}
		this.update(entity); //更新数据库的数据
	}

c 删除章节的数据:

公共的弹窗发出删除的提示信息,点击确定ajax提交删除操作的id在这里插入图片描述

function deleteSection(id) {
      Modal.confirm('确定删除',function () {
          $.ajax({
              url:'${base}/deleteSection',
              dataType:'json',
              data:{'id':id},
              success:function (resp) {
                  if (resp.errcode == 0){
                      window.location.reload();
                  }else {
                      Modal.alert('删除失败')
                  }
              }
          })
      })
    }

先根据 id 获取这条要被删除的数据。
更新课程的时长。
删掉对应的数据。
如果删除的是章的数据,要删除章下所有的小节。(删除parentId是章id的小节的数据)
如果删除的是小节的数据,更新章的时长:获取节的父节点,getById获取章,获取章的时长,减掉小节的时长,更新章的数据。

@Transactional
	public void deleteSection(Long id){
		CourseSection courseSection = entityDao.getById(id);

		//不管删除的是章还是节,都要更新课程的时间
		//每条章或节的数据都有课程的id,传入课程的id,和删除此条章或节的数据要减掉的时长
		courseService.updateCourseTime(courseSection.getCourseId(),-courseSection.getTime());

		//删除对应的分类
		entityDao.delete(courseSection);

		if (courseSection != null){ //判断能不能获取到操作的数据,能获取到再做以下的处理,避免空指针
			if (courseSection.getParentId() == 0){ //如果删除的是章,要删除章下的所有小节
				entityDao.deleteByParentId(courseSection);
				entityDao.update(courseSection);
			}else { //如果删除的是节,要更新章的时间
				CourseSection chapter = entityDao.getById(courseSection.getParentId()); //获取章的数据
				chapter.setTime(chapter.getTime()-courseSection.getTime()); //更新章的时间
				entityDao.update(chapter); //更新章的数据
			}
		}
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值