从零开始编写自己的C#框架(18)——Web层后端权限模块——菜单管理

简介:

从本章开始,主要讲解的是页面中对框架相关功能的调用方法,比如列表页面(又分为有层次感列表和普通列表)、编辑页面、多标签页面等,只要熟悉了这些函数的使用方法,那么开发起来就会很便捷了。

 

  1、如图先创建菜单列表与编辑页面

   

   MenuInfoList.aspx

  View Code

  MenuInfoList.aspx.cs

  View Code

 

  先上列表页面运行效果图

  

  2、列表页代码说明

  在页面中,可以看到这条工具条,我们打开aspx页面,找到<f:Toolbar ID="toolBar" runat="server"></f:Toolbar>标签

复制代码
 1         <f:Toolbar ID="toolBar" runat="server">
 2                 <Items>
 3                     <f:Button ID="ButtonRefresh" runat="server" Text="刷新" Icon="ArrowRefresh" OnClick="ButtonRefresh_Click" CssClass="inline"></f:Button>
 4                     <f:Button ID="ButtonAdd" runat="server" Text="添加" Icon="Add" OnClick="ButtonAdd_Click"></f:Button>
 5                     <f:Button ID="ButtonSearch" runat="server" Text="查询" Icon="Magnifier" OnClick="ButtonSearch_Click"></f:Button>
 6                     <%--<f:Button ID="ButtonEdit" runat="server" Text="编辑" Icon="BulletEdit" OnClick="ButtonEdit_Click"
 7                         OnClientClick="if(!F('Panel1_Grid1').getSelectionModel().hasSelection()|| F('Panel1_Grid1').getSelectionModel().getCount()>=2){F.alert('您没有选择编辑项或只能选择一项进行编辑!'); return false; }">
 8                    </f:Button>--%> 
 9                     <f:Button ID="ButtonSaveAutoSort" runat="server" Text="自动排序" Icon="ArrowJoin" OnClick="ButtonSaveAutoSort_Click" ConfirmTitle="自动排序提示" ConfirmText="是否对所有数据进行自动排序?"></f:Button>
10                     <f:Button ID="ButtonSaveSort" runat="server" Text="保存排序" Icon="Disk" OnClick="ButtonSaveSort_Click"></f:Button>
11                     <f:Button ID="ButtonDelete" runat="server" Text="删除" Icon="Delete" OnClick="ButtonDelete_Click" ConfirmTitle="删除提示" ConfirmText="是否删除记录?" 
12                         OnClientClick="if (!F('Panel1_Grid1').getSelectionModel().hasSelection() ) { F.alert('删除时必须选择一条将要删除的记录!'); return false; }  if (F('Panel1_Grid1').getSelectionModel().getCount() >= 2) { F.alert('只能选择一条记录进行删除!');return false; }">
13                     </f:Button>
14                 </Items>
15             </f:Toolbar>
复制代码

  在里面放置的按键都会在这里显示出来,这个标签的Id必须命名为toolBar,因为在PageBase这个父类的初始化函数OnInit中有下面这段代码,会自动为放在这里的按键进行权限判断处理,检查当前用户是否有对应按键的操作权限,没有操作权限的按键自动禁用掉,这样的话我们在开发时就不用为这些按键权限一个个进行赋值,做这么多麻烦的操作了

(灰白色的为已禁用按键)

