谷粒学苑 —— 6、课程管理:课程发布页面1 —— 添加课程信息

目录

1、使用代码生成器生成代码

2、添加课程信息

2.1、后端代码

2.1.1、创建 VO 类用于封装表单信息

2.1.2、修改课程简介实体类的主键生成策略

2.1.3、Service 方法

2.1.4、Controller 方法

2.2、前端

2.2.1、添加路由

2.2.2、整合步骤条组件

2.2.3、讲师下拉列表

2.2.3.1、组件

2.2.3.2、定义 API

2.2.3.3、组件脚本

2.2.4、课程多级分类联动下拉列表

2.2.4.1、组件

2.2.4.2、组件脚本

2.2.5、课程简介整合 Tinymce

2.2.5.1、获取相关组件

2.2.5.2、配置 HTML 变量

2.2.5.3、在页面引入 JS 脚本

2.2.5.4、在需要使用的页面引入组件

2.2.5.5、添加组件样式

2.2.5.6、页面组件

4、课程信息修改

4.1、后端

4.1.1、根据课程 ID 查询课程信息

4.1.2、根据课程 ID 修改课程信息

4.2、前端

4.2.1、定义 API

4.2.2、课程信息回显及监听路由变化

4.2.3、实现修改

5、课程信息完整页面(含表单校验)


1、使用代码生成器生成代码

在 CodeGenerator 中修改代码生成对应的表名

strategy.setInclude("edu_course", "edu_course_description", "edu_chapter", "edu_video"); // 对应的表名

修改完后执行即可,生成后可以将 EduCourseDescriptionController 课程简介的 Controller 删去,将课程简介相关代码放在 EduCourseController 中。

并在 EduCourseController 的上面添加 @CrossOrigin 注解解决跨域问题,在每个 mapper 上添加 @Mapper 注解

2、添加课程信息

2.1、后端代码

2.1.1、创建 VO 类用于封装表单信息

@ApiModel(value = "课程基本信息", description = "编辑课程基本信息的表单对象")
@Data
public class CourseInfoVO 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 subjectParentId;

    @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.1.2、修改课程简介实体类的主键生成策略

修改为手动设置 

    @ApiModelProperty(value = "课程ID")
    @TableId(value = "id", type = IdType.INPUT)
    private String id;

2.1.3、Service 方法

在 EduCourseService 中添加方法

    /**
     * 添加课程基本信息
     * @param courseInfoVO 课程基本信息的表单对象
     * @return 返回添加后的课程信息id
     */
    String saveCourseInfo(CourseInfoVO courseInfoVO);

在 EduCourseServiceImpl 中添加方法

    @Autowired
    private EduCourseDescriptionService courseDescriptionService;

    /**
     * 添加课程基本信息
     * @param courseInfoVO 课程基本信息的表单对象
     */
    @Override
    public String saveCourseInfo(CourseInfoVO courseInfoVO) {
        // 向课程表添加课程基本信息
        EduCourse eduCourse = new EduCourse();
        BeanUtils.copyProperties(courseInfoVO, eduCourse);
        boolean isSave = this.save(eduCourse);
        if(!isSave) {
            // 添加失败
            throw new GuliException(20001, "添加课程信息失败");
        }

        String id = eduCourse.getId();

        // 向课程简介表添加课程简介
        EduCourseDescription courseDescription = new EduCourseDescription();
        courseDescription.setId(id);
        courseDescription.setDescription(courseInfoVO.getDescription());
        courseDescriptionService.save(courseDescription);

        return id;
    }

2.1.4、Controller 方法

在 EduCourseController 中添加方法

    @Autowired
    private EduCourseService courseService;

    /**
     * 添加课程基本信息
     * @param courseInfoVO 课程基本信息的表单对象
     * @return 返回添加后的课程信息id
     */
    @PostMapping("/addCourseInfo")
    public R addCourseInfo(
            @ApiParam(name = "CourseInfoVO", value = "课程基本信息的表单对象", required = true) @RequestBody CourseInfoVO courseInfoVO
    ){
        String id = courseService.saveCourseInfo(courseInfoVO);
        return R.ok();
    }

2.2、前端

2.2.1、添加路由

