业务系统设计之一:系统菜单设计

简介:
本文主要介绍业务系统设计里的菜单设计,关注我博客的朋友或许以前见过一篇我写的关于菜单的文章,文章连接: 使用RadControls的RadMenu控件开发系统菜单  ,这篇文章主要是介绍了RadControls的RadMenu控件的基本使用,没有详细介绍到菜单如何设计,为什么要那么设计。本文就以这片文章为基础,同样通过此文章的示例程序和示例数据库,结合业务系统设计的相关术语介绍业务系统的菜单设计。
                        
      首先看看上面的数据库设计结构,其中ID为自动编号的主键字段,Code为菜单编码(也称业务编码),Name为菜单名称, Url为单击菜单所导航的路径,ImageUrl为菜单上显示的图片地址,ShortCut为快捷键,Order为菜单项显示顺序,Grade为菜单级限,EndGrade为是否为末级菜单(既最后一菜单项),SupMenuCode为当前菜单项的父级菜单编码(对应于Code字段),完整的还应该包括是否受权限控制等字段,这里不一一列出。
      上面的数据库设计其实很简单,需要主要的字段有Code菜单编码(也称业务编码),在业务系统里通常设计为每一菜单项都可以认为是一个业务操作,这里的Code非常重要,业务系统的后续工作都是从这里开始,通常与权限设计结合使用得最多。
      系统菜单应该是多层次结构的,比如常见的Windows菜单,业务系统里的菜单设计同样如此,通过SupMenuCode字段来标记该菜单项属于那一项菜单的子菜单,如果没有父级菜单(系统顶层菜单)则标记为0。
      既然菜单有层次结构,那就一定有层次标识,通过Grade来标记;EndGrade则表示当前菜单项在该层次级别上的菜单项上是否为末级。
      分析清楚了需求和菜单设计方案,下面我们着手代码开发,下图为项目解决方案截图:
                        
      如上图,Menu.cs里封装了数据库查询功能,App_Data下存放的Access数据库,RadControls为RadMenu控件所需要的相关文件,Default.aspx则为菜单UI界面。
      首先需要配置数据库连串,如下:
1  private   static   string  connectionString  =   " Provider=Microsoft.jet.OLEDB.4.0;data Source= "  
2       +  HttpContext.Current.Server.MapPath( @" App_Data\MenuDB.mdb " );
 
      接着我们需要一个执行SQL的方法,如下代码块:
 1  private   DataTable ExecuteQuery( string  cmdText)
 2  {
 3       using  (OleDbConnection conn  =   new  OleDbConnection(connectionString))
 4      {
 5           using  (OleDbDataAdapter oda  =   new  OleDbDataAdapter(cmdText, conn))
 6          {
 7              DataSet ds  =   new  DataSet();
 8              oda.Fill(ds);
 9               return  ds.Tables[ 0 ];
10          }
11      }
12  }
 
      最后我们还需要写两个方法,一个是查询顶层菜单的方法,一个则是实现查询菜单下的子菜单方法(做法有很多种,我个人建议把所有的数据查询出然后在操作内存数据,这里为了方便理解我故采用多次查询数据库的方式来实现)。
 1  public  DataTable GetMenu()
 2  {
 3       string  sql  =   " select * from menu where grade=0 " ;
 4       return  ExecuteQuery(sql);
 5  }
 6 
 7  public  DataTable GetMenuBySupCode( string  supMenuCode)
 8  {
 9       string  sql  =   " select * from menu where supmenucode=' "   +  supMenuCode  +   " ' " ;
10       return  ExecuteQuery(sql);
11  }
 
      OK,准备工作做好后,现在就是需要到UI层上去做菜单的展现工作了。菜单的展现我通过RadContrls的RadMenu控件来实现,此控件相对ASP.NET的标准Menu控件功能强大。要使用RadMenu则需要注册控件的引用,如果你是通过RadContrls控件库安装包安装的则会自动注册到VS工具箱,和标准控件使用方法一样。
1  <% @ Register Assembly = " RadMenu.Net2 "  Namespace = " Telerik.WebControls "  TagPrefix = " rad "   %>
 
1       <%-- 菜单开始 --%>
2       < rad:RadMenu ID = " SystemMenu "  runat = " server "  Skin = " Vista " >
3       </ rad:RadMenu >
4       <%-- 菜单结束 --%>
 
      上面准备好了顶层菜单的查询方法,直接通过该方法查询出顶层菜单项对菜单进行初始化:
 1  protected   void  Page_Load( object  sender, EventArgs e)
 2  {
 3       if  ( ! IsPostBack)
 4      {
 5          InitMenu();
 6      }
 7  }
 8 
 9  Menu menu  =   new  Menu();
