天天看点

springboot+mybatisplus+layui+restful实现dtree树形结构显示,以左右两侧传值显示

1.首先我们看一下layui中的dtree组件的json格式,我才用简单的json封装,也就是list风格的json。格式如下:

{
"status":{"code":200,"message":"操作成功"},
"data": [
  {"id":"001","title": "湖南省","checkArr": "0","parentId": "0"},
  {"id":"002","title": "湖北省","checkArr": "0","parentId": "0"},
  {"id":"003","title": "广东省","checkArr": "0","parentId": "0"},
  {"id":"004","title": "浙江省","checkArr": "0","parentId": "0"},
  {"id":"005","title": "福建省","checkArr": "0","parentId": "0"},
  {"id":"001001","title": "长沙市","checkArr": "0","parentId": "001"},
  {"id":"001002","title": "株洲市","checkArr": "0","parentId": "001"},
  {"id":"001003","title": "湘潭市","checkArr": "0","parentId": "001"},
  {"id":"001004","title": "衡阳市","checkArr": "0","parentId": "001"},
  {"id":"001005","title": "郴州市","checkArr": "0","iconClass": "dtree-icon-caidan_xunzhang","parentId": "001"}
]
}      

2.TreeNode.java 对树中结构的数据的封装

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TreeNode {

    private Integer id;//自己的id
    @JsonProperty("parentId") //返回的json的名称 parentId ,为了确定层级关系
    private Integer pid;
    private String title;//名称
    private String icon;
    private String href;
    private Boolean spread;//是否展开
    private List<TreeNode> children = new ArrayList<TreeNode>();

    /**
     * 0为不选中  1为选中
     */
    private String checkArr="0";

    /**
     * 部门 dtree的构造器,我们只用到了这四个
     * @param id id
     * @param pid 父亲parentId
     * @param title 名称
     * @param spread 是否展开
     */
    public TreeNode(Integer id, Integer pid, String title, Boolean spread) {
        this.id = id;
        this.pid = pid;
        this.title = title;
        this.spread = spread;
    }

}      

3.sql,我们看一下数据库文件的结构

