首页 > 其他分享 >zTree实现树形结构菜单

zTree实现树形结构菜单

时间:2023-02-13 15:04:35浏览次数:53  
标签:菜单 false String List zTree moduleCode 树形 return public


文章目录

  • ​​一、简介​​
  • ​​二、前端渲染效果​​
  • ​​三、实现步骤​​
  • ​​1、数据库表结构​​
  • ​​2、引入zTree插件​​
  • ​​3、树形结构实体类SysModule​​
  • ​​4、表示层代码​​
  • ​​5、js渲染部分​​
  • ​​1、树初始化配置​​
  • ​​2、加载数据树​​
  • ​​4、控制器关键代码​​
  • ​​5、业务逻辑层代码:​​
  • ​​6、数据访问层代码:​​
  • ​​四、碰到的bug及解决方案​​
  • ​​1、指定结点选中无效​​
  • ​​2、mybatis多对多关系的处理较为麻烦​​

一、简介

zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。
官方文档:​​​http://www.treejs.cn/v3/api.php​

功能很强大,API都是中文的,但是在样式上面稍有欠缺,且容易受到开发环境版本的影响。

二、前端渲染效果

zTree实现树形结构菜单_bootstrap

三、实现步骤

1、数据库表结构

zTree实现树形结构菜单_javascript_02

zTree实现树形结构菜单_zTree_03

2、引入zTree插件

<link rel="stylesheet"
href="/ccms/commons/jslib/ztreeV3.5.15/css/zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript"
src="/ccms/commons/jslib/ztreeV3.5.15/jquery.ztree.all-3.5.js"></script>
<script type="text/javascript"
src="/ccms/commons/jslib/js-gmxt-define/ztreeTool.js"></script>

3、树形结构实体类SysModule

省略get和set方法

public class SysModule {
/**模板编码*/
private String moduleCode;
/**模板名称*/
private String moduleName;
/**模板路径*/
private String modulePath;
/**父级模板编号*/
private String parentCode;
/**是否为叶子节点*/
private int isLeaf;
/**同级排序编号*/
private int sortNumber;
}

树形结构辅助类:

package com.ccms.tools;

import java.util.List;

public class Tree {

private String id;

private String pId;

private String name;

private boolean isParent;

private boolean open;

private boolean checked;

private boolean nocheck;

private List<Tree> children;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public boolean getParent() {
return isParent;
}

public void setParent(boolean isParent) {
this.isParent = isParent;
}

public boolean isOpen() {
return open;
}

public void setOpen(boolean open) {
this.open = open;
}

public boolean isChecked() {
return checked;
}

public void setChecked(boolean checked) {
this.checked = checked;
}

public List<Tree> getChildren() {
return children;
}

public void setChildren(List<Tree> children) {
this.children = children;
}

public boolean isNocheck() {
return nocheck;
}

public void setNocheck(boolean nocheck) {
this.nocheck = nocheck;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getpId() {
return pId;
}

public void setpId(String pId) {
this.pId = pId;
}

private String attributes;

public void setAttributes(String attributes) {
this.attributes = attributes;
}

public String getAttributes() {
return attributes;
}

/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}

/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Tree other = (Tree) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}




}

4、表示层代码

<div class="col-sm-3">
<ul id="protree" class="ztree" style="background: #fff"></ul>
</div>

5、js渲染部分

1、树初始化配置

