说道考勤,不仅仅是人员信息的录入,还有指纹信息的录入。有的公司录指纹,就是打开指纹机,给员工录个指纹,员工的编号基本都是自增上去。而我们的系统显然不会这么做,一个单位1000人,一个个在卡机录入人名和指纹,显然比较慢。因此我们的实现方式是将人员信息先通过web页面录入。然后通过一个同步程序将人员信息同步至考勤机,再让人员过来录入指纹。
ok,先看一下主界面,如下
在列表中我们选择导入本页
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之后,将选中的人员传入另一个界面。
点击导入,将人员信息导入指纹机,看一下导入代码。
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注册后引入我们的项目中。
总共是上面的这些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,看一下这个页面
对于已有人员并且已经录入指纹的,提示成功,对于没有录入指纹的提示失败。
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地址,子网掩码等。
接下来看看导入的人员信息。
OK,关于考勤机同步的逻辑,今天就到这里,再见。
下一篇 如何终止多个Task