注册
web

给自己编写一个批量填写日报的工具

背景


公司要求我们每天填写工时,每天的时间都花在了哪些地方,干了什么。平时没顾得上填,欠下了一屁股工时债。收到邮件催填通知后,发现要补两个月的工时,填了一会儿,感觉变化的只是日期和工作内容,其它的内容项都是固定内容。一天一天填着实费劲,于是决定写一个填写日报的小工具,只要在js文件中,补充一下每天的工作内容,然后执行node命令,批量完成工时的填写。


思路



  1. 先根据设置的起始结束时间,查询一下当月有多少个工作日,要补多少天的工时。要排除当月每周周末,法定节假日的日期,加上调休补班的日期。
  2. 根据计算出来的需要补充工时的天数,编辑好要补填的工作内容条数,然后批量发送网络请求,完成工时的填写。

工作日查询实现


发现了一个叫蛙蛙工具的网站,免费提供接口给第三方使用,可以用来查询工作日。每分钟限制查10次。下图是抓取的响应数据:重点说一下要用到的weekend_date_listholiday_date_list字段;



  • weekend_date_list 周末日期
  • holiday_date_list 法定节假日

只要排除这两个数组中的日期,剩下的就是查询日期时间段工作日。


image.png


思路有了,来看看实现。首先要写好发送查询请求的逻辑,要知道请求地址,请求参数,请求参数格式,响应数据内容。其次,拿到响应结果后,生成一个从开始日期到结束日期,格式为YYYY-MM-DD的数组,从这个数组中剔除周末和法定节假日,剩余的日期就是工作日,知道工作日的天数后,就知道要写几天的工作日报。代码如下:


import axios from "axios";
import dayjs from "dayjs";
import { startDate,endDate } from "./config.js";


// 查询从本月的工作日
export const queryWorkingDay = () => {
return new Promise((resolve, reject) => {
const url = "https://www.iamwawa.cn/home/workingday/ajax";
const params = {
start_date: startDate.format("YYYY-MM-DD"),
end_date: endDate.format("YYYY-MM-DD"),
};

axios
.post(url, params, { headers: { "Content-Type": "application/x-www-form-urlencoded" } })
.then(({ data: res }) => {
const { status, data, info } = res;
const {
// 平常的周末
weekend_date_list = [],
// 法定节假日
holiday_date_list = [],
// 工作日天数
working_date_count,
} = data;

// console.log(data);

// 生成设置的当月起始结束日期数组
const dayOfMonth = genNumArr(startDate.date(), endDate.date()).map((day) =>
dayjs().date(day).format("YYYY-MM-DD")
);

// 需要排除的法定节假日和周末日期
const excludeDays = [
weekend_date_list.map((item) => item.date),
holiday_date_list.map((item) => item.date),
].flat();

// 工作日
const workDays = dayOfMonth.filter((day) => !excludeDays.includes(day));

// console.log(status,data,info);
console.log(`本月你需要补充${working_date_count}天日报`);
console.log(`需要填写的日期:`);
workDays.forEach((day) => {
console.log(day);
});

console.log(`需要排除的日期:`);
excludeDays.forEach((day) => {
console.log(day);
});

resolve(workDays);
});
});
};

// 生成连续数字数组
function genNumArr(start, end) {
return Array.from(new Array(end + 1).keys()).slice(start);
}


提交工时实现


先登录填报工时网站, 手动填写一条,在调试模式下查看一下请求地址和请求参数。
1679728451342.png
请求地址我就不贴出来了,这里只提供思路,请求数据为:


{
"workDate": "2023-03-14",
"tapdId": null,
"groupId": 12,
"projectId": 159,
"lineId": 2,
"taskId": 16,
"workContent": "xxxxxx",
"workHours": 8
}

如法炮制查询工作日的方法,发起工时提交请求,结果吃了闭门羹。提示没有权限。


image.png