DROP TABLE IF EXISTS `sys_dept`;
CREATE TABLE `sys_dept` (
  `id` int(11) NOT NULL AUTO_INCREMENT, #只用到了它
  `pid` int(11) DEFAULT NULL, #只用到了它
  `name` varchar(255) DEFAULT NULL, #只用到了它
  `open` int(11) DEFAULT NULL, #只用到了它
  
  `remark` varchar(255) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  `available` int(11) DEFAULT NULL COMMENT '状态【0不可用1可用】',
  `ordernum` int(11) DEFAULT NULL COMMENT '排序码【为了调试显示顺序】',
  `createtime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;      

4.DataGridView.java用来返回前台json数据的实体

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataGridView {
    private Integer code = 0;
    private String msg = "";
    private Long count = 0L;
    private Object data; //这里是dtree中部门的数据

    public DataGridView(Long count, Object data) {
        this.count = count;
        this.data = data;
    }

    public DataGridView(Object data) {
        this.data = data;
    }
}      

5.Dept.java

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_dept")
@ToString
public class Dept implements Serializable {

    private static final long serialVersionUID=1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    private Integer pid;

    private String name;

    /**
     * 是否展开,0不展开,1展开
     */
    private Integer open;

    private String remark;

    private String address;

    /**
     * 是否可用,0不可用,1可用
     */
    private Integer available;

    /**
     * 排序码
     */
    private Integer ordernum;

    private Date createtime;


}      

6.DeptController.java

@RestController
@RequestMapping("/dept")
public class DeptController {

    @Autowired
    private DeptService deptService;

    /**
     * 加载部门左边的菜单树json
     * @param
     * @return
     */
    @RequestMapping("/loadDeptManagerLeftTreeJson")
    public DataGridView loadManagerLeftTreeJson(){
        //查询出所有的部门,存放进list中
        List<Dept> list = deptService.list();

        List<TreeNode> treeNodes = new ArrayList<>();
        //将部门放入treeNodes中,组装成json
        for (Dept dept : list) {
            Boolean open = dept.getOpen() == 1?true:false;
            treeNodes.add(new TreeNode(dept.getId(),dept.getPid(),dept.getName(),open));
        }

        //返回树的Json实体,装着树,树中有部门数据
        return new DataGridView(treeNodes);
    }
}      

7.DeptService.java

public interface DeptService extends IService<Dept> {
}      

8.DeptServiceImpl.java

@Service
@Transactional
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
}      

9.DeptMapper.java

public interface DeptMapper extends BaseMapper<Dept> {
}      

10.父页面,用来分开里面的树结构和右侧内容

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>部门管理</title>
</head>
<!--左右两侧-->
<frameset cols="220,*" border="2" frameborder="yes">
    <frame th:src="@{/sys/toDeptLeft}" name="left">
    <frame th:src="@{/sys/toDeptRight}" name="right">
</frameset>
</html>      

11.Left 树页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>left</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephnotallow=no">
    <link rel="icon" href="/resources/favicon.ico">
    <link rel="stylesheet" href="resources/layui/css/layui.css" th:href="@{/resources/layui/css/layui.css}" media="all"/>
    <link rel="stylesheet" th:href="@{/resources/css/public.css}" media="all"/>
    <link rel="stylesheet" th:href="@{/resources/layui_ext/dtree/dtree.css}" media="all"/>
    <link rel="stylesheet" th:href="@{/resources/layui_ext/dtree/font/dtreefont.css}" media="all"/>
</head>
<body>

<!--存放树的容器开始-->
<ul id="deptTree" class="dtree" data-id="0"></ul>
<!--存放树的容器结束-->

<script type="text/javascript" th:src="@{/resources/layui/layui.js}"></script>
<script type="text/javascript" th:src="@{/resources/layui_ext/dtree/dtree.js}"></script>
<script type="text/javascript">
    var deptTree;
    layui.extend({
        dtree: '/resources/layui_ext/dtree/dtree'   // {/}的意思即代表采用自有路径,即不跟随 base 路径
    }).use(['dtree','layer','jquery'], function(){
        var dtree = layui.dtree;
        var layer = layui.layer;
        var $ = layui.jquery;

        // 初始化树
        deptTree = dtree.render({
            elem: "#deptTree",
            dataStyle: "layuiStyle", //使用layui风格的数据格式
            dataFormat: "list",     //配置data的风格为list,这里是简单的json格式
            response:{message:"msg",statusCode:0},  //修改response中返回数据的定义
            url: "/dept/loadDeptManagerLeftTreeJson" // 使用url加载(可与data加载同时存在)
        });

        // 绑定节点点击事件
        dtree.on("node('deptTree')" ,function(obj){
            //将树节点的id传到reloadTable方法中
            window.parent.right.reloadTable(obj.param.nodeId);
        });
    });
</script>
</body>
</html>      

12.Right 右侧显示部门具体信息的页面【不做详细,只展示如何拿到左侧部门的ID】

<script type="text/javascript" th:src="@{/resources/layui/layui.js}"></script>

<script type="text/javascript">

    //提升数据表格的作用域,因为底下还有一个reloadTable方法
    var tableIns;

    layui.extend({
        dtree: '/resources/layui_ext/dtree/dtree'
    }).use(['jquery', 'form', 'layer', 'laydate', 'table', 'layedit','dtree'], function () {
        var $ = layui.jquery;
        var form = layui.form;
        var layer = layui.layer;
        var table = layui.table;
        var dtree = layui.dtree;

        //初始化表格 加载数据
        tableIns = table.render({
            elem: "#deptTable",
            title: "部门数据表格",
            url: "/dept/loadAllDept",
            toolbar: "#deptToolBar",
            page: true,
            height: "full-180",
            cols: [ [
                {field: 'id', title: 'ID', align: 'center',width:'50'},
                {field: 'pid', title: '父级部门ID', align: 'center',width:'100'},
                {field: 'name', title: '部门名称', align: 'center',width:'150'},
                {field: 'remark', title: '部门备注', align: 'center',width:'150'},
                {field: 'address', title: '部门地址', align: 'center',width:'100'},
                {field: 'available', title: '是否可用', align: 'center',width:'100',templet:function (d) {
                    return d.available==1?'<font color="blue">可用</font>':'<font color="red">不可用</font>';
                }},
                {field: 'open', title: '是否展开', align: 'center',width:'100',templet:function (d) {
                    return d.open==1?'<font color="blue">展开</font>':'<font color="red">不展开</font>';
                }},
                {field: 'ordernum', title: '排序码', align: 'center',width:'80'},
                {field: 'createtime', title: '部门创建时间', align: 'center',width:'160'},
                {fixed: 'right', title: '操作', toolbar: '#deptRowBar', align: 'center',width:'180'}
            ] ],
            done: function (data, curr, count) {
                //不是第一页时,如果当前返回的数据为0那么就返回上一页
                if (data.data.length == 0 && curr != 1) {
                    tableIns.reload({
                        page: {
                            curr: curr - 1
                        }
                    })
                }
            }
        });

        //监控模糊查询按钮事件
        form.on("submit(doSearch)", function (data) {
            tableIns.reload({
                where: data.field,
                page: {
                    curr: 1
                }
            });
            return false;
        });

        //监控工具条事件
        table.on("toolbar(deptTable)", function (obj) {
            switch (obj.event) {
                case 'add':
                    openAddLayer();
                    break;
            };
        });

        //监控行工具条事件
        table.on("tool(deptTable)", function (obj) {
            //获取当前行数据
            var data = obj.data;
            switch (obj.event) {
                case 'delete':
                    deleteDept(data);
                    break;
                case 'update':
                    updateDept(data);
                    break;
            };
        });

        var mainIndex;
        var url;

        //打开添加弹出层
        function openAddLayer() {
            mainIndex = layer.open({
                type:1,
                content:$("#addOrUpdateDiv"),
                area:['800px','500px'],
                title:'添加部门',
                success:function () {
                    $("#dataFrm")[0].reset();
                    //设置下拉树中父节点的值为空
                    $("#pid").val("");
                    url="/dept/addDept";
                    //初始化排序码
                    $.get("/dept/loadDeptMaxOrderNum",function (res) {
                        $("#ordernum").val(res.value);
                    });
                    //设置下拉树的value值为空
                    selectTree.selectVal("");
                }
            });
        }

        //打开修改的弹出层
        function updateDept(data) {
            mainIndex = layer.open({
                type:1,
                content:$("#addOrUpdateDiv"),
                area:['800px','500px'],
                title:'修改部门',
                success:function () {
                    //清空原有的数据
                    $("#dataFrm")[0].reset();
                    //装载新的数据
                    form.val("dataFrm",data);
                    //选中之前的父级部门  nodeId=data.pid
                    dtree.dataInit("deptTree",data.pid);
                    dtree.selectVal("deptTree");
                    url="/dept/updateDept";
                }
            });
        }

        form.on("submit(doSubmit)",function (data) {
            $.post(url,data.field,function (res) {
                if (res.code==200){
                    tableIns.reload();
                    //重新加载添加弹出层的下拉树
                    selectTree.reload();
                    //重新加载左边的部门树
                    window.parent.left.deptTree.reload();
                }
                layer.msg(res.msg);
                layer.close(mainIndex);
            });
            return false;
        });

        /*$("#doSubmit").click(function () {
            var data = $("#dataFrm").serialize();
            $.post(url,data,function (res) {
                if (res.code==200){
                    tableIns.reload();
                    //重新加载添加弹出层的下拉树
                    selectTree.reload();
                    //重新加载左边的部门树
                    window.parent.left.deptTree.reload();
                }
                layer.msg(res.msg);
                layer.close(mainIndex);
            });
        });*/

        //删除
        function deleteDept(data) {
            $.post("/dept/checkDeptHasChildrenNode", {id: data.id}, function (resoult) {
                if (resoult.value){
                    layer.msg("当前部门节点有子部门,请选择删除子部门!")
                }else {
                    layer.confirm('你确定要删除【' + data.name + '】这个部门吗?', {icon: 3, title: '提示'}, function (index) {
                        $.post("/dept/deleteDept", {id: data.id},function (res) {
                            if (res.code == 200) {
                                tableIns.reload({
                                    where:"",
                                });
                                //刷新下拉树
                                selectTree.reload();
                                //刷新左边的部门树
                                window.parent.left.deptTree.reload();
                            }
                            layer.msg(res.msg);
                        });
                        layer.close(index);
                    });
                }
            });
        }

        //初始化下拉树
        var selectTree = dtree.renderSelect({
            elem: "#deptTree",
            width: "100%", // 可以在这里指定树的宽度来填满div
            dataStyle: "layuiStyle", //使用layui风格的数据格式
            dataFormat: "list",     //配置data的风格为list
            response:{message:"msg",statusCode:0},  //修改response中返回数据的定义
            url: "/dept/loadDeptManagerLeftTreeJson" // 使用url加载(可与data加载同时存在)
        });

        //监听点击的方法
        dtree.on("node(deptTree)",function (obj) {
            $("#pid").val(obj.param.nodeId);
            console.log(obj.param.nodeId);
        })


    });

    //拿到右侧页面接受id,并传给后台,给其它页面刷新当前页面数据表格的方法
    function reloadTable(id) {
        tableIns.reload({
            where:{
                id:id
            },
            page:{
                curr:1
            }
        });
    }

</script>      

继续阅读