通用權限管理系統之權限菜單zTree樹的展現及移動的處理方法

在通用權限管理系統中,有不少數據結構是有父子關係的,如組織機構,部門,權限菜單等,在展現的時候,大多數是經過zTree樹的形式展示的,以下:前端

權限菜單展現

這種數據後臺輸出比較容易處理,參考以下獲取某個子系統的所有操做菜單:node

後臺輸出zTree樹的數據
        /// <summary>
        /// 獲取module樹結構數據
        /// </summary>
        /// <param name="systemCode"></param>
        /// <returns></returns>
        public ActionResult GetModuleTree(string systemCode = null)
        {
            if (string.IsNullOrWhiteSpace(systemCode))
            {
                systemCode = BaseSystemInfo.SystemCode;
            }
            string tableName = systemCode + "Module"; ;
            BaseModuleManager moduleManager = new BaseModuleManager(UserInfo, tableName);
            List<KeyValuePair<string, object>> parameters = new List<KeyValuePair<string, object>>();
            parameters.Add(new KeyValuePair<string, object>(BaseModuleEntity.FieldEnabled, 1));
            //parameters.Add(new KeyValuePair<string, object>(BaseModuleEntity.FieldDeletionStateCode, 0));
            parameters.Add(new KeyValuePair<string, object>(BaseModuleEntity.FieldIsVisible, 1));
            var entityList = moduleManager.GetList<BaseModuleEntity>(parameters, BaseModuleEntity.FieldSortCode);

            Hashtable hashTable = new Hashtable();
            if (entityList != null)
            {
                var result = (from p in entityList select new { id = p.Id, parentId = p.ParentId, name = p.FullName }).ToList();
                hashTable.Add("treeNodes", result);
            }
            else
            {
                hashTable.Add("treeNodes", null);
            }
            return Json(hashTable, JsonRequestBehavior.AllowGet);
        }
前端的JS部分的代碼
        var _zTree;
        //獲取樹對象
        function getTree() {
            return $.fn.zTree.getZTreeObj("tree-1");
        }

        //刷新樹
        function RefreshTree() {
            var systemCode = $("#systemCode").attr("relValue");
            if (typeof (systemCode) != "undefined") {
                setting1.async.url = "/Module/GetModuleTree?systemCode=" + systemCode;
                $.fn.zTree.init($("#tree-1"), setting1);
                _zTree = $.fn.zTree.getZTreeObj("tree-1");
            }
        }

        //過濾
        function filter(treeNodes) {
            var filterName = $("#OrganizeName").attr("reltext");
            if (filterName == "AAAA" || filterName == "") {
                return false;
            }
            return (treeNodes.name.indexOf(filterName) > -1);
        }

        //樹的設置
        var setting1 = {
            async: {
                enable: true,
                dataType: 'JSON',
                //返回的JSON數據的名字
                dataName: 'treeNodes',
                url: "/Module/GetModuleTree",
                autoParam: ["id", "name", "desc"],
                otherParam: {
                    "otherParam1": "zTreeAsyncTest1",
                    "otherParam2": "zTreeAsyncTest2"
                }
                //,傳回的數據格式不是ztree所須要的格式的時候,能夠對數據進行轉化。正常狀況下不須要實現dataFilter
                //dataFilter: filter
            },
            view: {
                addHoverDom: addHoverDom,
                removeHoverDom: removeHoverDom,
                selectedMulti: true
            },
            edit: {
                enable: true,
                showRemoveBtn: false,
                showRenameBtn: false,
                renameTitle: "修改",
                removeTitle: "刪除",
                drag: {
                    isCopy: false,
                    isMove: true
                }
            },
            callback: {
                onClick: onClick,
                beforeDrop: function(treeId, treeNodes, targetNode, moveType) { return onDrop(treeId, treeNodes, targetNode, moveType); },
                onAsyncSuccess: onAsyncSuccess
            }
        };

        //轉移
        function onDrop(treeId, treeNodes, targetNode, moveType) {
            debugger;
            // 當前節點不能移動到當前節點上
            var node, newParent = targetNode;
            var nodeNames = "",nodeIds="";
            for (var i = 0; i < treeNodes.length; i++) {
                node = treeNodes[i];
                nodeNames += node.name + ",";
                nodeIds += node.id + ",";
                if (node.id == newParent.id) {
                    top.Dialog.alert("不能將本身設爲本身的父級節點");
                    return false;
                };
            }
            if (nodeIds.length>0) {
                nodeIds = nodeIds.substring(0, nodeIds.length - 1);
            }
            // 當前節點不能移動到本身的子節點上去
            for (var i = 0; i < treeNodes.length; i++) {
                //debugger;
                // 交換測試
                //newParent = treeNodes[0];
                //node = targetNode;
                node = treeNodes[i];
                var pid = newParent.getParentNode();
                while (pid != null) {
                    pid = pid.getParentNode();
                    if (node == pid) {
                        top.Dialog.alert("當前節點不能移動到本身的子節點上去");
                        return false;
                    }
                }
            }

            if (!confirm("你肯定要將{0}轉移到{1}名下嗎?".replace("{0}", '\'' + nodeNames + '\'').replace("{1}", '\'' + newParent.name + '\''))) {
                return false;
            } else {
                var systemCode = $("#systemCode").attr("relValue");
                $.ajax({
                    url: '/Module/MoveTo',
                    type: 'POST',
                    data: { moduleIds: nodeIds, parentId: newParent.id, systemCode: systemCode },
                    success: function(response, options) {
                        // 重載樹
                        top.Dialog.alert(response.StatusMessage, function() {
                                RefreshTree();
                            }
                        );
                    }
                });
                return true;
            }
        };

        //異步加載成功後
        function onAsyncSuccess(event, treeId, treeNode, msg) {
            _zTree.expandNode(_zTree.getNodes()[0], true, false, false);
        }

        //初始化函數
        function initComplete() {
            $("#layout1").layout({
                leftWidth: 200,
                onEndResize: function() {
                    //g.resetWidth();
                }
            });
            RefreshTree();
            //綁定change事件
            $("#systemCode").bind("change", function() {
                if (!$(this).attr("relValue")) {
                    top.Dialog.alert("沒有選擇節點");
                } else {
                    //top.Dialog.alert("選中節點文本:" + $(this).attr("relText") + "<br/>選中節點值:" + $(this).attr("relValue"));
                    setting1.async.url = "/Module/GetModuleTree?systemCode=" + $(this).attr("relValue"),
                        $.fn.zTree.init($("#tree-1"), setting1);
                    _zTree = $.fn.zTree.getZTreeObj("tree-1");
                    AddModule();
                }
            });
        }

        //點擊樹節點
        function onClick(event, treeId, treeNode, clickFlag) {
            //設置表單的值
            $("#frmContent").attr("src", "/Module/Edit?id=" + treeNode.id + "&systemCode=" + $("#systemCode").attr("relValue"));
        }

        var _treeNode;

        // 添加
        function addHoverDom(treeId, treeNode) {
            if (treeNode.editNameFlag || $("#addBtn_" + treeNode.id).length > 0) return;
            var sObj = $("#" + treeNode.tId + "_span");
            var addStr = "<span class='zbutton add' id='addBtn_" + treeNode.id + "' title='添加' onfocus='this.blur();'></span>";
            sObj.append(addStr);
            var btn = $("#addBtn_" + treeNode.id);
            if (btn) {
                btn.bind("click", function() {
                    _treeNode = treeNode;
                    $("#frmContent").attr("src", "/Module/Add?id=" + treeNode.id + "&systemCode=" + $("#systemCode").attr("relValue"));
                    return false;
                });
            }
        };

        function refreshFrmContent() {
            window.frames["frmContent"].location.reload();
        };

        function removeHoverDom(treeId, treeNode) {
            $("#addBtn_" + treeNode.id).unbind().remove();
        };

        //新增
        function AddModule() {
            var systemCode = $("#systemCode").attr("relValue");
            if (typeof (systemCode) != "undefined") {
                $("#frmContent").attr("src", "/Module/Add?systemCode=" + systemCode);
            } else {
                top.Dialog.alert("請選擇一個子系統。");
            }
        };

        // 權限設置
        function permissionSet() {
            top.Dialog.open({
                ID: "selectWin",
                URL: "/Module/Permission?systemCode=@ViewBag.SystemCode&moduleId=@moduleEntity.Id", //+ systemCode,
                Title: "權限設置",
                Width: 640,
                Height: 480
            });
        };

