bootstrap - selectree树形结构下拉框

1、首先导入Bootstrap js、样式

<script src="/static/common/ztree/js/jquery.ztree.all.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/exp/treeselect/selectree.js"></script>

在这里插入图片描述

2、引入的 selectree.js (这是固定代码,哪里有变动我会详细说明)

(function ($) {
    "use strict";
    //default selecttree
    var defaultOptions = {
        width: 'auto',
        height: '300px',
        isSimpleNode: true, //是否启用简单的节点属性(id,ame),次配置是form表单传递到后台的参数值,数据通过json传递
        pIcon: '',
        cIcon: '',
        debug: false,
        data: [{
            id: '111111',
            name: "父节点1",
            children: [
                {id: '22222', name: "子节点1"},
                {id: '33333', name: "子节点2"}
            ]
        }]
    }
    //define some global dom
    var SelectTree = function (element, options) {
        this.options = options;
        this.$element = $(element);
        this.$containner = $('<div></div>');
        this.$ztree = $('<ul   id="ztree" class="ztree"></ul>');
        this.$pInput = $('<input id="nodes" type="hidden"/>'); // 这里为隐藏域数据 id='nodes',选中的数都存储在这。
    }
    //prototype method
    SelectTree.prototype = {
        constructor: SelectTree,
        init: function () {
            var that = this,
                st = this.$element;
            // style
            that.$containner.css({'display': 'inline-block', 'position': 'relative'});
            that.$ztree.css({
                'position': 'absolute',
                'z-index': 10000,
                'border-radius': '3px',
                'border': '1px #ccc solid',
                'overflow': 'auto',
                'background': '#fff',
                'margin-top': '30px'
            });
            that.$ztree.css({'width': this.options.width || that.defaultOptions.width});
            that.$ztree.css({'height': this.options.height || taht.defaultOptions.height});
            // dom
            if (that.$element.data('pname')) {
                that.$pInput.attr('name', that.$element.data('pname'));
            }
            if (that.$element.attr('name')) {
                that.$element.removeAttr('name');
            }
            that.$ztree.attr('id', 'selectTree-ztree');
            that.$ztree.css('display', 'none');
            that.$element.attr('readonly', 'readonly');
            st.wrap(that.$containner);
            st.after(that.$pInput);
            st.after(that.$ztree);

            //listener
            that.$element.bind('click', function (e) {
                that.$ztree.toggle();
            });

            //ztree 
            //listener
            this.options.ztree.setting.callback = {
                onCheck: function (event, treeId, treeNode) {
                    return that._onSelectTreeCheck(event, treeId, treeNode);
                }
            }
            $.fn.zTree.init(that.$ztree, this.options.ztree.setting, this.options.ztree.data);
			
            // this 这个东西啊你理解成 它是当前选中的数据 赋给 selectttt ,aaaa 这是一个function 往下看
            aaaa.selectttt(this);
        },
        _onSelectTreeCheck: function (event, treeId, treeNode) {
            var that = this;
            //获得所有选中节点
            var pValue = '',
                text = '';
            var treeObj = $.fn.zTree.getZTreeObj(that.$ztree.attr('id'));
            console.log(treeObj)
            if (treeObj) {
                var nodes = treeObj.getCheckedNodes(true);
                if (this.options.debug) {
                    console.log("选中的节点:");
                    console.log(nodes);
                }
                for (var i = 0; i < nodes.length; i++) {
                    if (nodes[i].isParent) {
                        text = text + nodes[i].name + ':';
                    } else {
                        text = text + nodes[i].name + ',';
                    }
                }
                if (this.options.isSimpleNode) {
                    nodes = common._transformToSimpleNodes(nodes);
                }
                if (this.options.debug) {
                    console.log("提交到表单的数据结构:");
                    console.log(JSON.stringify(nodes));
                }
                // nodes数据 从这赋给隐藏域input(id='nodes')
                that.$pInput.val(JSON.stringify(nodes));
                text = text ? text.substr(0, text.length - 1) : '';
                that.$element.val(text);
                that.$element.attr('title', text);
            }
        }
    }
    var common = {
        //这里组织默认参数,用户传过来的参数,ztree的一些固定参数
        _getSelectTreeOptions: function (options) {
            options = options ? options : {};
            return {
                width: options.width || defaultOptions.width,
                height: options.height || defaultOptions.height,
                isSimpleNode: options.isSimpleNode || defaultOptions.isSimpleNode,
                pIcon: options.pIcon || defaultOptions.pIcon,
                cIcon: options.cIcon || defaultOptions.cIcon,
                debug: options.debug || defaultOptions.debug,
                ztree: {
                    data: options.data || defaultOptions.data,
                    setting: {
                        check: {
                            enable: true,
                            chkStyle: "checkbox",
                            chkboxType: {"Y": "ps", "N": "ps"}
                        }
                    }
                }
            }
        },
        //转换ztree为简单的节点,只包含id,name
        _transformToSimpleNodes: function (nodes) {
            var newNodes = [];
            if (nodes instanceof Array) {
                for (var i = 0; i < nodes.length; i++) {
                    var pNode = nodes[i].getParentNode();
                    var node = {};
                    node.pId = pNode ? pNode.id : null;
                    node.id = nodes[i].id;
                    node.name = nodes[i].name;
                    newNodes.push(node);
                }
            }
            return newNodes;
        }
    }
    $.fn.selectTree = function (options) {
        var data = new SelectTree(this, common._getSelectTreeOptions(options));
        return data.init();
    }
    $.fn.selectTree.Constructor = SelectTree;

    // 为什么这有一个aaaa?他的作用是用来回显你当前选中的数据,回显展示在input输入框内 ,这个是需求问题,如果不需要回显,可以忽略这段代码
    var aaaa ={
        selectttt:function (e) {
            debugger
            var that = e;
            //获得所有选中节点
            var pValue = '',
                text = '';
            var treeObj = $.fn.zTree.getZTreeObj(that.$ztree.attr('id'));
            console.log(treeObj)
            if (treeObj) {
                var nodes = treeObj.getCheckedNodes(true);
                if (that.options.debug) {
                    console.log("选中的节点:");
                    console.log(nodes);
                }
                for (var i = 0; i < nodes.length; i++) {
                    if (nodes[i].isParent) {
                        text = text + nodes[i].name + ':';
                    } else {
                        text = text + nodes[i].name + ',';
                    }
                }
                if (that.options.isSimpleNode) {
                    nodes = common._transformToSimpleNodes(nodes);
                }
                if (that.options.debug) {
                    console.log("提交到表单的数据结构:");
                    console.log(JSON.stringify(nodes));
                }
                that.$pInput.val(JSON.stringify(nodes));
                text = text ? text.substr(0, text.length - 1) : '';
                that.$element.val(text);
                that.$element.attr('title', text);
            }
        }
    }
})(jQuery)

3、HTML 页面中接收数据

// 通过id = selectree, 赋值数据到div中
<script type="text/javascript">
    $(function() {
        var nodes = [{
            id: '111111',
            name: "父节点1",
            children: [
                { id: '22222', name: "子节点1" },
                { id: '33333', name: "子节点2" }
            ]
        }];
        $("#selectree").selectTree({
            isSimpleNode: true,
            debug: true,
            data: JSON.parse('${data}') // 后台查询的数据 返回为data
        }); 
    });
</script>

// input框在页面上展示数据
<div class="col-md-3">
    <div class="input-group">
        <span class="input-group-addon" id="zh_box">部门</span>
        <input type="text"  autocomplete="off"
        class="input-sm form-control"  id="selectree"/>
    </div>
</div>

// 从Selectree.js nodes 中获取选中的数据,传到后台作为查询条件使用
var nos =  $('#nodes').val(); // 通过nodes 拿到
    if(nos!="") {
        var nodesJson = eval('(' + $('#nodes').val() + ')');// 转换成字符串
        var deptIds = '';
        if (nodesJson != null && nodesJson.length > 0) { // 进行遍历存储到deptIdS中 返回到后台
            for (var i = 0; i < nodesJson.length; i++) {
                deptIds += nodesJson[i].id + ',';
            }
        }
        if (nodesJson != null && nodesJson.length > 0) {
            url += "&dement=" + deptIds // 传到后台 dement 作为查询条件
        }
    }

4、前台说完了,咱们主要来看后台代码的实现,如何返回json数据,是通过什么方式 继续往下看

后台代码

 1、Controller
        // 我这个是通过权限控制的:dept当前登录人有哪些部门,dement默认所有部门
        List<SysDepartment> dment = iSysDepartmentService.findDepartmentTreeList(dept, dement);
        // dment 查询出所部门数据
        modelAndView.addObject("data", JSON.toJSONString(dment));//部门下拉框,返回页面data
2、service
    	List<SysDepartment> findDepartmentTreeList(DepartmentAllPo<SysDepartmentVo> dept, String dement);
3、serviceImpl
	   // 当前部门全查询 ,递归查询
        @Override
        public List<SysDepartment> findDepartmentTreeList(DepartmentAllPo<SysDepartmentVo> dept, String dement) {
            List<SysDepartment> firstDepart = null;
            if(dept != null){
            // 遍历一级菜单
                List<SysDepartment> deptList = sysDepartmentMapper.selectList(new QueryWrapper<SysDepartment>().lambda().in(SysDepartment::getId,dept.getDepts()).eq(SysDepartment::getIsDelete,0));
                for (SysDepartment d:deptList) {// 遍历判断当前默认全部选中,或者选中进行查询
                    if(StringUtils.isBlank(dement) || StringUtils.indexOf(dement,d.getId())>-1){
                        d.setChecked(true); // 选中状态
                    }
                }
        // 查询一级数据
        firstDepart = deptList.stream().filter(o -> StringUtils.equals(o.getParentId(),"0")).sorted(Comparator.comparing(SysDepartment::getDepartmentLevel)).collect(Collectors.toList());
                for (SysDepartment o : firstDepart) {
                    fullChild(o,deptList);// 子级数据存储到fullChild
                }
            }
            return firstDepart;
        }
        
	// 递归查询树形结构
    private void fullChild(SysDepartment o, List<SysDepartment> deptList) {
        // 查询上级部门与它父级部门的ID是否相同
        List<SysDepartment> clist = deptList.stream().filter(d->StringUtils.equals(d.getParentId(),o.getId())).collect(Collectors.toList());
        if(clist.isEmpty()){// 如果为空不执行任何操作

        }else{// 遍历多级树形结构
            o.setChirldList(clist);
            for (SysDepartment c:clist) {
                fullChild(c,deptList);
            }
        }
    }

5、树形结构 以及 结构数据格式

在这里插入图片描述
在这里插入图片描述

6、json数据格式

[{"pId":null,"id":"b18163ce656911e99d9200163e2e7cd0","name":"润兴科技"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"163869757257f5050285a3330f53e514","name":"市场运营部"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"2d9f849249bd859b6e0281a54504e7cb","name":"人力行政部"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"9fa5921e170654f932865e1adfa497f7","name":"总经理办公室"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"bdf8691f38e5e1a84b50c2ad002b828c","name":"研发部"},{"pId":"bdf8691f38e5e1a84b50c2ad002b828c","id":"5eab5513531e6c25a2f1a83a14bd6dfb","name":"市局研发"},{"pId":"bdf8691f38e5e1a84b50c2ad002b828c","id":"793122a044131109b71decb2ab95321c","name":"研发中心"},{"pId":"bdf8691f38e5e1a84b50c2ad002b828c","id":"fbf41954c2fbc5b2dbf0e6021b35b6ac","name":"测试部"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"d395473b953d37a88b43fb79840e80d4","name":"物联网事业部"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"f1ec10683d539eaae6a626d8eeb634c2","name":"政府事业部"},{"pId":"b18163ce656911e99d9200163e2e7cd0","id":"f9a6b6bccb77db27e9c4af26c520704c","name":"经营财务部"}]
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值