六、EnterpriseFrameWork框架基础功能之权限管理
回《【开源】EnterpriseFrameWork框架系列文章索引》
从本章开始进入框架的第二块内容“EnterpriseFrameWork框架的基础功能”,包括:权限管理、字典数据管理、报表管理和消息管理四块,这些功能又包括两个版本,Web版和Winform版也就是说有两套界面。
既然开始讲基础功能,顺便说一下EnterpriseFrameWork框架的适用范围,前面也有提到过就是此框架适合中小团队这是一方面,还一方面就是此框架适合行业应用系统软件的开发,你用它做一个“超市库存管理系统”、“企业EPR”等类似系统是非常适合的;但如果觉得用它有Web开发模式,就用它来开发互联网应用的话还是很麻烦的;互联网的功能的开放性、随意性在此框架中受很大的限制,所以在这系列完成后,下一个系列中我会继续分享针对“互联网应用开发框架系列”,敬请期待!
继续本章的内容讲解框架的“权限管理”,从本章的讲解思路分成下面几个部分:
1)功能清单介绍
2)功能界面展示
3)核心业务流程图与数据库表关系图
4)关键点的技术实现代码
框架中的权限管理的思想类似于Windows操作系统中的用户和用户组的设计,用户配置角色,角色配置菜单,所以用户没必要跟菜单直接关联,通过角色进行关联。
框架中权限除了到菜单级别,还可以精确到页面内部的一个按钮、数据展示或操作内容,也就是页面子权限。
简要的说明一下页面子权限的实现方式,在每个页面定义了一组权限标识,角色配置菜单同时勾选子权限标识保存起来。打开这个页面的时候根据配置的子权限标识控制页面的操作内容。举个列子,比如查看“工作日志的页面”有员工、经理、老总三个级别,首页我们在日志页面三个定义子权限标识分别为“员工权限”、“经理权限”和“老总权限”,再在角色配置权限的界面分别对三个角色配置相应的页面子权限。
那么不同级别的用户登录后,打开此页面看到的内容就不一样了。
1.权限管理功能清单
模块名称 |
功能名称 |
功能说明 |
权限管理 |
系统登录 |
输入正确用户名和密码,点击确定登录 |
系统主界面 |
登录后进入的主界面,菜单根据用户配置的权限动态生成 |
|
机构管理 |
添加机构、启用停用机构 |
|
用户部门管理 |
用户管理,新增、修改、停用用户,用户配置部门和设置角色 |
|
系统菜单管理 |
菜单维护,新增、修改、删除菜单,设置菜单的图片等 |
|
角色权限配置 |
角色维护,新增、删除角色 |
2. 权限管理功能界面展示,包括Winform版和Web版
1)登录
2)主界面
3)机构管理
4)用户部门管理
5)系统菜单管理
6)角色权限配置
3.权限管理核心业务流程图与数据库表关系图
4.权限管理关键点技术实现
1)登录控制器LoginController
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using EFWBaseLib.Entity; using EFWBaseLib.ObjectModel.RightManager; using EFWBaseLib.ObjectModel.UserLogin; using EFWBaseLib.WinController.IViewform; using EFWCoreLib.CoreFrame.BusinessArchitecture; using EFWCoreLib.CoreFrame.Init; using EFWCoreLib.WinformFrame.Controller; using EFWCoreLib.WinformFrame.Common; using System.Management; using EFWCoreLib.CoreFrame.Common; namespace EFWBaseLib.WinController.Ation { [EFWCoreLib.WinformFrame.Controller.Menu] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.FrmLogin", DefaultView = true)] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.FrmMain")] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.FrmMainRibbon")] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.FrmSetting")] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.ReDept")] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.FrmPassWord")] [View(DllName = "EFWWin.exe", ViewTypeName = "EFWWin.Viewform.FrmWeclome")] public class LoginController : BaseController { IfrmLogin frmlogin; IfrmMain frmmain; #region 登录 private Form _frmsplash; public Form Frmsplash { get { return _frmsplash; } set { _frmsplash = value; } } public override void Init() { frmlogin = (IfrmLogin)iBaseView["FrmLogin"]; int mainStyle = EFWCoreLib.WinformFrame.Common.CustomConfigManager.GetMainStyle(); if (mainStyle == 0) frmmain = (IfrmMain)iBaseView["FrmMain"]; else frmmain = (IfrmMain)iBaseView["FrmMainRibbon"]; } public void UserLogin() { User user = NewObject<User>(); bool islogin = user.UserLogin(frmlogin.usercode, frmlogin.password); if (islogin) { BaseUser EbaseUser = user.GetUser(frmlogin.usercode); SysLoginRight right = new SysLoginRight(); right.UserId = EbaseUser.UserId; right.EmpId = EbaseUser.EmpId; right.WorkId = EbaseUser.WorkId; Dept dept = NewObject<Dept>(); BaseDept EbaseDept = dept.GetDefaultDept(EbaseUser.EmpId); if (EbaseDept != null) { right.DeptId = EbaseDept.DeptId; right.DeptName = EbaseDept.Name; } BaseEmployee EbaseEmp = (BaseEmployee)NewObject<BaseEmployee>().getmodel(EbaseUser.EmpId); right.EmpName = EbaseEmp.Name; BaseWorkers EbaseWork = (BaseWorkers)NewObject<BaseWorkers>().getmodel(EbaseUser.WorkId); right.WorkName = EbaseWork.WorkName; if (EbaseWork.DelFlag == 0) { string regkey = EbaseWork.RegKey; DESEncryptor des = new DESEncryptor(); des.InputString = regkey; des.DesDecrypt(); string[] ret = (des.OutString == null ? "" : des.OutString).Split(new char[] { '|' }); if (ret.Length == 2 && ret[0] == EbaseWork.WorkName && Convert.ToDateTime(ret[1]) > DateTime.Now) { AppGlobal.cache.Add("RoleUser", right); frmmain.UserName = right.EmpName; frmmain.DeptName = right.DeptName; frmmain.WorkName = right.WorkName; frmmain.modules = NewObject<Module>().GetModuleList(right.UserId).OrderBy(x => x.SortId).ToList(); frmmain.menus = NewObject<EFWBaseLib.ObjectModel.RightManager.Menu>().GetMenuList(right.UserId); frmmain.depts = NewObject<Dept>().GetHaveDept(right.EmpId); frmmain.showSysMenu(); ShowWeclomeForm(); ((Form)frmmain).Icon = System.Drawing.Icon.ExtractAssociatedIcon(EFWCoreLib.CoreFrame.Init.AppGlobal.AppRootPath + @"images\msn.ico"); ((Form)frmmain).Show(); //InitMessageForm();//? CustomConfigManager.xmlDoc = null; } else { throw new Exception("登录用户的当前机构注册码不正确!"); } } else { throw new Exception("登录用户的当前机构还未启用!"); } } else { throw new Exception("输入的用户名密码不正确!"); } } public void ShowWeclomeForm() { frmmain.ShowForm((Form)iBaseView["FrmWeclome"], "首页", "1"); } public string GetBackGroundImage() { return CustomConfigManager.GetBackgroundImage(); } public void ReLogin() { frmlogin.isReLogin = true; ((Form)frmlogin).ShowDialog(); } public void Quit() { _frmsplash.Dispose(); } #endregion #region 设置 public void OpenSetting() { List<InputLanguage> list = new List<InputLanguage>(); foreach (InputLanguage val in InputLanguage.InstalledInputLanguages) { list.Add(val); } ((IfrmSetting)iBaseView["FrmSetting"]).languageList = list; ((IfrmSetting)iBaseView["FrmSetting"]).inputMethod_CH = CustomConfigManager.GetInputMethod(EFWCoreLib.WinformFrame.CustomControl.EN_CH.CH); ((IfrmSetting)iBaseView["FrmSetting"]).inputMethod_EN = CustomConfigManager.GetInputMethod(EFWCoreLib.WinformFrame.CustomControl.EN_CH.EN); //打印机 ManagementObjectSearcher query; ManagementObjectCollection queryCollection; string _classname = "SELECT * FROM Win32_Printer"; query = new ManagementObjectSearcher(_classname); queryCollection = query.Get(); ((IfrmSetting)iBaseView["FrmSetting"]).loadPrinter(queryCollection, CustomConfigManager.GetPrinter(0), CustomConfigManager.GetPrinter(1), CustomConfigManager.GetPrinter(2)); //消息 ((IfrmSetting)iBaseView["FrmSetting"]).runacceptMessage = CustomConfigManager.GetrunacceptMessage() == 1 ? true : false; ((IfrmSetting)iBaseView["FrmSetting"]).displayWay = CustomConfigManager.GetDisplayWay() == 1 ? true : false; ((IfrmSetting)iBaseView["FrmSetting"]).setbackgroundImage = CustomConfigManager.GetBackgroundImage(); ((IfrmSetting)iBaseView["FrmSetting"]).mainStyle = CustomConfigManager.GetMainStyle(); ((Form)iBaseView["FrmSetting"]).ShowDialog(); } public void SaveSetting() { ((Form)iBaseView["FrmSetting"]).Close(); CustomConfigManager.SaveConfig(((IfrmSetting)iBaseView["FrmSetting"]).inputMethod_EN, ((IfrmSetting)iBaseView["FrmSetting"]).inputMethod_CH, ((IfrmSetting)iBaseView["FrmSetting"]).printfirst, ((IfrmSetting)iBaseView["FrmSetting"]).printsecond, ((IfrmSetting)iBaseView["FrmSetting"]).printthree, ((IfrmSetting)iBaseView["FrmSetting"]).runacceptMessage ? 1 : 0, ((IfrmSetting)iBaseView["FrmSetting"]).displayWay ? 1 : 0, ((IfrmSetting)iBaseView["FrmSetting"]).setbackgroundImage, ((IfrmSetting)iBaseView["FrmSetting"]).mainStyle); } #endregion #region 切换科室 public void OpenReDept() { ((IfrmReSetDept)iBaseView["ReDept"]).UserName = base.GetSysLoginRight.EmpName; ((IfrmReSetDept)iBaseView["ReDept"]).WorkName = base.GetSysLoginRight.WorkName; ((IfrmReSetDept)iBaseView["ReDept"]).loadDepts(frmmain.depts,GetSysLoginRight.DeptId); ((Form)iBaseView["ReDept"]).ShowDialog(); } public void SaveReDept() { BaseDept dept = ((IfrmReSetDept)iBaseView["ReDept"]).getDept(); ((SysLoginRight)EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser")).DeptId = dept.DeptId; ((SysLoginRight)EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser")).DeptName = dept.Name; frmmain.DeptName = dept.Name; } #endregion #region 修改密码 public void OpenPass() { ((IfrmPassWord)iBaseView["FrmPassWord"]).clearPass(); ((Form)iBaseView["FrmPassWord"]).ShowDialog(); } public void AlterPass() { bool b = NewObject<User>().AlterPassWrod(GetSysLoginRight.UserId, ((IfrmPassWord)iBaseView["FrmPassWord"]).oldpass, ((IfrmPassWord)iBaseView["FrmPassWord"]).newpass); if (b == false) throw new Exception("您输入的原始密码不正确!"); } #endregion #region 消息提醒 /*//? MessageTimer mstimer = null;//消息提醒触发器 public void InitMessageForm() { if (mstimer != null) { mstimer.Enabled = false; if (TaskbarForm.instance != null) TaskbarForm.instance.ClearMessages(); } mstimer = new MessageTimer(); mstimer.FrmMain = (Form)frmmain; //mstimer.Interval = 20000; mstimer.Enabled = true; } public void ShowMessageForm() { TaskbarForm.ShowForm((Form)frmmain); } */ #endregion } }
2)页面内部子权限控制
3)关于Web版与Winform版配置菜单的不同之处
Web版菜单配置人员部门管理,如:ModulePlugin/UserLogin/PageUI/DeptEmployeeManager.aspx
Winform版菜单配置人员部门管理,如:EFWBaseLib.WinController.Ation.EmpUserController
前者是配置界面文件地址,后者是配置控制器对象;后来想想这两个方式有没有办法统一,都配置控制器对象?但两者的实现方式确实思路不一样,应该说后者更超前一点吧,因为以前后者也是配置界面文件的,后来引入了控制器的概念,一个业务操作的出发点不是从菜单开始,而是又控制器来安排的,比如:点界面修改按钮会弹出另外一个修改界面,传统的实现是先Show出窗体,再在窗体Load事件加载修改数据;这种传统的方式开发起来很简单,但是有个最大的问题就是把对后台数据的操作分隔开,前后相隔到不同的文件代码或方法中;而用控制器的方式是这样,点修改按钮,向控制器发送一个方法消息,控制器先从后台加载数据,然后在赋值在界面上并Show出窗体;如果我们修改界面换掉了,或不用弹出窗了,控制器前面的数据加载代码都无需修改,只需修改展示代码;所以控制器承担了后台数据访问与前台界面的展示,所以配菜单的方式由以前的配置界面文件,转变为配置控制器;
再说一下Web版的菜单配置,web页面向后台获取数据都是通过ajax请求并返回数据;而控制器不能主动发送数据到web页面,两者不能双向通讯,这也是Http底层协议的所决定,所以Web版无法像Winform版这种方式来实现;