谷粒学苑_第七天

12 篇文章 0 订阅
10 篇文章 1 订阅

第七天

1.添加课程分类的前端

2.课程分类列表显示功能(树形)

3.课程管理模块需求

4.添加课程信息

课程信息

前端
添加路由

在src/router/index.js

  {
    path: '/subject',
    component: Layout,
    redirect: '/subject/list',
    name: '课程分类管理',
    meta: { title: '课程分类管理', icon: 'el-icon-s-help' },
    children: [
      {
        path: 'list',
        name: '课程分类列表',
        component: () => import('@/views/edu/subject/list'),
        meta: { title: '讲师列表', icon: 'table' }
      },
      {
        path: 'save',
        name: '添加课程分类',
        component: () => import('@/views/edu/subject/save'),
        meta: { title: '添加讲师', icon: 'tree' }
      }
    ]
  },

添加vue页面

在这里插入图片描述

上传页面

save.vue

<template>
  <div class="app-container">
    <el-form label-width="120px">
      <el-form-item label="信息描述">
        <el-tag type="info">excel文件</el-tag>
        <el-tag>
          <i class="el-icon-download"/>
          <a :href='"https://lkw-edu.oss-cn-chengdu.aliyuncs.com/01.xlsx"'>点击下载模版</a>
        </el-tag>
      </el-form-item>
      <el-form-item label="选择Excel">
        <el-upload
          ref="upload"
          :auto-upload="false"
          :on-exceed="fileUploadExceed"
          :on-success="fileUploadSuccess"
          :on-error="fileUploadError"
          :limit="1"
          action="http://localhost:8001/eduservice/subject/addSubject"
          name="file"
          accept="application/vnd.ms-excel">
          <!-- 设置接收的类型 -->
          <el-button
            slot="trigger"
            size="small"
            type="primary">选取文件</el-button>
          <el-button
            :disabled="importBtnDisabled"
            style="margin-left: 10px;"
            size="small"
            type="success"
            @click="submitUpload()">导入</el-button>
        </el-upload>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
 
  data() {
    return {
      //BASE_API: process.env.BASE_API, // 接口API地址

      importBtnDisabled: false, // 按钮是否禁用,
      loading: false,
    };
  },
  created() {},
  methods: {
    //点击按钮上传文件到接口里:   导入
    submitUpload(){
      this.importBtnDisabled=true
      this.loading=true
      this.$refs.upload.submit()

    },
    //上传成功:   成功
    fileUploadSuccess(){
      //提示信息
      this.loading=false
      this.$message({
        type: 'success',
        message: '添加课程分类成功'
      })
      //跳转课程分类列表
      //路由跳转
      this.$router.push({path:'/subject/list'})

      
    },
    //上传失败
    fileUploadError(){
      //提示信息
      this.loading=false
      this.$message({
        type: 'error',
        message: '添加课程分类失败'
      })
    }
  


  },
};
</script>
controller

要返回二级的json格式,不用拼接,效率低

所以使用二级实体类

OneSubject.java

package com.lkw.eduservice.entity.subject;

import lombok.Data;

//二级分类
@Data
public class TwoSubject {

    private String id;
    private String title;
}

TwoSubject.java

package com.lkw.eduservice.entity.subject;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

//一级分类
@Data
public class OneSubject {

    private String id;
    private String title;
    //集合存储多个二级分类
    private List<TwoSubject> children=new ArrayList<>();
}

controller封装:

    //课程分类列表(树形)
    @GetMapping("getAllSubject")
    public R getAllSubject(){
        //list集合泛型是一级分类
        List<OneSubject> list=subjectService.getAllOneTwoSubject();
        return R.ok().data("list",list);
    }

接口:

    List<OneSubject> getAllOneTwoSubject();

