Mvc.Ext.Net项目架构(二)
不好意思我的语文是体育老师教的所以.....。
我每次需要和数据库交互的时候需要先写一个接口在IDAL里面,然后在DAL实现代码并做一些逻辑处理,web层直接调用BLL中的方法来实现数据的持久化操作。整个系统对于某些表的实体映射是有的但是在最主要的档案数据和文件数据中就没有映射,因为这个表的字段是可以通过项目人员来自行配置的也就是说我只需要设置下面这张表
1 CREATE TABLE [dbo].[Arch_Fields]( 2 [Id] [int] IDENTITY(1,1) NOT NULL, 3 [FId] [int] NOT NULL, 4 [FieldName] [nvarchar](50) NOT NULL, 5 [FieldCName] [nvarchar](80) NOT NULL, 6 [FieldType] [tinyint] NULL, 7 [IsMust] [bit] NULL, 8 [IsPhyFld] [bit] NULL, 9 [IsSystem] [bit] NULL, 10 [DisplayOrder] [int] NULL, 11 [AutoFormula] [ntext] NULL, 12 [Format] [varchar](50) NULL, 13 [FieldTop] [int] NULL, 14 [FieldLeft] [int] NULL, 15 [FieldHeight] [int] NULL, 16 [FieldWidth] [int] NULL, 17 [FieldLength] [int] NULL, 18 [ListVisible] [bit] NULL, 19 [ListOrder] [smallint] NULL, 20 [ListWidth] [smallint] NULL, 21 [VouchVisible] [bit] NULL, 22 [RefId] [int] NULL, 23 [IsModify] [bit] NULL, 24 [SearchVisible] [bit] NULL, 25 [SearchOrder] [smallint] NULL, 26 [SearchIsSection] [bit] NULL, 27 [SearchIsFuzzy] [bit] NULL, 28 [IsMultiLine] [bit] NULL, 29 [ToolTip] [text] NULL, 30 [FieldMode] [tinyint] NULL, 31 [IsBatch] [bit] NULL, 32 [AutoFormulaIndex] [int] NULL, 33 [CaptionWidth] [int] NULL, 34 [IsCarryon] [bit] NULL, 35 [IsImpFormula] [bit] NULL, 36 [IsAllField] [bit] NULL, 37 [IsExport] [bit] NULL, 38 [ExportFormat] [varchar](50) NULL, 39 [FillColor] [smallint] NULL, 40 [GroupId] [int] NULL, 41 [IsImpExcelFormula] [bit] NULL, 42 [LabelWidth] [int] NULL, 43 CONSTRAINT [PK_Arch_FieldsDK] PRIMARY KEY CLUSTERED 44 ( 45 [Id] ASC 46 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 47 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 48 49 GO 50 51 SET ANSI_PADDING OFF 52 GO 53 54 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'字段编辑方式0常规1缺省值2固定值' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Arch_Fields', @level2type=N'COLUMN',@level2name=N'FieldMode' 55 GO 56 57 ALTER TABLE [dbo].[Arch_Fields] ADD CONSTRAINT [DF_Arch_Fields_LabelWidth] DEFAULT ((0)) FOR [LabelWidth] 58 GO
我的关键数据都是和目录有关系,所以点击目录的时候会自行去查找项目人员自行配置的列表数据然后显示数据,或者选择数据时增删改数据,下图为一个实例
这就是mvc.ext.net的一个布局,不需要我们自己写样式只要使用他已经封装好的框架就好了其实代码在mvc.ext.net实例里面有,以下为我自己的代码,分为两块一块是整个大的布局也就是上左右的外层框架,其实里面的数据区域是另外一个页面当点击目录树时Load进页面中,
1 @functions{ 2 protected string CreateMainMenu() 3 { 4 //顶部布局,顶部功能菜单 5 Panel north = new Panel(); 6 north.Region = Region.North; 7 north.Split = false; 8 north.Border = false; 9 // north.Cls = "toolbar"; 10 north.Height = 78; 11 north.TitleCollapse = false; 12 north.Collapsible = false; 13 north.BaseCls = "background-color:RGB(214,228,242)"; 14 north.Html = string.Format(@"<div class='maintop'> 15 <div class='mainlogo'> 16 <img src='../Content/University/logo/{0}' style='float:left;' /> 17 </div> 18 </div>", ViewBag.MenuName); 19 20 //顶部增加按钮 21 Toolbar topButton = new Toolbar(); 22 topButton.BaseCls = "background-color:RGB(214,228,242);url();"; 23 topButton.Items.Add(new ToolbarFill()); 24 25 26 topButton.Items.Add(new Label() { Icon = Icon.User, Text = ViewData["UserName"].ToString() }); 27 topButton.Items.Add(new Label() { Text = " " });//间隔 28 topButton.Items.Add(new Label() { Icon = Icon.Time, Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); 29 topButton.Items.Add(new Label() { Text = " " });//间隔 30 topButton.Items.Add(new Ext.Net.Button { ID = "btn_DataLog", Icon = Icon.Information, Text = "日志信息",DirectClickUrl = Url.Action("OpenLogWindow", "Data_Archives") }); 31 topButton.Items.Add(new Label() { Text = " " });//间隔 32 topButton.Items.Add(new Ext.Net.Button { ID = "btn_Return", Icon = Icon.TextSubscript, Text = "子系统", DirectClickUrl = Url.Action("ReturnSusSys") }); 33 topButton.Items.Add(new Label() { Text = " " });//间隔 34 topButton.Items.Add(new Ext.Net.Button { ID = "btn_ChangePassword", Icon = Icon.Key, Text = "修改密码", DirectClickUrl = Url.Action("OpenModifyPasswordWindow") }); 35 topButton.Items.Add(new Label() { Text = " " });//间隔 36 topButton.Items.Add(new Ext.Net.Button { ID = "btn_Exit", Icon = Icon.UserRed, Text = "注销", DirectClickUrl = Url.Action("LoginOut", "Home") }); 37 north.BottomBar.Add(topButton); 38 39 40 41 //左边功能菜单 42 Panel west = new Panel(); 43 west.ID = "pnlWest"; 44 west.Icon = Icon.Outline; 45 west.Region = Region.West; 46 west.Title = "<a style='font-size:14px;' onclick='alert(App.ctmFolderMenu.show())'>功能菜单</a>"; 47 west.Layout = "AccordionLayout"; 48 west.Width = 220; 49 west.MinWidth = 220; 50 west.MaxWidth = 400; 51 west.Split = true; 52 west.Collapsible = true; 53 west.ContextMenuID = "ctmFolderMenu"; 54 55 west.Loader = Html.X().ComponentLoader() 56 .Url(Url.Action("FunMenuView")) 57 .Mode(LoadMode.Script) 58 .Params(new { containerId = "pnlWest" }) 59 .LoadMask(lm => 60 { 61 lm.ShowMask = true; 62 lm.Msg = "正在加载功能菜单,请稍后..."; 63 }); 64 65 ////中间数据展示区域 66 TabPanel center = new TabPanel(); 67 center.Region = Region.Center; 68 center.ID = "tabShowFunction"; 69 // center.BaseCls = "background-color:RGB(29,73,119)"; 70 Panel pnl = new Panel(); 71 pnl.Title = "<span style='font-size:14px;'>数据信息</span>"; 72 73 pnl.ID = "pnlCenter"; 74 pnl.Icon = Icon.Folder; 75 pnl.Collapsible = true; 76 //pnl.Loader = Html.X().ComponentLoader() 77 // .Url(Url.Action("Data_Archives", "Data_Archives", new { isLoad = true, isSystem = true })) 78 // .Mode(LoadMode.Frame) 79 // .LoadMask(lm => 80 // { 81 // lm.ShowMask = true; 82 // lm.Msg = "正在加载档案信息,请稍后..."; 83 // }); 84 center.Items.Add(pnl); 85 86 Viewport mainViewPort = new Viewport 87 { 88 Layout = "Border", 89 Items ={ 90 north, 91 west, 92 center 93 } 94 }; 95 96 return mainViewPort.ToScript(); 97 } 98 }
上面的这个页面布局就是mvc.ext.net的写法,里面有各个不同部分的注释,在这个框架里面我使用了局部视图,这样便于刷新目录和数据区域,目录加载如下:
首先在界面Load
1 west.Loader = Html.X().ComponentLoader() 2 .Url(Url.Action("FunMenuView")) 3 .Mode(LoadMode.Script) 4 .Params(new { containerId = "pnlWest" }) 5 .LoadMask(lm => 6 { 7 lm.ShowMask = true; 8 lm.Msg = "正在加载功能菜单,请稍后..."; 9 });
然后通过FunMenuView这个Action方法请求后台去寻找目录树界面
1 public Ext.Net.MVC.PartialViewResult FunMenuView(string containerId) 2 { 3 //清空查询条件 4 //ConstData.DataWhere = string.Empty; 5 6 //获取当前用户的菜单使用权限 7 string currentMenuAuth = " 80,81,83,93"; 8 this.GetCmp<Panel>(containerId).RemoveAll(); 9 IList<Sys_Menu> lstSys_Menu = null; 10 if (menuType == "SystemManage") 11 lstSys_Menu = _Sys_MenuService.GetMenuByMenuName(menuType); 12 else 13 lstSys_Menu = _Sys_MenuService.GetMenuByParentID(0, currentMenuAuth).OrderBy(m => m.DisplayOrder).ToList(); 14 15 foreach (Sys_Menu item in lstSys_Menu) 16 { 17 switch (item.MenuName) 18 { 19 case "PrepareFinishArchiveCenter": 20 case "ArchivesManageCenter": 21 case "ArchiveUseCenter": 22 case "ArchiveTidyCenter": 23 item.MenuId = -1; 24 break; 25 default: 26 break; 27 } 28 } 29 30 31 return new Ext.Net.MVC.PartialViewResult 32 { 33 RenderMode = RenderMode.AddTo, 34 ContainerId = containerId, 35 Model = lstSys_Menu, 36 WrapByScriptTag = false 37 }; 38 }
Ext.Net.MVC.PartialViewResult就是返回的部分视图界面,这样就可以另起一个界面创建目录树
1 @if (Model.Count > 0) 2 { 3 foreach (Sys_Menu item in Model) 4 { 5 @(X.Panel() 6 .Title("<span style='font-size:14px;' >"+item.MenuText+"</span>") 7 .ID("pnl" + item.MenuName) 8 .Border(false) 9 .BodyPadding(6) 10 .AutoScroll(true) 11 .Icon(Icon.FolderGo) 12 .Items(Html.X().TreePanel() 13 .TitleCollapse(false) 14 .RootVisible(false) 15 .Layout(LayoutType.Fit) 16 .ID("tpl" + item.MenuName) 17 .Tag(item) 18 //.TopBar(X.Toolbar().Items()) 19 .Border(false) 20 .Store( 21 Html.X().TreeStore() 22 .ID("store" + item.MenuName) 23 .Proxy(Html.X().AjaxProxy().Url(Url.Action("GetChildNode", "Main"))) 24 .Parameters(new { menuName = item.MenuName }) 25 26 ) 27 .Root(Html.X().Node().NodeID(item.MenuId.ToString()).Text("")) 28 .Listeners(l => l.ItemContextMenu.Fn = "RightMenu") 29 .Listeners(l=>l.ItemContextMenu.StopEvent=true) 30 .Listeners(l => l.ItemClick.Handler = "folderItemClick(record)") 31 .Listeners(l => l.BeforeItemExpand.Fn = "itemExpand") 32 ) 33 34 ) 35 } 36 }
当然这个目录树的数据也是需要从数据库中查询所得,其中目录树还有一个就是根据目录的某一个字段累分类,在生活中这个很常见,比如一个目录树是食品那它的子节点会有水果,零食,其他等等,当然这些数据都需要事先保存到数据库中部分代码如下
1 public ActionResult GetChildNode(string node, string menuName) 2 { 3 NodeCollection nodes = new NodeCollection(); 4 try 5 { 6 int id = 0; 7 //获取目录Id信息 8 if (node.StartsWith("Sys")) 9 try 10 { 11 id = Int32.Parse(node.Substring(4)); 12 } 13 catch (Exception ex) 14 { 15 logs.Error("186行", ex); 16 } 17 18 else if (node.StartsWith("Fol")) 19 try 20 { 21 id = int.Parse(node.Split('_')[1]); 22 } 23 catch (Exception ex) 24 { 25 logs.Error("196行", ex); 26 } 27 else 28 id = Int32.Parse(node); 29 switch (menuName) 30 { 31 // case "AcceptCenter": 32 case "PrepareFinishArchiveCenter": 33 case "ArchivesManageCenter": 34 case "ArchiveUseCenter": 35 case "ArchiveTidyCenter": 36 Arch_FolderService _Arch_FolderService = new Arch_FolderService(Session["SubsName"].ToString()); 37 IList<Sys_Menu> lstMenu = new List<Sys_Menu>(); 38 IList<Arch_Folder> lstData = null; 39 DataTable dtData = null; 40 bool isAdmin = true; 41 string folderAuth = ""; 42 int uId = Convert.ToInt32(CookiesDataService.GetPropertyValueOfSys_User("UId")); 43 //查询当前目录的自动分类串 44 Folder_QueryService _Folder_QueryService = new Folder_QueryService(Session["SubsName"].ToString()); 45 IList<Folder_Query> fldQuery = null; 46 BaseService baseservice = new BaseService(Session["SubsName"].ToString()); 47 48 49 //查看当前用户是否有权限访问此目录 50 try 51 { 52 if (!Convert.ToBoolean(CookiesDataService.GetPropertyValueOfSys_User("IsAdmin"))) 53 { 54 isAdmin = false; 55 folderAuth = UserAuth.GetOperateAuth("FolderAuth"); 56 } 57 } 58 catch (Exception ex) 59 { 60 logs.Error("CookiesDataService.GetValue(\"Sys_User\", \"IsAdmin\"),大约210行,cookies超时:", ex); 61 return RedirectToAction("Login", "Login"); 62 } 63 64 //根目录数据 65 if (id == -1) 66 { 67 lstData = _Arch_FolderService.GetFolderDataByFolderCode(menuName, folderAuth, isAdmin).OrderBy(f => f.DisplayOrder).ToList(); 68 69 foreach (Arch_Folder item in lstData) 70 { 71 Sys_Menu _Sys_Menu = new Sys_Menu(); 72 _Sys_Menu.MenuId = item.FId; 73 _Sys_Menu.MenuText = item.FolderName; 74 _Sys_Menu.MenuName = "Name" + item.FId.ToString(); 75 //判断当前节点是否有子节点 76 _Sys_Menu.IsChild = !item.Ischild; //当前目录是否有子节点 77 if (_Arch_FolderService.GetFolderDataByParentID(item.FId).Where(f => f.FolderType == (int)FolderType.QueryData && f.UserId == uId).Count() > 0) 78 _Sys_Menu.IsChild = false; 79 80 //当前目录是否有自动分类 81 fldQuery = _Folder_QueryService.GetFolder_QueryData(item.FId, uId).Where(f => !string.IsNullOrEmpty(f.QueryStr)).ToList(); 82 if (fldQuery != null && fldQuery.Count() > 0) 83 _Sys_Menu.IsChild = false; 84 85 lstMenu.Add(_Sys_Menu); 86 } 87 } 88 else if (node.StartsWith("Sys"))//系统节点数据 89 { 90 lstData = _Arch_FolderService.GetFolderDataByParentID(id); 91 foreach (Arch_Folder item in lstData) 92 { 93 Sys_Menu _Sys_Menu = new Sys_Menu(); 94 _Sys_Menu.MenuId = item.FId; 95 _Sys_Menu.MenuText = item.FolderName; 96 _Sys_Menu.MenuName = "Name" + item.FId.ToString(); 97 lstMenu.Add(_Sys_Menu); 98 } 99 } 100 else//子节点数据包括自动分类、节点目录、自动分类目录 101 { 102 103 //自动分类数据 104 try 105 { 106 fldQuery = _Folder_QueryService.GetFolder_QueryData(id, Convert.ToInt32(CookiesDataService.GetPropertyValueOfSys_User("UId"))); 107 } 108 catch (Exception ex) 109 { 110 logs.Error("大约cookies超时:大约277行", ex); 111 } 112 113 Folder_Query _Folder_Query = null; 114 string queryStr = "";//分组字段信息 115 //当前节点的父节点条件 116 string currNodeParentWhere = Session["SelectedNodeGroup"].ToString(); 117 //当前节点的自动分类条件 118 string currNodeWhereStr = node.Split('_')[2]; 119 try 120 { 121 _Folder_Query = fldQuery.Where(f => f.IsDefault).ToList()[0]; 122 queryStr = _Folder_Query.QueryStr; 123 } 124 catch (Exception ex) 125 { 126 logs.Info("获取自定义分类设置数据问题:", ex); 127 } 128 129 if (queryStr != "") 130 { 131 string[] aryGroupField = queryStr.Split(','); 132 133 DataTable dt = baseservice.Query("Select TableName,Filter,TypeCode From Arch_Folder Where FId=" + id); 134 string currTableName = dt.Rows[0]["TableName"].ToString(); 135 string filter = dt.Rows[0]["Filter"].ToString(); 136 string typeCode = dt.Rows[0]["TypeCode"].ToString(); 137 //分组数据源 138 string vSource = @"Select * From " + currTableName + " Where Status=0 And TypeCode Like '%" + typeCode + "%'"; 139 if (filter != "") 140 vSource += " And " + filter; 141 //设置只能查看当前个人所属的部门数据 142 if (!isAdmin) 143 { 144 string operateAuth = UserAuth.GetOperateAuth("OperateAuth"); 145 bool deptAuth = AuthSeting("data_OrganizationAuth", operateAuth); 146 //如果权限中设置了数据受组织结构控制则用户只能查看本部门的数据 147 if (deptAuth) 148 vSource += " And DeptCode='" + CookiesDataService.GetPropertyValueOfSys_User("DeptCode") + "'"; 149 } 150 //当前所选择的分类字段 151 string currentField = currNodeWhereStr.Split('=')[0]; 152 153 //当前分组字段的下一个字段 154 string groupNextField = ""; 155 156 if (currNodeWhereStr != "") 157 { 158 int indexField = Array.IndexOf(aryGroupField, currentField); 159 if (aryGroupField.Length > indexField) 160 groupNextField = aryGroupField[indexField + 1]; 161 if (currNodeParentWhere.TrimStart().StartsWith("And")) 162 vSource += currNodeParentWhere; 163 else 164 vSource += " And " + currNodeParentWhere; 165 } 166 else 167 groupNextField = aryGroupField[0]; 168 //获取下一个分组的数据信息 169 dtData = _Arch_FolderService.InvokingProcedure(vSource, groupNextField, groupNextField, groupNextField); 170 if (dtData != null) 171 { 172 foreach (DataRow item in dtData.Rows) 173 { 174 Sys_Menu _Sys_Menu = new Sys_Menu(); 175 _Sys_Menu.MenuId = id; 176 _Sys_Menu.MenuText = item[groupNextField].ToString() == "" ? "空值" : item[groupNextField].ToString(); 177 _Sys_Menu.MenuName = "Name" + item[groupNextField]; 178 _Sys_Menu.CurrGroupChar = groupNextField + "='" + item[groupNextField] + "'"; 179 _Sys_Menu.GroupChar = queryStr; 180 if (queryStr.EndsWith(groupNextField)) 181 _Sys_Menu.IsChild = true; 182 lstMenu.Add(_Sys_Menu); 183 } 184 } 185 } 186 187 if (string.IsNullOrEmpty(currNodeWhereStr)) 188 { 189 //节点目录数据 190 if (isAdmin) 191 lstData = _Arch_FolderService.GetFolderDataByParentID(id).OrderBy(o => o.DisplayOrder).ToList(); 192 else 193 lstData = _Arch_FolderService.GetFolderDataByParentID(id, folderAuth, uId).OrderBy(o => o.DisplayOrder).ToList(); 194 195 //把当前数据加入节点菜单数据中 196 foreach (Arch_Folder folder in lstData) 197 { 198 199 Sys_Menu _Sys_Menu = new Sys_Menu(); 200 _Sys_Menu.MenuId = folder.FId; 201 _Sys_Menu.FolderType = folder.FolderType; 202 _Sys_Menu.MenuText = folder.FolderName; 203 // _Sys_Menu.IsChild = false; 204 //if (_Arch_FolderService.GetFolderDataByParentID(folder.FId).Count() <= 0) 205 _Sys_Menu.IsChild = !folder.Ischild; 206 //查询目录没有子节点 207 if (_Arch_FolderService.GetFolderDataByParentID(folder.FId).Where(f => f.FolderType == (int)FolderType.QueryData && f.UserId == uId).Count() > 0) 208 _Sys_Menu.IsChild = false; 209 else 210 _Sys_Menu.IsChild = true; 211 //没有自动分类的数据没有子节点 212 fldQuery = _Folder_QueryService.GetFolder_QueryData(folder.FId, uId); 213 if (fldQuery != null && fldQuery.Count() > 0) 214 _Sys_Menu.IsChild = false; 215 lstMenu.Add(_Sys_Menu); 216 } 217 } 218 } 219 if (lstMenu != null) 220 { 221 foreach (Sys_Menu item in lstMenu) 222 { 223 Node asyncNode = new Node(); 224 if (item.FolderType == (int)FolderType.QueryData) 225 { 226 asyncNode.Icon = Icon.MagnifierZoomIn; 227 asyncNode.Text = "<span style='font-size:12px;font-color:blue;'>" + item.MenuText + "</span>"; 228 } 229 else 230 asyncNode.Text = "<span style='font-size:12px'>" + item.MenuText + "</span>"; 231 string groupChar = item.CurrGroupChar == "" ? "0" : item.CurrGroupChar; 232 asyncNode.NodeID = "Fol_" + item.MenuId.ToString() + "_" + groupChar + "_" + Guid.NewGuid().ToString(); 233 asyncNode.Leaf = item.IsChild; 234 nodes.Add(asyncNode); 235 } 236 } 237 break; 238 default: 239 IList<Sys_Menu> lstSys_Menu = _Sys_MenuService.GetMenuByParentID(id, "").ToList(); 240 241 foreach (Sys_Menu item in lstSys_Menu) 242 { 243 IList<Sys_Menu> parentNode = _Sys_MenuService.GetMenuByMenuID(item.ParentId); 244 245 Node asyncNode = new Node(); 246 asyncNode.Text = "<span style='font-size:12px'>" + item.MenuText + "</span>"; 247 248 asyncNode.NodeID = "Sys_" + item.MenuId.ToString(); 249 if (_Sys_MenuService.GetMenuByParentID(item.MenuId, "").ToList().Count() <= 0) 250 asyncNode.Leaf = true; 251 nodes.Add(asyncNode); 252 253 } 254 break; 255 } 256 257 } 258 catch (Exception ex) 259 { 260 logs.Error("获取子节点数据错误:" + ex.Message + "," + ex); 261 } 262 return this.Store(nodes); 263 }
不好意思我的代码太乱,让各位大虾见笑了,如果有好的意见请多多指点。未完待续..求大虾能对我的框架不管是后台和前段都能给我提出宝贵的意见,再次先谢谢