这种树的实现你Get了吗?(详细解读:神仙需求)

也是很久没有和大家见面,算是小结一篇(Working…)

总的来说,确实是开始慢慢的减缓更新速度了…(很多都在草稿箱中…堆积数量也正在慢慢清理)
啥都很奇怪,但是又都不奇怪。工作就是这样,有时候需要处理的很多,要学习也很多。

前提:数据啥的不能从数据库中删除…数据只能是越来越多,所有就有了下面的种种需求
需求:
第一次进来加载只加载第一级的数据,不是一次返回数据
当个点击的时候查询下一级,交给前端进行拼接
模糊查询,只出现有关系的树

图片使用的是ElementUI里面的树菜单图片,大概都差不多其实
在这里插入图片描述
框架就是SpringMVC:Spring:Mybitas做的一颗神奇的树…
下面的内容采用文字加代码来书写…做到一次到胃(啊Sir,开车?)

快上车。来不及解释了
在这里插入图片描述
说到Mybitas第一步必须是xm文件(内容太长,有的没用的方法就直接去掉吧…看我的,不会少的)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.excegroup.dao.SysDataLabelDao" >
  <resultMap id="BaseResultMap" type="com.excegroup.bean.DataLabelBean" >
    <id column="ID" property="id" jdbcType="VARCHAR" />
    <result column="Pid" property="Pid" jdbcType="VARCHAR" />
    <result column="Name" property="Name" jdbcType="VARCHAR" />
    <result column="Level" property="Level" jdbcType="INTEGER" />
  </resultMap>
  <sql id="Base_Column_List" >
    ID, label_Pid, label_Code, label_Name, label_Type,label_Level, status, time_Stamp, create_By, 
    create_Time, modify_By, modify_Time,attr_Subject_Id,attr_Org_Id,attr_Region_Id
  </sql>