实现类:

    //课程分类列表(树形)
    @Override
    public List<OneSubject> getAllOneTwoSubject() {

        //1、查出所有一级分裂 parentid=0
        QueryWrapper<EduSubject> wrapperOne = new QueryWrapper<>();
        wrapperOne.eq("parent_id","0");
        List<EduSubject> oneSubjectList = baseMapper.selectList(wrapperOne);

        //2、查出所有二级分类 parentid!=0
        QueryWrapper<EduSubject> wrapperTwo = new QueryWrapper<>();
        wrapperTwo.ne("parent_id","0");
        List<EduSubject> twoSubjectList = baseMapper.selectList(wrapperTwo);

        //创建list集合,用于存储最终封装数据
        List<OneSubject> finalSubjectList = new ArrayList<>();

        //3、封装一级分类
        //查出出所有的一级分类list集合遍历,得到每一个一级分类对象,获取每一个分类对象值
        //封装到要求的list集合里面List<OneSubject> finalSubjectList
        for (int i = 0; i < oneSubjectList.size(); i++) {
            //得到oneSubjectList每个eduSubject
            EduSubject eduSubject = oneSubjectList.get(i);
            //把多个eduSubject里面值取出来,放到OneSubject对象里面
            OneSubject oneSubject = new OneSubject();
            //oneSubject.setId(eduSubject.getId());
            //oneSubject.setTitle(eduSubject.getTitle());
            //eduSubject值复制到oneSubject里面
            BeanUtils.copyProperties(eduSubject,oneSubject);
            //多个OneSubject放到finalSubjectList里面
            finalSubjectList.add(oneSubject);

            //4、封装二级分类
            //在一级分类循环遍历查询所有的二级分类
            //在创建list集合封装每一个一级分类的二级分类
            List<TwoSubject> twoFinalSubjectList = new ArrayList<>();
            //遍历二级分类list集合
            for (int m = 0; m < twoSubjectList.size(); m++) {
                //获取每个二级分类
                EduSubject tSubject = twoSubjectList.get(m);
                //判断二级分类parentid和一级分类id是否一样
                if(tSubject.getParentId().equals(eduSubject.getId())){
                    //把tSubject值复制到TwoSubject里面,放到twoFinalSubject里面
                    TwoSubject twoSubject = new TwoSubject();
                    BeanUtils.copyProperties(tSubject,twoSubject);
                    twoFinalSubjectList.add(twoSubject);
                }
            }
            //把一级下面所有的二级分类放到一级分类里面
            oneSubject.setChildren(twoFinalSubjectList);
        }


        return finalSubjectList;
    }


丝袜哥测试

http://localhost:8001/swagger-ui/#/edu-subject-controller/getAllSubjectUsingGET
在这里插入图片描述

前端树形显示

创建src\api\subject\subject.js

import request from '@/utils/request'


export default{

  getSubjectList() {
    return request({
      //细节:url后面是`不是'
      url: `http://localhost:8001/eduservice/subject`,
      method: 'get',
      //teacherQuery条件对象,后端使用RequestBody获取数据
      //data表示把对象转换json进行传递到接口里面
    })
  }
}

在list.vue

<template>
  <div class="app-container">
    <el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;" />

    <el-tree
      ref="tree2"
      :data="data2"
      :props="defaultProps"
      :filter-node-method="filterNode"
      class="filter-tree" 
      default-expand-all
    />

  </div>
</template>

<script>
import subject from '@/api/subject/subject'
export default {  

  data() {
    return {
      filterText: '',
      data2: [],//返回的所有分类
      defaultProps: {
        children: 'children',
        label: 'title'
      }
    }
  },
  created(){
    this.getAllSubjectList()
  },
  watch: {
    filterText(val) {
      this.$refs.tree2.filter(val)
    }
  },

  methods: {
    getAllSubjectList(){
        subject.getSubjectList()
        .then(response=>{
            this.data2=response.data.list
        })

    },
    filterNode(value, data) {
      if (!value) return true
      return data.title.indexOf(value) !== -1
    }
  }
}
</script>


效果:
在这里插入图片描述

路由跳转和搜索改进

课程管理

需要实现相当复杂的数据库操作
在这里插入图片描述

课程添加

需要个步骤条
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

mybatisX生成

生成除了这两个的其他包:
在这里插入图片描述
在这里插入图片描述

注意这几个地点
在这里插入图片描述

创建完成

但是要处理一些小问题

比如说:

详细的可以在github上对照:https://github.com/like-wen/guli_edu.git

然后把各种id改成:varchar32位的,因为我自己配置的雪花算法是用的32位的

在这里插入图片描述

写好各个Controller

@RestController
@CrossOrigin
@RequestMapping("/eduservice/course")
public class EduChapterController {
}

不需要EduCourseDescriptionController.java

创建vo类

作为提交数据封装

CourseInfoVo.java

package com.lkw.eduservice.entity.vo;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;

@Data
public class CourseInfoVo {
    @ApiModelProperty(value = "课程ID")
    private String id;

    @ApiModelProperty(value = "课程讲师ID")
    private String teacherId;

    @ApiModelProperty(value = "课程专业ID")
    private String subjectId;

    @ApiModelProperty(value = "课程专业父级ID")
    private String subjectParentId;

    @ApiModelProperty(value = "课程标题")
    private String title;

    @ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")
    // 0.01
    private BigDecimal price;

    @ApiModelProperty(value = "总课时")
    private Integer lessonNum;

