- 首先,数据库中,字段要有id和pid,并且pid内的内容都能在id中找到,当然pid要有个根null,类型也都是String;
- 用递归的方式把得到的内容存在集合中,并以json的形式传递到页面。
- talk is cheap,show me code;
public class Menu implements Serializable{
private String id;
private String name;
private String pId;
private boolean open;
private List<Menu> children;
set....get....toString....不写了就
以上是树的实体类要有的,命名为Menu;
- 还有建一个目标实体类,要有id和pid(命名可以不一样);
public interface TreeMapper {
/**
* 查询树状图,查询语句companyid,
* @return
*/
List<Menu> selectByCompanyid(@Param("companyid")String companyid);
```
以上是接口mapper,
```
<mapper namespace="地址接口就是上面的.TreeMapper">
<!-- 查询部门资料树状图 List<Menu> selectByCompanyid
把表中的字段 rowid,ccname,Parentrowid重新命名为树结构的名字,-->
<select id="selectByCompanyid" resultType="实体类的位置.Menu">
SELECT
Rowid as id,ccname as name,Parentrowid as pId,cccode, companyid
FROM
表
where
<if test="companyid != null and companyid !='' ">
companyid = #{companyid} and
</if>
1=1
</select>
```
以上是xxmapper.xml文件
public interface ITreeService {
/*
* 根据公司编码查询部门名称
*/
List<Menu> getByCompanyid(@Param("companyid")String companyid);
业务层接口
@Service
public class TreeService implements ITreeService{
@Resource
private TreeMapper treeMapper;
/*
* 根据公司编码查询部门名称
*/
public List<Menu> getByCompanyid(String companyid) {
return treeMapper.selectByCompanyid(companyid);
}
业务层实现类
控制器层:
@RequestMapping("/basic/hrgeneral")
@Controller
public class TreeHrgeneralController {
//得到树里的集合
@Resource
private ITreeService treeService;
@RequestMapping("/List.do")
public String showList(String companyid) {
//System.out.println("1空页面");
return "showlist";
}
@RequestMapping("/showTree.do")
@ResponseBody
public JSONArray showTree() {
// 得到业务层数据,children里面全部为空,左边树全部显示
List<Menu> rootMenu = treeService.getByCompanyid(null);
// 查看结果
for (Menu menu : rootMenu) {
}
// 最后的结果
List<Menu> menuList = new ArrayList<Menu>();
// 先找到所有的一级菜单
for (int i = 0; i < rootMenu.size(); i++) {
// 一级菜单没有parentId,方法的意思是String为空时
if (StringUtils.isBlank(rootMenu.get(i).getpId())) {
menuList.add(rootMenu.get(i));
}
}
// 为一级菜单设置子菜单,getChild是递归调用的
for (Menu menu : menuList) {
menu.setChildren(getChilden(menu.getId(), rootMenu));
//System.out.println("后代:" + menu);
}
// 我们用的ztree需要的json对象,而不是json字符串
JSONArray jsonArray = JSONArray.fromObject(menuList);
return jsonArray;
}
/**
*我写在控制器中了,
* 递归查找子菜单
*
* @param id
* 当前菜单id
* @param rootMenu
* 要查找的列表
* @return
*/
public List<Menu> getChilden(String id, List<Menu> rootMenu) {
// 子菜单
List<Menu> childList = new ArrayList();
for (Menu menu : rootMenu) {
// 遍历所有节点,将父菜单id与传过来的id比较
if (StringUtils.isNotBlank(menu.getpId())) {
//这里是判断,要根据自己的数据库关系改,当时我这里困了一会,才出来
if (menu.getpId().equals(id)) {
childList.add(menu);
}
}
}
// 把子菜单的子菜单再循环一遍
for (Menu menu : childList) {
if (menu.getpId().equals(id)) {
// 递归
menu.setChildren(getChilden(menu.getId(), rootMenu));
}
} // 递归退出条件
if (childList.size() == 0) {
return null;
}
return childList;
}
<link rel="stylesheet"
href="${pageContext.request.contextPath}/css/demo.css" type="text/css">
<link rel="stylesheet"
href="${pageContext.request.contextPath}/css/zTreeStyle.css"
type="text/css">
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery.ztree.core.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery.ztree.excheck.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery.ztree.exedit.js"></script>
<body>
<div id="container">
<div id="tree"> <!-- 树状图的位置和id -->
<ul id="newTree" class="ztree"></ul>
</div>
<script type="text/javascript">
var setting = {
callback: {
onDblClick: zTreeOnDblClick,//双击起的方法名
onClick: onClick //单击起的方法名
},
view:{
fontCss: { 'color': '', 'font-family': '微软雅黑', "font-size": "18px" },//只更改了颜色,大小可去原css修改,把颜色去掉了blue;
showLine:true, //有没有连线
showIcon: false, //显不示显示图标
dblClickExpand : false}, //设置双击展开为false
/*复选框设置
check : {
enable : true,
chkStyle : "checkbox",
chkboxType : { "Y" : "p", "N" : "s"}
},*/
data : {
key : {
name : "name", //zTree 节点数据保存节点名称的属性名称
children : "children" //zTree 节点数据中保存子节点数据的属性名称。没有用到
},
//下面语句可以让pid相同的分层
simpleData : {
enable : true, //确定 zTree 初始化时的节点数据、异步加载时的节点数据
idKey : "id", //节点数据中保存唯一标识的属性名称。[setting.data.simpleData.enable = true 时生效]
pIdKey : "pId" //节点数据中保存其父节点唯一标识的属性名称。[setting.data.simpleData.enable = true 时生效]
}
}
};
//单击事件,单双击是自己的功能,可以删掉
//判断是单击还是双击所触发的事件
var clickFlag = null; //是否点击标识(定时器编号)
function onClick(event,treeId, treeNode) {
if(clickFlag) { //取消上次延时未执行的方法
clickFlag = clearTimeout(clickFlag);
}
clickFlag = setTimeout(function() {
// click 事件的处理,展开树节点
var zTree = $.fn.zTree.getZTreeObj("newTree");
zTree.expandNode(treeNode);
}, 300); //延时300毫秒执行,太短没有效果,太长等待时间久
}
function zTreeOnDblClick(event,treeId, treeNode) {
//双击事件,先判断
if(clickFlag) {//取消上次延时未执行的方法
clickFlag = clearTimeout(clickFlag);
}
// dblclick 事件的处理
function zTreeOnDblClick(event, treeId, treeNode) {
// alert(treeNode.tId + ", " + treeNode.name+","+treeNode.cccode+","+treeNode.companyid);
//ajax代码
}
$(function(){
//显示树状结构
$.ajax({
"url":"${pageContext.request.contextPath}/basicData/hrgeneral/showTree.do",
"data":"" , //$("#query").serialize(),//将id为query的表单持久化,参数传给控制器
"type":"POST",
"dataType":"json",
"success":function(obj){ //将url返回的数据放在obj中,即返回来的内容
var zNodes = eval('obj');
$.fn.zTree.init($("#newTree"), setting, zNodes);
}
});
});
就这样了,看看能实现吗,前端页面引入的css和js,大家在ztree官网下载吧http://www.treejs.cn/v3/main.php#_zTreeInfo。