组织机构树

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            box-sizing: border-box;
            padding: 0;
            margin: 0;
            list-style: none;
        }

        .zsw-org {
            display: table;
            margin: 0 auto;
        }

        .zsw-org li {
            display: table-cell;
            text-align: center;
        }

        .zsw-cc {
            padding: 0 10px;
            text-align: center;
        }

        .zsw-cc>div {
            display: inline-block;
            border: 1px solid #990000;
            height: 35px;
            line-height: 35px;
            padding: 0 10px;
            border-radius: 3px;
            white-space: nowrap;
            cursor: default;
            position: relative;
        }

        .zsw-cc>div:hover>.child-hide {
            display: block !important;
        }

        .child-hide {
            position: absolute;
            bottom: -10px;
            display: none;
            height: 15px;
            line-height: 15px;
             100%;
            left: 0;
            text-align: center;
        }

        .zsw-vertical {
            text-align: left;
        }

        .zsw-vertical div {
            display: inline-block;
             50%;
            border-right: 1px solid #990000;
            height: 15px;
        }

        .zsw-org-tree {
            margin-top: -6px;
        }

        .zsw-org-tree>li .zsw-line>span {
            height: 15px;
            display: inline-block;
             100%;
            border-top: #990000 1px solid;
            text-align: left;
        }

        .zsw-org-tree>li .zsw-line>span>span {
             50%;
            border-right: #990000 1px solid;
            display: block;
            height: 15px;
        }

        .zsw-org-tree>li:first-child {
            text-align: right;
        }

        .zsw-org-tree>li:first-child>.zsw-content>.zsw-line>span {
             50%;
            border-left: #990000 1px solid;
        }

        .zsw-org-tree>li:first-child>.zsw-content>.zsw-line>span>span,
        .zsw-org-tree>li:last-child>.zsw-content>.zsw-line>span>span {
            border: none;
        }

        .zsw-org-tree>li:last-child {

            text-align: left;
        }

        .zsw-org-tree>li:last-child>.zsw-content>.zsw-line>span {
             50%;
            border-right: #990000 1px solid;
        }

        .zsw-line-sign>span {
            border-left: none !important;
            border-top: none !important;
        }
        .zsw-org-tree-active{
            background-color: cadetblue;
            color: #fff;
        }
    </style>
</head>

<body id="orgTree">
    <!-- <ul class="zsw-org">
        <li>
            <div class="zsw-content">
                <div class="zsw-cc">
                    <div>内容</div>
                </div>
            </div>
            <div class="zsw-vertical">
                <div></div>
            </div>
            <ul class="zsw-org-tree">
                <li>
                    <div class="zsw-content">
                        <div class="zsw-line">
                            <span>
                                <span></span>
                            </span>
                        </div>
                        <div class="zsw-cc">
                            <div>内容</div>
                        </div>
                    </div>
                    <div class="zsw-vertical">
                        <div></div>
                    </div>
                    <ul class="zsw-org-tree">
                        <li>
                            <div class="zsw-content">
                                <div class="zsw-line">
                                    <span>
                                        <span></span>
                                    </span>
                                </div>
                                <div class="zsw-cc">
                                    <div>内容</div>
                                </div>
                            </div>
                        </li>
                        <li>
                            <div class="zsw-content">
                                <div class="zsw-line">
                                    <span>
                                        <span></span>
                                    </span>
                                </div>
                                <div class="zsw-cc">
                                    <div>内容</div>
                                </div>
                            </div>
                        </li>
                        <li>
                            <div class="zsw-content">
                                <div class="zsw-line">
                                    <span>
                                        <span></span>
                                    </span>
                                </div>
                                <div class="zsw-cc">
                                    <div>内容</div>
                                </div>
                            </div>
                        </li>
                    </ul>
                </li>
                <li>
                    <div class="zsw-content">
                        <div class="zsw-line">
                            <span>
                                <span></span>
                            </span>
                        </div>
                        <div class="zsw-cc">
                            <div>内容</div>
                        </div>
                    </div>
                </li>
                <li>
                    <div class="zsw-content">
                        <div class="zsw-line">
                            <span>
                                <span></span>
                            </span>
                        </div>
                        <div class="zsw-cc">
                            <div>内容</div>
                        </div>

                    </div>
                    <div class="zsw-vertical">
                        <div></div>
                    </div>
                    <ul class="zsw-org-tree">
                        <li>
                            <div class="zsw-content">
                                <div class="zsw-line">
                                    <span>
                                        <span></span>
                                    </span>
                                </div>
                                <div class="zsw-cc">
                                    <div>内容</div>
                                </div>
                            </div>
                        </li>
                        <li>
                            <div class="zsw-content">
                                <div class="zsw-line">
                                    <span>
                                        <span></span>
                                    </span>
                                </div>
                                <div class="zsw-cc">
                                    <div>内容</div>
                                </div>
                            </div>
                        </li>
                        <li>
                            <div class="zsw-content">
                                <div class="zsw-line">
                                    <span>
                                        <span></span>
                                    </span>
                                </div>
                                <div class="zsw-cc">
                                    <div>内容</div>
                                </div>
                            </div>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul> -->
</body>

</html>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script>
    function orgTree(opt) {
        //默认参数
        this._defOpt = {
            //data: undefined,
            el: "#orgTree",
            //afterContent: undefined,
            //afterContentEvent: undefined,
            dicNameSet: {
                "name": "name",
                "child": "child"
            },
            //contentClick: undefined,
            isFlex: false
        };

        let _opt = $.extend({}, this._defOpt, opt);

        //处理html
        function joinHtml() {
            //第一个节点与后续节点有区别
            if (_opt.data) {
                //根目录
                let _$html = $('<ul class="zsw-org"></ul>');

                //第一个节点
                let _$li = $('<li></li>')

                //第一个节点内容
                let _content = '';
                _content += '<div class="zsw-content">';
                _content += '<div class="zsw-cc">';
                _content += '<div>' + _opt.data[_opt.dicNameSet.name] + '</div>';
                _content += '</div>';
                _content += '</div>';

                let _$content = $(_content);

                addCustomNode(_$content, null, _opt.data);

                _$li.append(_$content);

                _$html.append(_$li)

                $(_opt.el).html(_$html);

                bindContentClick(_$li, _opt.data);

                if (_opt.data[_opt.dicNameSet.child]) {
                    joinHtmlChild(_opt.data[_opt.dicNameSet.child], _$li);
                }
            }
        }

        function joinHtmlChild(obj, el) {
            if (obj !== null && obj.length > 0) {

                //竖线
                let verHtml = '';
                verHtml += '<div class="zsw-vertical">';
                verHtml += '<div></div>';
                verHtml += '</div>';
                verHtml = $(verHtml);

                el.append(verHtml);

                //添加子级
                let ul = $('<ul class="zsw-org-tree"></ul>');
                el.append(ul);

                $.each(obj, function (i, item) {

                    let li = $("<li></li>")

                    ul.append(li);

                    let content = '';
                    content += '<div class="zsw-content">';
                    if (obj.length > 1) {
                        content += '<div class="zsw-line">';
                    }
                    else {
                        content += '<div class="zsw-line zsw-line-sign">';
                    }
                    content += '<span>';
                    content += '<span></span>';
                    content += '</span>';
                    content += '</div>';
                    content += '<div class="zsw-cc">';
                    content += '<div>' + item[_opt.dicNameSet.name] + '</div>';
                    content += '</div>';
                    content += '</div>';

                    content = $(content);

                    addCustomNode(content, obj, item);

                    li.append(content);

                    bindContentClick(li, item);

                    if (item[_opt.dicNameSet.child]) {
                        joinHtmlChild(item[_opt.dicNameSet.child], li)
                    }
                })
            }
        }


        function addCustomNode(el, parentData, data) {
            if (_opt.afterContent !== undefined && _opt.afterContent !== '') {
                let afterConten = $(_opt.afterContent)

                el.find(".zsw-cc div").append(afterConten);

                if (typeof _opt.afterContentEvent === 'function') {
                    _opt.afterContentEvent(afterConten, el, parentData, data)
                }
            }
        }

        //绑定内容点击事件
        function bindContentClick(el, data) {
            $(el).on("click", ".zsw-cc div", function (e) {
                if (_opt.isFlex) {
                    let ver = $(el).children(".zsw-vertical");
                    let org = $(el).children(".zsw-org-tree");

                    if (ver.css("display") === 'block') {
                        ver.hide();
                        org.hide();

                        $(this).append("<span class='child-hide'>V</span>")
                    }
                    else {
                        ver.show();
                        org.show();

                        $(this).children(".child-hide").remove()
                    }
                }

                $(".zsw-org-tree-active").removeClass('zsw-org-tree-active');
                $(el).children(".zsw-content").find(".zsw-cc div").addClass('zsw-org-tree-active')

                if (typeof _opt.contentClick === 'function') {
                    _opt.contentClick(e, data);
                }

                //阻止冒泡
                return false;
            })
        }

        function removeAaary(_arr, _obj) {
            var length = _arr.length;
            for (var i = 0; i < length; i++) {
                if (_arr[i] == _obj) {
                    if (i == 0) {
                        _arr.shift(); //删除并返回数组的第一个元素
                        return _arr;
                    }
                    else if (i == length - 1) {
                        _arr.pop();  //删除并返回数组的最后一个元素
                        return _arr;
                    }
                    else {
                        _arr.splice(i, 1); //删除下标为i的元素
                        return _arr;
                    }
                }
            }
        }

        //初始化
        joinHtml();



        return {
            //刷新结构
            refresh: function () {
                alert(111)
                joinHtml();
            },
            //添加数据
            addNode: function (el, pdata, data) {
                //alert("未实现");
                //addChildNode();


                let ul = "";
                if (pdata.child != null && pdata.child != undefined && pdata.child) {
                    pdata.child.push(data);
                    ul = $(el).siblings("ul")
                }
                else {
                    pdata.child = [];
                    pdata.child.push(data);
                    ul = $('<ul class="zsw-org-tree"></ul>')

                    let verHtml = '';
                    verHtml += '<div class="zsw-vertical">';
                    verHtml += '<div></div>';
                    verHtml += '</div>';
                    verHtml = $(verHtml);
                    el.parent().append(verHtml)

                    el.parent().append(ul)
                }

                let li = '';
                li += '<li>';
                li += '<div class="zsw-content">';

                if (pdata.child.length > 1) {
                    li += '<div class="zsw-line">';

                    //修改样式,只允许修改直接下级
                    ul.children("li").children(".zsw-content").find(".zsw-line-sign").removeClass('zsw-line-sign');
                }
                else {
                    li += '<div class="zsw-line zsw-line-sign">';
                }
                //li += '<div class="zsw-line">';
                li += '<span>';
                li += '<span></span>';
                li += '</span>';
                li += '</div>';
                li += '<div class="zsw-cc">';
                li += '<div>' + data[_opt.dataSet.name] + '</div>';
                li += '</div></div>';
                li += '</li>';

                li = $(li);
                ul.append(li);

                let _$content = li.find(".zsw-content")

                addCustomNode(_$content, data);

                bindContentClick(li, data);
            },
            //删除数据
            delNode: function (el, pData, data) {
                //alert("未实现")
                //delete data;

                if (pData == null) {
                    //顶级节点
                    _opt.data = null;

                    $(_opt.el).html("")
                }
                else {
                    removeAaary(pData, data);

                    if(pData.length > 0){
                        if(pData.length == 1){
                            let li = el.parent();

                            li.siblings().children(".zsw-content").find(".zsw-line").addClass("zsw-line-sign");

                            li.remove();
                        }
                    }
                    else{
                        let ul = el.parent().parent();
                        ul.siblings(".zsw-vertical").remove();
                        ul.remove();
                    }
                }

                console.log(_opt.data);
            },
            //更新数据
            uptNode: function (el, contentNode, nData) {
                //alert("未实现")
                let nodeData = $.extend(contentNode, nData);

                let content = el.find('.zsw-cc div');

                content.html(nodeData[_opt.dicNameSet.name]);
            },
            //重置数据
            resetData: function (data) {
                _opt.data = data;
                joinHtml();
            }
        };
    }

    //使用示例
    var orgTree = new orgTree({
        //数据
        data: {
            name: "名称1",
            child: [
                {
                    name: "名称2",
                    child: [
                        {
                            name: "名称2"
                        },
                        {
                            name: "名称3"
                        }
                    ]
                },
                {
                    name: "名称3",
                    child: [
                        {
                            name: "名称2"
                        }
                    ]
                }
            ]
        },
        //容器
        //el: "#orgTree",
        //在名称后面增加的自定义内容
        afterContent: "<span>∷</span>",
        //自定义内容的函数,将自定义内容的jquery对象以及当前级别的数据抛出,方便自定义事件
        afterContentEvent: function (custormNode, contentNode, childNodes, node) {
            /*
             * custormNode:当前节点中自定义的节点jquery对象  说不定什么时候就能用到
             * contentNode:当前节点jquery对象  增删改都需要
             * node:当前节点数据,包含子节点  曾删改都需要
             * childNodes:当前节点的父节点的子节点集合  删除数据需要,因为数据需要从此集合删除
             */
            $(custormNode).on("click", function () {
                // console.log("custorm:")
                // console.log(node);
                // console.log(parentNodeData);

                //新节点或者更新后的节点
                // var nData = {
                //     name: "我是新的"
                // }

                //添加数据
                //orgTree.addNode(contentNode, node, nData);

                //修改数据
                //orgTree.uptNode(contentNode, node, nData);

                //删除数据
                //orgTree.delNode(contentNode, childNodes, node);

                //此处冒泡到内容节点时,注释  return false即可
                return false;
            })

            //addChildNode()
        },
        //data中的key设置,以下是默认设置
        // dataSet: {
        //     "name": "name",
        //     "child": "child"
        // },
        //是否可以隐藏
        isFlex: true,
        //节点点击方法
        contentClick: function (e, data) {
            /*
             * e:jquery event对象
             * data:当前节点数据,包含子节点
             */

            console.log("node:")
            console.log(data);
        }
    })
</script>

  

哎,我这个审美啊

原文地址:https://www.cnblogs.com/zhoushangwu/p/11512776.html