后面经过排查,发现网络请求的请求头,需要带一个authorization的参数,服务器根据这个参数判断有没有提交权限。这个参数你必须登录原网站才能拿到,把这个参数复制出来,配置到代码中,再发请求,这次很顺利的提交了。


image.png


提交数据跑通之后,要实现批量提交数据就很Easy了,循环调用提交单条数据的接口就可以了。有个细节需要注意一下,提交请求太快,服务器会返回错误,所以每个请求之间加了一个500ms的延时。提交工时的代码如下:


import axios from "axios";
import { queryWorkingDay } from "./queryDay.js";
import { authorization, workContentList } from "./config.js";

// 提交每月的工时
export const submitMonthWorkHour = async () => {
const workDays = await queryWorkingDay();

for (let index = 0, len = workContentList.length; index < len; index++) {
await submitEachDayData(workDays[index], workContentList[index]);
}
};

/**
* 提交每天的工时数据
* @param {*} workDate 工作日期
* @param {*} workContent 工作内容
*/

const submitEachDayData = (workDate, workContent) => {
return new Promise((resolve, reject) => {
const url = "https://xxx/xxx",
authorization,
"Content-Type": "application/json",
};

const params = {
workDate,
workContent,
tapdId: null,
groupId: 12,
projectId: 159,
lineId: 2,
taskId: 16,
workHours: 8,
};

setTimeout(() => {
axios
.post(url, params, { headers })
.then(({ data }) => {
const { ret, retdata, retmsg } = data;
// if (ret === 0) {
console.log(`${workDate}--${retmsg}`);
resolve("ok");
// }
})
.catch((err) => reject(err));
}, 500);
});
};

主流程实现


在package.json中配置两条指令,一条用于查询设置的起始结束时间有多少个工作日,需要补充多少天的工作日报,接着在上面的submitMonthWorkHour方法中,手动编辑,给工作内容列表workContentList填充数据,一条数据对应一天的工作日报。填写完之后,执行提交命令。


{
"license":"MIT",
"scripts": {
"query": "node main.js query",
"submit": "node main.js submit"
},
"dependencies": {
"axios": "^1.3.4",
"dayjs": "^1.11.7"
},
"type": "module",
"devDependencies": {}
}


顺便说一下,node v9+版本,若要使用import/export语法, 需要在package.json中指定 "type": "module"


在主函数中, 根据不同的指令执行不同的操作。实际使用时, 肯定是要先调用yarn query查询补充多少天日报才行。


import { queryWorkingDay } from "./queryDay.js";
import { submitMonthWorkHour } from "./submitData.js";

main();
// 主流程
function main() {
const argv = process.argv;
// 先查询需要补充多少天日报
if (argv.includes("query")) {
queryWorkingDay();
} else if (argv.includes("submit")) {
submitMonthWorkHour();
} else {
console.log('指令错误');
process.exit(1);
}
}


把配置数据放到config.js中, 这里要说一下dayjs().date()dayjs().daysInMonth(), 它们的执行结果都是一个数字,代表的含义是这个月的日期,默认开始时间是当天日期,结束时间是月底日期。可手动修改。


import dayjs from "dayjs";
// 设置查询工作日的开始时间
export const startDate = dayjs().set("date", dayjs().date());
export const endDate = dayjs().set("date", dayjs().daysInMonth());
// 每次先登录一下填报工时的网站,把http请求头中的authorization复制出来
export const authorization = "";
// 手动填写需要补充的工时
export const workContentList = [""];

结语


至此,批量提交日报的小工具就开发完了。爱因斯坦说, 比知识更重要的是想象力。文中列举的知识点大家可能都懂,但是要把这些知识串接起来,开发一个有实用价值的工具,是需要一点灵动和想象力的。而灵动来源于优化意识,需要一个善于发现问题的心灵,洞悉生活中,工作中的痛点,寻找改进之法。 这个小工具已上传至码云,感兴趣的朋友可点击这里下载


作者:去伪存真
来源:juejin.cn/post/7214349925064802362

0 个评论

要回复文章请先登录注册