    @ApiModelProperty(value = "课程封面图片路径")
    private String cover;

    @ApiModelProperty(value = "课程简介")
    private String description;
}

Controller

package com.lkw.eduservice.controller;

import com.lkw.commonutils.R;
import com.lkw.eduservice.entity.vo.CourseInfoVo;
import com.lkw.eduservice.service.EduCourseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@CrossOrigin
@RequestMapping("/eduservice/course")
public class EduCourseController {



    @Autowired
    private EduCourseService courseService;
    //添加课程基本信息的方法
    @PostMapping("addCourseInfo")
    public R addCourseInfo(@RequestBody CourseInfoVo courseInfoVo){

        courseService.saveCourseInfo(courseInfoVo);



        return R.ok();
    }

}

impl

package com.lkw.eduservice.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lkw.eduservice.entity.EduCourse;
import com.lkw.eduservice.entity.EduCourseDescription;
import com.lkw.eduservice.entity.vo.CourseInfoVo;
import com.lkw.eduservice.service.EduCourseDescriptionService;
import com.lkw.eduservice.service.EduCourseService;
import com.lkw.eduservice.mapper.EduCourseMapper;
import com.lkw.servicebase.exceptionhandler.GuliException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse>
    implements EduCourseService{



    @Autowired
    private EduCourseDescriptionService courseDescriptionService;

    @Override
    public void saveCourseInfo(CourseInfoVo courseInfoVo) {

        //Vo转换成entity类
        EduCourse eduCourse = new EduCourse();
        BeanUtils.copyProperties(courseInfoVo,eduCourse );

        int insert = baseMapper.insert(eduCourse);
        if(insert<=0){
            //添加失败
            throw new GuliException(20001,"添加课程失败");
        }
        //添加成功获取id
        String cid = eduCourse.getId();

        //课程描述
        EduCourseDescription courseDescription = new EduCourseDescription();
        courseDescription.setDescription(courseInfoVo.getDescription());
        courseDescription.setId(cid);
        courseDescriptionService.save(courseDescription);

    }
}
前端部分

添加路由

 {
    path: '/course',
    component: Layout,
    redirect: '/course/list',
    name: '课程管理',
    meta: { title: '课程管理', icon: 'el-icon-s-help' },
    children: [
      {
        path: 'list',
        name: '课程列表',
        component: () => import('@/views/edu/course/list'),
        meta: { title: '课程分类列表', icon: 'table' }
      },
      {
        path: 'info',
        name: '添加课程',
        component: () => import('@/views/edu/course/info'),
        meta: { title: '添加课程', icon: 'tree' }
      },
      {
        path: 'info/:id',
        name: 'InfoEdit',
        component: () => import('@/views/edu/course/info'),
        meta: { title: '编辑课程基本信息', icon: 'table' },
        hidden: true
      },
      {
        path: 'chapter/:id',
        name: 'ChapterEdit',
        component: () => import('@/views/edu/course/chapter'),
        meta: { title: '编辑课程大纲', icon: 'tree' },
        hidden: true
      }, {
        path: 'publish/:id',
        name: 'PublishEdit',
        component: () => import('@/views/edu/course/publish'),
        meta: { title: '发布课程', icon: 'tree' },
        hidden: true
      }
    ]
  },

添加4个vue文件
在这里插入图片描述

添加api

src/api/course/course

import request from '@/utils/request'


export default{

    //添加课程信息
    addCourseInfo(courseInfo){
        return request({
            url: `http://localhost:8001/eduservice/course/addCourseInfo`,
            method: 'post',
            data: courseInfo
        })


    },

    //查询所有讲师
    getListTeacher(){
        return request({
            url: 'http://localhost:8001/eduservice/teacher/findAll',
            method: 'get'
        })
    }


}

在elemnetui选一个步骤条,然后一系列操作

编辑得到整体代码:

chapter.vue

<template>
<div class="app-container">
    <h2 style="text-align: center;">发布新课程</h2>
<el-steps :active="2" finish-status="success">
  <el-step title="填写课程基本信息"></el-step>
  <el-step title="创建课程大纲"></el-step>
  <el-step title="最终发布"></el-step>
</el-steps>

<el-button style="margin-top: 12px;" @click="previous">上一步</el-button>
<el-button style="margin-top: 12px;" @click="next">下一步</el-button>
</div>
    
</template>

<script>
  export default {
    data() {
      return {
        active: 0
      };
    },

    methods: {
        previous(){
            this.$router.push({path:'/course/info/1'})
        },
      
         next(){
            //跳转到第三步
            this.$router.push({path:'/course/publish/1'})


        }
    },

    created(){
     

    }
  }
