SpringBoot vue 下拉选多级联动
效果图
数据库
一、定义实体类
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//
版权:本文版权归作者和博客园共有
转载:欢迎转载,文章中请给出原文连接,此文章仅为个人知识学习分享,否则必究法律责任