自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

讓打卡小工具"智能一點(diǎn)”:添加請(qǐng)假過(guò)濾、Token自動(dòng)刷新

開(kāi)發(fā) 前端
本篇介紹了釘釘打卡小工具兩個(gè)方面的優(yōu)化,還有配置部分的代碼我也做了精簡(jiǎn),可以更快的接入自己的釘釘應(yīng)用。

大家好,我是楊成功。

前面寫(xiě)了一篇文章,介紹了如何用 Node.js + 釘釘 API 實(shí)現(xiàn)考勤打卡連續(xù)提醒的小工具。

有的同學(xué)留言說(shuō)為什么不直接調(diào)用釘釘 API 自動(dòng)打卡(這個(gè)我也想過(guò))??上曳榱酸斸?shù)奈臋n都沒(méi)有找到這個(gè) API。

再說(shuō)了,怎么可能有這個(gè) API 呢?想啥呢?

還有的同學(xué)嚴(yán)厲的指出了問(wèn)題:“我請(qǐng)假了你還一直提醒?token 用幾個(gè)小時(shí)就過(guò)期!”。

針對(duì)這兩個(gè)問(wèn)題,我們?cè)谏洗螌?shí)現(xiàn)代碼的基礎(chǔ)上進(jìn)行優(yōu)化,添加兩個(gè)邏輯:

  1. 獲取未打卡的人員時(shí),過(guò)濾已請(qǐng)假人員。
  2. 當(dāng) token 過(guò)期時(shí),自動(dòng)刷新 token。

接下來(lái)我們一起實(shí)現(xiàn)新增的需求,優(yōu)化打卡功能。

過(guò)濾已請(qǐng)假人員

使用釘釘 API 可以獲取一些人員的打卡狀態(tài)。

目前我們的做法是,將需要檢測(cè)打卡狀態(tài)的人員(我們?nèi)M人員)的 userid 維護(hù)在一個(gè)列表中,然后獲取到這些人的打卡數(shù)據(jù),從而篩選出未打卡的人員。

特殊情況是,假設(shè)我們組的一個(gè)組員今天請(qǐng)假了,他會(huì)被當(dāng)作未打卡人員不斷地被提醒,這是不合理的。

其實(shí)我們應(yīng)該將已請(qǐng)假的人員排除在外。要實(shí)現(xiàn)這個(gè),第一步是要獲取今日已請(qǐng)假的人員。

獲取請(qǐng)假狀態(tài)的 API 如下:

API 地址:${baseURL}/topapi/attendance/getleavestatus。

請(qǐng)求方法:POST。

這個(gè) API 的請(qǐng)求體是一個(gè)對(duì)象,對(duì)象的屬性如下:

  • userid_list:查詢請(qǐng)假狀態(tài)的 userid 列表。
  • start_time:查詢開(kāi)始時(shí)間(當(dāng)天上班時(shí)間)。
  • end_time:查詢結(jié)束時(shí)間(當(dāng)天下班時(shí)間)。
  • size:返回條數(shù),最大 20。
  • offset:分頁(yè),從 0 開(kāi)始。

將獲取請(qǐng)假狀態(tài)寫(xiě)為一個(gè)單獨(dú)的方法,代碼如下:

const dayjs = require('dayjs');
const access_token = new DingToken().get();
// 獲取請(qǐng)假狀態(tài)
const getLeaveStatus = async (userid_list) => {
let params = {
access_token,
};
let body = {
start_time: dayjs().startOf('day').valueOf(),
end_time: dayjs().endOf('day').valueOf(),
userid_list: userid_list.join(), // userid 列表
offset: 0,
size: 20,
};
let res = await axios.post(`${baseURL}/topapi/attendance/getleavestatus`, body, { params });
if (res.errcode != 0) {
return res;
} else {
return res.result.leave_status.map((row) => row.userid);
}
};

執(zhí)行以上方法后,就可以獲取到當(dāng)天已請(qǐng)假的用戶。接著在所有需要檢測(cè)打卡狀態(tài)的用戶列表中,過(guò)濾掉已請(qǐng)假的用戶:

// 需要檢測(cè)打卡的 userid 數(shù)組
let alluids = ['xxx', 'xxxx'];
// 獲取請(qǐng)假狀態(tài)
let leaveRes = await getLeaveStatus(alluids);
if (leaveRes.errcode) {
return leaveRes;
}
alluids = alluids.filter((uid) => !leaveRes.includes(uid));
console.log(alluids); // 過(guò)濾后的 userid 數(shù)組

這樣就不會(huì)對(duì)已請(qǐng)假的用戶發(fā)出提醒了。

釘釘 token 自動(dòng)刷新

在獲取釘釘 API 時(shí),首先要獲取接口調(diào)用憑證(也就是 access_token),每個(gè) API 調(diào)用時(shí)都要攜帶這個(gè)憑證。但這個(gè)憑證是有期限的,有效期一過(guò) API 就會(huì)被禁止調(diào)用。

