美文网首页工作生活
考勤系统全生命周期

考勤系统全生命周期

作者: 抹绿茶 | 来源:发表于2019-07-12 14:28 被阅读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

    相关文章

      网友评论

        本文标题:考勤系统全生命周期

        本文链接:https://www.haomeiwen.com/subject/jpvzcctx.html