layui 组织机构树

原创
09/22 11:04
阅读数 62

1、数据库为mysql5.6(没有自带的级联查询函数),layui版本2.5.6;组织机构表的主要列有id(机构id),pid(所属机构id),title(组织名称),order_num(同级组织机构的排列顺序)。最终要显示的效果如下:

    

2、实现方案分两种:

一是分级异步加载,初始显示一级组织经,点击某个组织机构,显示该机构的下一级组织机构并刷新树。

这种方案的特点是,后台查询简单,只要根据点击的节点id,查询其下一级所属组织机构,SQL如下:

select id,title where pid=? order by order_num

前端通过ajax拿到这些下属组织机构后,重新生成组织机构树的数据,然后重新渲染树(需要注意被点击节点spread的设置,否则树会折叠起来,看不到刚点击的节点);同时在树节点的点击事件中,向后台发送ajax请求,代码大概这样:

  layui.tree.render({
			    elem: '#deptId' //展示树的div的id
			    ,data: deptData // 树所需的数据
			    , onlyIconControl: true //点击图标才折叠的配置
			    ,accordion: false // 禁止手风琴样式
			    , click: function (obj) {
			        //getDepts(obj.data.id) // 查询点击节点的下一级组织机构
			        checkedDeptId = obj.data.id;
			    }
			  });
        	  form.render();

getDepts方法就是向后台请求下级组织机构:

function getDepts(parentId){
        	  $.ajax({
                  cache: false,
                  async: false,
                  url: '/user/getUnitList',
                  data:{'parentId':parentId},
                  type: 'GET',
                  dataType: 'json',
                  success: function (data) {
                	  console.info('data',data);
                	  if(data.result != null && data.result.length>0){
                		  deptData = data.result;
                		  //根节点
                		  if(parentId ==0){
                			  for(var i=0;i<data.result.length;i++){
                    			  var node = {'title':data.result[i].name,'id':data.result[i].deptId};
                    			  deptData.push(node);
                    		  }  
                		  }else{
                			  for(var j=0;j<deptData.length;j++){
                				  if(deptData[j].id == parentId){
                					  var deptj = deptData[j];
                					  var children =[];
                					  for(var i=0;i<data.result.length;i++){
                            			  var node = {'title':data.result[i].name,'id':data.result[i].deptId,'spread':true};
                            			  children.push(node);
                            		  } 
                					  deptj.spread = true;
                					  // 设置选中节点的样式
                					  deptj.title = "<font color='green'>" + deptj.title + "</font>";
                					  deptj.children = children;
                					  deptData[j] = deptj;
                					 // break;
                				  }
                			  }
                		  }
                	  }
                	  checkedDeptId = parentId; 
                  }, error: function (data) {
                      alert(data.msg);
                  }
              })
              
			  //手风琴模式
			  layui.tree.render({
			    elem: '#deptId'
			    ,data: deptData
			    , onlyIconControl: true
			    ,accordion: true 
			    , click: function (obj) {
			        getDepts(obj.data.id)
			    }
			  });
        	  
        	  form.render();
        }

这段代码是有bug的,就是根据id查询json数组的对应节点,这里的写法只能实现查找第二级,再有更深层级,就查不到了(若喜欢用这种分级加载数据的,需要修改根据节点id查询节点的代码,其他部分不用修改)。所以弃用第一个方案,改为从后台拿到完整数据,前台对数据不做任何处理,直接渲染。此时,前端代码比较简洁:

  var deptData = [];
        function getDepts(parentId){
        	  $.ajax({
                  cache: false,
                  async: false,
                  url: '/user/getUnitList',
                  data:{'parentId':parentId},
                  type: 'GET',
                  dataType: 'json',
                  success: function (data) {
                	  console.info('data',data);
                	  if(data.result != null && data.result.length>0){
                		  deptData = data.result;
                	  }
                	  checkedDeptId = parentId; 
                  }, error: function (data) {
                      alert(data.msg);
                  }
              })
			  //手风琴模式
			  layui.tree.render({
			    elem: '#deptId' 
			    ,data: deptData 
			    , onlyIconControl: true 
			    ,accordion: false 
			    , click: function (obj) {
			        checkedDeptId = obj.data.id;
			    }
			  });
        	  form.render();
        }

后台通过递归,查出所有的子孙节点:

@RequestMapping(value = "/getUnitList", method = RequestMethod.GET)
			Map<String, Object> getUnitList(@RequestParam Integer parentId) {
				try {
					JSONObject root = new JSONObject();
					root.put("id", 0);
					root.put("title", "虚拟根");
					JSONArray arr = new JSONArray();
					arr.add(root);
					arr =  getChildren(0,arr);
					return  new ResultPO(arr.getJSONObject(0).getJSONArray("children"));
				} catch (Exception e) {
					logger.error(e.getMessage());
					return  ResultPO.error("查询失败,请检查输入条件");
				}
			}
			
			/**获取指定节点的所有子孙节点
			 * @param pid 节点id
			 * @param arr 节点数组
			 * @return
			 */
			private JSONArray getChildren(int pid, JSONArray arr) {
				try {
					//查询id的下级节点
					List<Map<String,Object>> units = service.getUnits(pid);
					if(units == null || units.size()<1) {
						return arr;
					}
					JSONArray children = new JSONArray();
					//遍历下级节点,生成id对应节点的children数据
					for(Map<String,Object>unit : units) {
						JSONObject json = new JSONObject();
						json.put("id", unit.get("deptId"));
						json.put("title", unit.get("name"));
						children.add(json);
					}
					setChildren(arr,children,pid);
					//对每一个子节点,再查询其子节点
					for(int i=0;i<children.size();i++) {
						JSONObject child = children.getJSONObject(i);
						getChildren(child.getIntValue("id"),arr);
					}
					return arr;
				}catch(Exception e) {
					e.printStackTrace();
					return arr;
				}
			}
		 
			/** 根据节点id设置其children
			 * @param nodes     原节点数组
			 * @param children  子节点数组
			 * @param id        节点id
			 */
			private void setChildren(JSONArray nodes, JSONArray children, int id) {
				
				int len = nodes.size();
				for(int i = 0;i<len;i++) {
					JSONObject node  = nodes.getJSONObject(i);
					if(node.getInteger("id") == id) {
						node.put("children", children);
						break;
					}
					JSONArray children2 = node.getJSONArray("children");
					if(children2 != null && children2.size()>0) {
						setChildren(children2,children, id);
					}
				}
			}

添加虚拟根节点,是为了在getChildren方法中,统一处理逻辑,不做额外的判断。

以上是全部内容。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部