Web開發框架之權限管理系統


記得我在很早之前,開始介紹我的Winform開發框架和我的WCF開發框架之初,我曾經給出下面的視圖,介紹我整理的一個框架體系,其中包含有WInform開發框架以及我的Web開發框架,由於前段時間一直忙於Winform開發框架的提煉以及優化,並統一整理了很多Winform開發框架以及WCF開發框架的隨筆文章。隨着我的Winform逐步完善,終於有時間來整理介紹我的Web開發框架的事宜了,下面先介紹一下我最新優化整理的Web開發框架之權限管理系統,其中這個權限管理系統可以說是集眾多寵愛於一身了,除了一貫的和代碼生成工具集成,可生成基礎性的框架代碼外,還整合Winform開發框架繼承而來的多數據庫支持,在界面層,也就是Web權限管理系統,整合了JQuery的Easy-UI界面組件,功能強大的zTree控件、KindEditor在線編輯控件、界面層獲取數據及保存使用基於JQuery的json數據操作,實現數據局部刷新等等操作,其中提供兩種不同的菜單布局操作,非常方便應用於其他業務系統的界面。

首先在介紹之前,我們來貼幾個Web權限系統的圖片進行感性的了解先。

1)簡潔的界面布局效果。這種效果頂部橫幅比較緊湊,左邊有一些常用的按鈕操作,適合於菜單功能不太多的小業務系統,如我的Web權限系統。

2)功能強大的界面企業業務系統布局。這種界面效果適合於功能比較眾多,菜單展示進行分類管理等業務系統。這種框架頂部的菜單為一級菜單,單擊一級菜單可以在左邊展示二級菜單,這種效果可以不用一次性列出所有系統的功能,而是分層次進行功能展示。

頂部的Tab選項卡每次打開頁面的時候,增加一個Tab頁,頁面可以雙擊進行關閉,也可以右鍵彈出菜單進行更多操作,如下圖所示。

如果需要了解整個系統的效果,也可以下載《Web權限系統操作視屏》進行全面的了解。

在提煉優化這個Web權限框架的過程中,碰到了不少的問題,一一進行解決,現總結一部分進行進行介紹。

1)使用JSON數據構造zTree

使用zTree確實比easy-ui自帶的Tree好很多,功能也強大很多,由於我的Web權限中,各個模塊幾乎都需要樹控件來展示相關的數據,如功能、組織機構等等。在對比了我自己的傳統Tree、Easy-UI的Tree控件以及zTree后,發現使用zTree還是可以提高不少的界面分數的。但是其自帶的例子,以及網上的例子,多數是使用預先弄好的樹形數據,而我需要動態使用ashx進行樹形數據的獲取及生成,這確實費了一些周折來進行調試。

首先要准備基於ashx處理程序生成的Tree數據,樹的數據使用JSON格式。如功能定義的樹形數據如下所示。

        /// <summary>
        /// 遞歸獲取樹形信息
        /// </summary>
        private string GetTreeJson(int PID, string folderIcon, string leafIcon)
        {
            string condition = string.Format("PID={0}", PID);
            List<FunctionInfo> nodeList = BLLFactory<Function>.Instance.Find(condition);
            StringBuilder content = new StringBuilder();
            foreach (FunctionInfo model in nodeList)
            {
                int ParentID = (model.PID == -1 ? 0 : model.PID);
                //string tempMenu = string.Format("{{ id:{0}, pId:{1}, name:\"{2}\",icon:\"{3}\" }},", model.ID, ParentID, model.Name, imgsrc); //簡單的作法
                string subMenu = this.GetTreeJson(model.ID, folderIcon, leafIcon);
                string parentMenu = string.Format("{{ \"id\":{0}, \"pId\":{1}, \"name\":\"{2}\" ", model.ID, ParentID, model.Name);
                if (string.IsNullOrEmpty(subMenu))
                {
                    if (!string.IsNullOrEmpty(leafIcon))
                    {
                        parentMenu += string.Format(",\"icon\":\"{0}\" }},", leafIcon);
                    }
                    else
                    {
                        parentMenu += "},";
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(folderIcon))
                    {
                        parentMenu += string.Format(",\"icon\":\"{0}\" }},", folderIcon);
                    }
                    else
                    {
                        parentMenu += "},";
                    }
                }

                content.AppendLine(parentMenu.Trim());
                content.AppendLine(subMenu.Trim());
            }

            return content.ToString().Trim();
        } 

然后就是頁面的調用了,這里為了增強體驗效果,使用了基於javascript的JQuery的異步操作進行數據處理,而不是基於aspx后台頁面的處理,如下所示。

        //重新加載樹形結構(異步)
        function reloadTree() {
            $("#loading").show();
            $.getJSON("http://www.cnblogs.com/AjaxHandler/FunctionJson.ashx?r=" + Math.random() + "&op=tree", function (json) {
                $.fn.zTree.init($("#treeDemo"), setting, json);
                $.fn.zTree.getZTreeObj("treeDemo").expandAll(true);

                var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
                var treeNodes = treeObj.getNodes();
                if (treeNodes != null) {
                    loadData(treeNodes[0].id);
                }
            });
            $("#loading").fadeOut(500);
        }

這樣處理的效果是頁面只是局部刷新,體驗很好。

2)基於JQuery的數據加載及保存操作

