Mooc項目開發筆記(十三):課程章節顯示前後端實現、課程基本信息回顯、課程基本信息更新實現

一、課程章節列表顯示後端實現

1、創建章節和小節vo類

/**
 * 章節和小節的vo類
 */
@Data
@ApiModel("章節和小節的vo類")
public class ChapterVo {

    private String id;
    private String title;

    //如果是章節用於存放其包含小節
    //如果是小節則爲空
    private List<ChapterVo> children = null;
}

2、服務層

接口

public interface EduChapterService extends IService<EduChapter> {
    List<ChapterVo> getChapterByCourseId(String courseId);
}

實現

@Service
public class EduChapterServiceImpl extends ServiceImpl<EduChapterMapper, EduChapter> implements EduChapterService {

    @Autowired
    private EduVideoMapper videoMapper;

    /**
     * 根據課程id獲取課程包含的章節和小節信息
     * 並以ChapterVo的形式作爲結果集返回
     * @param courseId
     * @return
     */
    @Override
    public List<ChapterVo> getChapterByCourseId(String courseId) {
        //用於存放章節和小節列表(樹狀)
        List<ChapterVo> res = new ArrayList<>();

        //根據課程id插入課程所有的章節
        QueryWrapper<EduChapter> chapterWrapper = new QueryWrapper<>();
        chapterWrapper.eq("course_id", courseId);
        List<EduChapter> chapters = baseMapper.selectList(chapterWrapper);

        //根絕課程id查詢出該課程所有小節
        QueryWrapper<EduVideo> videoWrapper = new QueryWrapper<>();
        chapterWrapper.eq("course_id", courseId);
        List<EduVideo> videos = videoMapper.selectList(videoWrapper);

        for (EduChapter chapter : chapters) {
            ChapterVo chapterVo = new ChapterVo();
            BeanUtils.copyProperties(chapter, chapterVo);

            //爲章節創建children列表
            chapterVo.setChildren(new ArrayList<>());
            String chapterId = chapterVo.getId();
            //遍歷所有小節,將與chapterVo對應的小節存入children列表中
            for (EduVideo video : videos) {
                if (chapterId != null && chapterId.equals(video.getChapterId())){
                    ChapterVo videoVo = new ChapterVo();
                    BeanUtils.copyProperties(video, videoVo);
                    chapterVo.getChildren().add(videoVo);
                }
            }

            //將章節存入結果集中
            res.add(chapterVo);
        }

        return res;
    }
}

3、controller層

@RestController
@RequestMapping("/eduservice/chapter")
@CrossOrigin
@Api("課程章節管理")
public class EduChapterController {

    @Autowired
    private EduChapterService chapterService;

    @ApiOperation("根絕課程id獲取其對應的章節和小節")
    @GetMapping("list/{courseId}")
    public R getCourseChapter(
            @PathVariable("courseId") String courseId) {
        List<ChapterVo> list = chapterService.getChapterByCourseId(courseId);
        return R.ok().data("list", list);
    }
}

4、測試

打開swagger,找到接口輸入課程id,點擊執行
在這裏插入圖片描述

二、課程章節列表顯示前端實現

1、定義api

scr/api/edu下創建chapter.js,內容如下:

import request from '@/utils/request'

//表示導出,別的文件可以使用
export default {

    /**
     * 添加課程信息
     */
    getCourseChapter(courseId){
        return request({
            url: `/eduservice/chapter/list/${courseId}`,
            method: 'get',
          })
    },
}

2、定義組件腳本

定義data

courseId: '', // 所屬課程
chapterNestedList: [] // 章節嵌套課時列表

methods中添加方法

  methods: {
    //根據課程id獲取章節和小節信息
    getCourseChapter(){
      chapterApi.getCourseChapter(this.courseId)
            .then(response => {
              this.chapterNestedList = response.data.list
            })
    },
        ...//其他方法
  }

created中調用上述方法

  created() {
    //根據路由獲取url中的id值
    if(this.$route.params && this.$route.params.id){
      this.courseId = this.$route.params.id
      //根據課程id獲取章節和小節信息
      this.getCourseChapter()
    }
  },

3、定義組件模板

