效果图


数据库

一、定义实体类
package com.stu.service.edu.entity.vo;
import com.stu.service.edu.entity.Subject;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/******************************
* 用途说明:课程分类树形显示
* 作者姓名: Administrator
* 创建时间: 2022-05-07 18:37
******************************/
@Data
public class SubjectVo implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String title;
private String sort;
private String parentId;
private List<SubjectVo> childList = new ArrayList<>();
}
二、主要逻辑代码
package com.stu.service.edu.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stu.service.edu.entity.Subject;
import com.stu.service.edu.entity.excel.SubjectExcelData;
import com.stu.service.edu.entity.vo.SubjectVo;
import com.stu.service.edu.listener.SubJectExcelListener;
import com.stu.service.edu.mapper.SubjectMapper;
import com.stu.service.edu.service.SubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 课程科目 服务实现类
* </p>
*
* @author stu
* @since 2022-05-06
*/
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {
@Autowired
private SubjectMapper subjectMapper;
@Override
public void batchImport(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(), SubjectExcelData.class,
new SubJectExcelListener(subjectMapper)).excelType(ExcelTypeEnum.XLS).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public List<SubjectVo> getAllSubject() {
//课程分类的树形结构集合
List<SubjectVo> rootList = new ArrayList<>();
Map<String, SubjectVo> tempMap = new HashMap<>();
List<SubjectVo> tempList = new ArrayList<>();
QueryWrapper<Subject> queryWrapper = new QueryWrapper<>();
List<Subject> subjectList = baseMapper.selectList(queryWrapper);
//组装树形结构数据的准备工作
for (Subject subject : subjectList) {
SubjectVo subjectVo = new SubjectVo();
//返回的实体和前端需要的实体vo进行赋值
BeanUtils.copyProperties(subject, subjectVo);
tempMap.put(subjectVo.getId(), subjectVo);
tempList.add(subjectVo);
}
//封装课程分类的树形结构数据
for (SubjectVo vo : tempList) {
SubjectVo child = vo;
if ("0".equals(vo.getParentId())) {
rootList.add(vo);
} else {
SubjectVo parent = tempMap.get(child.getParentId());
parent.getChildList().add(child);
}
}
return rootList;
}
}
三、vue页面
<template>
<div class="app-container">
<el-form :inline="true" class="demo-form-inline">
<el-form-item label="课程标题">
<el-input
v-model="searchData.title"
placeholder="示例:Java基础课"
></el-input>
</el-form-item>
<el-form-item label="课程类别">
<el-select
v-model="searchData.subjectLevelOne"
placeholder="一级分类"
@change="getTwoSubjectList"
>
<el-option
v-for="info in subjectLevelOneList"
:key="info.id"
:label="info.title"
:value="info.id"
>
</el-option>
</el-select>
<el-select v-model="searchData.subjectLevelTwo" placeholder="二级分类">
<el-option
v-for="info in subjectLevelTwoList"
:key="info.id"
:label="info.title"
:value="info.id"
>
</el-option>
</el-select>
</el-form-item>
<!--课程讲师ID-->
<el-form-item label="课程讲师">
<el-select v-model="searchData.teacherId">
<el-option
v-for="teacher in teacherList"
:key="teacher.id"
:label="teacher.name"
:value="teacher.id"
>
</el-option>
</el-select>
</el-form-item>
<el-button type="primary" icon="el-icon-search" @click="getList()"
>查询</el-button
>
<el-button type="default" @click="resetData()">清空</el-button>
</el-form>
<el-table :data="pageList" border>
<el-table-column label="序号" width="70" align="center">
<template slot-scope="scope">
{{ (page - 1) * limit + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="封面" width="200" align="center">
<template slot-scope="scope">
<img :src="scope.row.cover" alt="scope.row.title" width="100%" />
</template>
</el-table-column>
<el-table-column label="课程信息" align="center">
<template slot-scope="scope">
<p>
标题:<a href="">{{ scope.row.title }}</a>
</p>
<p>一级分类:{{ scope.row.subjectParentTitle }}</p>
<p>二级分类: {{ scope.row.subjectTitle }}</p>
<p>
课时:{{ scope.row.lessonNum }} 游览:{{
scope.row.viewCount
}}
付费学员:{{ scope.row.buyCount }}
</p>
</template>
</el-table-column>
<el-table-column label="讲师" width="100" align="center">
<template slot-scope="scope">
{{ scope.row.teacherName }}
</template>
</el-table-column>
<el-table-column label="价格" width="100" align="center">
<template slot-scope="scope">
<el-tag type="success" v-if="Number(scope.row.price) === 0"
>免费</el-tag
>
<el-tag v-else>{{ scope.row.price }}</el-tag>
</template>
</el-table-column>
<el-table-column label="课程状态" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 'Draft' ? 'warning' : 'success'">
{{ scope.row.status === "Draft" ? "未发布" : "已发布" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" width="180" align="center">
<template slot-scope="scope">
{{ scope.row.gmtCreate }}
</template>
</el-table-column>
<el-table-column label="操作" width="300" align="center">
<template slot-scope="scope">
<router-link :to="'/course/editCourse/' + scope.row.id">
<el-button type="primary" size="mini" icon="el-icon-edit" v-if="hasPerm('course.update')"
>修改</el-button
>
</router-link>
<router-link :to="'/course/editChapter/' + scope.row.id">
<el-button type="primary" size="mini" icon="el-icon-edit" v-if="hasPerm('chapter.update')"
>编辑大纲</el-button
>
</router-link>
<el-button
type="primary"
size="mini"
icon="el-icon-edit"
@click="deleteById(scope.row.id)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
:current-page="page"
:page-size="limit"
:total="total"
:page-sizes="[5, 10, 15, 20]"
style="padding: 12px 8px; text-align: center"
layout="sizes, prev, pager, next, jumper, ->, total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
import courseApi from "@/api/course";
import teacherApi from "@/api/teacher";
import subjectApi from "@/api/subject";
export default {
data() {
return {
pageList: [],
total: 0,
limit: 5,
page: 1,
searchData: {
title: "",
teacherId: "",
subjectLevelOne: "",
subjectLevelTwo: "",
},
teacherList: [],
subjectLevelOneList: [],
subjectLevelTwoList: [],
};
},
created() {
this.init();
},
methods: {
//删除
deleteById(courseId) {
this.$confirm("此操作将永久删除, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
//删除api
courseApi.deleteById(courseId).then((res) => {
if (res.code === 20000) {
this.$message({
type: "info",
message: "刪除成功: ",
});
} else {
this.$message({
type: "info",
message: "刪除失败: ",
});
}
this.pageCourses();
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除",
});
});
},
init() {
this.getAllSubject();
this.getTeacher();
this.pageCourses();
},
//分页
pageCourses() {
courseApi
.pageCourses(this.page, this.limit, this.searchData)
.then((res) => {
if (res.code === 20000) {
if (res.data.data.records) {
this.pageList = res.data.data.records;
}
if (res.data.data.total) {
this.total = res.data.data.total;
}
}
});
},
//改变数量
handleSizeChange(size) {
this.limit = size;
this.pageCourses();
},
//改变页码
handleCurrentChange(page) {
this.page = page;
this.pageCourses();
},
getTeacher() {
teacherApi.listAllTeachers().then((res) => {
if (res.code === 20000 && res.data.list) {
this.teacherList = res.data.list;
}
});
},
getAllSubject() {
subjectApi.treeList().then((res) => {
if (res.code === 20000 && res.data.treeList) {
this.subjectLevelOneList = res.data.treeList;
}
});
},
//点击一级分类,显示二级分类
getTwoSubjectList(value) {
//选中一级分类,在改变一级分类,二级分类显示的数据没有清空的问题
// this.searchData.subjectLevelTwo = ''
let tempOneSbujectList = this.subjectLevelOneList.filter(
(item) => item.id === value && item.id
);
this.subjectLevelTwoList = tempOneSbujectList[0].childList;
if (
!this.subjectLevelTwoList.includes(this.searchData.subjectLevelTwo) &&
this.searchData.subjectLevelTwo
) {
this.searchData.subjectLevelTwo = "";
}
},
//清空查询条件
resetData() {
this.searchData = {};
},
},
};
</script>
>
上边需要注意一点,选中一级分类,在改变一级分类,二级分类显示的数据没有清空的问题
比如下边,现在一级分类选择后端开发,二级分类选中的是java,这个时候在改变一级分类,二级分类需要清空,重新赋值,赋改变后的一级分类的二级分类而不是之前的。

作者:明出处:https://www.cnblogs.com/konglxblog//版权:本文版权归作者和博客园共有转载:欢迎转载,文章中请给出原文连接,此文章仅为个人知识学习分享,否则必究法律责任
本文介绍了一个课程分类管理系统的设计与实现,包括实体类定义、主要逻辑代码和服务实现类等内容。通过前端Vue页面展示了课程分类的选择功能,并提供了批量导入等功能。
1万+

被折叠的 条评论
为什么被折叠?