复制代码
 1               #region 设置页面按键权限
 2                 try
 3                 {
 4                     //定义按键控件
 5                     Control btnControl = null;
 6                     //找到页面放置按键控件的位置
 7                     ControlCollection controls = MenuInfoBll.GetInstence().GetControls(this.Controls, "toolBar");
 8                     //逐个读取出来
 9                     for (int i = 0; i < controls.Count; i++)
10                     {
11                         //取出控件
12                         btnControl = controls[i];
13                         //判断是否除了刷新、查询和关闭以外的按键
14                         if (btnControl.ID != "ButtonRefresh" && btnControl.ID != "ButtonSearch" && btnControl.ID != "ButtonClose" && btnControl.ID != "ButtonReset")
15                         {
16                             //是的话检查该按键当前用户是否有控件权限,没有的话则禁用该按键
17                             ((FineUI.Button)btnControl).Enabled = MenuInfoBll.GetInstence().CheckControlPower(this, btnControl.ID);
18                         }
19                     }
20                 }
21                 catch (Exception) { }
22                 #endregion        
复制代码

 

  对于表格的绑定也很方便,我们想显示那几列,只要将字段绑定到列表中就可以了,修改字段名称或添加新字段时,只需要对数据层与逻辑层的代码重新一键生成后,不用修改其他代码,这里重新绑定就可以显示出来,非常方便,大家可以试试删除下面代码中的几列或在数据库添加新字段测试一下就明白了。

复制代码
 1           <f:Grid ID="Grid1" Title="菜单列表" EnableFrame="false" EnableCollapse="true" AllowSorting="true" SortField="Depth" SortDirection="ASC"
 2             PageSize="15" ShowBorder="true" ShowHeader="true" AllowPaging="true" runat="server" EnableCheckBoxSelect="True" DataKeyNames="Id" EnableColumnLines="true"
 3             OnPageIndexChange="Grid1_PageIndexChange" OnPreRowDataBound="Grid1_PreRowDataBound" OnRowCommand="Grid1_RowCommand">
 4                 <Columns>
 5                     <f:RowNumberField />
 6                     <f:BoundField Width="180px" DataField="Name" DataFormatString="{0}" DataSimulateTreeLevelField="Depth" HeaderText="菜单(页面)名" />
 7                     <f:BoundField DataField="Url" HeaderText="访问路径" ExpandUnusedSpace="true" />
 8                     <f:TemplateField HeaderText="排序" Width="100px">
 9                         <ItemTemplate>
10                             <asp:TextBox ID="tbSort" runat="server" Width="50px" Text='<%# Eval("Sort") %>' AutoPostBack="false"></asp:TextBox>
11                         </ItemTemplate>
12                     </f:TemplateField>
13                     <f:LinkButtonField HeaderText="是否显示" Icon="BulletCross" TextAlign="Center" ToolTip="点击修改是否显示" ColumnID="IsDisplay" CommandName="IsDisplay" />
14                     <f:LinkButtonField HeaderText="是否页面" Icon="BulletCross" TextAlign="Center" ToolTip="点击修改是否页面" ColumnID="IsMenu" CommandName="IsMenu" />
15                     <f:BoundField DataField="Depth" HeaderText="级别层次" TextAlign="Center" />
16                     <f:LinkButtonField HeaderText="操作" TextAlign="Center" ToolTip="点击修改当前记录" ColumnID="ButtonEdit" CommandName="ButtonEdit" />
17                 </Columns>
18             </f:Grid>    
复制代码

  对于列表的事件,在Grid标签中,敲一下空格就会弹出可以使用的事件列表出来,只要绑定对应名称后,在cs文件中添加对应函数就能直接调用,具体大家可以去FineUI官网查看使用例子

  

   列表页中,可以看到<f:Label runat="server" ID="lblSpendingTime" Text=""></f:Label>这个标签,这是用来显示列表执行时间的,只需要放上它就会自动显示列表执行时间:

  <f:window>标签是用来处理显示和隐藏弹出编辑窗口用的,大家可以根据需要自己修改编辑宽与高

 

 

  由于MenuInfoList.aspx.cs必须继承PageBase类,所以我们必须实现Init()与LoadData()这两个函数

  在列表页面中,我们需要实现Init()函数,并为当前页面所调用的逻辑层对象与表格对象进行赋值,如下面代码。赋值后不少功能就自动实现了,具体请看后面的演示效果。