在 src\router\index.js 中添加路由

  {
    path: '/course',
    component: Layout,
    redirect: '/course/lsit',
    name: '课程管理',
    meta: { title: '课程管理', icon: 'example' },
    children: [  // 子标签
      {
        path: 'table',
        name: '课程列表',
        component: () => import('@/views/edu/course/list'),
        meta: { title: '课程列表', icon: 'table' }
      },
      {
        path: 'save',
        name: '添加课程',
        component: () => import('@/views/edu/course/info'), 
        meta: { title: '添加课程', icon: 'tree' }
      },
      {
        path: 'info/:id',
        name: 'EduCourseInfoEdit',
        component: () => import('@/views/edu/course/info'),
        meta: { title: '编辑课程基本信息', noCache: true },
        hidden: true  // 隐藏路由
      },
      {
        path: 'chapter/:id',
        name: 'EduCourseChapterEdit',
        component: () => import('@/views/edu/course/chapter'),
        meta: { title: '编辑课程大纲', noCache: true },
        hidden: true
      },
      {
        path: 'publish/:id',
        name: 'EduCoursePublishEdit',
        component: () => import('@/views/edu/course/publish'),
        meta: { title: '发布课程', noCache: true },
        hidden: true
      }
    ]
  },

2.2.2、整合步骤条组件

src\views\edu\course\info.vue

<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="1" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="提交审核"/>
    </el-steps>

    <el-form label-width="120px">

      <el-form-item>
        <el-button :disabled="saveBtnDisabled" type="primary" @click="next">保存并下一步</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      saveBtnDisabled: false // 保存按钮是否禁用
    }
  },

  created() {
    console.log('info created')
  },

  methods: {

    next() {
      console.log('next')
      this.$router.push({ path: '/edu/course/chapter/1' })
    }
  }
}
</script>

src\views\edu\course\chapter.vue

<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="2" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="提交审核"/>
    </el-steps>

    <el-form label-width="120px">

      <el-form-item>
        <el-button @click="previous">上一步</el-button>
        <el-button :disabled="saveBtnDisabled" type="primary" @click="next">下一步</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>

export default {
  data() {
    return {
      saveBtnDisabled: false // 保存按钮是否禁用
    }
  },

  created() {
    console.log('chapter created')
  },

  methods: {
    previous() {
      console.log('previous')
      this.$router.push({ path: '/edu/course/info/1' })
    },

    next() {
      console.log('next')
      this.$router.push({ path: '/edu/course/publish/1' })
    }
  }
}
</script>

src\views\edu\course\publish.vue

<template>

  <div class="app-container">

    <h2 style="text-align: center;">发布新课程</h2>

    <el-steps :active="3" process-status="wait" align-center style="margin-bottom: 40px;">
      <el-step title="填写课程基本信息"/>
      <el-step title="创建课程大纲"/>
      <el-step title="提交审核"/>
    </el-steps>

    <el-form label-width="120px">

      <el-form-item>
        <el-button @click="previous">返回修改</el-button>
        <el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>

export default {
  data() {
    return {
      saveBtnDisabled: false // 保存按钮是否禁用
    }
  },

  created() {
    console.log('publish created')
  },

  methods: {
    previous() {
      console.log('previous')
      this.$router.push({ path: '/edu/course/chapter/1' })
    },

    publish() {
      console.log('publish')
      this.$router.push({ path: '/edu/course/list' })
    }
  }
}
</script>

2.2.3、讲师下拉列表

2.2.3.1、组件

            <!-- 课程讲师 -->
            <el-form-item label="课程讲师">
                <el-select v-model="courseInfo.teacherId" placeholder="请选择">
                    <el-option 
                        v-for="teacher in teacherList" 
                        :key="teacher.id" 
                        :label="teacher.name"
                        :value="teacher.id" 
                    />
                </el-select>
            </el-form-item>

2.2.3.2、定义 API

src\api\edu\course.js

    /**
     * 获取所有讲师信息
     * @returns 
     */
    getTeacherList() {
        return request({
            url: '/eduservice/teacher/findAll',
            method: 'GET'
        })
    }

2.2.3.3、组件脚本

在 data 中定义

teacherList: [],    // 所有讲师信息

