[点晴永久免费OA]C#获取钉钉考勤机的打卡记录并且解析
					当前位置:点晴教程→点晴OA办公管理信息系统
					
					→『 经验分享&问题答疑 』
					
				 
				
 关注点: 
 需求详解公司前台有个大屏,领导想显示全部员工的考勤结果统计情况和车间的实时监控视频,还有车间的看板。简单说就是把大屏分割成几个区域。现在遇到的难题是钉钉获取考勤结果的api是只有明细记录,比如你公司1000人,那么可能回给你2000条考勤结果。分别是上班考勤和下班考勤的。没有整个公司的,我就需要这么一条数据就行了。但人家没有这样的接口提供。卷起袖子,干! 趟坑过程考勤打卡数据开放业务场景该接口仅限企业接入使用,用于返回企业内员工的实际打卡结果。比如,企业给一个员工设定的排班是上午9点和下午6点各打一次卡,即使员工在这期间打了多次,该接口也只会返回两条记录,包括上午的打卡结果和下午的打卡结果 考勤打卡数据开放请求说明(ISV无调用权限) Https请求方式: POST 
 请求包结构体{    "workDateFrom": "yyyy-MM-dd hh:mm:ss",    "workDateTo": "yyyy-MM-dd hh:mm:ss",    "userIdList":["员工UserId列表"],    // 必填,与offset和limit配合使用,不传表示分页获取全员的数据    "offset":0,    // 必填,第一次传0,如果还有多余数据,下次传之前的offset加上limit的值    "limit":1,     // 必填,表示数据条数,最大不能超过50条}参数说明
 1)获取AccessToken 钉钉的服务器很牛X可以并行访问的。但是获取回来的数据集有点乱,其中有个关于分页的参数需要顺序读取,就是“hasMore”还有没有下一页。所以最终没有使用TPL。 /// <summary> /// 获取AccessToken /// </summary> /// <returns></returns> private AccessToken GetAccessToken() { string URL_GetToken = "https://oapi.dingtalk.com/gettoken?corpid={0}&corpsecret={1}"; string fileName = AppDomain.CurrentDomain.BaseDirectory + "AccessToken.xml"; if (!System.IO.File.Exists(fileName)) { string respon = Program.HttpGetRequest(string.Format(URL_GetToken, Program.CorpId, Program.CorpSecret)); DingTalkRespond obj = JsonConvert.DeserializeObject<DingTalkRespond>(respon); if (obj != null && obj.errcode == 0) { var result = new AccessToken { access_token = obj.access_token, expires_in = GetCurrentTimeStamp() }; SerializerHelper.SerializerToXML(fileName, result); return result; } else return new AccessToken { access_token = obj.access_token, expires_in = GetCurrentTimeStamp() }; } else { var fileResult = SerializerHelper.LoadFromXML<AccessToken>(fileName); long ts = (GetCurrentTimeStamp() - fileResult.expires_in) / 1000; if (ts >= 7200) { string respon = Program.HttpGetRequest(string.Format(URL_GetToken, Program.CorpId, Program.CorpSecret)); DingTalkRespond obj = JsonConvert.DeserializeObject<DingTalkRespond>(respon); if (obj != null && obj.errcode == 0) { fileResult.access_token = obj.access_token; fileResult.expires_in = GetCurrentTimeStamp(); SerializerHelper.SerializerToXML(fileName, fileResult); } } return fileResult; } } 2)获取企业总人数 /// <summary> /// 获取公司总人数 /// </summary> /// <returns></returns> private int GetFactoryEmployeeCount(AccessToken token) { int result = 0; string url = string.Format("https://oapi.dingtalk.com/user/get_org_user_count?access_token={0}&onlyActive=0", token.access_token); string jsonObj = Program.HttpGetRequest(url); var objResult = JsonConvert.DeserializeObject<DingTalkRespond>(jsonObj); if (objResult != null && objResult.errcode == 0) result = objResult.count; return result; } 3)获取全体员工的考勤结果 /// <summary> /// 获取指定页的考勤结果 /// </summary> /// <param name="offset"></param> /// <returns></returns> private void GetAttendance(AccessToken token) { EmployeeAttendanceList.Clear(); string url = string.Format("https://oapi.dingtalk.com/attendance/list?access_token={0}", token.access_token); int offset = 0; bool bHasMore = true; while (bHasMore) { var request = new AttendanceRequest { workDateFrom = DateTime.Now.ToString("yyyy-MM-dd") + " 00:00:00", workDateTo = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), limit = 50, userIdList = null, offset = offset * 50 }; string jsonRequest = JsonConvert.SerializeObject(request).Replace("null", "[]"); string jsonResult = Program.PostJsonData(url, jsonRequest); var objResult = JsonConvert.DeserializeObject<DingTalkRespond>(jsonResult); if (objResult != null && objResult.errcode == 0) { foreach (var item in objResult.recordresult) { if (!EmployeeAttendanceList.Any(a => a.id == item.id)) EmployeeAttendanceList.Add(item); } offset++; bHasMore = objResult.hasMore; } else break; } EmployeeAttendanceList = EmployeeAttendanceList.Where(a => a.checkType == "OnDuty").OrderBy(e => e.id).ToList(); } private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)       {           AccessToken token = GetAccessToken();           GetAttendance(token);           var report = from q in EmployeeAttendanceList                        group q by q.timeResult into g                        select new AttendanceReportItemDTO                        {                            TimeResult = g.Key,                            PersonNumber = g.Count()                        };           BulletinBoardInit();           #region 考勤统计           attendanceReport.Total = GetFactoryEmployeeCount(token);           var normalObj = report.Where(p => p.TimeResult == "正常").FirstOrDefault();           attendanceReport.Normal = normalObj == null ? 0 : normalObj.PersonNumber;           var lateObj = report.Where(p => p.TimeResult == "迟到").FirstOrDefault();           attendanceReport.Late = lateObj == null ? 0 : lateObj.PersonNumber;           var earlyObj = report.Where(p => p.TimeResult == "早退").FirstOrDefault();           attendanceReport.Early = earlyObj == null ? 0 : earlyObj.PersonNumber;           var seriousLateObj = report.Where(p => p.TimeResult == "严重迟到").FirstOrDefault();           attendanceReport.SeriousLate = seriousLateObj == null ? 0 : seriousLateObj.PersonNumber;           var absenteeismObj = report.Where(p => p.TimeResult == "旷工").FirstOrDefault();           attendanceReport.Absenteeism = absenteeismObj == null ? 0 : absenteeismObj.PersonNumber;           int total_temp = report.Sum(p => p.PersonNumber);           var notSignedObj = report.Where(p => p.TimeResult == "未打卡").FirstOrDefault();           attendanceReport.NotSigned = notSignedObj == null ? 0 : notSignedObj.PersonNumber;           attendanceReport.NotSigned = attendanceReport.NotSigned + (attendanceReport.Total - total_temp);           #endregion           #region 判断有没有公告信息           if (BulletinImages != null && BulletinImages.Length > 0)           {               if (BulletinImages.Length == 1)               {                   pbxNotity.Image = Image.FromFile(BulletinImages[0]);               }               if (BulletinImages.Length > 1)               {                   if (notifyShowIndex == BulletinImages.Length - 1)                   {                       notifyShowIndex = 0;                   }                   pbxNotity.Image = Image.FromFile(BulletinImages[notifyShowIndex]);                   notifyShowIndex++;               }           }           else           {               Action task = () =>               {                   BulletinBoardInit();               };               task.BeginInvoke(null, null);               string dir = AppDomain.CurrentDomain.BaseDirectory + "公告栏图片\\";               if (!Directory.Exists(dir))               {                   Directory.CreateDirectory(dir);               }               string[] bgFiles = Directory.GetFiles(dir);               if (bgFiles != null && bgFiles.Length > 0)               {                   int imgIndex = rd.Next(bgFiles.Length);                   pbxNotity.BackgroundImage = Image.FromFile(bgFiles[imgIndex]);               }           }           #endregion       }效果展示
 该文章在 2020/4/27 17:29:27 编辑过  | 
		
			 关键字查询 
				相关文章 
				正在查询...  |