<el-button type="text">添加章節</el-button>
<!-- 章節 -->
<ul class="chanpterList">
    <li
        v-for="chapter in chapterNestedList"
        :key="chapter.id">
        <p>
            {{ chapter.title }}

            <span class="acts">
                <el-button type="text">添加課時</el-button>
                <el-button style="" type="text">編輯</el-button>
                <el-button type="text">刪除</el-button>
            </span>
        </p>

        <!-- 視頻 -->
        <ul class="chanpterList videoList">
            <li
                v-for="video in chapter.children"
                :key="video.id">
                <p>{{ video.title }}
                    <span class="acts">
                        <el-button type="text">編輯</el-button>
                        <el-button type="text">刪除</el-button>
                    </span>
                </p>
            </li>
        </ul>
    </li>
</ul>
<div>
    <el-button @click="previous">上一步</el-button>
    <el-button :disabled="saveBtnDisabled" type="primary" @click="next">下一步</el-button>
</div>

4、定義樣式

將樣式的定義放在頁面的最後

scope表示這裏定義的樣式只在當前頁面範圍內生效,不會污染到其他的頁面

<style scoped>
.chanpterList{
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0;
}
.chanpterList li{
  position: relative;
}
.chanpterList p{
  float: left;
  font-size: 20px;
  margin: 10px 0;
  padding: 10px;
  height: 70px;
  line-height: 50px;
  width: 100%;
  border: 1px solid #DDD;
}
.chanpterList .acts {
    float: right;
    font-size: 14px;
}
.videoList{
  padding-left: 50px;
}
.videoList p{
  float: left;
  font-size: 14px;
  margin: 10px 0;
  padding: 10px;
  height: 50px;
  line-height: 30px;
  width: 100%;
  border: 1px dotted #DDD;
}
</style>

5、效果

在這裏插入圖片描述

三、課程信息回顯實現

1、業務層

接口:CourseService.java

CourseInfoVo getCourseInfoById(String id);

實現:CourseServiceImpl.java

    /**
     * 根據課程id獲取課程基本信息和課程描述信息
     * 並封裝到CourseInfoVo中
     * @param id
     * @return
     */
    @Override
    public CourseInfoVo getCourseInfoById(String id) {
        CourseInfoVo courseInfo = new CourseInfoVo();

        //從數據庫獲取課程基本信息
        EduCourse eduCourse = baseMapper.selectById(id);
        //將基本信息賦值給courseInfo
        BeanUtils.copyProperties(eduCourse, courseInfo);

        //從數據庫獲取課程描述信息,描述信息id和課程信息一致
        EduCourseDescription description = descriptionService.getById(id);
        courseInfo.setDescription(description.getDescription());

        return courseInfo;
    }

2、controller層

    @ApiOperation(value = "根據id獲取課程基本信息")
    @GetMapping("{id}")
    public R getCourseById(@PathVariable String id) {
        //根據id獲取課程基本信息,包括課程描述信息
        CourseInfoVo course = courseService.getCourseInfoById(id);
        return R.ok().data("course", course);
    }

後端實現之後,接下來實現前端的內容

3、定義api

api/edu/course.js中添加如下內容

    /**
     * 根據課程id獲取課程基本信息和課程描述信息
     */
    getCourseInfoById(id){
        return request({
            url: `/eduservice/course/${id}`,
            method: 'get',
          })
    },

4、修改chapter.vue中的跳轉路徑

    previous() {
      console.log('previous')
      this.$router.push({ path: '/course/info/'+this.courseId })
    },

    next() {
      console.log('next')
      this.$router.push({ path: '/course/publish/'+this.courseId })
    }

5、定義data

在course.vue中

  data() {
    return {
      ...
      courseId: '', //修改時路徑中傳來的課程id
      ...
    }
  }

6、編寫方法

在course.vue中

  methods: {
    //根據課程id獲取課程信息
    getCourseInfo(id){
        courseApi.getCourseInfoById(id)
            .then(response => {
                this.courseInfo = response.data.course
            })
    },
    ...
  }

7、初始化時調用方法

在course.vue中

  created() {
    //根據路由獲取url中的id值
    if(this.$route.params && this.$route.params.id){
        this.courseId = this.$route.params.id
        this.getCourseInfo(this.courseId)
    }

    this.getAllTeacherList()
    this.getAllSubjectrList()
  },

8、測試

在這裏插入圖片描述

四、解決級聯下拉菜單回顯問題

可以看到上面的測試中課程的二級類編顯示是id而不是名稱,所以我們需要進行解決

1、修改init方法

將 this.initSubjectList()移至else

  created() {
    //根據路由獲取url中的id值
    if(this.$route.params && this.$route.params.id){ //修改
        this.courseId = this.$route.params.id
        this.getCourseInfo(this.courseId)
    } else{ //添加
        this.getAllSubjectrList()
    }
    //獲取講師列表
    this.getAllTeacherList()
  },

2、修改getCourseInfo方法

    //根據課程id獲取課程信息
    getCourseInfo(id){
        courseApi.getCourseInfoById(id)
            .then(response => {
                this.courseInfo = response.data.course
                //調用接口獲取所有的課程分類信息
                subjectApi.getAllSubject()
                    .then(response => {
                        debugger
                        this.subjectParentList = response.data.list
                        //對一級分類進行遍歷找到其中courseId與this.courseId相等的一級分類
                        //並將其中包含的二級分類信息賦值爲this.subSubjidectList
                        for (let i = 0; i < this.subjectParentList.length; i++) {
                            if (this.subjectParentList[i].id === this.courseInfo.subjectParentId) {
                            this.subSubjectList = this.subjectParentList[i].children
                            }
                        }
                    })
            })
    },

3、效果

在這裏插入圖片描述

五、課程信息的更新實現

1、業務層

接口:CourseService.java

void updateCourseInfo(CourseInfoVo course);

實現:CourseServiceImpl.java

    /**
     * 更新課程基本信息和描述信息
     * @param courseInfo
     */
    @Override
    public void updateCourseInfo(CourseInfoVo courseInfo) {
        //創建並賦值EduCourse對象
        EduCourse course = new EduCourse();
        BeanUtils.copyProperties(courseInfo, course);
        //更新數據庫
        int update1 = baseMapper.updateById(course);
        if (update1 == 0) {
            throw new CustomException(20001, "修改課程基本信息失敗");
        }
        //創建並賦值EduCourseDescription對象
        EduCourseDescription description = new EduCourseDescription();
        description.setId(courseInfo.getId());
        description.setDescription(courseInfo.getDescription());
        description.setGmtModified(new Date());
        //更新數據庫
        boolean update2 = descriptionService.updateById(description);
        if (!update2) {
            throw new CustomException(20001, "修改課程描述信息失敗");
        }
    }

2、controller層

    @ApiOperation(value = "根據課程基本信息,包括課程描述信息")
    @PostMapping("update")
    public R updateCourse(@RequestBody CourseInfoVo course) {
        courseService.updateCourseInfo(course);
        return R.ok();
    }

後端實現之後,接下來實現前端的內容

3、定義api

api/edu/course.js中添加如下內容

   /**
     * 更新課程基本信息和描述信息
     */
    updateCourseInfo(courseInfo){
        return request({
            url: `/eduservice/course/update`,
            method: 'post',
            data:courseInfo
          })
    },

4、組件js

將之前的next方法修改爲下面的內容

    //添加或者修改課程信息
    next() {
        //更新時會從接口查詢出courseInfo,其中會包括id
        if(this.courseInfo.id){ //修改
            this.updateCourse()
        } else {
            this.addCourse()
        }
    },

    //修改課程信息
    updateCourse(){
        courseApi.updateCourseInfo(this.courseInfo)
            .then(response => {
                this.$message({
                    type: 'success',
                    message: '修改課程信息成功'
                })
                this.$router.push({ path: '/course/chapter/'+this.courseId })
            })
            .catch(error => {
                this.saveBtnDisabled = false
                console.log(error)
            }) //請求失敗
    },

    //添加課程信息
    addCourse(){
        console.log('next')
        this.saveBtnDisabled = true
        courseApi.addCourseInfo(this.courseInfo)
                .then(response=>{
                    this.$message({
                        type: 'success',
                        message: '添加課程信息成功'
                    })
                    this.$router.push({ path: '/course/chapter/'+response.data.id })
                })
                .catch(error => {
                    this.saveBtnDisabled = false
                    console.log(error)
                }) //請求失敗
    }

5、測試

首先在表單中輸入信息並點擊保存下一步

在這裏插入圖片描述

之後點擊上一步,再次修改表單內容表單

在這裏插入圖片描述

點擊保存並下一步,提示修改課程信息成功

在這裏插入圖片描述

查看數據庫中已經修改成功

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章