页面渲染前获取讲师信息

    created() {
        this.getListTeacher();
    },
    methods: {
        /**
         * 获取所有讲师信息
         */
        getListTeacher() {
            course.getTeacherList().then(response => {
                this.teacherList = response.data.items;
            })
        }
    }

2.2.4、课程多级分类联动下拉列表

2.2.4.1、组件

            <!-- 所属分类 -->
            <el-form-item label="课程类别">
                <!-- 一级分类 -->
                <el-select v-model="courseInfo.subjectParentId" placeholder="一级分类" @change="subjectLevelOneChanged">
                    <el-option 
                        v-for="subject in subjectOneList" 
                        :key="subject.id" 
                        :label="subject.title"
                        :value="subject.id" 
                    />
                </el-select>
                <!-- 二级分类 -->
                <el-select v-model="courseInfo.subjectId" placeholder="二级分类">
                    <el-option 
                        v-for="subject in subjectTwoList" 
                        :key="subject.id" 
                        :label="subject.title" 
                        :value="subject.id" 
                    />
                </el-select>
            </el-form-item>

2.2.4.2、组件脚本

在 data 中定义

            subjectOneList: [], // 所有一级分类
            subjectTwoList: [], // 所有二级分类

使用

    created() {
        this.getListTeacher();
        this.getOneSubject();
    },
    methods: {
        /**
         * 查询所有一级分类(一级分类下含有其包含的二级分类)
         */
        getOneSubject() {
            subject.getSubjectList().then(response => {
                this.subjectOneList = response.data.list;
            })
        },

        /**
         * 更换选择的一级分类调用的方法,更新二级分类数据
         * @param {*} value 一级分类ID
         */
        subjectLevelOneChanged(value) {
            // 初始化
            this.subjectTwoList = [];
            this.courseInfo.subjectId = '';

            // 遍历所有一级分类,若其ID和value的值相等,将其孩子(二级分类)赋值给subjectTwoList
            for(var i = 0; i < this.subjectOneList.length; i++) {
                if(value === this.subjectOneList[i].id) {
                    this.subjectTwoList = this.subjectOneList[i].children;
                }
            }
        }
    }

2.2.5、课程简介整合 Tinymce

2.2.5.1、获取相关组件

在项目源码的 day07 的 富文本编辑器组件 中,复制到项目对应的目录下

2.2.5.2、配置 HTML 变量

在 build\webpack.dev.conf.js 添加配置,使在 htm l页面中可以使用这里定义的BASE_URL变量

new HtmlWebpackPlugin({
    ......,
    templateParameters: {
        BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory
    }
})

2.2.5.3、在页面引入 JS 脚本

在 index.html 中引入

<script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
<script src=<%= BASE_URL %>/tinymce4.7.5/langs/zh_CN.js></script>

引入后若报错,需要重启项目

2.2.5.4、在需要使用的页面引入组件

在 src\views\edu\course\info.vue 中引入

import Tinymce from '@/components/Tinymce'

export default {
    // 声明组件
    components: {Tinymce},
    ……,
}

2.2.5.5、添加组件样式

在 src\views\edu\course\info.vue 的末尾添加组件样式

<style scoped>
.tinymce-container {
    line-height: 29px;
}
</style>

2.2.5.6、页面组件

            <!-- 课程简介 -->
            <el-form-item label="课程简介">
                <tinymce :height="300" v-model="courseInfo.description" />
            </el-form-item>

4、课程信息修改

在课程大纲页面点击上一步后,可以回显课程信息,并且可以保存修改

4.1、后端

4.1.1、根据课程 ID 查询课程信息

EduCourseService

    /**
     * 根据课程ID查询课程信息
     * @param courseId 课程ID
     * @return
     */
    CourseInfoVO getCourseInfo(String courseId);

EduCourseServiceImpl

    /**
     * 根据课程ID查询课程信息
     * @param courseId 课程ID
     * @return
     */
    @Override
    public CourseInfoVO getCourseInfo(String courseId) {
        CourseInfoVO courseInfoVO = new CourseInfoVO();

        // 查询课程基本信息
        EduCourse course = this.getById(courseId);
        BeanUtils.copyProperties(course, courseInfoVO);

        // 查询课程简介
        EduCourseDescription description = courseDescriptionService.getById(courseId);
        BeanUtils.copyProperties(description, courseInfoVO);

        return courseInfoVO;
    }

EduCourseController

    /**
     * 根据课程ID查询课程信息
     * @return
     */
    @ApiOperation(value = "根据课程ID查询课程信息")
    @GetMapping("/getCourseInfo/{courseId}")
    public R getCourseInfo(
            @ApiParam(name = "courseId", value = "课程ID", required = true) @PathVariable String courseId
    ) {
        CourseInfoVO course = courseService.getCourseInfo(courseId);
        return R.ok().data("courseInfo", course);
    }

4.1.2、根据课程 ID 修改课程信息

EduCourseService

    /**
     * 更新指定课程ID的课程
     * @param courseInfoVO 修改内容
     */
    void updateCourseInfo(CourseInfoVO courseInfoVO);

EduCourseServiceImpl

    /**
     * 更新指定课程ID的课程
     * @param courseInfoVO 修改内容
     */
    @Override
    public void updateCourseInfo(CourseInfoVO courseInfoVO) {
        // 修改课程表
        EduCourse eduCourse = new EduCourse();
        BeanUtils.copyProperties(courseInfoVO, eduCourse);
        boolean a = this.updateById(eduCourse);
        if(!a){
            throw new GuliException(20001, "修改课程基本信息失败");
        }

        // 修改简介表
        EduCourseDescription courseDescription = new EduCourseDescription();
        courseDescription.setId(courseInfoVO.getId());
        courseDescription.setDescription(courseInfoVO.getDescription());
        boolean b = courseDescriptionService.updateById(courseDescription);
        if(!b) {
            throw new GuliException(20001, "修改课程简介失败");
        }
    }

EduCourseController

    /**
     * 更新指定课程ID的课程
     * @param courseInfoVO 修改内容
     * @return
     */
    @ApiOperation("更新指定课程ID的课程")
    @PostMapping("/updateCourseInfo")
    public R updateCourseInfo(
            @ApiParam(name = "courseInfoVO", value = "课程基本信息", required = true) @RequestBody CourseInfoVO courseInfoVO
    ) {
        courseService.updateCourseInfo(courseInfoVO);
        return R.ok();
    }

4.2、前端

4.2.1、定义 API

在 src\api\edu\course.js 中定义方法

    /**
     * 根据课程ID获取课程信息
     * @param {*} courseId 
     * @returns 
     */
    getCourseInfoById(courseId) {
        return request({
            url: `/eduservice/course/getCourseInfo/${courseId}`,
            method: 'GET'
        })
    },

    /**
     * 修改指定课程ID的信息
     * @param {*} courseInfo 
     * @returns 
     */
    updateConrseInfo(courseInfo) {
        return request({
            url: `/eduservice/course//updateCourseInfo`,
            method: 'POST',
            data: courseInfo
        })
    }

4.2.2、课程信息回显及监听路由变化

在 methods 中定义方法

        /**
         * 根据课程ID获取课程信息,同时给课程分类的级联下拉列表赋值
         */
        getCourseInfoById() {
            course.getCourseInfoById(this.courseId).then(response => {
                this.courseInfo = response.data.courseInfo;     // 获取课程信息

                subject.getSubjectList().then(response => {
                    this.subjectOneList = response.data.list;   // 一级分类赋值
                    this.subjectTwoList = [];   // 初始化二级分类

                    // 遍历所有一级分类
                    for (var i = 0; i < this.subjectOneList.length; i++) {
                        if (this.courseInfo.subjectParentId === this.subjectOneList[i].id) {
                            // 二级分类赋值
                            this.subjectTwoList = this.subjectOneList[i].children;
                        }
                    }
                });
            })
        },

        /**
         * 初始化数据
         */
        init() {
            this.getListTeacher();  // 获取所有教师信息

            // 获取路由ID值
            if (this.$route.params && this.$route.params.id) {
                this.courseId = this.$route.params.id;
                this.getCourseInfoById();   // 获取课程信息
            } else {
                this.courseInfo = {
                    title: '',
                    subjectId: '',  // 二级分类ID
                    subjectParentId: '', // 一级分类ID
                    teacherId: '',
                    lessonNum: undefined,
                    description: null,
                    cover: '/static/course_cover.jpg',
                    price: ''
                };
                this.courseInfo.description = null; // 解决Tinymce富文本清空不了问题
                this.getOneSubject();   // 获取所有一级分类
            }
        },

在 created 和 watch 中调用

    watch: {
        // 路由发生变化就会执行
        $route(to, from) {
            this.init();
        }
    },
    created() {
        this.init();
    },

4.2.3、实现修改

修改 methods 中的 saveOrUpdate 方法,并添加方法

        /**
         * 点击下一步跳转到src\views\edu\course\chapter.vue页面
         * 同时保存或修改课程信息
         */
        saveOrUpdate() {
            if(!this.courseId) {
                this.addCourseInfo();
            } else {
                this.updateCourseInfo();
            }
        },

        /**
         * 添加课程信息
         */
        addCourseInfo() {
            this.$refs['loginForm'].validate((valid) => {
                if (valid) {
                    course.addCourseInfo(this.courseInfo).then(response => {
                        // 提示
                        this.$message({
                            type: 'success',
                            message: '课程信息保存成功'
                        });

                        // 跳转到下一页面,附带课程信息id
                        this.$router.push({ path: '/course/chapter/' + response.data.courseId });
                    })
                } else {
                    return false;
                }
            });
        },

        /**
         * 修改课程信息
         */
        updateCourseInfo() {
            this.$refs['loginForm'].validate((valid) => {
                if (valid) {
                    course.updateConrseInfo(this.courseInfo).then(response => {
                        // 提示
                        this.$message({
                            type: 'success',
                            message: '课程信息修改成功'
                        });

                        // 跳转到下一页面,附带课程信息id
                        this.$router.push({ path: '/course/chapter/' + this.courseId });
                    })
                } else {
                    return false;
                }
            });
        }

5、课程信息完整页面(含表单校验)

<template>
    <div class="app-container">
        <h2 style="text-align: center;">发布新课程</h2>

        <el-steps :active="1" process-status="wait" align-center style="margin-bottom: 40px;">
            <el-step title="填写课程基本信息" />
            <el-step title="创建课程大纲" />
            <el-step title="最终发布" />
        </el-steps>

        <el-form label-width="120px" :rules="rules" ref="loginForm" :model="courseInfo">
            <el-form-item label="课程标题" prop="title">
                <el-input v-model="courseInfo.title" placeholder=" 示例:机器学习项目课:从基础到搭建项目视频课程。专业名称注意大小写" />
            </el-form-item>

            <!-- 所属分类 -->
            <el-form-item label="课程类别">
                <el-col :span="5">
                    <el-form-item prop="subjectParentId">
                        <!-- 一级分类 -->
                        <el-select v-model="courseInfo.subjectParentId" placeholder="一级分类" @change="subjectLevelOneChanged">
                            <el-option 
                                v-for="subject in subjectOneList" 
                                :key="subject.id" 
                                :label="subject.title"
                                :value="subject.id" 
                            />
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="5">
                    <el-form-item prop="subjectId">
                        <!-- 二级分类 -->
                        <el-select v-model="courseInfo.subjectId" placeholder="二级分类">
                            <el-option 
                                v-for="subject in subjectTwoList" 
                                :key="subject.id" 
                                :label="subject.title" 
                                :value="subject.id" 
                            />
                        </el-select>
                    </el-form-item>
                </el-col>
            </el-form-item>
            

            <!-- 课程讲师 -->
            <el-form-item label="课程讲师" prop="teacherId">
                <el-select v-model="courseInfo.teacherId" placeholder="请选择">
                    <el-option 
                        v-for="teacher in teacherList" 
                        :key="teacher.id" 
                        :label="teacher.name"
                        :value="teacher.id" 
                    />
                </el-select>
            </el-form-item>

            <el-form-item label="总课时" prop="lessonNum">
                <el-input-number :min="1" v-model="courseInfo.lessonNum" placeholder="请填写课程的总课时数" />
            </el-form-item>

            <!-- 课程简介 -->
            <el-form-item label="课程简介" prop="description">
                <tinymce ref="description" :height="300" v-model="courseInfo.description" />
            </el-form-item>

            <!-- 课程封面-->
            <el-form-item label="课程封面">
                <el-upload :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"
                    :action="BASE_API +'/eduoss/fileoss/upload'" class="avatar-uploader">
                    <img :src="courseInfo.cover">
                </el-upload>
            </el-form-item>

            <el-form-item label="课程价格">
                <el-input-number :min="0" v-model="courseInfo.price" controls-position="right"
                    placeholder="免费课程请设置为0元" /> 元
            </el-form-item>

            <el-form-item>
                <el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存并下一步</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>
