工作生活

考勤系统全生命周期

2019-07-12  本文已影响0人  抹绿茶

考勤系统

1、需求概述

1.1 背景

考勤已经成为人们上下班的一个必须过程,但是当今还是有许多是以纸质签到作为考勤。这样的考勤效率低,为了更好地解决这一问题,所以需要建立一个完善的考勤系统。

1.2 系统目标

建立考勤系统管理,提高考勤工作的效率和准确性,避免因为考勤问题影响正常工作,主要是实现员工上下班打卡考勤进行记录,对自己考勤信息的查询,另一个是管理人员对员工考勤记录的修改,激活或者注销员工信息。

1.3 功能需求

功能需求

1.4 非功能需求

1.4.1 安全性

(1)该考勤系统对于安全性的考虑就是数据不被串改与丢失即可

(2)可以做到一人一号,降低出错概率

1.4.2 可靠性

(3)当系统出现故障和用户出现错误的操作后支持恢复

(4)当用户在使用过程中遇到错误的时候可以立即定位问题

(5)当网络不稳定或使用中异常中断的情况下系统有相应的容错措施

1.4.3 易使用性

(1)用户能够快速地找到所需功能并使用

(2)软件在熟练使用后应该可以更快的进行各项操作

1.4.4 可维护性

(1)管理员可以在后台查到公司员工各时间段的打卡记录

(2)管理员能在后台进行系统维护及个时间段一次的考勤记录统计,如有差错可修改考勤记录

1.4.5 性能需求

(3)估计公司员工为39人,每天登录员工数为25左右,网络的带宽为100M带宽。

(4)在非高峰时间根据工号或名字特定条件进行搜索,可以在3秒内得到搜索结果。

(5)当通过互联网接入系统的时候,期望在编号和名称搜索时最长查##询时间<10秒。

1.5 软件与硬件或其他外部系统接口

1.6 设计和实现的限制

(1)系统建设成本是否符合公司利益

(2)在连通互联网后,网络速率能否符合查询需求

(3)在系统出错时能否有及时的技术补救措施与完整的相对策略

(4)管理员的修改权限能否在技术上实现

2、系统数据库设计

2.1 第一步:标识实体

打卡机
员工

2.2 第二步:绘制ER图

ER图

2.3 第三步:制作数据表

数据库表

2.4 第四步:生成数据库表

根据数据表建立数据库表,在员工数据库表中将编号设置为主键,打卡机表中将编号设置为外键,打卡表中把打卡号设置为主键,员工编号和打卡机编号设置为外键,在将他们联系起来。

(1) 根据数据表在数据库中新建punch(打卡机)表,并添加数据