10  private   void  InitMenu()
11  {
12       // 查询出菜单配置信息
13      DataTable dtMenu  =  menu.GetMenu();
14 
15       for  ( int  i  =   0 ; i  <  dtMenu.Rows.Count; i ++ )
16      {
17           // Rad菜单项
18          RadMenuItem item  =   new  RadMenuItem();
19 
20          item.ID  =  dtMenu.Rows[i][ " Code " ].ToString();
21          item.Text  =  dtMenu.Rows[i][ " Name " ].ToString();
22          item.Value  =  dtMenu.Rows[i][ " Url " ].ToString();
23          item.AccessKey  =  dtMenu.Rows[i][ " ShortCut " ].ToString();
24 
25           this .SystemMenu.Items.Add(item);
26 
27           // 菜建子菜单
28          InitSubMenu(item, dtMenu.Rows[i][ " Code " ].ToString());
29      }
30  }
 
      我们设计为多层次菜单结构,那么在初始化顶层菜单的时候就应该判断该菜单项是否有子菜单,如果有则也初始化子菜单,如果是多级层次的结构,通过递归算法来完成多层次的初始化。如下代码块:
 1 
 2  private   void  InitSubMenu(RadMenuItem item,  string  supMenuCode)
 3  {
 4       // 根据父菜单编码查询出子菜单配置项
 5      DataTable dtMenu  =  menu.GetMenuBySupCode(supMenuCode);
 6 
 7       if  (dtMenu  !=   null )
 8      {
 9           foreach  (DataRow dataRow  in  dtMenu.Rows)
10          {
11              RadMenuItem subItem  =   new  RadMenuItem();
12 
13              subItem.ID  =  dataRow[ " ID " ].ToString();
14              subItem.Text  =  dataRow[ " Name " ].ToString();
15              subItem.Value  =  dataRow[ " Url " ].ToString();
16              subItem.AccessKey  =  dataRow[ " ShortCut " ].ToString();
17 
18              item.Items.Add(subItem);
19 
20               if  (Convert.ToInt32(dataRow[ " EndGrade " ])  !=   1 )
21              {
22                  InitSubMenu(subItem, Convert.ToString(dataRow[ " Code " ]));
23              }
24          }
25      }
26  }
 
      如上就完成了系统的菜单设计,实际项目开发中的设计与这样的设计几乎都大同小异。主要是了解设计思想,或许看完了本文你还是没有明白为什么要这样设计,如果是这样那请你关注下一篇文章,下一篇文章中就用到了菜单中的业务编码,应该可以给一个满意的答案。





本文转自 beniao 51CTO博客,原文链接:http://blog.51cto.com/beniao/202205,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
前端开发 关系型数据库 定位技术
WEBGIS系统整体设计
WEBGIS系统整体设计
39 6
WEBGIS系统整体设计
|
10月前
智能排班系统 【管理系统功能、操作说明——中篇】
智能排班系统 【管理系统功能、操作说明——中篇】
188 1
|
11月前
|
存储 SQL 缓存
用户系统设计
注册、登录、查询、用户信息修改,哪个需求量最大? 支持100M DAU。注册,登录,信息修改 QPS 约 100M * 0.1 / 86400 ~ 100 0.1 = 平均每个用户每天登录+注册+信息修改 Peak = 100 * 3 = 300
146 0
|
设计模式 监控 安全
内部系统界面设计【下】 | 设计技巧
关于内部系统 UI 设计的五个技巧
468 0
内部系统界面设计【下】 | 设计技巧
|
存储 安全 前端开发
内部系统界面设计【上】 | 问题与挑战
在企业中,生产力和效率就是一切。本篇文章中,码匠将带您深入探讨内部系统 UI 设计,具体我们会介绍内部系统界面设计以及它所面临的挑战。
292 0
内部系统界面设计【上】 | 问题与挑战
|
JSON uml 数据格式
设计系统
设计系统
112 0
设计系统
|
存储 缓存 负载均衡
系统设计:如何让系统容易扩展?
系统设计:如何让系统容易扩展?
334 0
系统设计:如何让系统容易扩展?
|
测试技术
第18章 系统功能设计
第III部分 项目综合实战 第18章 系统功能设计 18.1 系统整体功能结构 18.2 系统用例描述 18.3 主要功能流程描述
743 0