<!-- 根据对象的父ID去查询当前数据(一般用来做查询父ID的全部数据) -->
  <select id="getDataLableByLabelPid" resultMap="BaseResultMap" >
    select 
    <include refid="Base_Column_List" />
    from sys_data_label a where a.status='1' 
    and a.label_Pid=#{labelPid,jdbcType=VARCHAR}
  </select>
  <!-- 根据对象的父ID去查询当前数据(一般用来做查询父ID的全部数据) -->
  <select id="selectLablePidById" resultMap="BaseResultMap" parameterType="java.lang.String">
    select 
 <include refid="Base_Column_List" />
   from sys_data_label a where a.label_Pid= #{id,jdbcType=VARCHAR} and a.status='1'
  </select>  
      <!-- 查询出模糊查询条件返回的数据(可能有多个,毕竟是模糊查询) -->
  <select id="selectLableByName" resultMap="BaseResultMap" parameterType="com.excegroup.bean.DataLabelBean">
    select 
   <include refid="Base_Column_List" />
   from sys_data_label a where a.status='1' and a.label_Level=2
   <if test="labelName != null and labelName != ''">
  	 and a.label_Name LIKE CONCAT(#{labelName,jdbcType=VARCHAR},'%')
   </if>
  </select>
    <!-- 查询出当前对象的第二级菜单有哪些, 以及第三级菜单有哪些 -->
  <select id="selectParentList" resultMap="BaseResultMap" parameterType="java.lang.String">
  select 
   ID, label_Pid, label_Code, label_Name,label_Level
  from sys_data_label where id in (${sql}) and status='1'
  union all
   select distinct
   ID, label_Pid, label_Code, label_Name,label_Level
  from sys_data_label where status='1' and
  	id in(select label_Pid from sys_data_label where id in (${sql}) and status='1')
  </select>
</mapper>
package com.excegroup.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class DataLabelBean{
   //有用的就给个注释写一下,其他无需关注
   //有的没有用的数据会再下面使用到,有注释,不管就可以了,这边懒得删除了
	private String id;//当前id
	private String labelPid;//父ID(重点,分为三级,第一级父ID为-1,第二级的父ID为上一级的ID,第三级同理)
	private String labelName;//标签名称
	private int labelLevel;//第一级的level为0;第二级的level为1,第三级的level为2
	private List<DataLabelBean> children = new ArrayList<>();//一个LIst集合用来做树结构用
	//提供set和get不说。浪费地方(自己加一下)
}

package com.excegroup.dao;


import java.util.List;
import com.excegroup.bean.DataLabelBean;

public interface SysDataLabelDao {//没有用的也丢掉,让神仙你少看一点代码
	    
	    List<DataLabelBean> getDataLableByLabelPid(DataLabelBean recode);

	    List<DataLabelBean> selectLablePidById(String id);
	    
	    List<DataLabelBean> selectLableByName(DataLabelBean recode);
	    
	    List<DataLabelBean> selectParentList(String sql);
}

package com.excegroup.service;

import java.util.List;

import com.excegroup.base.bean.ResultMsg;
import com.excegroup.bean.DataLabelBean;
//ResultMsg,一个工具包,用来做返回结果的处理,有没有无所谓,你们没有的就按照Dao层写也是一样的
public interface SysDataLableService {
	/**
	 * 删除标签
	 * @param id
	 * @return
	 */
	ResultMsg updateStatus(String id);
	/**
	 * 新增标签
	 * @param id
	 * @return
	 */
	ResultMsg insert(DataLabelBean record);
	/**
	 * 查询标签
	 * @param id
	 * @return
	 */
	ResultMsg selectByPrimaryKey(String id);
	/**
	 * 修改标签
	 * @param id
	 * @return
	 */
	ResultMsg updateByPrimaryKeySelective(DataLabelBean record);
	/**
	 * 修改标签
	 * @param id
	 * @return
	 */
	ResultMsg updateByPrimaryKey(DataLabelBean record);
	
	/**
	 * 加载标签菜单
	 */
	ResultMsg labelTree(DataLabelBean recode);
	/**
	 * 根据id查询lablePid
	 * @param id
	 * @return
	 */
	List<DataLabelBean> selectLablePidById(String id);
}

package com.excegroup.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.excegroup.base.bean.ResultMsg;
import com.excegroup.bean.DataLabelBean;
import com.excegroup.constant.SequenceConstant;
import com.excegroup.core.DbcContext;
import com.excegroup.core.Utils;
import com.excegroup.dao.SysDataLabelDao;
import com.excegroup.service.SysDataLableService;
import com.excegroup.service.SysSequenceService;

@Service
public class SysDataLableServiceImpl implements SysDataLableService {
    //重点就是下面的这一个方法,同时做到了查询,点击,模糊查询三个功能
	@Autowired
	SysDataLabelDao SysDataLabelDao;
	@Override
	public ResultMsg labelTree(DataLabelBean recode) {
		ResultMsg msg = new ResultMsg();
		//没有就不写,然后返回的结果就直接在return中带回去就可以了
		if (StringUtils.isEmpty(recode.getLabelPid())) {
		//由于是一个接口,在第一次进来的时候(及加载页面),第一次肯定是没有父ID,所以手动设置查询父ID为-1的
			recode.setLabelPid("-1");
			//设置pid为-1就是进来默认查询第一级的数据
		}
		if (!StringUtils.isEmpty(recode.getId())) {
		//判断是否有Id,这里和前端做的同步(前端点击第一级的时候需要展开第一级对应的第二次数据,则传递id过来)
			recode.setLabelPid(recode.getId());
			//设置id为当前点击的id
		}
		if (StringUtils.isEmpty(recode.getLabelName())) {
		//判断是否使用了模糊查询功能,没有传递labelName代表没有进行模糊查询
		//可能是点击下一个,或者是第一次进来查询
			List<DataLabelBean> dataList = SysDataLabelDao.getDataLableByLabelPid(recode);
			//根据pid查询全部数据,分为两个情况,点击和不点击,不点击的情况就不说了,加载一级菜单。
			//点击的情况就是要求前端传递一个id给我,在上面就这设置了id当做Pid去查询儿子信息
				//这个for循环没有什么用,使用来个前端传递两个参数的,可以不看
			for (DataLabelBean sysDataLabel : dataList) {
				sysDataLabel.setLoading(false);
				sysDataLabel.setExpand(false);
			}
			if (dataList != null) {
			//这里就是用的上面说的工具包,没有的可以直接返回数据就完事了
				msg.setCode("000");
				msg.setDescribe("查询成功1");
				msg.setData(dataList);
			}
		} else {
		//这边就是说明传递了labelName,进行模糊查询,重点来了
		//需求:哪些有这个模糊查询的数据都需要显示出来。及两个二级都有第三级的模糊查询条件的时候,两个二级都要有
			List<DataLabelBean> threeList = SysDataLabelDao.selectLableByName(recode);
			//进行模糊查询。返回出来的数据可能有很多条,可能来自不同的第二级菜单。
			//说实话,懵逼了,数据库查询出来的数据是没有顺序的,有可能后面for循环加载的时候重复了,怎么搞?
			//这里就是本篇博客的重点内容了
			if (null == threeList || threeList.isEmpty()) {
				return msg;
			}
			//上面的if做判断,没有符合条件的直接返回,你们可以直接返回null;
			StringBuffer sql = new StringBuffer();
			// sql用来存放所有的父节点PId,用于sql语句查询
			for (DataLabelBean label : threeList) {
				sql.append("'" + label.getLabelPid() + "',");
				//对所有的父节点进行拼接,但是最后还是会携带一个, 这样会导致sql语句查询的时候报错
			}
			sql.append("'-1'");
			//用于最后拼接一个-1,不会导致sql出错。大概意思就是sql="'1','2','3','-1'" 这么个感觉
			List<DataLabelBean> parList = SysDataLabelDao.selectParentList(sql.toString());
			//查询出来的结果就是满足与输入的模糊查询的全部结果
			List<DataLabelBean> oneList = new ArrayList<DataLabelBean>();
			//新建一个List集合,用来做拼接存放第一级的数据
			for (DataLabelBean one : parList) {
				one.setLoading(false);
				one.setExpand(false);
				//上面两个不用管,给前端用的,和树没有关系
				if (0 == one.getLabelLevel()) {
				//进行循环拼接:满足这个条件意思就是第一级的数据,进行拼接加到oneList
					oneList.add(one);
				}
			}
			//这里for循环出来就已经是拼接完了全部有的第一级
			for (DataLabelBean one : oneList) {
			//还是去循环我们查询出来的全部结果
				List<DataLabelBean> twoList = new ArrayList<DataLabelBean>();
				//新建一个List集合,用来做拼接存放第二级的数据
				for (DataLabelBean two : parList) {
					two.setLoading(false);
					two.setExpand(false);
					//上面两个不用管,给前端用的,和树没有关系
					if (one.getId().equals(two.getLabelPid())) {
					//这里是满足第一级的id为第二级的pid,这里代表意思就是 two是属于one 下面的一个子节点
						twoList.add(two);
						//满足的时候新增子节点。进行拼接
						// 三級樹
						List<DataLabelBean> thrList = new ArrayList<DataLabelBean>();
						//新建一个List集合,用来做拼接存放第三级级的数据
						for (DataLabelBean thr : threeList) {//从开始的全部数据里面去找有没有第三级
							thr.setLoading(false);
							thr.setExpand(false);
							//上面两个不用管,给前端用的,和树没有关系
							if (two.getId().equals(thr.getLabelPid())) {
							//这里是满足第二级的id为第三级的pid,这里代表意思就是 thr是属于two下面的一个子节点
								thrList.add(thr);
								//满足的时候新增子节点。进行拼接
							}
						}
						two.setChildren(thrList);
						//给第二级拼接属于他的第三级
					}
				}
				one.setChildren(twoList);
				//给第一级拼接属于他的第二级
			}
			msg.setData(oneList);
			//返回数据完事
		}
		return msg;
	}
}

模拟出来的数据库,和上面的xml内容可能不一致。但是不影响理解
在这里插入图片描述
一些返回数据结果:手动写的…(应该没有问题)
第一次加载:

{
    "code": "000",
    "describe": "查询成功1",
    "data": [{
        "id": "1",
        "Pid": "-1",
        "Name": "第一级One",
        "Level": 0
    }, {
        "id": "2",
        "labelPid": "-1",
        "labelName": "only老K",
        "labelLevel": 0
    }]
}

点击的时候:

{
    "code": "000",
    "describe": "查询成功1",
    "data": [{
        "id": "121",
        "Pid": "1",
        "Name": "第二级One",
        "Level": 1
    }, {
        "id": "122",
        "Pid": "1",
        "Name": "第二级TWO",
        "Level": 1
    }, {
        "id": "123",
        "Pid": "1",
        "Code": "L008",
        "Name": "第二级Three",
        "Level": 2
    }]
}

模糊查询:

{
    "code": "000",
    "describe": "Operation succeed!",
    "data": [{
        "id": "1",
        "Pid": "-1",
        "Name": "第一级One",
        "Level": 0,
        "children": [{
            "id": "123",
            "Pid": "1",
            "Name": "第二级Three",
            "Level": 1,
            "children": [{
                "id": "132",
                "Pid": "123",
                "Name": "带第三级TWO",
                "Level": 2
            }, {
                "id": "131",
                "Pid": "123",
                "Name": "带第三级One",
                "Level": 2
            }]
           
        }]
    }]
}

猜你喜欢

转载自blog.csdn.net/weixin_44255950/article/details/106816367
今日推荐