社区精选 | 组员老是忘记打卡,我开发了一款小工具,让全组三个月全勤!
今天小编为大家带来的是社区作者 杨成功 的文章,看看他开发的这款有意思的打卡小工具。
大家好,我是杨成功。
我司使用钉钉考勤打卡,人事要求的比较严格,两次未打卡记缺勤一天。但我们组醉心于工作,老是上下班忘记打卡,每月的工资被扣到肉疼。
开始的时候我们都设置了一个打卡闹铃,下班后准时提醒,但有的时候加班,加完班回家又忘记打卡了。还有的时候迷之自信的以为自己打卡了,第二天看考勤记录发现没打卡。
为了彻底解决这个问题,守住我们的钱袋子,我开发了一款打卡提醒工具,让全组连续三个月全勤!
下面介绍一下,这个小工具是如何实现的。
小工具实现思路
首先思考一下:闹铃提醒为什么不能百分之百有用?
机械的提醒
不能重复提醒
检测用户是否打卡,未打卡则提醒,已打卡不提醒。 对未打卡用户循环检测,重复提醒,直到打卡为止。
认识钉钉 API
获取凭证 获取用户 ID 检查打卡状态 群内消息推送 @某人推送
申请开放平台应用
进入 OA 管理后台,选择设置-权限管理-管理组-添加开发者权限下的对应权限。
AppKey AppSecret
搭建服务端应用
|-- app.js // 入口文件
|-- catch // 缓存目录
|-- router // 路由目录
| |-- ding.js // 钉钉路由
|-- utils // 工具目录
| |-- token.js // token相关
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
app.use(bodyParser.json());
app.use(cors());
// 路由配置
app.use('/ding', require('./router/ding'));
// 捕获404
app.use((req, res, next) => {
res.status(404).send('Not Found');
});
// 捕获异常
app.use((err, req, res, next) => {
console.error(err);
res.status(err.status || 500).send(err.inner || err.stack);
});
app.listen(8080, () => {
console.log(`listen to http://localhost:8080`);
});
// router/ding.js
var express = require('express');
var router = express.Router();
router.get('/', (req, res, next) => {
res.send('钉钉API');
});
module.exports = router;
$ node app.js
对接钉钉应用
1. 获取 API 调用凭证
const fetchToken = async () => {
try {
let params = {
appkey: 'xxx',
appsecret: 'xxx',
};
let url = `${baseURL}/gettoken`;
let result = await axios.get(url, { params });
if (result.data.errcode != 0) {
throw result.data;
} else {
return result.data;
}
} catch (error) {
console.log(error);
}
};
var fs = require('fs');
var path = require('path');
var catch_dir = path.resolve(__dirname, '../', 'catch');
class DingToken {
get() {
let res = fs.readFileSync(`${catch_dir}/ding_token.json`);
return res.toString() || null;
}
set(token) {
fs.writeFileSync(`${catch_dir}/ding_token.json`, token);
}
}
var res = await fetchToken();
if (res) {
new DingToken().set(res.access_token);
}
2. 查找组员 ID
let access_token = new DingToken().get();
let params = {
access_token,
};
axios
.post(
`${baseURL}/topapi/v2/user/getbymobile`,
{
mobile: 'xxx', // 用户手机号
},
{ params },
)
.then((res) => {
console.log(res);
});
3. 获取打卡状态
请求方法:POST
workDateFrom:查询考勤打卡记录的起始工作日。 workDateTo:查询考勤打卡记录的结束工作日。 userIdList:查询用户的用户 ID 列表。 offset:数据起始点,用于分页,传 0 即可。 limit:获取考勤条数,最大 50 条。
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:下班。
上班打卡 下班打卡
// 获取上班打卡记录
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. 发送提醒通知
请求方法: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('我是打卡机器人');
综合代码实现
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
上班:8:30-9:00 之间,每 5 分钟检测一次; 下班:18:00-19:00 之间,每 10 分钟检测一次;
crontab 配置解析
// 分别表示:分钟、小时、天、月、周、要执行的命令
minute hour day month weekday cmd
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
$ 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
总结
关注公众号:拾黑(shiheibook)了解更多
赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
- Milvus用于处理输入向量查询的数据库
- TDengine专为物联网而生的大数据平台
- 英镑兑换人民币汇率2024年6月17日
- 卢布汇率人民币2023年12月3日
- 加币兑换人民币汇率2023年10月24日
- 欧元人民币汇率2023年09月02日
- 闲鱼要收软件服务费了:超门槛订单每笔抽成1%
- 计算机视觉能否在一张大图里识别非常小的目标;博客框架推荐;两年半经验的前端,不了解 async 和 await |极客观点
- 赛迪重大课题|《产业科技创新能力建设的路径与对策》顺利通过中期评审
- 5毛钱的降温神器火了,成本仅几分钱,义乌商人月销几百万片
- 这款有趣的应用,Android 比 iPhone 版本强... 9.16 倍?
- 英特尔新任CEO战略出台:扩大产能,抱拥代工
赞助链接