在线教育业务笔记02- 课程分类管理模块
一、EasyExcel基本使用
1、EasyExcel写操作

package com.atguigu.demo.excel;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
public class TestEasyExcel {
public static void main(String[] args) {
String filename = "F:\\write.xlsx";
EasyExcel.write(filename,DemoData.class).sheet("学生列表").doWrite(getData());
}
private static List<DemoData> getData() {
List<DemoData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setSno(i);
data.setSname("lucy" + i);
list.add(data);
}
return list;
}
}
2、EasyExcel读操作

2.1、创建读取操作的监听器
package com.atguigu.demo.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.Map;
public class ExcelListener extends AnalysisEventListener<DemoData> {
@Override
public void invoke(DemoData data, AnalysisContext analysisContext) {
System.out.println("****"+data);
}
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头:"+headMap);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) { }
}
2.2、调用实现最终读取
package com.atguigu.demo.excel;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
public class TestEasyExcel {
public static void main(String[] args) throws Exception {
String filename = "F:\\write.xlsx";
EasyExcel.read(filename, DemoData.class, new ExcelListener()).sheet().doRead();
InputStream in = new BufferedInputStream(new FileInputStream("F:\\01.xlsx"));
ExcelReader excelReader = EasyExcel.read(in, ReadData.class, new ExcelListener()).build();
ReadSheet readSheet = EasyExcel.readSheet(0).build();
excelReader.read(readSheet);
excelReader.finish();
}
}
二、课程分类管理添加课程和课程分类树形显示后端业务
1、添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>service</artifactId>
<groupId>com.atguigu</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service_edu</artifactId>
<dependencies>
<!--电子表格上传-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
</project>
2、api接口
2.1、Controller

package com.atguigu.eduservice.controller;
import com.atguigu.commonutils.R;
import com.atguigu.eduservice.entity.subject.OneSubject;
import com.atguigu.eduservice.service.EduSubjectService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@Api(description="课程分类管理")
@CrossOrigin
@RestController
@RequestMapping("/eduservice/subject")
public class EduSubjectController {
@Autowired
private EduSubjectService subjectService;
@ApiOperation(value = "Excel批量导入")
@PostMapping("addSubject")
public R addSubject(MultipartFile file) {
subjectService.saveSubject(file, subjectService);
return R.ok();
}
@GetMapping("getAllSubject")
public R getAllSubject() {
List<OneSubject> list = subjectService.getAllOneTwoSubject();
return R.ok().data("list",list);
}
}
2.2、创建和Excel对应的实体类(添加课程分类使用)
package com.atguigu.eduservice.entity.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data
public class SubjectData {
@ExcelProperty(index = 0)
private String oneSubjectName;
@ExcelProperty(index = 1)
private String twoSubjectName;
}
2.3、创建用于封装课程分类的vo对象(页面显示树形结构使用)
2.3.1、第一种实现实体类
package com.atguigu.eduservice.entity.subject;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class OneSubject {
private String id;
private String title;
private List<OneSubject> children = new ArrayList<>();
}
package com.atguigu.eduservice.entity.subject;
import lombok.Data;
@Data
public class TwoSubject {
private String id;
private String title;
}
2.3.2、第二种实现实体类
package com.atguigu.eduservice.entity.subject;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class OneSubject {
private String id;
private String parentId;
private String title;
}
3、Service
3.1、接口

package com.atguigu.eduservice.service;
import com.atguigu.eduservice.entity.EduSubject;
import com.atguigu.eduservice.entity.subject.OneSubject;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface EduSubjectService extends IService<EduSubject> {
void saveSubject(MultipartFile file, EduSubjectService subjectService);
List<OneSubject> getAllOneTwoSubject();
}
3.2、实现类

