从零开始编写自己的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天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
16天前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
15天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【4月更文挑战第9天】本文对比了Python三大Web框架Django、Flask和Pyramid。Django功能全面,适合快速开发,但学习曲线较陡;Flask轻量灵活,易于入门,但默认配置简单,需自行添加功能;Pyramid兼顾灵活性和可扩展性,适合不同规模项目,但社区及资源相对较少。选择框架应考虑项目需求和开发者偏好。
|
8天前
|
缓存 负载均衡 数据库
优化后端性能:提升Web应用响应速度的关键策略
在当今数字化时代,Web应用的性能对于用户体验至关重要。本文探讨了如何通过优化后端架构和技术手段,提升Web应用的响应速度。从数据库优化、缓存机制到异步处理等多个方面进行了深入分析,并提出了一系列实用的优化策略,以帮助开发者更好地应对日益增长的用户访问量和复杂的业务需求。
12 1
|
10天前
|
前端开发 数据挖掘 API
使用Python中的Flask框架进行Web应用开发
【4月更文挑战第15天】在Python的Web开发领域,Flask是一个备受欢迎的轻量级Web框架。它简洁、灵活且易于扩展,使得开发者能够快速地构建出高质量的Web应用。本文将深入探讨Flask框架的核心特性、使用方法以及在实际开发中的应用。
|
22天前
|
前端开发 安全 Java
使用Java Web框架:Spring MVC的全面指南
【4月更文挑战第3天】Spring MVC是Spring框架的一部分,用于构建高效、模块化的Web应用。它基于MVC模式,支持多种视图技术。核心概念包括DispatcherServlet(前端控制器)、HandlerMapping(请求映射)、Controller(处理请求)、ViewResolver(视图解析)和ModelAndView(模型和视图容器)。开发流程涉及配置DispatcherServlet、定义Controller、创建View、处理数据、绑定模型和异常处理。
使用Java Web框架:Spring MVC的全面指南
|
26天前
|
前端开发 JavaScript 数据管理
描述一个使用Python开发Web应用程序的实际项目经验,包括所使用的框架和技术栈。
使用Flask开发Web应用,结合SQLite、Flask-SQLAlchemy进行数据管理,HTML/CSS/JS(Bootstrap和jQuery)构建前端。通过Flask路由处理用户请求,模块化代码提高可维护性。unittest进行测试,开发阶段用内置服务器,生产环境可选WSGI服务器或容器化部署。实现了用户注册登录和数据管理功能,展示Python Web开发的灵活性和效率。
14 4
|
1月前
|
数据库
最全三大框架整合(使用映射)——struts.xml和web.xml配置
最全三大框架整合(使用映射)——数据库资源文件jdbc.properties
10 0
|
1月前
|
前端开发 API 网络架构
Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!
Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!
|
17天前
|
前端开发 小程序 Java
uniapp上传图片 前端以及java后端代码实现
uniapp上传图片 前端以及java后端代码实现
32 0