Code "Xiaobai" knows something new from the past (I) - - OA Management System

Posted by Sxooter on Wed, 19 Jun 2019 02:49:18 +0200

Ancient Cloud: Reviewing the Past and Knowing the New. This is excellent. Recently, as a little white man, I have used my spare time to revisit an OA system I wrote as a trainer in the past few months. I hope I can get some new inspiration on the basis of consolidation. Now, in retrospect, the previous person, writing stop, do not feel exclamation, the importance of the team in peacetime work and the insignificance of personal strength. Because it's a hands-on project, the whole system is designed by itself from the database to the front end, so it seems a bit shabby, not like spraying, but there are still some key points, as for artists, haha, conciseness is also a kind of beauty, can we only comfort ourselves in this way.

Preparations:

1. Conduct preliminary needs analysis (there are four sections: my desktop, human resources management, attendance management, workflow management)

2. Divide under each large plate into small pieces.

(My desktop -) Daily attendance, application submission, my approval [senior staff], my application;

Human resources - --"employee management, Department management, position management, role management;

Attendance Management - --- Workday Settings, Working Hours Settings, Attendance Records Query;

Workflow Management--Process Management

3. Technical realization: ASP.NET MVC, EF, Jquery, T4, log4Net, MD5, Jquery-easy-uI, Sqlser2008, Membercache, later spring.net

 

Let's first look at an earlier page presentation.

Home page:

Employee Information Page:

Add staff:

Editorial staff:

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

Text:

Well, not much gossip. Let's design the database first. Before designing the database, we need to pay attention to a few points.

1. Naming tables must be standardized.

2. The design principle of a table is that only one thing is recorded in a table. If the table is related to the table, it is related by a foreign key.

In this regard, the design of menu table ActionInfo should be paid attention to when building tables, because it has different levels, one level menu and two level menu.

ActionId Identifies Column Primary Key - (rendered to the front end is id)

Title

Leval 1 2 int Determines the hierarchical icons to be displayed in the future (1 for menus, 2 for menu items)

URLs: Allow empty, level 1 is not, Level 2 has [access through this url]

PrentId int not null for the first-level menu, the value is 0 [important]

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

The next step is to build a framework, using a simple abstract factory three-tier project structure.

After the frame is built, make the main page first, the html code of Index under the control of Home/Index Home

  1 @using Model.Models
  2 @{
  3     Layout = null;
  4     EmployeeInfo emp = ViewData["user"] as EmployeeInfo;
  5    
  6 }
  7 
  8 <!DOCTYPE html>
  9 
 10 <html>
 11 <head>
 12     <meta name="viewport" content="width=device-width" />
 13     <title>Tongda OA</title>
 14     <script src="~/Scripts/jquery-1.7.1.js"></script>
 15     <script src="~/Scripts/MyAjaxForm.js"></script>
 16     <script src="~/Scripts/jquery.easyui.min.js"></script>
 17     <script src="~/Scripts/easyui-lang-zh_CN.js"></script>
 18     <link href="~/Content/easyui.css" rel="stylesheet" />
 19     <link href="~/Content/icon.css" rel="stylesheet" />
 20    <style type="text/css">
 21        a
 22        {
 23            text-decoration:none;
 24        }
 25        #emp
 26        {
 27            position:absolute;
 28            color:red;
 29            bottom:5px;
 30            left:5px;
 31 
 32        }
 33      
 34    </style>
 35 </head>
 36     
 37 <body class="easyui-layout" onselectstart=" return false;">
 38     <div data-options="region:'north',split:false" style="height: 110px; background: url(/Content/Images/OA2.png) no-repeat 0px -52px ;position:relative">
 39        <p id="emp">Welcome to login:@emp.EmpName <a  href="/User/Login?state=false">[logoff]</a></p>
 40     </div>
 41 
 42     <div data-options="region:'west',title:'Navigation menu',split:false" style="width: 150px;  background: url(/Content/Images/OA.jpg) no-repeat -20px ">
 43         <ul id="tt">
 44         </ul>
 45     </div>
 46 
 47     <div data-options="region:'center',title:'Home page'" style="padding: 5px; background: url(/Content/Images/OA3.jpg) no-repeat; opacity:0.88">
 48         <div id="p" style="padding: 10px;">
 49                      
 50         </div>  
 51     </div>
 52 
 53     @* Pop-up independent window *@
 54     <div id="editwin">
 55         <iframe id="editframe" width="100%" frameborder="0" scrolling="no">
 56             
 57         </iframe>
 58     </div>  
 59 
 60 
 61     <script type="text/javascript">
 62 
 63         //Refresh
 64         function afterSave() {
 65             $("#editwin").window("close");
 66             $("#editframe").attr("src", "null");
 67             $("#dg").datagrid("reload");
 68         };
 69 
 70 
 71         $('#tt').tree({
 72             url: "/Action/LoadData",
 73             checkbox: 'true',
 74             lines: 'true',
 75             dnd: 'false',
 76             animate: 'true',
 77             formatter: function (node) {
 78                 return ("[" + node.text + "]");
 79             },
 80             onClick: function (node) {
 81                 $('#p').panel({
 82                     fit:true,
 83                     title: node.text,
 84                     href:node.url
 85                    
 86                 });
 87             }
 88            
 89         });
 90    
 91         //Popup
 92         function popEditWindow(caption,width,src)
 93         {    
 94                 $("#editwin").css("display", "block");
 95                 $('#editwin').window({
 96                     title: caption,
 97                     width: width,                    
 98                     resizable: false,
 99                     shadow:false,
100                     modal: true
101                 });
102              
103                 $("#editframe").attr("src", src);
104                 $("#editframe").load(function () {
105                     var mainheight = $(this).contents().find("body").height() + 30;
106                     $(this).height(mainheight);
107                 });
108          
109         }
110      
111 
112 
113     </script>
114 </body>
115 </html>