由於JQuery的方便性及良好體驗性,我統一了數據的獲取及保存操作。下面給出相關的處理代碼供參考。

        //加載制定的對象數據
        function loadData(id) {
            $("#loading").show();
            $.getJSON("http://www.cnblogs.com/AjaxHandler/FunctionJson.ashx?r=" + Math.random() + "&op=findbyid&id=" + id, function (json) {
                $("#txtID").val(json.ID);
                $("#txtName").val(json.Name);
                $("#txtControlID").val(json.ControlID);
                $("#txtPID").val(json.PID);
            });

            $('#lbxRoles').empty();
            $.getJSON("http://www.cnblogs.com/AjaxHandler/RoleJson.ashx?r=" + Math.random() + "&op=getrolesbyfunction&id=" + id, function (json) {
                $.each(json, function (i, item) {
                    $('#lbxRoles').append('<option value="' + item.ID + '">' + item.Name + '</option>');
                });
            });
            $("#loading").fadeOut(500);
        }

        //保存對象數據
        function saveData() {
            $.ajax({
                type: 'POST',
                url: 'http://www.cnblogs.com/AjaxHandler/FunctionJson.ashx?r=' + Math.random() + '&op=insert',
                async: false,
                data: { ID: $("#txtID").val(), Name: $("#txtName").val(), ControlID: $("#txtControlID").val(), PID: $("#txtPID").val() },
                success: function (id) {
                    alert("操作成功! ");
                    reloadTree();

                    if (id != "")
                        loadData(id);
                },
                error: function (xhr, status, error) {
                    alert("操作失敗"); //xhr.responseText
                }
            });
        }

3)在數據操作等待的時候,頁面中間顯示Loading效果。

整個系統,在各種請求操作,我都統一了作法,在界面顯示Loading的等待效果,任務結束后關閉,這種效果在費事的操作,用戶體檢會好一些,下面看看其效果以及實現代碼。

增加下面javascript腳本

        //對象居中的函數,調用例子:$("#loading").center();
        jQuery.fn.center = function () {
            this.css("position", "absolute");
            this.css("top", Math.max(0, (($(window).height() - this.outerHeight()) / 2) +
                                                $(window).scrollTop()) + "px");
            this.css("left", Math.max(0, (($(window).width() - this.outerWidth()) / 2) +
                                                $(window).scrollLeft()) + "px");
            return this;
        }

        //初始化對象
        $(document).ready(function () {

            $("#loading").center();//loading的圖片顯示居中
        });

然后再頁面Body后面增加一行代碼即可(默認loading圖片不顯示的哦)。

    <div id="loading" style="display: none;"><img alt="數據正在加載中..." src="http://images.cnblogs.com/loading02.gif" /></div>

4)控件數據清空操作

由於添加和編輯公用界面控件元素,因此我們在要添加數據的時候,需要清空或者設置某些控件的值,但我們的控件可能比較多,一種好的方法是利用JQuery的選擇器功能來進行有目的的控件清空操作。

如下面的例子所示。

        //新增清空控件
        function addData() {
            $("#txtPID").val($("#txtID").val());
            $("input[type=text][id*='txt']").val("");
            $("textarea[id*='txt']").empty();
            $("select[id*='lbx']").empty();
        }

其中$("#txtPID").val($("#txtID").val());是把當前的用戶作為添加數據的上級,其他的就是清空控件的數據了,不同的類型控件清空的步驟有些不同。

5)Ashx處理程序的安全性考慮

我們在系統中,多數都是調用ashx進行數據處理,雖然一般業務系統在VPN或者內網中運行,但是也要考慮用戶沒登陸的時候,不運行調用ashx程序,這樣可以提高數據的安全性。

默認的ashx處理程序是沒有Session的操作的,所以我們需要修改其繼承接口(多增加IReadOnlySessionState 的繼承)

,然后才能調用Session來進行判斷。

    /// <summary>
    /// 權限功能操作類
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class FunctionJson : IHttpHandler, IReadOnlySessionState 
    {        
        public void ProcessRequest(HttpContext context)
        {
            //類對象要顯式的實現接口 IReadOnlySessionState,才能訪問Session數據
            if (context.Session["Identity"] == null)
            {
                throw new ArgumentException("用戶未登錄!");
            }

6)Tab界面布局的兼容。

Web權限系統提供了兩種常用的菜單布局進行管理,一般對於常用的業務系統肯定是沒問題了。

另外一種效果是系統復雜的時候用的,可以定義一級菜單和關聯的二級菜單。

對於后者,一級菜單打開的時候,可以關聯打開一個新的頁面,並且刷新二級菜單的關系。

        <!----------- 一級導航 ------------------>
        <ul class="navigation" style="display:block">
            <li><a href="#" onclick="showSubMenu('ListUser.aspx', '用戶管理', 'default')">權限管理</a></li>
            <li><a href="#" onclick="showSubMenu('../Commonpage/MyJob.aspx', '事務中心開發中...', 'point', 'icon-organ')">事務中心</a></li>
            <li><a href="#" onclick="showSubMenu('../Commonpage/building.htm', '合同起草開發中...', '')">合同起草</a></li>
            <li><a href="#" onclick="showSubMenu('../Commonpage/building.htm', '合同管理開發中...', '')">合同管理</a></li>
            <li><a href="#" onclick="showSubMenu('../Commonpage/building.htm', '查詢打印開發中...', '')">查詢打印</a></li>
            <li><a href="#" onclick="showSubMenu('../Commonpage/building.htm', '知識管理開發中...', '')">知識管理</a></li>
            <li><a href="#" onclick="showSubMenu('../Commonpage/building.htm', '系統管理開發中...', '')">系統管理</a></li>
        </ul>

 好了,很多其他的特點,以后繼續介紹,歡迎多多提出寶貴意見。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM