文章目录
尝试换一种风格写文章,用别人优秀模板,慢慢形成自己的优雅写作风格。
前言
我和小伙伴在这个假期在一个新场所学习,每天的考勤情况由钉钉打卡机进行统计。
一切看起来总是那么美好…
可是总有各种意外情况导致团队的考勤结果比较糟,比如:打卡机信号不好,扫脸识别打卡统计不上,忘记打卡,中午不回宿舍休息然后就木得打卡各种情况,于是新一款钉钉机器人考勤统计提醒机器人就在构想中诞生了。
一、需要准备什么?
- 开启自定义机器人的钉钉群
- 一个具体钉钉考勤报表统计权限的appkey和appsecret
- springboot,定时任务(我主要学习的是java,其他语言也可以,钉钉文档上十分全面)
- 最好配置redis
二、使用步骤
1.开启自定义群机器人
设置 --> 智能群助手 --> 添加机器人 --> 自定义(通过Webhook接入自定义服务)
安全设置的话可以看自己的需求,我这儿选择了加签
这儿的Webhook和加签密钥需要保存之后调用机器人发送信息的接口就是通过这两个参数
2.使用钉钉开放平台的在线调试
在线调试平台: 钉钉开放平台
这儿我们需要注意的几个接口请求:
1、获取企业内部应用的access_token
2、获取用户所在的分组群的部门用户详情 :
主要是获取userid和姓名,userid用来改用户考勤统计查询,姓名主要是向外展示,这儿为了避免频繁调用接口,优化筛选速度,使用的redis存储,只查询了一次。
3、考勤统计,获取报表列自定义,方便我们直接获取到某一个考勤数据。
4、获取报表列值
三、代码实现
1.引入第三方钉钉jar包
下载地址:https://developers.dingtalk.com/document/resourcedownload?pnamespace=app
2.测试机器人发送信息是否成功
我们可以自定义各种信息形式发送:查看详情
/*发送信息的接口*/
void createSign(String msg) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, ApiException {
Long timestamp = System.currentTimeMillis();
String secret = ding.getSecret();
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
// System.out.println(sign);
String url = "https://oapi.dingtalk.com/robot/send?access_token="+ ding.getToken() +"×tamp="+ timestamp +"&sign=" +sign;
DingTalkClient client = new DefaultDingTalkClient(url);
OapiRobotSendRequest request = new OapiRobotSendRequest();
request.setMsgtype("text");
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(msg);
request.setText(text);
OapiRobotSendResponse response = client.execute(request);
}
3.获取部门用户userid和name
// 初始化获取用户信息并存到redis中
public void getDepUser(String accessToken) {
// 调用获取部门用户详情的接口
try {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list");
OapiV2UserListRequest req = new OapiV2UserListRequest();
req.setDeptId(492458960L);
req.setCursor(0L);
req.setSize(100L); // 这是一个分页,因为我群人数也就50人所以就不多次处理了
OapiV2UserListResponse rsp = client.execute(req, accessToken);
System.out.println(rsp.getBody());
redisUtils.set("userInfo",rsp.getBody(),-1);
log.info("【userInfo】:{}",rsp.getBody());
} catch (ApiException e) {
e.printStackTrace();
}
}
4.通过在线调试平台获取报表的自定义列
5.获取个人指定时间和批次的考勤数据
// 考勤报表接口(个人信息)
public String getColumnVal(String userid, String columnIdList, String fromDate,String token) {
try {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/getcolumnval");
OapiAttendanceGetcolumnvalRequest req = new OapiAttendanceGetcolumnvalRequest();
req.setUserid(userid);
req.setColumnIdList(columnIdList);
req.setFromDate(StringUtils.parseDateTime(fromDate));
req.setToDate(StringUtils.parseDateTime(fromDate));
OapiAttendanceGetcolumnvalResponse rsp = client.execute(req, token);
// System.out.println(rsp.getBody());
log.info(rsp.getBody());
JSONObject jsonObject = JSON.parseObject(rsp.getBody());
JSONObject jsonObject1 = JSON.parseObject(jsonObject.get("result").toString());
JSONArray jsonObject2 = JSON.parseArray(jsonObject1.get("column_vals").toString());
JSONObject jsonObject3 = JSON.parseObject(jsonObject2.get(0).toString());
JSONArray jsonObject4 = JSON.parseArray(jsonObject3.get("column_vals").toString());
JSONObject jsonObject5 = JSON.parseObject(jsonObject4.get(0).toString());
// System.out.println(jsonObject1);
// System.out.println(jsonObject5.get("value"));
return jsonObject5.get("value").toString();
} catch (ApiException e) {
e.printStackTrace();
return null;
}
}
6.筛选出符合条件的数据
@Override
public List<CardStatus> getDepUserListUpdate() {
// token过期的话获取token
if (!redisUtils.hasKey("token")) accessToken.getAccessToken();
// 如果redis中没有用户信息,则获取用户信息
if (!redisUtils.hasKey("userInfo")) getDepUser(redisUtils.get("token").toString());
List<CardStatus> userUpdate = getUserUpdate();
System.out.println(userUpdate.toString());
List<CardStatus> cardStatuses = new ArrayList<>();
for (CardStatus cardStatus : userUpdate) {
if (!cardStatus.getStatus().equals("正常")) {
cardStatuses.add(cardStatus);
}
}
return cardStatuses;
}
7.调用钉钉机器人发送信息的接口
8.开启定时任务
@Scheduled(cron="0 55 07 * * ?") // 每天7点55分执行一次
@Scheduled(cron="0 05 08 * * ?") // 同上类似
@Scheduled(cron="0 55 13 * * ?")
@Scheduled(cron="0 05 14 * * ?")
@Scheduled(cron="0 55 19 * * ?")
@Scheduled(cron="0 05 20 * * ?")
4、实现效果
5、最终成果
胜利
6、存在的问题
1、没有关联请假的数据(自定义获取到的报表列中有,娱乐时间写来玩的,就没有太严格)
2、周日freetime空闲时间没有考虑(数据筛选可以多加层空判断或者改变定时任务的执行)
7、代码仓库
gitee地址:https://gitee.com/mfei8/dingding/tree/develop/
总结
团队中每一个人的表现都影响着整个团体,纪律的保持得益于每个人的努力,当遇到问题解决困难的地方时,不妨换一个思路,利用现有的资源让大家乐于改善配合,其实忘记打卡往往相互提醒一句的事情,这个方法就是让大家有条件相互提醒,开玩笑一句