My overall page layout uses Easy-UI, the home page content uses panel components, and the menu bar uses tree components.

It should be noted that:

1.panel components can load pages remotely by setting href attributes, but only by loading the body content of the page. But when we need to make some additional changes in the style of css, such as adding employees and editing employees, panel components become invalid. So in the panel, I added an Iframe framework, which has an src attribute, which can be requested. A remote interface (complete, independent pages) where you can make your own CSS style changes.

2. How does the iframe framework adapt to height?

Solution:

 $("#editframe").load(function () {

    var mainheight = $(this).contents().find("body").height() + 30;

      $(this).height(mainheight);

                    });

3. How to access the resources of his home page in the web pages embedded in the iframe framework?

Solution:

Define the resource method to be used on the main page, and then call window.parent. method name () on the sub-page containing iframe.

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Action/Index | | Menu Bar Code

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();
        }
        /// <summary>
        /// One-time loading menu data
        /// </summary>
        /// 
        /// <returns>
        /// accord with tree Tree control json Objects in Format
        /// </returns>
        public ActionResult LoadData()
        {
            //There is no permission allocation, all menu lists are loaded after default login.
            List<ActionInfo> actionList = new ActionService().GetActionList(a => true);

            //Call stored procedures for filtering
           // List<ActionInfo> actionList = new ActionService().GetActionListByEmp(this.user.EmpId);

            //Use EF Query filtering
            //List<ActionInfo> actionList = new ActionService().GetActionByEmpId(this.user.EmpId);

            //Structural coincidence tree Tree control json Objects in Format
            List<MenuItem> menulist = new List<MenuItem>();
            foreach (var item in actionList.Where(a=>a.Leval==1))
            {
                //Level 1 menu
                MenuItem first = new MenuItem { id = item.ActionId, text = item.Title, state = "closed", url = null };
                List<MenuItem> second = new List<MenuItem>();
                List<ActionInfo> secondActionList = actionList.Where(a=>a.PrentId==item.ActionId).ToList();
                foreach (var i in secondActionList)
                {
                    second.Add(new MenuItem { id = i.ActionId, text = i.Title,state="open",url = i.URL });
                }
                first.children = second;
                menulist.Add(first);
            }
            //JSON serialize
            JavaScriptSerializer jss = new JavaScriptSerializer();
            string result = jss.Serialize(menulist);
            return Content(result);
        }


    }

    //Structural coincidence tree Entity classes of components
    public class MenuItem
    {
        public int id { get; set; }
        public string  text { get; set; }
        public string state { get; set; }
        public string  url { get; set; }
        public List<MenuItem>  children { get; set; }
    }
}