</script>

info.vue

<template>
<div class="app-container">
    <h2 style="text-align: center;">发布课程</h2>
<el-steps :active="1" finish-status="success">
  <el-step title="填写课程基本信息"></el-step>
  <el-step title="创建课程大纲"></el-step>
  <el-step title="最终发布"></el-step>
</el-steps>

<!-- 课程信息表单 -->
<el-form label-width="120px">
    <el-form-item label="课程标题">
        <el-input v-model="courseInfo.title" placeholder=" 示例:机器学习项目课:从基础到搭建项目视频课程。专业名称注意大小写"/>
    </el-form-item>
    
     <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-option>
        </el-select>
    </el-form-item>
    
    <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-option>
        </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-option>
        </el-select>
    </el-form-item>
    
    
    


    <el-form-item label="总课时">
        <el-input-number :min="0" v-model="courseInfo.lessonNum" controls-position="right" placeholder="请填写课程的总课时数"/>
    </el-form-item>
    <el-form-item label="课程简介">
        <el-input :min="0" v-model="courseInfo.description" controls-position="right" placeholder="请填写课程的简介"/>
    </el-form-item>

     
    <el-form-item label="课程封面">
    

<!-- 上传图片代码 -->
<el-upload
  class="upload-demo"
  action="http://localhost:8002/eduoss/fileoss/"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :on-success="success"
  :file-list="fileList"
  list-type="picture">
  <el-button size="small" type="primary">点击上传</el-button>
  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</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-button style="margin-top: 12px;" @click="saveOrUpdate">下一步</el-button>
</el-form>
</div>
    
</template>
<script>

import course from '@/api/course/course'
import subject from '@/api/subject/subject'
  export default {
    data() {
      return {
        saveBtnDisabled:false,
        courseInfo:{
            title: '',
            subjectId: '',
            subjectParentId: '',
            teacherId: '',
            lessonNum: 0,
            description: '',
            cover: '',
            price: 0
        },
        //封装所有讲师
        teacherList:[],
        subjectOneList:[],
        subjectTwoList:[]
      };
    },

    methods: {

 success(response){
      this.courseInfo.cover=response.data.url;
    },
        //上传成功调用的方法
        handleAvatarUpload(){
            this.courseInfo.cover=res.data.url

        },
        //上传前的方法
        beforeAvatarUpload(){
            const isJPG=file.type==='image/jpeg'
            const isLt2M=file.size / 1024 /1024 <2
            if(!isJPG){
                this.$message.error('上传格式只能jpg')
            }
            if(!isJPG){
                this.$message.error('上传大小不超过2MB')
            }

        },



        //点击一级分类开始查询二级分类
        subjectLevelOneChanged(value){
            for(let i=0;i<this.subjectOneList.length;i++){
                var oneSubject=this.subjectOneList[i]
                if(value===oneSubject.id){
                    this.subjectTwoList=oneSubject.children
                    this.courseInfo.subjectId=''//清空二级分类id
                }
            }
        },
         
        //查询所有的一级分类
        getOneSubject(){
            subject.getSubjectList()
            .then(response=>{
                this.subjectOneList=response.data.list
            })
        },


        //查询所有讲师

        getListTeacher(){
            course.getListTeacher()
            .then(response=>{
                this.teacherList=response.data.items
            })
             
        },

      
        saveOrUpdate(){

            course.addCourseInfo(this.courseInfo)
            .then(response=>{
                //提示
                this.$message({
                    type: 'success', 
                    message: '添加课程信息成功'
                })

            //跳转到第二步
            this.$router.push({path:'/course/chapter/'+response.data.courseId})

            })
        }
    },

    created(){
     this.getListTeacher()
     this.getOneSubject()
    }
  }
</script>

publish.vue

<template>
<div class="app-container">
    <h2 style="text-align: center;">发布新课程</h2>
<el-steps :active="3" finish-status="success">
  <el-step title="填写课程基本信息"></el-step>
  <el-step title="创建课程大纲"></el-step>
  <el-step title="最终发布"></el-step>
</el-steps>

<el-button style="margin-top: 12px;" @click="previous">上一步</el-button>
<el-button style="margin-top: 12px;" @click="next">发布</el-button>
</div>
    
</template>

<script>
  export default {
    data() {
      return {
        active: 0
      };
    },

    methods: {
        previous(){
            this.$router.push({path:'/course/chapter/1'})
        },
      
         next(){
            //跳转到第三步
            this.$router.push({path:'/course/list'})


        }
    },

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

    }
  }
</script>
最终效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值