USE [Attendance]
GO
/****** Object:  Table [dbo].[punch]    Script Date: 07/12/2019 16:49:35 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[punch](
    [id] [varchar](50) NOT NULL,
    [positon] [varchar](50) NULL,
 CONSTRAINT [PK_punch] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO

(2) 根据数据表在数据库中新建record(记录)表,并添加数据

USE [Attendance]
GO

/****** Object:  Table [dbo].[record]    Script Date: 07/12/2019 16:54:55 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[record](
    [serial] [int] IDENTITY(1,1) NOT NULL,
    [s_id] [varchar](50) NULL,
    [date] [date] NULL,
    [time] [time](0) NULL,
    [p_id] [varchar](50) NULL,
 CONSTRAINT [PK_record] PRIMARY KEY CLUSTERED 
(
    [serial] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[record]  WITH CHECK ADD  CONSTRAINT [FK_record_punch] FOREIGN KEY([p_id])
REFERENCES [dbo].[punch] ([id])
GO

ALTER TABLE [dbo].[record] CHECK CONSTRAINT [FK_record_punch]
GO

ALTER TABLE [dbo].[record]  WITH CHECK ADD  CONSTRAINT [FK_record_staff] FOREIGN KEY([s_id])
REFERENCES [dbo].[staff] ([id])
GO

ALTER TABLE [dbo].[record] CHECK CONSTRAINT [FK_record_staff]
GO

(3) 根据数据表在数据库中新建staff(职员)表,并添加数据


USE [Attendance]
GO

/****** Object:  Table [dbo].[staff]    Script Date: 07/12/2019 16:56:15 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[staff](
    [id] [varchar](50) NOT NULL,
    [name] [varchar](50) NULL,
    [sex] [varchar](10) NULL,
    [par] [varchar](50) NULL,
    [role] [varchar](50) NULL,
    [pwd] [varchar](50) NULL,
 CONSTRAINT [PK_staff] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

3、考勤系统界面设计

3.1 登录界面设计

登录界面

3.2 管理员主界面设计

管理员主界面

3.2.1 新用户注册界面设计

注册界面

3.3 职员主界面设计

职员主界面

4、考勤系统功能实现——登录、注册

4.1.1 登录界面及登录功能实现代码:

员工或者管理员输入账号和密码后即可实现登录


登录界面

4.1.2登录功能实现代码如下:

(1)连接数据库

private void bt_Login_Click(object sender, EventArgs e)
        {
            String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
            SqlConnection sqlConn = new SqlConnection(connStr);
            try
            {
                // 连接数据库
                sqlConn.Open();

                // 构造命令发送给数据库
                String sqlStr = "select * from staff where ID=@id and pwd=@pwd";
                SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);

                // 注意是用用户ID登录,而不是用户名,用户名可能会重复
                cmd.Parameters.Add(new SqlParameter("@id", this.tb_User.Text.Trim()));
                cmd.Parameters.Add(new SqlParameter("@pwd", this.tb_Password.Text.Trim()));
                SqlDataReader dr = cmd.ExecuteReader();

(2)连接数据库后,查询数据库记录,能否登录

// 如果从数据库中查询到记录,则表示可以登录
                if (dr.HasRows)
                {
                    dr.Read();
                    UserInfo.userId = int.Parse(dr["id"].ToString());
                    UserInfo.userName = dr["name"].ToString();
                    UserInfo.userPwd = dr["pwd"].ToString();
                    UserInfo.userRole = dr["role"].ToString();
                    MessageBox.Show(UserInfo.userRole + "登录成功");

(3)输入账号和密码后,判断登录人员的角色并跳转到相应的界面,并隐藏当前界面

  if (UserInfo.userRole == "管理员")
                    {
                        // 显示收银员主界面
                        MainFormAdmin formAdmin = new MainFormAdmin();
                        formAdmin.Show();
                      

                        // 隐藏登录界面
                        this.Hide();
                    }

                    if (UserInfo.userRole == "职员")
                    {
                        // 显示库管员主界面
                        MainFormUser formUser = new MainFormUser();
                        
                        formUser.Show();

                        // 隐藏登录界面
                        this.Hide();
                    }
                }
else
                {
                    MessageBox.Show("用户名或密码错误", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception exp)
            {
                MessageBox.Show("访问数据库错误:" + exp.Message);
            }
            finally
            {
                sqlConn.Close();
            }
        }

4.2.1 注册界面

注册员工界面.PNG

在新用户注册窗口启动时,自动从数据库中获取最大的员工编号,
并加1作为新员工编号.


注册成功界面.PNG image.png

//在新用户注册窗口启动时,自动从数据库中获取最大的员工编号,
并加1作为新员工编号。

String sqlStr = "select MAX(id+1) as id from employee";

4.2.2 实现注册职员信息功能代码:

在管理员界面实现注册员工信息,并能够将信息存储到后台数据库上
(1)连接数据库;构造查询命令

 private void RecordForm2_Load(object sender, EventArgs e)
        {
           
            String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
            SqlConnection sqlConn = new SqlConnection(connStr);
    
            try

            {
                // 连接数据库
                sqlConn.Open();

                // 构造查询命令

                String sqlStr = "select MAX(id+1) as id from staff";
                SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
                SqlDataReader dr = cmd.ExecuteReader();
             
             if(dr.HasRows)
             {
                 dr.Read();
                 this.tb_Id.Text =  dr["id"].ToString();
             }

            }
            catch (Exception exp)
            {
                MessageBox.Show("访问数据库错误:" + exp.Message);
            }
            finally
            {
                sqlConn.Close();
            }
        }

(2)点击“确认”按钮,录入职员信息

 // 点击“确认”按钮,录入职员信息
        private void bt_Ok_Click(object sender, EventArgs e)
        {
            String id = this.tb_Id.Text.Trim();
            String name = this.tb_Name.Text.Trim();
            String pwd = this.tb_Pwd.Text.Trim();
            String sex = this.tb_sex.Text.Trim();
            String par = this.tb_par.Text.Trim();
            String role = this.tb_role.Text.Trim();

(3)更新数据库,并构造查询命令

 // 更新数据库
            String connStr = ConfigurationManager.ConnectionStrings["Attendence"].ConnectionString;
            SqlConnection sqlConn = new SqlConnection(connStr);
            try
            {
                // 连接数据库
                sqlConn.Open();

                // 构造命令
                String sqlStr = "insert into staff(ID, NAME, PWD, SEX, PAR, ROLE) values(@id, @name, @pwd, @sex, @par, @role)";
                SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);

                // SQL字符串参数赋值
                cmd.Parameters.Add(new SqlParameter("@id", id));
                cmd.Parameters.Add(new SqlParameter("@name", name));
                cmd.Parameters.Add(new SqlParameter("@pwd", pwd));
                cmd.Parameters.Add(new SqlParameter("@sex",sex));
                cmd.Parameters.Add(new SqlParameter("@par", par));
                cmd.Parameters.Add(new SqlParameter("@role", role));

(4)命令发送给数据库; 根据返回值判断是否插入成功

 // 将命令发送给数据库
                int res = cmd.ExecuteNonQuery();

                // 根据返回值判断是否插入成功
                if (res != 0)
                {
                    MessageBox.Show("员工信息录入成功");
                }
                else
                {
                    MessageBox.Show("员工信息信息录入失败");
                }
            }
            catch (Exception exp)
            {
                MessageBox.Show("访问数据库错误:" + exp.Message);
            }
            finally
            {
                sqlConn.Close();
            }
        }

5、串口及串口编程

5.1 串口编程界面

(1)主要包括串口设置和注册新卡的功能界面 ,实现串口选择、读取卡片和写入卡片信息的功能: 串口界面.png

(2)功能效果实现


串口调试.gif

5.2 使用串口调试工具实现数据传输

(1)在下拉列表中列出本机所有串口

// TODO: 在下拉列表中列出本机所有串口
            string[] ports = SerialPort.GetPortNames();//获取计算机可用串口
            if (ports.Length > 0)//有可用串口
            {
                comboBoxCOMList.Items.AddRange(ports);//添加到下拉列表
                comboBoxCOMList.SelectedIndex = 0;//默认选择第一项
            }

(2)初始化串口参数

// TODO: 初始化串口参数
                serialPort1.BaudRate = 115200;//波特率115200
                serialPort1.DataBits = 8;
                serialPort1.Parity = Parity.None;
                serialPort1.StopBits = StopBits.One;

(3)将待发送数据发送出去

 // TODO: 将`待发送数据`发送出去
               string sendContent = this.tbWrite.Text.ToString();
                this.serialPort1.Write(sendContent);
                MessageBox.Show("已发送数据!");

(4)接收数据,并在接收数据区域显示出来

// TODO: 接收数据,并在接收数据区域显示出来

                Control.CheckForIllegalCrossThreadCalls = false;

                string str = serialPort1.ReadExisting().ToString();
                tbRead.Text = str;

(5)清空接收区域

// TODO: 清空接收区域
            tbRead.Text = "";

6、考勤系统功能实现——打卡

6.1 主要代码

private void Form1_Load(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();//获取计算机可用串口
            if(ports.Length > 0)//有可用串口
            {
                comboBoxCOMList.Items.AddRange(ports);//添加到下拉列表
                comboBoxCOMList.SelectedIndex = 0;//默认选择第一项
            }

            comboBoxHandle.SelectedIndex = 0;
        }

        private void InitSerialPort()//初始化串口
        {
            serialPort1.BaudRate = 115200;//波特率115200
            serialPort1.DataBits = 8;
            serialPort1.Parity = Parity.None;
            serialPort1.StopBits = StopBits.One;
            serialPort1.ReceivedBytesThreshold = 1;
        }

7、考勤系统功能实现——查询

7.1 界面展示

7.1.1 员工登陆查询后的界面

员工查询.gif

7.2 主要代码

连接数据库;构造命令发送给数据库

// 连接数据库
                sqlConn.Open();

                // 构造命令发送给数据库
                String sqlStr = "select * from record where date>=@start and date<=@end and s_id = @id";
                SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);

                cmd.Parameters.Add(new SqlParameter("@start", this.start.Value.ToShortDateString()));
                cmd.Parameters.Add(new SqlParameter("@end", this.end.Value.ToShortDateString()));
                cmd.Parameters.Add(new SqlParameter("@id", UserInfo.userId));



                SqlDataAdapter adp = new SqlDataAdapter();

                adp.SelectCommand = cmd;

将DataSet和DataAdapter绑定

                // 将DataSet和DataAdapter绑定
                DataSet ds = new DataSet();

自定义一个表(MyGoods)来标识数据库的GOODS表

                // 自定义一个表(MyGoods)来标识数据库的GOODS表
                adp.Fill(ds, "MyGoods");

指定DataGridView的数据源为DataSet的MyGoods表

                // 指定DataGridView的数据源为DataSet的MyGoods表
                this.dgv_Goods.DataSource = ds.Tables["MyGoods"];

8、考勤系统功能实现——统计

8.1 界面展示

8.1.1 管理员界面

管理员界面

8.1.2 考勤统计

考勤统计

8.1.3 部门迟到早退名单统计结果界面

营销部迟到统计

8.2 主要代码

(1)构造命令,统计一个部门中有哪些员工工作时间不满540分钟

//构造命令,统计一个部门中有哪些员工工作时间不满540分钟
                string sqlStr = @"select t4.par, COUNT(*) as count from
            (
                

              select t3. *,t.name,t.par from  
(
          select t1.s_id,t1.date,datediff(n,t1.time,t2.time) as diff from record t1
          inner join record t2
          on t1.date=t2.date
          and t1.s_id=t2.s_id
          and t1.p_id=1
          and t2.p_id=2
          and t1.date>=@start
          and t1.date<=@end
          )t3,staff t where t3.s_id=t.id
          )t4 where t4.diff<540 group by t4.par";

(2)添加查询条件

                // 添加查询条件
                SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
                cmd.Parameters.Add(new SqlParameter("@start", this.dtp_Start.Value.ToShortDateString()));
                cmd.Parameters.Add(new SqlParameter("@end", this.dtp_End.Value.ToShortDateString()));

(3)将该查询过程绑定到DataAdapte

                // 将该查询过程绑定到DataAdapter
                SqlDataAdapter adp = new SqlDataAdapter();
                adp.SelectCommand = cmd;

(4)将DataSet和DataAdapter绑定

                // 将DataSet和DataAdapter绑定
                DataSet ds = new DataSet();

(5)自定义一个表(MyAttendance)来标识数据库的MyAttendance表

                // 自定义一个表(MyGoods)来标识数据库的MyAttendance表
                adp.Fill(ds, "MyAttendance");

(6)指定DataGridView的数据源为DataSet的MyGoods表

                // 指定DataGridView的数据源为DataSet的MyGoods表
                this.dataGridView1.DataSource = ds.Tables["MyAttendance"];

            }
            catch (Exception exp)
            {
                MessageBox.Show("访问数据库错误:" + exp.Message);
            }
            finally
            {
                sqlConn.Close();
            }

9、考勤系统发布安装

9.1 考勤系统发布安装前的准备

(1)为考勤系统添加图标


1.PNG
添加图标 (2).PNG

(注:主窗体图标需要右键(SuperAttendance),点击属性,找到应用程序中的图标选项。其他的窗体需要变图标则需要在属性中找Icon选项,换上图标)
(2)为管理员主界面添加关于窗体


添加关于窗体.PNG
添加关于窗体 (2).PNG
添加关于窗体 (3).PNG

9.2 安装流程及效果实现

发布.PNG
发布 (2).PNG 发布 (3).PNG
效果实现图.gif
上一篇下一篇

猜你喜欢

热点阅读