Employee | | Code under Controller

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;
            List<EmployeeInfo> emplist = new EmployeeService().GetEmpListByPage(page, rows, ref totalCount);
            //Solution 2: Use Newtonsoft Assembly
            var result = JsonConvert.SerializeObject(new { total = totalCount, rows = emplist });          
            return Content(result);

        }

        [HttpGet]
        public ActionResult AddEmp(int? id)
        {
            string url = "/Employee/AddEmp";
            List<DepartmentInfo> depList = new DepartmentService().GetDepList(d => true);
            List<PositionInfo> 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");
        }

        //Show employee details
        public ActionResult ShowEmp(int id)
        {
            EmployeeInfo emp = new EmployeeService().GetDepByEmp(e => e.EmpId == id).SingleOrDefault();

          List<AdjustPosition> adplist = new AdjustPositionService().GetAdpList(a => a.EmpId == emp.EmpId);
          List<AdjustDepartment> addlist = new AdjustDepartmentService().GetAddList(a => a.EmpId == emp.EmpId);


            string gender = emp.EmpGender ? "female" : "male";
            ViewData["gender"] = gender;
            ViewData["adp"] = adplist;
            ViewData["add"]=addlist;
            return View(emp);
        }

        //Modification of Employees
        [HttpPost]
        public ActionResult Update(EmployeeInfo emp)
        {
            bool falg = new EmployeeService().UpdateEmp(emp);
            return falg ? Content("ok") : Content("fail");
        }
        /// <summary>
        /// Delete employees
        /// </summary>
        /// <param name="idlist"></param>
        /// <returns></returns>
        public ActionResult Delete(string idlist)
        {
            bool falg = new EmployeeService().DeleteEmpList(idlist);
            return falg ? Content("ok") : Content("fail");
        }

        //Staff adjustment
        [HttpGet]
        public ActionResult AdjustEmp(int id)
        {           
            List<DepartmentInfo> depList = new DepartmentService().GetDepList(d => true);
            List<PositionInfo> posList = new PositionService().GetPosList(p => true);
            EmployeeInfo emp = new EmployeeInfo();
            emp = new EmployeeService().GetDepByEmp(e => e.EmpId == id).SingleOrDefault();
            //How to bind the queried data to the drop-down list box in the view,The fourth parameter is the selected value
            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)
        {
            //Receive the number of the original department
            int OldDepartmentId = Convert.ToInt32(Request["OldDepartmentId"]);
            //Receive the number of the original position
            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;
            //Job adjustment and no departmental adjustment
            if (add.NewDepartmentId == add.OldDepartmentId&&adp.NewPositionId != adp.OldPositionId)
            {
              
                falg = am.Add(adp);
            }
            //Departmental adjustment and no job adjustment
            else if (add.NewDepartmentId != add.OldDepartmentId && adp.NewPositionId == adp.OldPositionId)
            {
                falg = am.Add(add);
            }
             //Departments and positions have been adjusted.
            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");


        }
    }
}

Give Employee List's view code, similar reference to the latter Department

  1 @{
  2     Layout = null;
  3 }
  4 <!DOCTYPE html>
  5 <html>
  6 <head>
  7     <meta name="viewport" content="width=device-width" />
  8     <title>Employee Interface</title>
  9 </head>
 10 <body>
 11     <table id="dg">
 12     </table>
 13     <script type="text/javascript">
 14         var fieldName;
 15         $("#editwin").css("display", "none");
 16         $('#dg').datagrid({
 17             url: '/Employee/LoadData',
 18             pagination: true,//page=1&rows=10
 19             pageList: [10, 15, 20],
 20             columns: [[
 21                 { field: 'check', checkbox: true, width: 50 },
 22                 { field: 'EmpId', title: 'Employee Number', width: 50 },
 23                 { field: 'EmpName', title: 'Name of Employee', width: 100 },
 24                 {
 25                     field: 'EmpGender', title: 'Employee Gender', width: 100, formatter: function (value, row, index) {
 26                         return value ? "female" : "male";
 27                     }
 28                 },
 29                 { field: 'EmpBirthday', title: 'Birthdays of Employees', width: 100 },
 30                 { field: 'EmpTelephone', title: 'Employee Telephone', width: 100 },
 31                 { field: 'EmpEmail', title: 'mailing address', width: 200 },
 32                 {
 33                     field: 'Operator', title: 'Employee Operation', width: 300,
 34                     formatter: function () {
 35                         return "<a href='#' class='editemp'>Editorial staff</a> |  <a href='#' class='detail' onclick='showEmp(this);'>detailed information</a> |<a href='#' class='adjustemp' onclick='AdjustEmp(this)'>Staff adjustment</a> |<a href='#' class='setAction' onclick='SetAction(this)'>Allocation of permissions</a>  ";
 36                     }
 37                 }
 38 
 39             ]],
 40             toolbar: [{
 41                 iconCls: 'icon-add',
 42                 text: 'Adding Employees',
 43                 handler: function () {
 44                     //Call on the main page Index Bullet Window Function in Medium Package
 45                     popEditWindow("Adding Employees", 400, "/Employee/AddEmp");                  
 46                 }
 47             }, '-', {
 48                 iconCls: 'icon-cancel',
 49                 text: 'Delete employees',
 50                 handler: function () {
 51                     var rows = $("#dg").datagrid('getSelections');
 52                     if (rows.length == 0) {
 53                         $.messager.alert("Tips", "Please select Delete line!");
 54                         return;
 55                     }
 56                     $.messager.confirm('confirm', 'Are you sure you want to delete it?', function (r) {
 57                         if (r) {
 58                             //Get Number id,And make strings with certain rules
 59                             var idlist = "";
 60                             for (var i = 0; i < rows.length; i++) {
 61                                 idlist = idlist + rows[i]["EmpId"] + ",";
 62                             }
 63                             //Intercept
 64                             idlist = idlist.substr(0, idlist.length - 1);
 65                             //Asynchronous request to send a string to be deleted
 66                             $.ajax({
 67                                 url: "/Employee/Delete",
 68                                 type: "post",
 69                                 data: { "idlist": idlist },
 70                                 dataType: "text",
 71                                 success: function (res) {
 72                                     if (res == "ok") {
 73                                         $("#dg").datagrid("reload");
 74                                     }
 75                                 }
 76                             })
 77                         }
 78                     });
 79                 }
 80             }],
 81             onClickCell: function (rowIndex, field, value) {
 82                 fieldName = field;
 83             },
 84             onSelect: function (rowIndex, rowData) {
 85                 if (fieldName == "Operator") {
 86                     $("#dg").datagrid("unselectRow", rowIndex);
 87                 }
 88             },
 89             onLoadSuccess: function () {
 90                 $(".editemp").click(function () {             
 91                     var empid = $(this).parents("tr").children("td").eq(1).text();
 92                     popEditWindow("Editorial staff", 400, "/Employee/AddEmp/"+empid);           
 93                 })
 94             }
 95         });
 96 
 97         //Show employee details
 98         function showEmp(node) {
 99             $(function(){
100                 var empid = $(node).parents("tr").children().eq(1).text();
101                 popEditWindow("Employee Details", 500, "/Employee/ShowEmp/" + empid);
102             })   
103         }
104 
105         //Employee Adjustment Bullet Window
106         function AdjustEmp(node) {
107             $(function () {
108                 var empid = $(node).parents("tr").children().eq(1).text();
109                 popEditWindow("Staff adjustment", 400, "/Employee/AdjustEmp/" + empid);
110             })
111         }
112         //Allocation of permissions
113         function SetAction(node) {
114             $(function () {
115                 var empid = $(node).parents("tr").children().eq(1).text();
116                 popEditWindow("Allocation of permissions", 400, "/Role/SetRole/" + empid);
117             })
118         }
119     </script>
120 
121 </body>
122 
123 </html>

[Note]

Common Error: Serialized Loop Reference Detected

Solution 1: Create a VO model object without navigation attributes.

Solution 2: Recommend Newton JSON assemblies

 

Okay, that's all for today's review. Looking forward to the next section of "learning from the past and learning from the new" (2).

Topics: ASP.NET JSON JQuery Database Javascript