因此,這里非常重要的一個(gè)優(yōu)化點(diǎn),就是自動(dòng)刷新 access_token。

怎么做呢?其實(shí)和在前端項(xiàng)目中實(shí)現(xiàn)一樣,在 axios 的攔截器中判斷 access_token 是否過(guò)期,如果過(guò)期則重新獲取,然后繼續(xù)執(zhí)行請(qǐng)求。

首先,將獲取憑證寫(xiě)成一個(gè)單獨(dú)的方法,如下:

const fetchToken = async () => {
try {
let params = {
appkey: 'xxx',
appsecret: 'xxx',
};
let url = 'https://oapi.dingtalk.com/gettoken';
let result = await axios.get(url, { params });
if (result.data.errcode != 0) {
throw result.data;
} else {
let token_str = JSON.stringify({
token: result.data.access_token,
expire: Date.now() + result.data.expires_in * 1000,
});
new DingToken().set(token_str);
return token_str;
}
} catch (error) {
console.log(error);
}
};

這個(gè)方法主要是調(diào)用獲取憑證的 API,調(diào)用成功后會(huì)返回 access_token 和有效時(shí)間。這里我們要設(shè)置一個(gè)過(guò)期時(shí)間,就是當(dāng)前時(shí)間+有效時(shí)間,生成一個(gè)過(guò)期時(shí)間的時(shí)間戳:

Date.now() + result.data.expires_in * 1000,

這里還有一個(gè) DingToken 類(lèi)是用于獲取和存儲(chǔ) access_token 的,代碼如下:

var fs = require('fs');
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);
}
}

將 access_token 和過(guò)期時(shí)間組成一個(gè) JSON 字符串存儲(chǔ)到文件中,接下來(lái)就可以在 axios 的請(qǐng)求攔截器中獲取到這個(gè) JSON 數(shù)據(jù),然后判斷當(dāng)前時(shí)間是否大于過(guò)期時(shí)間。

如果是,則重新調(diào)用 fetchToken() 方法生成新 token,并繼續(xù)執(zhí)行請(qǐng)求。攔截器代碼如下:

const axios = require('axios');
const instance = axios.create({
baseURL: 'https://oapi.dingtalk.com',
timeout: 5000,
});
const dingToken = new DingToken();
// 請(qǐng)求攔截器
instance.interceptors.request.use(async (config) => {
if (!config.params.access_token) {
let catoken = {};
if (dingToken.get()) {
catoken = JSON.parse(dingToken.get());
// 判斷是否過(guò)期
if (Date.now() - catoken.expire >= 0) {
console.log('釘釘 token 過(guò)期');
await fetchToken();
catoken = JSON.parse(dingToken.get());
}
} else {
// 第一次獲取token
await fetchToken();
catoken = JSON.parse(dingToken.get());
}
// 將 token 攜帶至請(qǐng)求頭
config.params.access_token = catoken.token;
}
return config;
});

通過(guò)上面在攔截器中編寫(xiě)的邏輯,我們就不需要關(guān)心 access_token 過(guò)期了。并且我們是在 token 過(guò)期之后才會(huì)重新請(qǐng)求,因此也不會(huì)觸發(fā)調(diào)用頻率限制。

總結(jié)

本篇介紹了釘釘打卡小工具兩個(gè)方面的優(yōu)化,還有配置部分的代碼我也做了精簡(jiǎn),可以更快的接入自己的釘釘應(yīng)用。

責(zé)任編輯:姜華 來(lái)源: 程序員成功
相關(guān)推薦

2009-12-08 14:02:25

Windows 7小工

2022-06-08 12:10:56

canvasvue.js

2009-11-19 08:48:10

Windows 7桌面工具

2016-09-01 08:36:27

Windows 10離線小工具

2022-12-28 12:29:45

duf命令

2017-07-25 14:20:13

戴爾配置功耗

2019-01-27 22:09:33

智能海灘物聯(lián)網(wǎng)工具物聯(lián)網(wǎng)

2022-09-01 09:56:14

工具通訊軟件API

2024-04-03 15:27:31

Python接口自動(dòng)化開(kāi)發(fā)

2010-07-01 10:24:30

UML小工具

2023-04-26 01:21:34

工具URL地址

2021-11-05 06:57:50

架構(gòu)工具代碼

2011-11-30 16:31:00

TimZon

2023-12-20 07:41:41

2011-03-10 09:03:35

Python

2022-03-30 15:11:26

Python房?jī)r(jià)工具

2012-03-15 10:32:05

Windows系統(tǒng)網(wǎng)絡(luò)故障

2016-04-05 10:12:58

HiveSQLHadoop

2022-01-17 06:27:28

Windows 11操作系統(tǒng)微軟

2009-07-07 08:49:33

微軟Windows 7新功能
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)