WinForm调用钉钉获取考勤结果
2021-01-17 06:15
标签:技术 plain check too 结构体 factor one 开发 标识
关注点: 公司前台有个大屏,领导想显示全部员工的考勤结果统计情况和车间的实时监控视频,还有车间的看板。简单说就是把大屏分割成几个区域。现在遇到的难题是钉钉获取考勤结果的api是只有明细记录,比如你公司1000人,那么可能回给你2000条考勤结果。分别是上班考勤和下班考勤的。没有整个公司的,我就需要这么一条数据就行了。但人家没有这样的接口提供。卷起袖子,干! 该接口仅限企业接入使用,用于返回企业内员工的实际打卡结果。比如,企业给一个员工设定的排班是上午9点和下午6点各打一次卡,即使员工在这期间打了多次,该接口也只会返回两条记录,包括上午的打卡结果和下午的打卡结果 请求说明(ISV无调用权限) Https请求方式: POST 1)获取AccessToken 钉钉的服务器很牛X可以并行访问的。但是获取回来的数据集有点乱,其中有个关于分页的参数需要顺序读取,就是“hasMore”还有没有下一页。所以最终没有使用TPL。 2)获取企业总人数 3)获取全体员工的考勤结果 WinForm调用钉钉获取考勤结果 标签:技术 plain check too 结构体 factor one 开发 标识 原文地址:https://www.cnblogs.com/lonelyxmas/p/12204188.html
需求详解
趟坑过程
考勤打卡数据开放
业务场景
考勤打卡数据开放
如果你是ISV(应用服务商,将开发的应用上架到钉钉应用市场,提供给钉钉其他企业用户使用),则无调用权限
如果你是企业内部开发者(将自己公司的HR、OA、客户管理、业务管理等系统接入钉钉),有权限调用
2017-10-16更新:新增用户userId列表参数(userIdList)和分页参数(offset,limit),提升接口稳定性。https://oapi.dingtalk.com/attendance/list?access_token=ACCESS_TOKEN
请求包结构体
{
"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条
}
参数说明
参数
参数类型
必须
说明
access_token
String
是
调用接口凭证
workDateFrom
String
是
查询考勤打卡记录的起始工作日
workDateTo
String
是
查询考勤打卡记录的结束工作日
userIdList
List
是
员工在企业内的UserID列表,企业用来唯一标识用户的字段
offset
Long
是
表示获取考勤数据的起始点,第一次传0,如果还有多余数据,下次获取传的offset值为之前的offset+limit
limit
Long
是
表示获取考勤数据的条数,最大不能超过50条
///
///
///
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
}
效果展示