谷粒学院-第七天- 前端功能完善

目录

一、内容介绍

二、添加课程分类前端

2.1 添加课程分类路由

 2.2 创建课程分类页面,修改路由对应的页面

 2.3 在添加课程分类页面 实现效果  

 2.4 课程列表功能

2.5 前端优化

 2.6 课程管理

2.6.1 课程添加


一、内容介绍

1.1 添加课程分类前端实现

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

1.3 课程管理模块需求

1.4 添加课程基本信息功能

二、添加课程分类前端

2.1 添加课程分类路由

 {
    path: '/subjext',
    component: Layout,
    redirect: '/subjext/list',
    name: '课程分类管理',
    meta: { title: '课程分类管理', icon: 'example' },
    children: [
      {
        path: 'list',
        name: '课程分类列表',
        component: () => import('@/views/edu/teacher/list'),
        meta: { title: '课程分类列表', icon: 'table' }
      },
      {
        path: 'sava',
        name: '添加课程分类',
        component: () => import('@/views/edu/teacher/save'),
        meta: { title: '添加课程分类', icon: 'tree' }
      }

    ]
  },

页面效果

 2.2 创建课程分类页面,修改路由对应的页面

 修改路径

 2.3 在添加课程分类页面 实现效果  

添加上传组件实现

2.3.1模板

<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="
              '/static/01.xlsx'
            "
            >点击下载模版</a
          >
        </el-tag>
      </el-form-item>
      <el-form-item label="选择Excel">
        <el-upload
          ref="upload"
          :auto-upload="false"
          :on-success="fileUploadSuccess"
          :on-error="fileUploadError"
          :disabled="importBtnDisabled"
          :limit="1"
          :action="BASE_API + '/admin/edu/subject/import'"
          name="file"
          accept="application/vnd.ms-excel"
        >
          <el-button slot="trigger" size="small" type="primary"
            >选取文件</el-button
          >
          <el-button
            :loading="loading"
            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: {},
};
</script>

2.3.2 js上传方法

 2.3.3 回调函数

2.3.4 save代码

<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="'/static/01.xlsx'">点击下载模版</a>
        </el-tag>
      </el-form-item>
      <el-form-item label="选择Excel">
        <el-upload
          ref="upload"
          :auto-upload="false"
          :on-success="fileUploadSuccess"
          :on-error="fileUploadError"
          :disabled="importBtnDisabled"
          :limit="1"
          :action="BASE_API + '/eduservice/subject/addSubject'"
          name="file"
          accept="application/vnd.ms-excel"
        >
          <el-button slot="trigger" size="small" type="primary"
            >选取文件</el-button
          >
          <el-button
            :loading="loading"
            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;
      // js: document.getElementById("upload").submit()
      this.$refs.upload.submit();
    },
    //上传成功
    fileUploadSuccess() {
      //提示信息
      this.$message({
        type: "success",
        message: "添加课程分类成功",
      });
      //跳转课程分类列表
    },
    //上传失败
    fileUploadError() {
        this.loading = false;
        this.$message({
        type: "error",
        message: "添加课程分类失败",
      });
    },
  },
};
</script>

2.3.5测试

 2.4 课程列表功能

 2.4.1 参考tree模块把前端整合出来

 需要做的事情,创建接口,把分类按照要求的格式返回数据就可以了

返回这种格式的数据

  

 OneSubject代码

//一级分类
@Data
public class OneSubject {
    private String id;
    private String title;
    
    //一个一级分类有多个二级分类
    private List<TwoSubject> children = new ArrayList<>();
}

TwoSubject代码

//二级分类
@Data
public class TwoSubject {
    private String id;
    private String title;
}

第三步 编写具体封装代码

1 Cotroller层

EduSubjectController

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

2 service

EduSubjectService

    //课程分类列表(树形)
    List<OneSubject> getAllOneTwoSubject();

EduSubjectServiceImpl

    //课程分类列表(树形)
    @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;
    }

3 Swagger测试

2.5 前端优化

1 先创建subjcect.js

代码如下

/* eslint-disable no-undef */
import request from '@/utils/request'

export default {

  // 1 课程分类列表
  // current当前页 limit分页 teacherQuery条件对象
  getSubjectList() {
    return request({
      url: '/eduservice/subject/getAllSubject',
      method: 'get'
    })
  }
}



2  修改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/edu/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.toLowerCase().indexOf(value.toLowerCase()) !== -1
    }
  }
}
</script>

 3 效果展示

 4 在save.vue中添加路由跳转

 2.6 课程管理

2.6.1 课程添加

细节问题

(1)创建vi实体类用于表单数据封装

(2)把表单提交过来的数据添加到数据库(向两张表添加数据:课程表和课程描述表)

(3)把讲师和分类使用下拉列表显示(课程分类做成二级联动效果)

edu_course 课程表:存储课程基本信息

edu_course_collect 课程简介表:存储课程简介信息

edu_chapter 课程章节表:存储课程章节信息

edu_video 课程小节表:存储章节里面的小节信息

课程管理-添加课程基本信息

第一步 使用代码生成器生成课程相关的代码

第二步 创建vo类封装表单提交的数据

代码如下

@Data
public class CourseInfoVo {
    private static final long serialVersionUID = 1L;
    
    @ApiModelProperty(value = "课程ID")
    private String id;
    
    @ApiModelProperty(value = "课程讲师ID")
    private String teacherId;
    
    @ApiModelProperty(value = "课程专业ID")
    private String subjectId;
    
    @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和service部分

1 创建controller  EduSubjectController

@RestController
@RequestMapping("/eduservice/subject")
@CrossOrigin
public class EduSubjectController {

    @Autowired
    private EduSubjectService subjectService;

    //添加课程分类
    //获取上传过来的文件,把文件内容读取出来

    @PostMapping("addSubject")
    public R addSubject(MultipartFile file){

        //上传excel文件
        subjectService.saveSubject(file,subjectService);
        return R.ok();
    }

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

}

2 service  EduCourseService

public interface EduCourseService extends IService<EduCourse> {

    //添加课程基本信息的方法
    void saveCourseInfo(CourseInfoVo courseInfoVo);
}

3 serviceImpl EduCourseServiceImpl

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

    //课程描述注入
  @Autowired
  private EduCourseDescriptionService courseDescriptionService;

   //添加课程基本信息的方法
    @Override
    public void saveCourseInfo(CourseInfoVo courseInfoVo) {
        //1 向课程表 添加课程基本信息
        //CourseInfoVo对象转换eduCourse对象
        EduCourse eduCourse = new EduCourse();
        BeanUtils.copyProperties(courseInfoVo,eduCourse);
        int insert = baseMapper.insert(eduCourse);

        if(insert == 0){
            //添加失败
            throw new GuliException(20001,"添加课程信息失败");
        }

        //2 向课程简介表添加课程简介
        //edu_course_description
        EduCourseDescription courseDescription = new EduCourseDescription();
        courseDescription.setDescription(courseInfoVo.getDescription());
        courseDescriptionService.save(courseDescription);

    }
}

4 进行测试

(1)先删除数据表中内容

DELETE FROM edu_course_description

(2)Swagger

注意:一定要取消设置  subject_parent_id 非空 否则测试报错

5 存在的问题

        课程和描述是一对一关系,添加之后,id值是一样的

修改描述实体类id生成策略

 

前端部分:

第一步 添加课程管理路由

 添加隐藏路由,做页面跳转

 {
    path: '/course',
    component: Layout,
    redirect: '/course/list',
    name: '课程管理',
    meta: { title: '课程管理', icon: 'example' },
    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: '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
      }

    ]
  },

1、课程信息页面 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() {

     
 },
 methods: {
     next(){
         //跳转到第二步
         this.$router.push({path:'/course/chapter/1'})
     }
 },
};
</script>

2、课程大纲页面 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() {

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

3、课程发布页面 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: "/course/chapter/1" });
    },
    publish() {
      console.log("publish");
      this.$router.push({ path: "/course/list" });
    },
  },
};
</script>

4.创建course.js

/* eslint-disable no-undef */
import request from '@/utils/request'

export default {

  // 1 添加课程信息功能
  addCourseInfo(courseInfo) {
    return request({
      url: '/eduservice/course/addCourseInfo',
      method: 'post',
      data:courseInfo
    })
  }
}

 5.在info.vue引入 并修改模板

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

      <!-- 所属分类 TODO -->
      <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>

      <!-- 课程讲师 TODO -->
      <!-- 课程讲师 -->
      <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>

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

      <!-- 课程简介 TODO -->
      <el-form-item label="课程简介">
        <el-input v-model="courseInfo.description" placeholder=" " />
      </el-form-item>

      <!-- 课程封面 TODO -->
      <!-- 课程封面-->
      <el-form-item label="课程封面">
        <el-upload
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
          :action="BASE_API + '/eduoss/fileoss'"
          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'
export default {
  data() {
    return {
      saveBtnDisabled: false,
      courseInfo: {
        title: "",
        subjectId: "",
        teacherId: "",
        lessonNum: 0,
        description: "",
        cover: "",
        price: 0,
      },
    };
  },
  created() {},
  methods: {
    saveOrUpdate() {
      course.addCourseInfo(this.courseInfo)
        .then(response => {
           //提示消息
          this.$message({
            type: "success",
            message: "添加课程信息成功!"
          });
           //跳转到第二步
          this.$router.push({ path: "/course/chapter/1" });
        })
    },
  },
};
</script>

6 页面测试效果

 第三步 添加之后返回id

1 修改接口

 2 修改info.vue

 3 测试

下拉列表显示所有讲师

 

1 修改course.js

 2 在页面进行调用

3 封装数据

 

4 初始化讲师

 

5  效果显示

 一级、二级分类做二级联动

1 在info.vue引入subject

 2 方法调用接口得到值 初始化 然后赋值

 3 在下拉列表遍历显示

 

4 效果展示

级联显示二级分类 

思路:给一级分类绑定change事件 值一改变就会取到二级分类的值

1 模板

        <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>   

2 注册change事件

3 定义change事件

4 每次点击一级分类 清空二级分类

 5 效果

 上传封面功能

1 上传组件

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

2 定义方法

    //上传封面成功调用的方法
    handleAvatarSuccess(res,file) {
      this.courseInfo.cover = res.data.url
    },
    //上传直接调用的方法
    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;
    },

3 设置默认图片

4效果4 效果显示

 

2.6.2 课程程列表

·

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值