接着进入【开发管理】,配置一下服务器出口 IP。这个 IP 指的是我们调用钉钉 API 的服务器 IP 地址,开发的时候可以填为 127.0.0.1,部署后更换为真实的 IP 地址。
做好这些准备工作,我们就可以获取打卡状态了。获取打卡状态的 API 如下:
API 地址:${baseURL}/attendance/list
请求方法:POST
这个 API 的请求体是一个对象,对象必须包含的属性如下:
- workDateFrom:查询考勤打卡记录的起始工作日。
- workDateTo:查询考勤打卡记录的结束工作日。
- userIdList:查询用户的用户 ID 列表。
- offset:数据起始点,用于分页,传 0 即可。
- limit:获取考勤条数,最大 50 条。
这里的字段解释一下。workDateFrom 和 workDateTo 表示查询考勤的时间范围,因为我们只需要查询当天的数据,因此事件范围就是当天的 0 点到 24 点。
userIdList 就是我们上一步取到的所有组员的 userid 列表。
将获取打卡状态写为一个单独的方法,代码如下:
const dayjs = require('dayjs');
const access_token = new DingToken().get();
// 获取打卡状态
const getAttendStatus = (userIdList) => {
let params = {
access_token,
};
let body = {
workDateFrom: dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss'),
workDateTo: dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss'),
userIdList, // userid 列表
offset: 0,
limit: 40,
};
return axios.post(`${baseURL}/attendance/list`, body, { params });
};
查询考勤状态的返回结果是一个列表,列表项的键字段如下:
- userId:打卡人的用户 ID。
- userCheckTime:用户实际打卡时间。
- timeResult:用户打卡结果。Normal:正常,NotSigned:未打卡。
- checkType:考勤类型。OnDuty:上班,OffDuty:下班。
其他更多字段的含义请参考:https://open.dingtalk.com/document/orgapp-server/open-attendance-clock-in-data
上面的 4 个字段可以轻松判断出谁应该打卡,打卡是否正常,这样我们就能筛选出没有打卡的用户,对这些未打卡的用户精准提醒。
筛选打卡状态分为两种情况:
- 上班打卡
- 下班打卡
上下班打卡要筛选不同的返回数据。假设获取的打卡数据存储在变量 attendList 中,获取方式如下:
// 获取上班打卡记录
const getOnUids = () =>
attendList
.filter((row) => row.checkType == 'OnDuty')
.map((row) => row.userId);
// 获取下班打卡记录
const getOffUids = () =>
attendList
.filter((row) => row.checkType == 'OffDut')
.map((row) => row.userId);
获取到已打卡的用户,接着找到未打卡用户,就可以发送通知提醒了。
4. 发送提醒通知在钉钉中最常用的消息推送方式是:在群聊中添加一个机器人,向这个机器人的 webhook 地址发送消息,即可实现自定义推送。
还是进入前面创建的 H5 应用,在菜单中找到【应用功能 -> 消息推送 -> 机器人】,根据提示配置好机器人。
创建好机器人后,打开组员所在的钉钉群(已有群或新建群都可)。点击【群设置 -> 智能群助手 -> 添加机器人】,选择刚才创建的机器人,就可以将机器人绑定在群里了。
绑定机器人后,点击机器人设置,会看到一个 Webhook 地址,请求这个地址即可向群聊发送消息。对应的 API 如下:
API 地址:${baseURL}/robot/send?access_token=xxx
请求方法:POST
现在发送一条“我是打卡机器人”,实现代码如下:
const sendNotify = (msg, atuids = []) => {
let access_token = 'xxx'; // Webhook 地址上的 access_token
// 消息模版配置
let infos = {
msgtype: 'text',
text: {
content: msg,
},
at: {
atUserIds: atuids,
},
};
// API 发送消息
axios.post(`${baseURL}/robot/send`, infos, {
params: { access_token },
});
};
sendNotify('我是打卡机器人');
解释一下:代码中的 atUserIds 属性表示要 @ 的用户,它的值是一个 userid 数组,可以 @ 群里的某几个成员,这样消息推送就会更精准。
发送之后会在钉钉群收到消息,效果如下:
前面几步创建了钉钉应用,获取了打卡状态,并用机器人发送了群通知。现在将这些功能结合起来,写一个检查考勤状态,并对未打卡用户发送提醒的接口。
在路由文件 router/ding.js 中创建一个路由方法实现这个功能:
var dayjs = require('dayjs');
router.post('/attend-send', async (req, res, next) => {
try {
// 需要检测打卡的 userid 数组
let alluids = ["xxx", "xxxx"];
// 获取打卡状态
let attendList = await getAttendStatus(alluids);
// 是否9点前(上班时间)
let isOnDuty = dayjs().isBefore(dayjs().hour(9).minute(0));
// 是否18点后(下班时间)
let isOffDuty = dayjs().isAfter(dayjs().hour(18).minute(0));
if (isOnDuty) {
// 已打卡用户
let uids = getOnUids(attendList);
if (alluids.length > uids.length) {
// 未打卡用户
let txuids = alluids.filter((r) => !uids.includes(r));
sendNotify("上班没打卡,小心扣钱!", txuids);
}
} else if (isOffDuty) {
// 已打卡用户
let uids = getOffUids(attendList);
if (alluids.length > uids.length) {
// 未打卡用户
let txuids = alluids.filter((r) => !uids.includes(r));
sendNotify("下班没打卡,小心扣钱!", txuids);
}
} else {
return res.send("不在打卡时间");
}
res.send("没有未打卡的同学");
} catch (error) {
res.status(error.status || 500).send(error);
}
});
上述接口写好之后,我们只需要调用一下这个接口,就能实现自动检测上班或下班的打卡情况。如果有未打卡的组员,那么机器人会在群里发通知提醒,并且 @ 未打卡的组员。
# 调用接口
$ curl -X POST http://localhost:8080/ding/attend-send
检查打卡状态并提醒的功能实现了,现在还差一个”循环提醒“功能。
循环提醒的实现思路是,在某个时间段内,每隔几分钟调用一次接口。如果检测到未打卡的状态,就会循环提醒。
假设上下班时间分别是上午 9 点和下午 18 点,那么检测的时间段可以划分为:
- 上班:8:30-9:00 之间,每 5 分钟检测一次;
- 下班:18:00-19:00 之间,每 10 分钟检测一次;
上班打卡相对比较紧急,所以时间检测短,频率高。下班打卡相对比较宽松,下班时间也不固定,因此检测时间长,频率低一些。
确定好检测规则之后,我们使用 Linux 的定时任务 crontab 来实现上述功能。
首先将上面写好的 Node.js 代码部署到 Linux 服务器,部署后可在 Linux 内部调用接口。
crontab 配置解析简单说一下 crontab 定时任务如何配置。它的配置方式是一行一个任务,每行的配置字段如下:
// 分别表示:分钟、小时、天、月、周、要执行的命令
minute hour day month weekday cmd
每个字段用具体的数字表示,如果要全部匹配,则用 * 表示。上班打卡检测的配置如下:
29-59/5 8 * * 1-5 curl -X POST http://localhost:8080/ding/attend-send
上面的 29-59/5 8 表示在 8:29 到 8:59 之间,每 5 分钟执行一次;1-5 表示周一到周五,这样就配置好了。
同样的道理,下班打卡检测的配置如下:
*/10 18-19 * * 1-5 curl -X POST http://localhost:8080/ding/attend-send
在 Linux 中执行 crontab -e 打开编辑页面,写入上面的两个配置并保存,然后查看是否生效:
$ crontab -l
29-59/5 8 * * 1-5 curl -X POST http://localhost:8080/ding/attend-send
*/10 18-19 * * 1-5 curl -X POST http://localhost:8080/ding/attend-send
看到上述输出,表示定时任务创建成功。
现在每天上班前和下班后,小工具会自动检测组员的打卡状态并循环提醒。最终效果如下: