古人云:温故而知新。这是极好的,近来,作为一个小白,利用点空闲时间把之前几个月自己写过的一个作为练手的一个OA系统又重新拿来温习一番,希望在巩固基础之上能得到新的启示。现在回想起来,之前一个人,写写停停,不觉感叹,平时工作中团队的重要性以及个人力量的渺小。因为是练手的项目,整个系统从数据库到前端都是自己设计,所以不免显得有点寒碜,不喜勿喷,但该有的重点还是有的,至于美工,哈哈,简洁也是一种美不是吗,只能这样安慰自己了。
准备工作:
1.进行初步的需求分析(有四大板块:我的桌面,人力资源管理,考勤管理,工作流管理)
2.每个大板块下又分小块
(我的桌面---》每日考勤,提交申请,我的审批【高级员工】,我的申请;
人力资源----》员工管理,部门管理,职位管理,角色管理;
考勤管理----》工作日设置,工作时间设置,考勤记录查询;
工作流管理----》流程管理)
3.技术实现:ASP.NET MVC,EF,Jquery,T4,log4Net,MD5,Jquery-easy-uI,Sqlser2008,Membercache,后期用到spring.net
先看看前期大概的一个页面展示图:
主页面:
员工信息页面:
添加员工:
编辑员工:
--------------------------------------------------------------------------------------------------------------------------------------------------------------
正文:
好了,闲话不多说,先设计数据库吧,在设计数据库之前,有几点我们也需要注意,
1.对于表的命名一定要规范;
2.表的设计原则是一张表只记录一件事,如果表与表有关系的,通过外键关联。
在这里面,建表需要注意的是对菜单表ActionInfo的设计,因为它分级别,有一级菜单,二级菜单,对于这种表的设计,
ActionId 标识列 主键---》(渲染到前端的是id)
Title 标题 nvarchar(20)---》(text)
Leval 1 2 int 决定将来显示的层级图标(1代表菜单,2代表菜单项)
URL:允许为空,一级没有,二级有【通过这个url访问】
PrentId int not null 对于一级菜单,取值为0【重要】
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
接下来就是搭建框架了,采用简单抽象工厂三层的项目结构
框架搭完,先做主页面,Home/Index Home控制下的Index的html代码 主页面
1 @using Model.Models 2 @{ 3 Layout = null; 4 EmployeeInfo emp = ViewData["user"] as EmployeeInfo; 5 6 } 7 8 9 10 11 12 13通达OA 14 15 16 17 18 19 20 35 36 37 383941 42欢迎您的登录:@emp.EmpName [注销用户]
404346 4744
454852 53 @* 弹出的独立窗口 *@ 5449 505155 5859 60 61 114 115
我整体的页面布局用的是Easy-UI,首页内容使用的是panel组件,菜单栏使用的是tree组件。
需要注意的是:
1.panel组件可以通过设置href属性从远程加载页面,但只会加载页面的body内容,可是像添加员工,编辑员工这样的,我们需要额外进行一些css样式的改变时,他却变得无效了,所以在面板之内,我添加了一个Iframe框架,Iframe 框架 有一个src属性,这个属性可以请求一个远程界面(完整的,独立的页面),你可以在里面做上你自己的css样式进行改变。
2.iframe框架如何自适应高度?
解决方案:
$("#editframe").load(function () {
var mainheight = $(this).contents().find("body").height() + 30;
$(this).height(mainheight);
});
3.如何在iframe框架内嵌的网页中去访问他所在的主页面的资源?
解决方案:
在主页面定义要使用的资源方法,然后再包含iframe的子页面中调用window.parent.方法名()。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Action/Index ||菜单栏代码
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Script.Serialization;using BLL;using Model.Models;namespace UI.Controllers{ public class ActionController :BaseController { // // GET: /Action/ public ActionResult Index() { return View(); } ////// 一次性加载菜单数据 /// /// ////// 符合tree树形控件的json格式的对象 /// public ActionResult LoadData() { //没有进行权限分配,默认登录后加载所有菜单列表 ListactionList = new ActionService().GetActionList(a => true); //调用存储过程进行过滤 // List actionList = new ActionService().GetActionListByEmp(this.user.EmpId); //采用EF查询进行过滤 //List actionList = new ActionService().GetActionByEmpId(this.user.EmpId); //构造符合tree树形控件的json格式的对象 List
Employee ||控制器下代码
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using Model.Models;using BLL;using UI.Models;using System.Web.Script.Serialization;using Newtonsoft.Json;namespace UI.Controllers{ public class EmployeeController : BaseController { // // GET: /Employee/ public ActionResult List() { return View(); } public ActionResult LoadData(int page, int rows) { int totalCount = 0; Listemplist = new EmployeeService().GetEmpListByPage(page, rows, ref totalCount); //解决方案二:使用Newtonsoft程序集 var result = JsonConvert.SerializeObject(new { total = totalCount, rows = emplist }); return Content(result); } [HttpGet] public ActionResult AddEmp(int? id) { string url = "/Employee/AddEmp"; List depList = new DepartmentService().GetDepList(d => true); List posList = new PositionService().GetPosList(p => true); EmployeeInfo emp; ViewEmpModel model = new ViewEmpModel(); if (id != null) { url = "/Employee/Update"; emp = new EmployeeService().GetDepByEmp(e => e.EmpId == id).SingleOrDefault(); model = new ViewEmpModel { EmpName = emp.EmpName, EmpBirthday = emp.EmpBirthday.ToString(), EmpEmail = emp.EmpEmail, EmpTelephone = emp.EmpTelephone, EmpUrl = url, LoginId = emp.LoginId, EmpGender = emp.EmpGender, DepId = emp.DepId, EmpId = emp.EmpId, PosId = emp.PosId, LoginPwd = emp.LoginPwd, DelFlag = emp.DelFlag }; ViewData["DepId"] = new SelectList(depList, "DepId", "DepName", emp.DepId); ViewData["PosId"] = new SelectList(posList, "PosId", "PosName", emp.PosId); } else { ViewData["DepId"] = new SelectList(depList, "DepId", "DepName"); ViewData["PosId"] = new SelectList(posList, "PosId", "PosName"); ViewData["deplist"] = depList; ViewData["poslist"] = posList; } ViewData.Model = model; return View(); } [HttpPost] public ActionResult AddEmp(EmployeeInfo emp) { emp.DelFlag = false; emp.LoginPwd = "888888"; bool flag = new EmployeeService().AddEmp(emp); return flag ? Content("ok") : Content("fail"); } //展示员工详细信息 public ActionResult ShowEmp(int id) { EmployeeInfo emp = new EmployeeService().GetDepByEmp(e => e.EmpId == id).SingleOrDefault(); List adplist = new AdjustPositionService().GetAdpList(a => a.EmpId == emp.EmpId); List addlist = new AdjustDepartmentService().GetAddList(a => a.EmpId == emp.EmpId); string gender = emp.EmpGender ? "女" : "男"; ViewData["gender"] = gender; ViewData["adp"] = adplist; ViewData["add"]=addlist; return View(emp); } //修改员工 [HttpPost] public ActionResult Update(EmployeeInfo emp) { bool falg = new EmployeeService().UpdateEmp(emp); return falg ? Content("ok") : Content("fail"); } /// /// 删除员工 /// /// ///public ActionResult Delete(string idlist) { bool falg = new EmployeeService().DeleteEmpList(idlist); return falg ? Content("ok") : Content("fail"); } //员工调整 [HttpGet] public ActionResult AdjustEmp(int id) { List depList = new DepartmentService().GetDepList(d => true); List posList = new PositionService().GetPosList(p => true); EmployeeInfo emp = new EmployeeInfo(); emp = new EmployeeService().GetDepByEmp(e => e.EmpId == id).SingleOrDefault(); //如何将查询到的数据绑定到视图中的下拉列表框,第四个参数是选中的值 ViewData["DepId"] = new SelectList(depList, "DepId", "DepName", emp.DepId); ViewData["PosId"] = new SelectList(posList, "PosId", "PosName", emp.PosId); ViewData["deplist"] = depList; ViewData["poslist"] = posList; ViewData.Model = emp; ViewData["EmpId"]=emp.EmpId; ViewData["OldDepartmentId"]=emp.DepId; ViewData["OldPositionId"] = emp.PosId; return View(); } [HttpPost] public ActionResult Adjust(EmployeeInfo emp,AdjustDepartment add,AdjustPosition adp) { //接收原来部门的编号 int OldDepartmentId = Convert.ToInt32(Request["OldDepartmentId"]); //接收原来职位的编号 int OldPositionId = Convert.ToInt32(Request["OldPositionId"]); AdjustManagerService am = new AdjustManagerService(); adp.NewPositionId = emp.PosId; add.NewDepartmentId = emp.DepId; adp.AdjustTime = DateTime.Now; add.AdjustTime = DateTime.Now; bool falg; //职位调整并且部门没调整 if (add.NewDepartmentId == add.OldDepartmentId&&adp.NewPositionId != adp.OldPositionId) { falg = am.Add(adp); } //部门调整并且职位没调整 else if (add.NewDepartmentId != add.OldDepartmentId && adp.NewPositionId == adp.OldPositionId) { falg = am.Add(add); } //部门和职位都调整了 else if (add.NewDepartmentId != add.OldDepartmentId && adp.NewPositionId != adp.OldPositionId) { falg = am.Add(add,adp); } falg = new EmployeeService().UpdateEmp(emp); return falg ? Content("ok") : Content("fail"); } }}
给出Employee的List的视图代码,后面部门类似参考
1 @{ 2 Layout = null; 3 } 4 5 6 7 8员工界面 9 10 11
【注】:
常见错误:检测到序列化循环引用
解决方案一:创建一个VO模型对象,不包含导航属性;
解决方法二:推荐使用牛顿JSON程序集
好了,今天的复习就到这。期待下一节的“温故而知新(二)”。