var setting = {
check : {
enable : true,
autoCheckTrigger : true, //触发事件回调函数
chkStyle : "checkbox", //勾选框类型:checkbox
chkboxType : {
"Y" : "s", //checkbox被勾选后,s标识操作会影响父级节点
"N" : "ps"
}
},
data : {
simpleData : {
enable : false,
}
},
edit : {
enable : true,
showRemoveBtn : false,
showRenameBtn : false,
drag : {
autoExpandTrigger : true,
prev : false,
inner : true,
next : false
}
},
callback : {
onClick : zTreeOnClick,
onDrop : zTreeOnDrop,
beforeDrop : zTreeBeforeDrop
}
};
//节点点击事件
function zTreeOnClick(event, treeId, treeNode) {
// 隐藏添加功能模块表单
$('#addwin').hide();
if (isSelected("protree")) {
if (getSelected("protree").id != "null") {
// 显示修改功能模块表单
$('#upwin').show();
// 在修改功能模块表单中,绑定修改前的数据
loadSingleData(getSelected("protree").id);
} else {
$("#addwin").hide();
$("#upwin").hide();
}
}
}
//加载单条数据
function loadSingleData(id) {
$.ajax({
url : '/ccms/module/getSingleData',
dataType : 'json',
data : {
id : id
},
type : 'post',
success : function(data) {
$("#pname_edit").val(data.moduleData.parentModuleName);
$("#moduleCode_edit").val(data.moduleData.moduleCode);
$("#moduleName_edit").val(data.moduleData.moduleName);
$("#modulePath_edit").val(data.moduleData.modulePath);
$("#parentCode_edit").val(data.moduleData.parentCode);
$("#isLeaf_edit>input[name='isLeaf']:checked").prop(
'checked', false);
$("#isLeaf" + data.moduleData.isLeaf + "_edit").prop(
'checked', true);
$("#sortNumber_edit").val(data.moduleData.sortNumber);
if (data.moduleData.moduleCode == '0') {
$("#moduleName_edit").attr('disabled', true);
$("#moduleCode_edit").attr('disabled', true);
$("#modulePath_edit").attr('disabled', true);
$("#parentCode_edit").attr('disabled', true);
$("#isLeaf_edit input[name='isLeaf']").attr('disabled',
true);
$("#sortNumber_edit").attr('disabled', true);
} else {
$("#moduleName_edit").attr('disabled', false);
$("#moduleCode_edit").attr('disabled', false);
$("#modulePath_edit").attr('disabled', false);
$("#parentCode_edit").attr('disabled', false);
$("#isLeaf_edit input[name='isLeaf']").attr('disabled', false);
$("#sortNumber_edit").attr('disabled', false);
}
},
error : function() {
swal('系统提示', '抱歉,数据加载失败。', 'info');
}
});
}
function zTreeOnDrop(event, treeId, treeNodes, targetNode, moveType) {
var selfId = treeNodes[0].id;
var parentId = targetNode.id;

$.ajax({
url : '/ccms/manager/ModuleController/changeJoin',
dataType : 'json',
data : {
selfId : selfId,
parentId : parentId
},
type : 'post',
success : function(jsonData) {
if (jsonData.rtnCode = 0) {
swal('系统提示', "修改层级关系成功", 'info');
loadProTree();
}

},
error : function() {
swal('系统提示', "修改层级关系失败~~", 'info');
}
});

};

function zTreeBeforeDrop(treeId, treeNodes, targetNode, moveType) {

if (jsonToObj(targetNode.attributes).isLeaf == '1') {
swal('系统提示', "目标节点已是末节点,不可进行拖拽~~", 'info');
return false;
} else {
return true;

}
};

2、加载数据树

//加载数据树
function loadProTree() {
$.ajax({
url : '/ccms/module/getTreeList',
type : 'post',
async : 'true',
cache : false,
data : {},
dataType : 'json',
success : function(data) {
$.fn.zTree.init($("#protree"), setting, data.zNodes);
}
});
}

4、控制器关键代码

// 获取module树
@RequestMapping(value = "/getTreeList", method = { RequestMethod.GET, RequestMethod.POST })
@ResponseBody
public Map<String, Object> getTreeList(HttpServletRequest req, HttpServletResponse resp)
throws UnsupportedEncodingException, IOException {
List<Tree> tree = moduleService.getProtocolTree();
Map<String, Object> result = new HashMap<String, Object>();
result.put("zNodes", tree);
return result;
}
// 根据id获取单条数据
@RequestMapping(value = "/getSingleData", method = { RequestMethod.GET, RequestMethod.POST })
@ResponseBody
public Map<String, Object> getSingleData(String id, HttpServletRequest req, HttpServletResponse resp)
throws UnsupportedEncodingException, IOException {
SysModule info = moduleService.getSingleDate(id);
Map<String, Object> result = new HashMap<String, Object>();
result.put("moduleData", info);
return result;
}

5、业务逻辑层代码:

public interface ModuleService {
//加载module树
public List<Tree> getProtocolTree();

// 查询是否有重复值,存在 exit,不存在 no
public String isExistName(String moduleName, String moduleCode);
//根据id获取module
public SysModule getSingleDate(String moduleCode);
}

实现类:

package com.ccms.service.impl;