复制代码
1         #region 接口函数,用于UI页面初始化,给逻辑层对象、列表等对象赋值
2         public override void Init()
3         {
4             //逻辑对象赋值
5             bll = MenuInfoBll.GetInstence();
6             //表格对象赋值
7             grid = Grid1;
8         }
9         #endregion
复制代码

  由于本列表页面要显示的是有层次感的列表,所以Sort调用的是自定义的代码(有层次感的列表排序必须先用Depth进行升序排序后,再用Sort排序),同时也去掉了列表中点击表头排序的功能(会弄乱层次感列表)

  对于表格的绑定、翻页等功能,我们在逻辑层已生成对应的函数了,所以这里直接调用就可以了,bll.BindGrid(Grid1, InquiryCondition(), sortList);这个是专门用于有层次感列表的

  为了保持列表的层次感,所以查询条件是直接绑定根级别的菜单

复制代码
 1         #region 加载数据
 2         /// <summary>读取数据</summary>
 3         public override void LoadData()
 4         {
 5             //设置排序
 6             if (sortList == null)
 7             {
 8                 Sort();
 9             }
10 
11             //绑定Grid表格
12             bll.BindGrid(Grid1, InquiryCondition(), sortList);
13         }
14 
15         /// <summary>
16         /// 查询条件
17         /// </summary>
18         /// <returns></returns>
19         private int InquiryCondition()
20         {
21             int value = 0;
22 
23             //选择菜单
24             if (ddlParentId.SelectedValue != "0")
25             {
26                 value = ConvertHelper.Cint0(ddlParentId.SelectedValue);
27             }
28             return value;
29         }
30 
31         #region 排序
32         /// <summary>
33         /// 页面表格绑定排序
34         /// </summary>
35         public void Sort()
36         {
37             //设置排序
38             sortList = new List<string>();
39             sortList.Add(MenuInfoTable.Depth + " asc");
40             sortList.Add(MenuInfoTable.Sort + " asc");
41         }
42         #endregion
43 
44         #endregion
复制代码

   查询效果图

  

 

  保存排序与自动排序功能(注意观察菜单名称与排序值的变化)

  在cs代码中,可以看到,里面并没有保存排序与自动排序的代码,因为在父类中已对这些常用功能进行了封装,所以我们在实现Init()函数时对逻辑层对象与表格对象进行赋值后,就会自动拥有这些功能

  未修改

  

  修改排序值

  

  点击保存排序按键

  

  点击自动排序按键

  

  当然对于有父Id的列表自动排序,无需要编写代码就会自动实现了,而对于没有父Id字段的表,我们就需要重写SaveAutoSort()函数来实现,请看下面重写代码

