zoukankan      html  css  js  c++  java
  • MVC+ZTree实现对树的CURD及拖拽操作

    上一讲中,我们学习了如何使用zTree对一棵大树(大数据量的树型结构的数据表,呵呵,名称有点绕,但说的是事实)进行异步加载,今天这讲,我们来说说,如何去操作这棵大树,无非就是添加子节点,删除节点,编辑节点,节点之间的拖拽,节点位置的变化(排序)等等。

    事实上,jquery.ZTree的demo已经把前台JS代码给的很清晰了,我们只要稍加修改,然后把后台CS代码写好就可以了,我将demo的前台代码做了简单的处理,减化了些代码,项目架构使用microsoft mvc 3.0

    前台HTML代码如下:

    复制代码
    <link href="../../Scripts/JQuery-zTree/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
    <script src="../../Scripts/JQuery-zTree/js/jquery-1.4.4.min.js"></script>
    <script src="../../Scripts/JQuery-zTree/js/jquery.ztree.all-3.5.min.js"></script>
    <style type="text/css">
        .ztree li span.button.add { margin-left: 2px; margin-right: -1px; background-position: -144px 0; vertical-align: top; *vertical-align: middle; }
        a { text-decoration: underline; }
    </style>
    <script type="text/javascript">
        /*
       动态数据测试部分开始 */
        var log, className = "dark";
        var treeID = "treeDemo";
        var curDragNodes, autoExpandNode;
        var newCount = 1;
    
        //异步加载节点
        var setting4 = {
            data: {
                simpleData: {
                    enable: true,
                    idKey: "id",
                    pIdKey: "pId",
                    rootPId: null
                }
            },
            edit: {
                enable: true,
                editNameSelectAll: true,
                showRemoveBtn: showRemoveBtn,
                showRenameBtn: showRenameBtn,
                removeTitle: "删除",
                renameTitle: "编辑",
                drag: {
                    autoExpandTrigger: true,
                    prev: dropPrev,
                    inner: dropInner,
                    next: dropNext
                }
            },
            view: {
                addHoverDom: addHoverDom,
                removeHoverDom: removeHoverDom,
                selectedMulti: false
            },
            async: {
                //异步加载
                enable: true,
                url: "/ZTree/AsyncGetNodes",
                autoParam: ["id", "name", "pId"]
            },
            callback: {
                /*节点获取与展开回调*/
                beforeExpand: beforeExpand,
                onAsyncSuccess: onAsyncSuccess,
                onAsyncError: onAsyncError,
                /*编辑与删除回调*/
                beforeEditName: beforeEditName,
                beforeRemove: beforeRemove,
                beforeRename: beforeRename,
                onRemove: onRemove,
                onRename: onRename,
                /*拖动回调*/
                beforeDrag: beforeDrag,
                beforeDrop: beforeDrop,
                beforeDragOpen: beforeDragOpen,
                onDrag: onDrag,
                onDrop: onDrop,
                onExpand: onExpand
            }
        };
        function beforeEditName(treeId, treeNode) {
            className = (className === "dark" ? "" : "dark");
            var zTree = $.fn.zTree.getZTreeObj(treeID);
            zTree.selectNode(treeNode);
            return confirm("进入节点 -- " + treeNode.name + " 的编辑状态吗?");
        }
        function beforeRemove(treeId, treeNode) {
            className = (className === "dark" ? "" : "dark");
            var zTree = $.fn.zTree.getZTreeObj(treeID);
            zTree.selectNode(treeNode);
            return confirm("确认删除 节点 -- " + treeNode.name + " 吗?");
        }
        function beforeRename(treeId, treeNode, newName, isCancel) {
            className = (className === "dark" ? "" : "dark");
            if (newName.length == 0) {
                alert("节点名称不能为空.");
                var zTree = $.fn.zTree.getZTreeObj(treeID);
                setTimeout(function () { zTree.editName(treeNode) }, 10);
                return false;
            }
            return true;
        }
        function onRemove(e, treeId, treeNode) {
            $.ajax({
                url: '/ZTree/AsyncDelNodes', //url  action是方法的名称
                data: { id: treeNode.id },
                type: 'POST',
                success: function (data) {
                    alert(data);
                }
            });
    
        }
        function onRename(e, treeId, treeNode, isCancel) {
            alert("编辑了节点" + treeNode.id + " " + treeNode.name);
            $.ajax({
                url: '/ZTree/AsyncEditNodes', //url  action是方法的名称
                data: { id: treeNode.id, name: treeNode.name },
                type: 'POST',
                success: function (data) {
                    alert(data);
                }
            });
    
        }
        function showRemoveBtn(treeId, treeNode) {
            //return !treeNode.isFirstNode;
            return true;
        }
        function showRenameBtn(treeId, treeNode) {
            // return treeNode.isLastNode;
            return true;
        }
        function addHoverDom(treeId, treeNode) {
            var sObj = $("#" + treeNode.tId + "_span");
            if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0) return;
            var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
                + "' title='add node' onfocus='this.blur();'></span>";
            sObj.after(addStr);
            var btn = $("#addBtn_" + treeNode.tId);
            if (btn) btn.bind("click", function () {
                var zTree = $.fn.zTree.getZTreeObj(treeID);
                zTree.addNodes(treeNode, {
                    id: (100 + newCount), pId: treeNode.id, name: "new node" + newCount
                });
                $.ajax({
                    url: '/ZTree/AsyncAddNodes', //url  action是方法的名称
                    data: { id: (100 + newCount), pid: treeNode.id, name: "new node" + newCount },
                    type: 'POST',
                    success: function (data) {
                        //异常完成后,刷新父节点及下面所有子节点
                        zTree.reAsyncChildNodes(treeNode, "refresh");
                    }
                });
                newCount++;
                return false;
            });
        };
        function removeHoverDom(treeId, treeNode) {
            $("#addBtn_" + treeNode.tId).unbind().remove();
        };
        function createTree() {
            $.ajax({
                url: '/ZTree/AsyncGetNodes', //url  action是方法的名称
                data: { id: 0 },
                type: 'Get',
                dataType: "text", //可以是text,如果用text,返回的结果为字符串;如果需要json格式的,可是设置为json
                success: function (data) {
                    $.fn.zTree.init($("#" + treeID), setting4, eval('(' + data + ')'));
                },
                error: function (msg) {
                    alert(" 数据加载失败!" + msg);
                }
            });
        }
        function beforeExpand(treeId, treeNode) {
            if (!treeNode.isAjaxing) {
                return true;
            } else {
                alert("zTree 正在下载数据中,请稍后展开节点。。。");
                return false;
            }
        }
        function onAsyncSuccess(event, treeId, treeNode, msg) {
    
        }
        function onAsyncError() {
            alert(" 数据加载失败");
        }
        $(document).ready(function () {
            createTree();
        });
    
    
    
        function dropPrev(treeId, nodes, targetNode) {
    
            var pNode = targetNode.getParentNode();
            if (pNode && pNode.dropInner === false) {
                return false;
            } else {
                for (var i = 0, l = curDragNodes.length; i < l; i++) {
                    var curPNode = curDragNodes[i].getParentNode();
                    if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
                        return false;
                    }
                }
            }
            return true;
        }
        function dropInner(treeId, nodes, targetNode) {
    
            if (targetNode && targetNode.dropInner === false) {
                return false;
            } else {
                for (var i = 0, l = curDragNodes.length; i < l; i++) {
                    if (!targetNode && curDragNodes[i].dropRoot === false) {
                        return false;
                    } else if (curDragNodes[i].parentTId && curDragNodes[i].getParentNode() !== targetNode && curDragNodes[i].getParentNode().childOuter === false) {
                        return false;
                    }
                }
            }
            return true;
        }
        function dropNext(treeId, nodes, targetNode) {
    
            var pNode = targetNode.getParentNode();
            if (pNode && pNode.dropInner === false) {
                return false;
            } else {
                for (var i = 0, l = curDragNodes.length; i < l; i++) {
                    var curPNode = curDragNodes[i].getParentNode();
                    if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
                        return false;
                    }
                }
            }
            return true;
        }
        function beforeDrag(treeId, treeNodes) {
            className = (className === "dark" ? "" : "dark");
            for (var i = 0, l = treeNodes.length; i < l; i++) {
                if (treeNodes[i].drag === false) {
                    curDragNodes = null;
                    return false;
                } else if (treeNodes[i].parentTId && treeNodes[i].getParentNode().childDrag === false) {
                    curDragNodes = null;
                    return false;
                }
            }
            curDragNodes = treeNodes;
            return true;
        }
        function beforeDragOpen(treeId, treeNode) {
            autoExpandNode = treeNode;
            return true;
        }
        function beforeDrop(treeId, treeNodes, targetNode, moveType, isCopy) {
            className = (className === "dark" ? "" : "dark");
            return true;
        }
        function onDrag(event, treeId, treeNodes) {
            className = (className === "dark" ? "" : "dark");
        }
        function onDrop(event, treeId, treeNodes, targetNode, moveType, isCopy) {
            className = (className === "dark" ? "" : "dark");
            $.ajax({
                url: '/ZTree/AsyncDragNodes', // url  action是方法的名称
                data: { id: treeNodes[0].id, pid: targetNode.id, name: treeNodes[0].name, moveType: moveType, isCopy: isCopy },
                type: 'POST',
                success: function (data) {
                }
            });
    
        }
        function onExpand(event, treeId, treeNode) {
            if (treeNode === autoExpandNode) {
                className = (className === "dark" ? "" : "dark");
            }
        }
    </script>
    
    <div class="zTreeDemoBackground left">
        <ul id="treeDemo" class="ztree"></ul>
    </div>
    复制代码

    面各种JS事件,所对应的MVC代码如下:

    复制代码
    #region 对节点的操作
            /// <summary>
            /// 得到一级子节点
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public string AsyncGetNodes(int? id)
            {
                var model = irepository.GetEntities()
                    .Where(i => i.ParentID == id).OrderBy(i => i.Sortable);
    
                return model.ToJson();
            }
            /// <summary>
            /// 添加节点
            /// </summary>
            /// <param name="id"></param>
            /// <param name="name"></param>
            /// <param name="pid"></param>
            /// <returns></returns>
            public string AsyncAddNodes(int id, string name, int pid)
            {
                try
                {
                    //得到父对象,但设置它的isParent属性
                    irepository.Modify(i => new Category
                      {
                          ID = pid,
                          IsParent = true,
                      });
    
                    var entity = new Category
                    {
                        Name = name,
                        ParentID = pid,
                        CreateDate = DateTime.Now,
                        Level = 1,
                        IsParent = false,
                    };
                    irepository.Add(entity);
    
                    return entity.ID.ToString();
                }
                catch (Exception ex)
                {
    
                    return ex.Message;
                }
    
            }
            /// <summary>
            /// 编辑节点(重命名)
            /// </summary>
            /// <param name="id"></param>
            /// <param name="name"></param>
            /// <returns></returns>
            public string AsyncEditNodes(int id, string name)
            {
                try
                {
                    irepository.Modify(i => new Category
                    {
                        ID = id,
                        Name = name,
                    });
                    return "操作成功";
                }
                catch (Exception ex)
                {
    
                    return ex.Message;
                }
            }
            /// <summary>
            /// 删除节点
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public string AsyncDelNodes(int id)
            {
                try
                {
                    irepository.Remove(irepository.GetEntity(i => i.ID == id));
                    return "操作成功";
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
            }
            /// <summary>
            /// 拖拽节点
            /// </summary>
            /// <param name="id"></param>
            /// <param name="pid"></param>
            /// <param name="sortable"></param>
            /// <returns></returns>
            public string AsyncDragNodes(
                int id,
                int pid,
                string name,
                string moveType,
                bool isCopy)
            {
                try
                {
                    var parent = irepository.GetEntity(i => i.ID == pid);
                    var parentSons = irepository.GetEntities(i => i.ParentID == pid);
                    var current = irepository.GetEntity(i => i.ID == id);
                    if (moveType == "inner")
                        parent.isParent = true;
                    else if (parentSons == null || parentSons.Count() == 0)
                        parent.isParent = false;
                    if (isCopy)//复制,前台目前不能实现
                    {
                        irepository.Add(new Category
                        {
                            ParentID = pid,
                            Name = name,
                            CreateDate = DateTime.Now,
                        });
                    }
                    else
                    {
                        if (moveType == "inner")
                        {
                            current.ParentID = pid;
                            irepository.Modify(current);
                        }
                        else
                        {
                            current.ParentID = parent.ParentID;//同级移动时,与目标节点父ID相同
                            current.Sortable = moveType == "next"
                                ? parent.Sortable + 1
                                : parent.Sortable - 1;
                            irepository.Modify(current);
                        }
                    }
                    irepository.Modify(parent);
                    return "操作成功";
                }
                catch (Exception ex)
                {
    
                    return ex.Message;
                }
            }
            #endregion
    复制代码

    好了,上面的代码只是对树结果做的最基本的操作,其中拖拽时的复制操作(按着ctrl键,拖拽节点),后台没有进行实现。

  • 相关阅读:
    js设计模式(一)---单例模式
    JavaScript---设计模式总结
    js设计模式---单例模式
    js设计模式---工厂模式
    react学习笔记01
    css常用布局
    js 继承
    vue路由动态加载
    vue 项目总结
    css文字两端对齐
  • 原文地址:https://www.cnblogs.com/sjqq/p/7530656.html
Copyright © 2011-2022 走看看