目录
一、主要功能
1.实现基本的增删改查功能;
2.使用cookie保存用户密码;
3.实现了通知发布功能(类似于教务在线的通知);
4.邮件发送功能;
二、开发环境
IDE:Microsoft visual studio 2017(现在已经是2019了)
语言:C#+ASP.NET相关
数据库:MySQL5.7.24(wampserver自带)
数据库管理工具:Navicat和PHPmyadmin4.8.4
其他:MySQL-connector版本:6.10.9,这个和你VS里那些mysql的包的版本必须是对上的不然各种错误。
三、数据库结构
3.1 用户表1
本表储存了用户信息以用于登录系统,本表中部分字段数据可能和其 他表重复,单独用于登录的目的是减少服务器不必要的读写负担。而另一 哈尔滨理工大学学士学位论文 - 20 - 张用户信息表则用来储存更详细的数据。
表3-1 用户表1(user,登录专用)
字段名 | 类型 | 长度 | 是否为空 | 键 | 注释 |
Id | Int | 10 | 否 | 自增长索引 | 唯一标识 |
Username | VarChar | 200 | 否 | 用户名 | |
Password | VarChar | 200 | 否 | 密码 |
3.2 用户表2
本表包含一个员工账户该拥有的所有数据,登录名和系统内昵称分离,并储存有封禁标识和个人联系方式等信息,如果修改到和用户表1相同的字段,两个表的数据会一起更改。具体的表结构如表3-2所示。(实际上某些字段也没用到,时间限制)
表3-2 用户表2(user_information)
字段名 | 类型 | 长度 | 是否为空 | 键 | 注释 |
Id | Int | 10 | 否 | 自增长索引 | 唯一标识 |
Username | VarChar | 200 | 否 | 唯一 | 用户名 |
Password | VarChar | 200 | 否 | 密码 | |
loginID | VarChar | 255 | 唯一 | 登录后的名字 | |
Type | VarChar | 255 | 员工种类 | ||
Flag | Int | 10 | 否 | 封禁标识 | |
| VarChar | 255 | 电子邮件地址 | ||
| VarChar | 255 | QQ号 | ||
Tel | VarChar | 255 | 电话号码 | ||
Eal1 | VarChar | 255 | Evaluation AssuranCe Level,评估等级(短期) | ||
Eal2 | VarChar | 255 | Evaluation AssuranCe Level,评估等级(综合) | ||
Registertime | Datetime | 否 | 注册时间 |
3.3 后台用户表
后台账户的专用表,只用于后台账户的登录,与员工表完全分离。具体的表结构如表3-3所示。
表3-3 后台用户表(admin_userinfo)
字段名 | 类型 | 长度 | 是否为空 | 键 | 注释 |
Id | Int | 10 | 否 | 自增长索引 | 唯一标识 |
Adminname | VarChar | 200 | 否 | 用户名 | |
Password | VarChar | 200 | 否 | 密码 |
3.4 通知表
通知表,用来保存通知的详细信息,ID代表唯一标识,正文使用了长度很长的可变字符串,两个时间标识均可见,用来让用户确认通知的时效性。
具体的表结构如表3-4所示。
表3-4 通知表(notice)
字段名 | 类型 | 长度 | 是否为空 | 键 | 注释 |
Id | Int | 10 | 否 | 自增长索引 | 唯一标识 |
Title | VarChar | 200 | 否 | 标题 | |
Contents | VarChar | 6000 | 正文 | ||
Subtime | Datetime | 否 | 发布时间 | ||
Edittime | Datetime | 否 | 修改时间 |
3.5 工资表
工资表并不是存储员工本身的工资数据,而是负责记录每个工种的工资系数细节,由后台设计并保存,在员工评估结果完成后进行调用计算。
具体的表结构如表3-5所示。
表3-5 工资表(wage)
字 段 | 描 述 | 类型和长度 | 主 键 | 可 空 | 默认值 |
Id | 自增长 | Int(10) | 是 | 否 | 1 |
Type | 工种 | VarChar(64) | 否 | 否 | 无 |
Basis | 基础工资 | Float | 否 | 否 | 无 |
Performance | 绩效加成(百分比) | Float | 否 | 是 | 0 |
Manqin | 满勤加成(百分比) | Float | 否 | 是 | 0 |
Craft | 工种加成 | Float | 否 | 是 | 0 |
3.6 评估表
该评估表为一个总体的数据,用于记载用户的评估成绩,时间等信息,具体的评估细则内容,需要根据不同的员工职位来设定。
具体的表结构如表3-6所示。
表3-6 评估表(assess)
字 段 | 描 述 | 类型和长度 | 主 键 | 可 空 | 默认值 |
Id | 自增长 | Int(10) | 是 | 否 | 无 |
Type | 工种 | VarChar(64) | 否 | 否 | 无 |
Attendance | 出勤时长 | Float | 否 | 否 | 无 |
Requirement | 需求达标 | Int | 否 | 否 | 无 |
Extra | 额外绩效 | Float | 否 | 是 | 无 |
Self | 自评得分 | Int | 否 | 否 | 0 |
Date | 评估日期 | Date | 否 | 否 | 0 |
LoginID | 评估的用户名 | Varchar(64) | 否 | 否 | 自动 |
Auditstatus | 审核标记 | Int | 否 | 否 | 0 |
AuditID | 评估单号 | Varchar(64) | 否 | 否 | 生成 |
Backres | 后台分数 | Int | 否 | 否 | -1 |
Result | 最终结果 | Float | 否 | 否 | -1 |
Wage | 所得工资 | Float | 否 | 否 | 0 |
四、设计实现
4.1 登录和注册
登录流程如下:
1.1打开系统,进入登录界面,输入用户名和密码;
1.2登录失败,重新返回登录界面;
1.3登录成功,按照用户的身份,进入对应的系统内部页面。
注册流程如下:
1.4打开系统,进入登录界面,点击标签“点此注册”;
1.5进入注册页面,输入要注册的信息;
1.6点击提交,如果出现用户名重复的情况,会被强制打回,重新注册。
1.7注册成功后,就可以使用新的账户登录。
登录状态保存:
在本系统中设置了Cookie来保存登录状态,免去用户每次访问软件开发人员管理与评估系统都要重新登录的繁琐操作,选择记住密码,登陆成功后会自动保存一个Cookie,保存着该用户的登录名和密码,即使关闭浏览器重新启动, Cookie也不会消失,会自动载入密码,如果是直接进入系统内部,如果Cookie读取正确,软件开发人员管理与评估系统可以跳过登录直接读取到用户的信息。清除Cookie的方法是登出账号,登出后Cookie内的信息被删除,再次登录强制重新输入密码,也不可以直接访问系统内部。
登录部分代码如下(一个actionresult就是一个页面的代码,在一个控制器文件里,controller.cs):
public ActionResult LoginPage(User user)
{
name1 = user.Username;
pwd1 = user.Password;
if (name1 == "" || pwd1 == "")
{
//Response.Write("<script>alert('Login Failed,your username or password can not be empty!');</script>");
return RedirectToAction("ErrorView");
}
try
{
loginConnection.Open();
MySqlCommand CheckLoginCmd = loginConnection.CreateCommand();
CheckLoginCmd.CommandText = "select * from user where username = '" + name1 + "'";
MySqlDataReader CheckLoginReader = CheckLoginCmd.ExecuteReader();
string pwd11 = MD5Str.MD5(pwd1);
while (CheckLoginReader.Read())
{
pwd2 = CheckLoginReader["password"].ToString();
}
if (pwd2 == pwd11)
{
//密码对上之后,要在cookie中把账号密码保存下来
//Session["uinfo"] = user;
ViewData["test1"] = user;
HttpCookie RememberCookie = new HttpCookie("RemeUser");
RememberCookie["UserName"] = name1;
RememberCookie["UserPwd"] = pwd1;
RememberCookie.Expires = DateTime.Now.AddDays(3);
//RememberCookie.Value = "username";
//RememberCookie.Expires = DateTime.Now;
Response.Cookies.Add(RememberCookie);
//Response.Write("<script>alert('"+ RemCheck.ToString() + "');</script>");
loginConnection.Close();
return RedirectToAction("../MemberLogon/Jumpto");
/*else
{
HttpCookie RememberCookie = new HttpCookie("RemeUser");
RememberCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(RememberCookie);
Response.Write("<script>alert('Login Success.');</script>");
loginConnection.Close();
}*/
}
else
{
//return RedirectToAction("Index");
//Response.Write("<script>alert('Login Failed,your username or password is error.');</script>");
loginConnection.Close();
return RedirectToAction("ErrorView");
}
return View();
}
catch (Exception exception)
{
string ex = exception.ToString();
//return View(ex);
return RedirectToAction("ErrorView");
}
}
页面代码(view层,cshtml文件):
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@{
ViewBag.Title = "User Login";
}
@{
var RemeUserInfo = ViewData["remeuser"] as bishe1.Models.User;
}
<h2>Login Page</h2>
<form role="form" action="/Login/LoginPage" method="post">
<div class="form-group">
<label for="name">用户名</label>
<input type="text" class="form-control" placeholder="请输入用户名" name="Username" value="@ViewBag.Username">
</div>
<div class="form-group">
<label for="name">密码</label>
<input type="password" class="form-control" placeholder="请输入密码" name="Password" value="@ViewBag.Password">
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="RemCheckbox" >记住密码
</label>
</div>
<p>
@Html.ActionLink("没有账号?点此注册", "RegisterPage")
</p>
<br />
<button type="sumbit" class="btn btn-primary btn-lg " name="LoginBtn" onclick="LoginBtn_Click()">Login</button>
<br />
</form>
<!--<form role="form">
<div class="form-group">
<label for="name">验证码</label>
<input type="text" class="form-control" placeholder="请输入验证码">
</div>
</form>-->
效果:《测试账号的密码就是123456 111111》
4.2 个人信息修改
在确保浏览器 Cookie 未失效的前提下,进入系统界面;
打开员工个人信息修改界面;
浏览个人信息,对需要修改的条目进行改正。
如果没有其他需求,点击保存提交;
保存完成后,配置员工岗位,设置权限,将数据存入数据库后台。
(笔者注:这里因为使用了MD5的一个现成的封装类,所以密码是从cookie里拿出来的,不然的话这里显示的就是)
4.3 后台通知管理
需要使用后台账户发布,普通员工只有查阅权限无修改删除的资格。
登录后台账户之后,进入通知管理模块,可以看到通知发布页面,一个标题框和一个文本域,输入完毕后即可发表。发表后后台端可以对任意一篇通知进行修改,但是员工端只有查阅选项。
这里使用了EF模型,.NET EF(Entity Framework)是一个功能很强的模型,可以实现对数据库的操作,无需开发者手写SQL语句。
为什么要使用EF模型呢?我在写通知这一块的时候想,我的通知表里有多少条帖子?我在后台添加一条新的通知,那这边也会变化,这些变化我用SQL语句是不是太麻烦了?怎么动态的显示他们?我点了一条帖子,就能显示他的内容?
EF模型就解决了这些问题。他封装了SQL语句的操作,使得你可以使用C#和cshtml就可以完成对数据库的访问和增删改查,当然,你得先把表结构对应进去。
EF文件是可以用XML格式打开的,打开你就发现表结构都在里面了。
关于EF模型的学习,我曾经参考了一篇博客,我认为受益匪浅,如果大家需要可以参考。这位写的非常清晰,我按照他的步骤一步到位。
Visual Studio2017中使用MVC+EF+MySql实现简单的增删改查1:Mysql数据库设计与项目的新建
HTML文件(视图)和控制器之间的数据传递,使用viewbag是一个很不错的方法。
public IList<notice> NoticeList { get; set; }
NoticeEntities1 ne = new NoticeEntities1();
/// <summary>
/// 这里用了EF模型
/// </summary>
/// <returns></returns>
public ActionResult NoticeOverView()
{
NoticeList = ne.Set<notice>().ToList();
ViewBag.NoteList = NoticeList;
return View();
}
public ActionResult NoticeVisit(int id)
{
notice noteInfo = ne.Set<notice>().Where(u => u.id == id).FirstOrDefault();
return View(noteInfo);
}
@model IEnumerable<bishe1.Entity.notice>
@using bishe1.Entity;
@{
ViewBag.Title = "NoticeOverView";
Layout = "~/Views/Shared/_MemberLayout.cshtml";
}
<h5>首页=>通知浏览(员工端)</h5>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.id)
</th>
<th>
@Html.DisplayNameFor(model => model.title)
</th>
<th>
@Html.DisplayNameFor(model => model.subtime)
</th>
<th>
@Html.DisplayNameFor(model => model.edittime)
</th>
<th>
操作
</th>
<th></th>
</tr>
@foreach (notice noticeInfo in ViewBag.NoteList)
{
<tr>
<td>@noticeInfo.id</td>
<td>@noticeInfo.title</td>
<td>@noticeInfo.subtime</td>
<td>@noticeInfo.edittime</td>
<td>
<a href="/MemberLogon/NoticeVisit/@noticeInfo.id">查看</a>
</td>
</tr>
}
</table>
说实话,看到这些日期(为了检测做的效果),也是浓浓的回忆,每次看到这些日子,就想起去年的夏天为了毕设奋斗的岁月。
通知的 修改(后台账号的权限密码admin1,123456)
4.4 邮件发送
软件开发人员管理与评估系统考虑到管理层很可能需要单独向某位员工传递讯息,特此开发了邮件功能,用于管理层与员工单独通信。
操作流程如下:
进入后台登录界面,登录后台账户;
点击邮件管理标签;
输入收件人,邮件标题,邮件正文三项。此处的收件人为用户的系统内昵称(loginID),软件开发人员管理与评估系统将根据该字段进入数据库表中搜索相对应的邮件地址,使用SMTP服务将邮件标题和正文获取后保存起来发送到对应的收件人邮箱,前提是该邮箱地址必须正确。
发送成功后,员工端应当收到提示自己收到了邮件,随后进入自己的邮箱查阅邮件内容。
这里是用了一个sendmail的类。
4.5 评估管理
软件开发人员管理与评估系统的评估分为员工端和后台两个版本,在员工端,选择对应自己的身份,进入评估界面,输入自身考核数据,随后提交,软件开发人员管理与评估系统会根据数据算出评估权值。评估模板会对员工公开,但员工不会第一时间获得考核结果。后台管理员操作完毕后,评估结果就会返回到员工的页面信息收集界面。
后台端可以查阅到所有员工的评估数据,并且可以修改考核的指标权重,当后台收集到评估数据时,可以直接通过,也可以根据数据给出管理方的主观评价,会与自动评估的数据取一个加权值保存,返回给员工。
软件开发人员管理与评估系统的评估流程如下图所示:
首先,要由员工进行自评,员工先行登录软件开发人员管理与评估系统员工端,进入评估首页。
下图展示了员工端评估系统的首页:
进入页面后,可以看到已经提交过的评估信息,以及审核状态,0为未审核,1为已经审核。提交过后的数据都不能修改,只能查看。如果想进行新的评估操作,需要点击“开始评估”。
下展示了员工端进行评估第一步,提交自评数据:
员工端输入自评数据
点击提交后,该数据会被记录为未审核状态,需要由后台端进行最后的审核打分。
提交后,未审核的数据标记为0,如图所示。
提交后的结果,审核标记显示为0
接下来进入后台端进行评估数据审核。所有未审核的评估条目都可以在此修改。但所有的条目都只有一次的修改机会,点击修改进入对应条目,而审核过的评估信息就只能查看了。
后台端审核的效果如图所示。
后台端的评估页面,可以看到只有未审核的评估记录才可以修改
进入条目可以看到其详细的数据,在backres(后台评分属性)中给出后台,也代表着该系统中软件公司管理层的评估结果,该结果会和自评结果进行加权处理,如果相差较小会取均值,如果差距很大则以后台的数据为更高的权重。
展示了后台对数据进行审核的效果:
后台可以根据员工自评数据与实际情况给出最后的评分
下图展示了后台对数据进行审核完毕的效果,可以看到刚刚修改后的属性已经被锁定了。
提交后数据由系统计算生成并锁定
后台进行审核并上传后,该评估条目就无法修改了,数据返回给员工端。但后台端也可以看到所有的条目详情,而员工只能看到属于自己的信息,其他人的评估信息无法看到。
下图为员工再次登录后可以看到自己的详细评估信息。
员工最后可以查阅评估结果
至此,一个完整的评估流程结束。接下来是一些具体的实现细节:
读取专属某个用户的评估信息:
AssessList = ae.Set<assess1>().Where(u=>u.loginID == loginID).ToList();
使用MVC5+EF6模型读取时如果想要加入where约束条件,可以调用EF模型的where方法。该方法源自C#的ienumerable类,可以在存在实体上下文的情况下生成SQL查询条件。如果where方法放在tolist之前,则是先执行where再进行查询。如果放在tolist之后,则是先查询所有数据,再根据where的条件进行筛选。
因此,在后台端,也可以利用该方法将未审核的评估单与已审核的分开显示,并且只有未审核的条目可以被修改(最终审核)。
public ActionResult Index(){
AssessList = ae.Set<assess1>().Where(u => u.auditstatus == 0).ToList();
ViewBag.AssessList = AssessList;
AssessList2 = ae.Set<assess1>().Where(u => u.auditstatus == 1).ToList();
ViewBag.AssessList2 = AssessList2;
return View();
}
至此,该系统的主体功能展示完毕,并给出某些具体细节。
代码链接如下: