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//
版权:本文版权归作者和博客园共有
转载:欢迎转载,文章中请给出原文连接,此文章仅为个人知识学习分享,否则必究法律责任

 

posted @ 2022-10-16 19:58  程序员小明1024  阅读(287)  评论(0编辑  收藏  举报