權限菜單的移動

菜單移動的本質是改變菜單的父節點,在編輯時能夠經過修改菜單的父節點來實現菜單的移動,爲了操做快捷,大多數狀況下但願能經過拖動節點來實現菜單的移動,實現的截圖以下:ajax

單個菜單的移動,鼠標左鍵按住須要移動的菜單,拖動到要移動的目的位置,而後鬆開鼠標左鍵,此時會彈出確認提示,點擊肯定,將會執行移動程序處理,點擊取消將恢復到原始位置。數據結構

點擊肯定後,菜單移到的位置:app

菜單移動支持多個菜單同時移動某個目標位置,異步

如上圖,多個菜單同時移動時,按住Ctrl鍵,逐個點擊要移動的菜單,而後鬆開Ctrl,鼠標拖動菜單移到目標位置。接下來操做如上。async

後臺處理菜單的移動方法,包括檢查節點可否移動(不能將本身設爲本身的父級節點,當前節點不能移動到本身的子節點上去):函數

        /// <summary>
        /// 節點移動
        /// </summary>
        /// <param name="moduleIds"></param>
        /// <param name="parentId"></param>
        /// <param name="systemCode"></param>
        /// <returns></returns>
        public ActionResult MoveTo(string moduleIds, string parentId, string systemCode = null)
        {
            string[] ids = moduleIds.Split(',');

            if (string.IsNullOrWhiteSpace(systemCode))
            {
                systemCode = BaseSystemInfo.SystemCode;
            }
            BaseResult baseResult = new BaseResult();
            string message = string.Empty;
            if (!MoveCheck(ids, parentId, systemCode, out message))
            {
                baseResult.Status = false;
                baseResult.StatusMessage = message;
            }
            else
            {
                string tableName = systemCode + "Module";
                var manager = new BaseModuleManager(UserCenterDbHelper, OperateContext.Current.UserInfo, tableName);
                // 設置moduleId的父級節點爲parentId
                int result = 0;
                for (int i = 0; i < ids.Length; i++)
                {
                    if (!string.IsNullOrWhiteSpace(ids[i]))
                    {
                        result += manager.SetProperty(ids[i], new KeyValuePair<string, object>(BaseModuleEntity.FieldParentId, parentId));
                    }
                }
                if (result > 0)
                {
                    baseResult.Status = true;
                    baseResult.StatusMessage = "移動成功。";
                }
                else
                {
                    baseResult.Status = false;
                    baseResult.StatusMessage = "移動失敗。";
                }
            }
            return Json(baseResult, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 節點移動檢查
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="parentId"></param>
        /// <param name="systemCode"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private bool MoveCheck(string[] ids, string parentId, string systemCode, out string message)
        {
            message = string.Empty;
            // 不能將本身設爲本身的父級節點
            for (int i = 0; i < ids.Length; i++)
            {
                if (string.Equals(ids[i], parentId, StringComparison.OrdinalIgnoreCase))
                {
                    message = "不能將本身設爲本身的父級節點。";
                    return false;
                }
            }
            string tableName = systemCode + "Module";
            var manager = new BaseModuleManager(UserCenterDbHelper, OperateContext.Current.UserInfo, tableName);
            // 目標節點
            BaseModuleEntity moduleEntity = manager.GetObject(parentId);

            // 當前節點不能移動到本身的子節點上去
            for (int i = 0; i < ids.Length; i++)
            {
                while (!string.IsNullOrWhiteSpace(moduleEntity.ParentId))
                {
                    moduleEntity = manager.GetObject(moduleEntity.ParentId);
                    if (string.Equals(ids[i], moduleEntity.Id, StringComparison.OrdinalIgnoreCase))
                    {
                        message = "當前節點不能移動到本身的子節點上去。";
                        return false;
                    }
                }
            }

            return true;
        }

相似的,其它父子類的數據參照這個就能夠很方便的處理展現和移動了。測試

相關文章
相關標籤/搜索