2019年02月17日 15:44
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

说道考勤,不仅仅是人员信息的录入,还有指纹信息的录入。有的公司录指纹,就是打开指纹机,给员工录个指纹,员工的编号基本都是自增上去。而我们的系统显然不会这么做,一个单位1000人,一个个在卡机录入人名和指纹,显然比较慢。因此我们的实现方式是将人员信息先通过web页面录入。然后通过一个同步程序将人员信息同步至考勤机,再让人员过来录入指纹。

ok,先看一下主界面,如下

QQ截图20190217145837.jpg

在列表中我们选择导入本页

 private void btn_ImportPage_Click(object sender, EventArgs e)
 {
     if (dg_UserList.Rows.Count == 0)
     {
         this.ShowMessage(Resources.Msg_NoUser);
         return;
     }

     if (!IsUserChecked())
     {
         this.ShowMessage(Resources.Msg_NoUserCheck);
         return;
     }

     var availableUserList = this.GetCheckedUserList();
     if (availableUserList == null || availableUserList.Count == 0)
     {
         this.ShowMessage(Resources.Msg_NoUserCheck);
         return;
     }

     FingerPrintFrm fingerPrintForm = new FingerPrintFrm(axCZKEM1, availableUserList);
     fingerPrintForm.ShowDialog();
 }

经过一系列简单的check之后,将选中的人员传入另一个界面。

QQ截图20190217145702.jpg

点击导入,将人员信息导入指纹机,看一下导入代码。

private void btn_Import_Click(object sender, EventArgs e)
{
    if (userModelList == null || userModelList.Count == 0) return;

    Thread thread = new Thread(new ThreadStart(ProcessUserImport));
    thread.IsBackground = true;
    thread.Start();
}

启动一个后台线程进行导入。

private void ProcessUserImport()
{
    axCZKEM1.EnableDevice(iMachineNumber, false);
    this.Invoke(new RefreshUI(() =>
    {
        this.progress_Import.Maximum = userModelList.Count;

        int processCount = 0;
        foreach (var user in userModelList)
        {
            this.lsb_Msg.Items.Add(string.Concat(user.RealName, " 正在导入......"));
            if (axCZKEM1.SSR_SetUserInfo(iMachineNumber, user.UserName, user.RealName, "", 0, true))
            {
                this.lsb_Msg.Items.Add("导入成功!");
            }
            else
            {
                int errorCode = 0;
                axCZKEM1.GetLastError(ref errorCode);
                this.lsb_Msg.Items.Add("导入失败!错误码:" + errorCode);
            }

            this.progress_Import.PerformStep();
            if (processCount++ % 10 == 0)
            {
                Application.DoEvents();
                Thread.Sleep(1000);
            }
        }
    }));
    axCZKEM1.RefreshData(iMachineNumber);
    axCZKEM1.EnableDevice(iMachineNumber, true);
}

其实到这一步,大家就需要了解中控的SDK去了,需要下载中控考勤机的SDK注册后引入我们的项目中。

image.png

image.png

总共是上面的这些dll,如果仅仅是指纹,用不了这么多dll,因为这里面有USB支持以及人脸识别相关的东西。我们主要是使用zkemkeeper.dll。

再倒导入的时候,我们将指纹机设置处于不可用状态,等同步完成后,在设置其为可用状态。在这里我们主要调用的是SSR_SetUserInfo,

传入了用机器编号,用户名,用户真实姓名等。因为我们需要将指纹机和后台数据库系统联系起来,因此我们这里传入的userName其实是数据库中的主键,通过主键用户信息就会和卡机建立映射关系。

为了区分导入成功和失败,这里对于结果都设置了颜色,成功为绿色,失败为红色。这里展示结果为一个ListBox控件。

private void lsb_Msg_DrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index == -1) return;

    e.DrawBackground();
    if (lsb_Msg.Items[e.Index].ToString().Contains("失败"))
    {
        e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font, new SolidBrush(Color.Red), e.Bounds);
    }
    else if (lsb_Msg.Items[e.Index].ToString().Contains("成功"))
    {
        e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font, new SolidBrush(Color.Green), e.Bounds);
    }
    else
    {
        e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
    }
    e.DrawFocusRectangle();
}

ok,最后看一下认证状态刷新,就是说录入指纹后,我们还需要刷新一下认证状态,通过数据库主键看看指纹机到底有没有这个人的信息。ok,看一下这个页面

QQ截图20190217145735.jpg

对于已有人员并且已经录入指纹的,提示成功,对于没有录入指纹的提示失败。

 private void ProcessIdentityStatus()
 {
     string tempDate = "";
     int templength = 0;
     int flag = 0;
     this.Invoke(new Action(() =>
     {
         this.progress_Status.Maximum = userModelList.Count;
         int processCount = 0;
         int userID;

         axCZKEM1.ReadAllTemplate(iMachineNumber);
         foreach (var user in userModelList)
         {
             userID = int.Parse(user.UserName);
             this.lsb_Msg.Items.Add(string.Concat(user.RealName, " 正在同步......"));

             templength = 0;
             bool suc = axCZKEM1.GetUserTmpExStr(iMachineNumber, user.UserName, 0, out flag, out tempDate, out templength);

             if (suc && !string.IsNullOrEmpty(tempDate))
             {
                 if (this.syncType == SyncType.Family)
                 {
                     var familyEntity = familyRecordService.GetFamilyRecordById(userID);
                     if (familyEntity != null)
                     {
                         familyEntity.Status = (int)IdentifyStatus.Confirmed;
                         familyRecordService.UpdateFamilyRecord(familyEntity);
                         this.lsb_Msg.Items.Add(string.Concat("同步成功!"));
                     }
                 }
                 else
                 {
                     var userEntity = userService.GetUserById(userID);
                     if (userEntity != null)
                     {
                         userEntity.Status = (int)IdentifyStatus.Confirmed;
                         userService.UpdateUser(userEntity);
                         this.lsb_Msg.Items.Add(string.Concat("同步成功!"));
                     }
                 }
             }
             else
             {
                 this.lsb_Msg.Items.Add(string.Concat("同步失败,卡机未录入指纹!"));
             }

             this.progress_Status.PerformStep();
             Application.DoEvents();
             if (processCount++ % 10 == 0)
             {
                 Application.DoEvents();
                 Thread.Sleep(1000);
             }
         }
     }));
 }

这里逻辑就是拿userName即主键去指纹机查找看有没有这个人的指纹GetUserTmpExStr,如果没有则会提示。

不过,开发前一定要连接好指纹机,一根网线插到路由器即可,然后设置好IP地址,子网掩码等。

image.png

接下来看看导入的人员信息。

image.png

OK,关于考勤机同步的逻辑,今天就到这里,再见。

发表评论
匿名  
用户评论
暂无评论