package com.atguigu.eduservice.service.impl;
import com.alibaba.excel.EasyExcel;
import com.atguigu.eduservice.entity.EduSubject;
import com.atguigu.eduservice.entity.excel.SubjectData;
import com.atguigu.eduservice.entity.subject.OneSubject;
import com.atguigu.eduservice.entity.subject.TwoSubject;
import com.atguigu.eduservice.listener.SubjectExcelListener;
import com.atguigu.eduservice.mapper.EduSubjectMapper;
import com.atguigu.eduservice.service.EduSubjectService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
@Override
public void saveSubject(MultipartFile file, EduSubjectService subjectService) {
try {
InputStream in = file.getInputStream();
EasyExcel.read(in, SubjectData.class, new SubjectExcelListener(subjectService)).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public List<OneSubject> getAllOneTwoSubject() {
List<EduSubject> eduSubjects = baseMapper.selectList(null);
ArrayList<OneSubject> oneSubjectsList = new ArrayList<>();
for (EduSubject eduSubject : eduSubjects) {
OneSubject oneSubject = new OneSubject();
BeanUtils.copyProperties(eduSubject,oneSubject);
oneSubjectsList.add(oneSubject);
}
System.out.println("============>>>>>>>"+oneSubjectsList.toString());
ArrayList<OneSubject> root = new ArrayList<>();
Map<String, OneSubject> subjectMap = new HashMap<>();
for (OneSubject oneSubject : oneSubjectsList) {
String id = oneSubject.getId();
subjectMap.put(id, oneSubject);
}
for (OneSubject oneSubject : oneSubjectsList) {
String parentId = oneSubject.getParentId();
if (Objects.equals(parentId, "0")) {
root.add(oneSubject);
continue;
}
OneSubject father = subjectMap.get(parentId);
father.getChildren().add(oneSubject);
}
return root;
}
}
4、创建监听器读取Excel

package com.atguigu.eduservice.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.atguigu.eduservice.entity.EduSubject;
import com.atguigu.eduservice.entity.excel.SubjectData;
import com.atguigu.eduservice.mapper.EduSubjectMapper;
import com.atguigu.eduservice.service.EduSubjectService;
import com.atguigu.servicebase.exceptionhandler.GuliException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
public EduSubjectService subjectService;
public SubjectExcelListener() {}
public SubjectExcelListener(EduSubjectService subjectService) {
this.subjectService = subjectService;
}
@Override
public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
if(subjectData == null) {
throw new GuliException(20001,"文件数据为空");
}
EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());
if(existOneSubject == null) {
existOneSubject = new EduSubject();
existOneSubject.setParentId("0");
existOneSubject.setTitle(subjectData.getOneSubjectName());
subjectService.save(existOneSubject);
}
String pid = existOneSubject.getId();
EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);
if(existTwoSubject == null) {
existTwoSubject = new EduSubject();
existTwoSubject.setParentId(pid);
existTwoSubject.setTitle(subjectData.getTwoSubjectName());
subjectService.save(existTwoSubject);
}
}
private EduSubject existOneSubject(EduSubjectService subjectService,String name) {
QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
wrapper.eq("title",name);
wrapper.eq("parent_id","0");
EduSubject oneSubject = subjectService.getOne(wrapper);
return oneSubject;
}
private EduSubject existTwoSubject(EduSubjectService subjectService, String name, String pid) {
QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
wrapper.eq("title", name);
wrapper.eq("parent_id", pid);
EduSubject twoSubject = subjectService.getOne(wrapper);
return twoSubject;
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
三、课程分类前端页面显示(目标)
1、课程分类页面显示过程分析(思路)

2、过程分析实现(代码)
2.1、添加路由进行页面跳转

{
path: '/subject',
component: Layout,
redirect: '/subject/list',
name: '课程分类管理',
meta: { title: '课程分类管理', icon: 'example' },
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' }
}
]
}
2.2、创建api调用后端接口

import request from '@/utils/request'
export default {
getSubjectList() {
return request({
url: '/eduservice/subject/getAllSubject',
method: 'get'
})
}
}
2.3、前端页面

<template>
<div class="app-container">
<!-- 搜索框 -->
<el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;" />
<!-- 课程分类列表以树形显示 ref="tree2" 相当于id-->
<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>