<script>
import course from '@/api/edu/course'
import subject from '@/api/edu/subject'
import Tinymce from '@/components/Tinymce'

export default {
    // 声明组件
    components: {Tinymce},

    data() {
        return {
            saveBtnDisabled: false,
            courseInfo: {
                title: '',
                subjectId: '',  // 二级分类ID
                subjectParentId:'', // 一级分类ID
                teacherId: '',
                lessonNum: undefined,
                description: '',
                cover: '/static/course_cover.jpg',
                price: ''
            },
            teacherList: [],    // 所有讲师信息
            subjectOneList: [], // 所有一级分类
            subjectTwoList: [], // 所有二级分类
            BASE_API: process.env.BASE_API, // 接口API地址
            rules: {
                title: [
                    { required: true, message: '请输入课程名称', trigger: 'blur' },
                    { min: 2, max: 15, message: '长度在 2 到 15 个字符', trigger: 'blur' }
                ],
                subjectId: [
                    { required: true, message: '请选择活动区域', trigger: 'blur' }
                ],
                subjectParentId: [
                    { required: true, message: '请选择活动区域', trigger: 'blur' }
                ],
                teacherId: [
                    { required: true, message: '请选择活动区域', trigger: 'blur' }
                ],
                lessonNum: [
                    { required: true, message: '请输入课时数', type:'number', trigger: 'blur' }
                ],
                description: [
                    { required: true, message: '请选择讲师头衔', trigger: 'blur' }
                ]
            }
        }
    },
    watch: {
        // 路由发生变化就会执行
        $route(to, from) {
            this.init();
        }
    },
    created() {
        this.init();
    },
    methods: {
        /**
         * 获取所有讲师信息
         */
        getListTeacher() {
            course.getTeacherList().then(response => {
                this.teacherList = response.data.items;
            })
        },

        /**
         * 查询所有一级分类(一级分类下含有其包含的二级分类)
         */
        getOneSubject() {
            subject.getSubjectList().then(response => {
                this.subjectOneList = response.data.list;
            })
        },

        /**
         * 更换选择的一级分类调用的方法,更新二级分类数据
         * @param {*} value 一级分类ID
         */
        subjectLevelOneChanged(value) {
            // 初始化
            this.subjectTwoList = [];
            this.courseInfo.subjectId = '';

            // 遍历所有一级分类,若其ID和value的值相等,将其孩子(二级分类)赋值给subjectTwoList
            for(var i = 0; i < this.subjectOneList.length; i++) {
                if(value === this.subjectOneList[i].id) {
                    // 二级分类赋值
                    this.subjectTwoList = this.subjectOneList[i].children;
                }
            }
        },

        /**
         * 课程封面上传之前调用的方法:设置文件格式及大小
         * @param {*} file 上传的文件
         */
        beforeAvatarUpload(file) {
            const isJPG = file.type === 'image/jpeg';
            const isLt2M = file.size / 1024 / 1024 < 2;

            if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!');
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!');
            }
            return isJPG && isLt2M;
        },

        /**
         * 课程封面上传成功调用的方法
         * @param {*} res 就是response
         * @param {*} file 
         */
        handleAvatarSuccess(res, file) {
            this.courseInfo.cover = res.data.url;
        },

        /**
         * 根据课程ID获取课程信息,同时给课程分类的级联下拉列表赋值
         */
        getCourseInfoById() {
            course.getCourseInfoById(this.courseId).then(response => {
                this.courseInfo = response.data.courseInfo;     // 获取课程信息

                subject.getSubjectList().then(response => {
                    this.subjectOneList = response.data.list;   // 一级分类赋值
                    this.subjectTwoList = [];   // 初始化二级分类

                    // 遍历所有一级分类
                    for (var i = 0; i < this.subjectOneList.length; i++) {
                        if (this.courseInfo.subjectParentId === this.subjectOneList[i].id) {
                            // 二级分类赋值
                            this.subjectTwoList = this.subjectOneList[i].children;
                        }
                    }
                });
            })
        },

        /**
         * 初始化数据
         */
        init() {
            this.getListTeacher();  // 获取所有教师信息

            // 获取路由ID值
            if (this.$route.params && this.$route.params.id) {
                this.courseId = this.$route.params.id;
                this.getCourseInfoById();   // 获取课程信息
            } else {
                this.courseInfo = {
                    title: '',
                    subjectId: '',  // 二级分类ID
                    subjectParentId: '', // 一级分类ID
                    teacherId: '',
                    lessonNum: undefined,
                    description: null,
                    cover: '/static/course_cover.jpg',
                    price: ''
                };
                this.courseInfo.description = null; // 解决Tinymce富文本清空不了问题
                this.getOneSubject();   // 获取所有一级分类
            }
        },


        /**
         * 点击下一步跳转到src\views\edu\course\chapter.vue页面
         * 同时保存或修改课程信息
         */
        saveOrUpdate() {
            if(!this.courseId) {
                this.addCourseInfo();
            } else {
                this.updateCourseInfo();
            }
        },

        /**
         * 添加课程信息
         */
        addCourseInfo() {
            this.$refs['loginForm'].validate((valid) => {
                if (valid) {
                    course.addCourseInfo(this.courseInfo).then(response => {
                        // 提示
                        this.$message({
                            type: 'success',
                            message: '课程信息保存成功'
                        });

                        // 跳转到下一页面,附带课程信息id
                        this.$router.push({ path: '/course/chapter/' + response.data.courseId });
                    })
                } else {
                    return false;
                }
            });
        },

        /**
         * 修改课程信息
         */
        updateCourseInfo() {
            this.$refs['loginForm'].validate((valid) => {
                if (valid) {
                    course.updateConrseInfo(this.courseInfo).then(response => {
                        // 提示
                        this.$message({
                            type: 'success',
                            message: '课程信息修改成功'
                        });

                        // 跳转到下一页面,附带课程信息id
                        this.$router.push({ path: '/course/chapter/' + this.courseId });
                    })
                } else {
                    return false;
                }
            });
        }

        
    }
}
</script>
<style scoped>
.tinymce-container {
    line-height: 29px;
}
</style>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
谷粒是一个教育机构,提供课程培训和习资源,其中有一个叫做Jenkins.war的项目。 Jenkins是一个流行的开源持续集成和交付工具,它提供了一个可视化的界面,帮助自动化构建、测试和发布软件项目。 Jenkins.war则是Jenkins的可执行文件,以.war(Web Application Archive)格式打包。通过将Jenkins.war部署到Java应用服务器中,可以快速搭建起Jenkins服务器环境。 Jenkins.war具有以下特点和功能: 1. 可扩展性:Jenkins.war支持安装插件以扩展其功能。用户可以根据自己的需求选择并安装各种插件,如Git、Maven、SonarQube等。 2. 自动化构建:Jenkins.war能够监控软件代码库的变化,并在检测到新的提交或推送时自动触发构建任务。这样可以确保代码在每次变更后都能正确构建,减少手动操作和人为错误。 3. 高度可配置:Jenkins.war提供了丰富的配置选项,可以根据项目的需求进行精细调整。用户可以设置构建触发条件、构建步骤、构建环境等,以满足不同项目的特定要求。 4. 可视化界面:Jenkins.war提供了直观友好的web界面,方便用户管理和监控构建任务的执行情况。用户可以通过界面查看构建历史、日志输出、构建报告等信息,以便随时了解项目的状态。 总之,Jenkins.war是谷粒所提供的一个工具,能够帮助开发团队提高软件开发流程的效率和质量。通过使用Jenkins.war,可以实现自动化构建、持续集成和交付,从而加快软件开发周期,减少人力成本,并提升软件质量和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值