import com.ccms.dao.ModuleDao;
import com.ccms.pojo.SysModule;
import com.ccms.service.ModuleService;
import com.ccms.tools.Tree;
import com.ccms.tools.UUIDGenerator;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
@Service("moduleService")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class ModuleServiceImpl implements ModuleService {

@Autowired
ModuleDao moduleDao;


//加载module树
@Override
public List<Tree> getProtocolTree() {
List<String> attributesList = new ArrayList<String>();
attributesList.add("isLeaf");
// 获取功能模块的所有父节点
List<SysModule> parentModuleLst = moduleDao.getParentTree();
List<Tree> parentTreesLst = new ArrayList<Tree>();
// 将List<SysModule>类型转换成List<Tree>
for (SysModule module : parentModuleLst) {
Tree rootTreeData = new Tree();
rootTreeData.setId(module.getModuleCode());
rootTreeData.setName(module.getModuleName());
rootTreeData.setOpen(true);
rootTreeData.setChecked(false);
rootTreeData.setParent(false);
rootTreeData.setNocheck(false);
JSONObject attributesJO = new JSONObject();
attributesJO.put("isLeaf", module.getIsLeaf());
rootTreeData.setAttributes(attributesJO.toString());
parentTreesLst.add(rootTreeData);
}
if (parentTreesLst != null) {
// 遍历List<Tree>类型对象parentTreesLst
for (Tree parentData : parentTreesLst) {
// 获取当前父节点模块编号
String moduleCode = parentData.getId();
// 根据当前父节点模块编号,获取其所包含的功能模块
List<SysModule> list = moduleDao.getTreeList(moduleCode);
List<Tree> treeList = new ArrayList<Tree>();
// 将List<SysModule>类型转换成List<Tree>
for (SysModule sysModule : list) {
Tree tempTreeData = new Tree();
tempTreeData.setId(sysModule.getModuleCode());
tempTreeData.setName(sysModule.getModuleName());
tempTreeData.setOpen(true);
tempTreeData.setChecked(false);
tempTreeData.setParent(false);
tempTreeData.setNocheck(false);
JSONObject attributesJO = new JSONObject();
attributesJO.put("isLeaf", sysModule.getIsLeaf());
tempTreeData.setAttributes(attributesJO.toString());
List childList = new ArrayList<Tree>();
childList = getChildTreeById(sysModule.getModuleCode());
tempTreeData.setChildren(childList);
treeList.add(tempTreeData);
}
parentData.setChildren(treeList);
}
}
return parentTreesLst;
}
// 查询是否有重复值,存在 exit,不存在 no
@Override
public String isExistName(String moduleName, String moduleCode) {
String result;
int i = moduleDao.existSameModuleName(moduleName, moduleCode);
if (i > 0) {
result = "exit";
} else {
result = "no";
}
return result;
}

//根据id获取module
@Override
public SysModule getSingleDate(String moduleCode) {
return moduleDao.getSingleDataById(moduleCode);
}


// 根据父节点CodeId获取子节点数据列表
private List getChildTreeById(String codeId) {
List<Tree> treeList = new ArrayList<Tree>();
List<SysModule> list = moduleDao.getTreeList(codeId);
for (SysModule sysModule : list) {
Tree tempTreeData = new Tree();
tempTreeData.setId(sysModule.getModuleCode());
tempTreeData.setName(sysModule.getModuleName());
tempTreeData.setOpen(true);
tempTreeData.setChecked(false);
tempTreeData.setParent(false);
tempTreeData.setNocheck(false);
JSONObject attributesJO = new JSONObject();
attributesJO.put("isLeaf", sysModule.getIsLeaf());
tempTreeData.setAttributes(attributesJO.toString());
List childList = new ArrayList<Tree>();
childList = getChildTreeById(sysModule.getModuleCode());
tempTreeData.setChildren(childList);
treeList.add(tempTreeData);
}
return treeList;
}
}

6、数据访问层代码:

package com.ccms.dao;

import com.ccms.pojo.SysModule;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface ModuleDao {
// 查询所有模块
@Select("select * from sys_module order by sortNumber asc")
public List<SysModule> getAllModule();

// 查询用户可以操作的模块编号集合
@Select("select distinct moduleCode from sys_role_module where roleCode "
+ "in (select roleCode from sys_user_role where userCode=#{userCode})")
List<String> getmoduleCodes(@Param("userCode") String userCode);

// 获取树形结构所有父节点
@Select("select * from sys_module where parentCode is null order by sortNumber asc")
public List<SysModule> getParentTree();

// 根据功能模块编号,获取其所包含的功能模块
@Select("select * from sys_module where parentCode = #{moduleCode} order by sortNumber asc")
public List<SysModule> getTreeList(@Param("moduleCode") String moduleCode);

// 根据id查询重复name
@Select("select ifnull(count(*),0) from sys_module where moduleName=#{moduleName} and moduleCode <> #{moduleCode}")
public int existSameModuleName(@Param("moduleName") String moduleName, @Param("moduleCode") String moduleCode);

// 根据功能模块编号获取数据
@Select("select cm.*, (case when cm.parentCode is null then '无' " + " else pm.moduleName end) as parentModuleName"
+ " from sys_module cm" + " left join sys_module pm" + " on cm.parentCode=pm.moduleCode"
+ " where cm.moduleCode= #{moduleCode}")
public SysModule getSingleDataById(@Param("moduleCode") String moduleCode);

}

四、碰到的bug及解决方案

1、指定结点选中无效

描述:​​checkNode(treeNode,checked,checkTypeFlag,callbackFlag)​​​方法不能指定某个结点选中
解决
若想在树加载之后设置指定的Id选中,请将ajax的async的值设为false,即同步加载(也就是说先要等树加载完再指定结点选中,要不会出现未知错误,很难发现)

2、mybatis多对多关系的处理较为麻烦



标签:菜单,false,String,List,zTree,moduleCode,树形,return,public
From: https://blog.51cto.com/u_15961549/6054138

相关文章