复制代码
 1         /// <summary>
 2         /// 保存自动排序
 3         /// </summary>
 4         public override void SaveAutoSort()
 5         {
 6             if (bll == null)
 7             {
 8                 Alert.ShowInParent("保存失败", "逻辑层对象为null,请联系开发人员给当前页面的逻辑层对象赋值");
 9                 return;
10             }
11 
12             if (bll.UpdateAutoSort(this))
13             {
14                 Alert.ShowInParent("保存成功", "保存自动排序成功", "window.location.reload();");
15             }
16             else
17             {
18                 Alert.ShowInParent("保存失败", "保存自动排序失败");
19             }
20         }
复制代码

  根据需要,还可以在UpdateAutoSort函数中加上不同的参数,来实现不同条件下自动排序的效果

 

  列表属性绑定说明

  在列表中,我们可以看到是否显示与是否页面的图像是可以点击的,点一下就可以将其改变,如下图

  点击之前

  

  点击之后

  

  这个就是在下面代码中进行绑定的

  View Code

  而更新状态的函数MenuInfoBll.GetInstence().UpdateIsDisplay()、MenuInfoBll.GetInstence().UpdateIsMenu(),我们模板里已经生成了,直接调用即可

 

  最后一列编辑按键,这个根据需要可以放到顶部的工具条里(在前面代码大家可以看到我将其注释了),也可以放到这里来,而放到这里的话,则需要在表格绑定的代码中实现

  由于整个权限模块未开发出来,所以我先将按键的权限判断注释掉了(//lbfEdit.Enabled = MenuInfoBll.GetInstence().CheckControlPower(this, "ButtonEdit");)

  在Grid点击事件中,打开隐藏的编辑窗口

  //打开编辑窗口
      Window1.IFrameUrl = "MenuInfoEdit.aspx?Id=" + id + "&" + MenuInfoBll.GetInstence().PageUrlEncryptStringNoKey(id + "");
      Window1.Hidden = false;  //显示窗口

   在上面的Url链接中,我们需要传递两个参数,一个是将要编辑的记录Id,一个是页面加密处理参数,通过MenuInfoBll.GetInstence().PageUrlEncryptStringNoKey(id + "")函数来生成对应的页面加密参数,系统在对密钥进行识别处理时,会按顺序默认对Id、pid、ParentId、Key这几个值做为密钥生成值进行识别,具体大家自行研究一下吧。

 

  而对于工具栏中的按键实现,添加新记录对应的是Add()函数、编辑记录对应的是Edit()函数、删除记录对应的是Delete(),当然工具栏中按键的命名要求必须同上面那几个一样,具体实现这里就不再一一细说,大家直接看代码吧。

 

   由于时间关系,编辑页面代码就不进行解说,大家自己进行研究吧,下面上一张编辑页面运行后的图片

  

 

  另外,为了由于权限模块未完成,所以将相关的权限判断都注释掉了,等后面完善后再启用。

  本次更新,除了修改一些小问题外,也修改了CommonBll.cs类的添加用户访问页面记录函数,以及自定义类UseLogBll.cs类的添加用户操作日志函数,让用户访问页面记录运行起来,当然这个表记录的不至这些访问内容,它还会将用户的增、删、查、改等所有操作都记录下来,下面看看效果图(这个函数会将用户登陆进系统后每一步访问都记录下来,这个要求是来自以前的公司老总,当时做了一个OA系统公司自己用,他看了后就说:OA开发后,如果大家都不登陆不使用那有等于没有,能不能实现通过后端查看,知道大家有没有使用。再然后就多了这个功能,呵呵)

  

 

 

  本章内容看起来比较乱,大家最好直接运行解决方案代码,在浏览器中运行查看效果,再结合代码查看可能会容易理解,还有一点要补充的是,本解决方案不包含extjs代码,需要大家自行下载放到根目录里

 

 




    本文转自 AllEmpty 博客园博客,原文链接:http://www.cnblogs.com/EmptyFS/p/3798936.html,如需转载请自行联系原作者




相关文章
|
16天前
|
缓存 自然语言处理 数据库
构建高效Python Web应用:异步编程与Tornado框架
【5月更文挑战第30天】在追求高性能Web应用开发的时代,异步编程已成为提升响应速度和处理并发请求的关键手段。本文将深入探讨Python世界中的异步编程技术,特别是Tornado框架如何利用非阻塞I/O和事件循环机制来优化Web服务的性能。我们将剖析Tornado的核心组件,并通过实例演示如何构建一个高效的Web服务。
|
3天前
|
前端开发 JavaScript 测试技术
web前端语言框架:探索现代前端开发的核心架构
web前端语言框架:探索现代前端开发的核心架构
15 4
|
5天前
|
运维 Serverless API
Serverless 应用引擎产品使用合集之如何实现一键迁移Web框架
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
9天前
|
前端开发 Python
|
17天前
|
分布式计算 前端开发 Java
Java的web框架
Java的web框架
|
18天前
|
存储 关系型数据库 MySQL
|
18天前
|
Web App开发 JavaScript 前端开发
构建高效Web API:使用Node.js与Express框架
构建高效Web API:使用Node.js与Express框架
20 0
|
1月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
|
1月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
|
1月前
|
存储 安全 网络安全
C#编程的安全性与加密技术
【4月更文挑战第21天】C#在.NET框架支持下,以其面向对象和高级特性成为安全软件开发的利器。本文探讨C#在安全加密领域的应用,包括使用System.Security.Cryptography库实现加密算法,利用SSL/TLS保障网络传输安全,进行身份验证,并强调编写安全代码的重要性。实际案例涵盖在线支付、企业应用和文件加密,展示了C#在应对安全挑战的同时,不断拓展其在该领域的潜力和未来前景。