前言
最近不知道为什么换了个考勤系统,上下班用新的系统打卡,有个考勤报表页面没有计算加班时长功能,所以就想自己通过插件实现加班时长,说干就干。
思路
在目标页面注入js,然后抓取页面元素处理数据完成统计。考虑到页面请求数据加载时间,所以不能一开始就将处理数据的js注入页面,不然会找不到元素得不到对应的结果。因此设计在点击插件按钮的时候再注入js到页面执行查询统计逻辑。
实现
1、配置manifest.json,添加permissions 权限配置
{
"name": "My Extension",
"version": "1.0",
"manifest_version": 3,
"description": "This is my first Chrome extension!",
"background": {
"service_worker": "background.js"
},
"action": {},
"permissions": [
"scripting","activeTab"
]
}
2、配置background.js
console.log("background.js");
chrome.action.onClicked.addListener(function(tab) {
chrome.scripting.executeScript({
target : {tabId : tab.id},
files : [ "content.js" ],
})
.then(() => console.log("script injected"));
});
3、配置content.js
var total = 0;
var list = document.getElementsByClassName('fixedDataTableRowLayout_rowWrapper');
for (let index = 1; index < list.length; index++) {
var tempList = list[index].getElementsByClassName('fixedDataTableCellLayout_main');
var a = tempList[1].innerText;
var b = tempList[2].innerText;
var c = tempList[3].innerText;
var cost = 0;
console.log(a + ' ' + b + ' ' + c);
if('--' === b || '--' === c){
console.log('加班时长:' + cost);
continue;
}
var start = new Date(b.slice(0, 11) + '18:30:00').getTime() / 1000;
var restDayFlag = tempList[1].getElementsByClassName('shapeCopy');
if(restDayFlag.length > 0){
start = new Date(b).getTime() / 1000;
}
var end = new Date(c).getTime() / 1000;
cost = (end - start) / 60;
if(cost < 30){
cost = 0;
}
console.log('加班时长:' + cost);
total = total + cost;
}
console.log('加班总时长:' + total);
使用document.getElementsByClassName('fixedDataTableRowLayout_rowWrapper');
查找到报表的每一行数据,然后逐行获取每一个需要的数据进行统计。
主要是使用元素iddocument.getElementById()
、标签名document.getElementsByTagName()
和类名document.getElementsByClassName()
等方法定位找到目标元素。
当然也可以使用JS选择器,语法类似JQuery
var find=function(n){return document.querySelector(n)},
var accountInput=find("#id"),
4、重新加载插件,点击插件查看效果
5、存在问题
不出意外的话这时候就有意外情况了。
用了一段时间后,发现数据较多的时候列表无法全部展示,这时候统计数据会有缺失,想到的第一个办法就是将让列表都展示出来。
摸索了一下页面,发现有个按钮可以调整每行间距,因此打算再查下数据的时候先点击按钮调整行间距。
这时候还有个问题,因为js执行太快的,点击效果还没执行完,下一步元素查下会有问题,所以加入了延迟方法,等待页面效果渲染好在继续执行。
content.js优化后的代码:
var total = 0;
var sleep = function(time){
setTimeout(()=>{
},time);
}
sleep(100);
document.getElementsByClassName('padding-set icon-datatable-setting-normal')[0].click();
sleep(100);
document.getElementsByClassName('padding-set-img-set')[0].click();
sleep(100);
var run = function(){
setTimeout(()=>{
var list = document.getElementsByClassName('fixedDataTableRowLayout_rowWrapper');
for (let index = 1; index < list.length; index++) {
var tempList = list[index].getElementsByClassName('fixedDataTableCellLayout_main');
var a = tempList[1].innerText;
var b = tempList[2].innerText;
var c = tempList[3].innerText;
var cost = 0;
console.log(a + ' ' + b + ' ' + c);
if('--' === b || '--' === c){
console.log('加班时长:' + cost);
continue;
}
var start = new Date(b.slice(0, 11) + '18:30:00').getTime() / 1000;
var restDayFlag = tempList[1].getElementsByClassName('shapeCopy');
if(restDayFlag.length > 0){
start = new Date(b).getTime() / 1000;
}
var end = new Date(c).getTime() / 1000;
cost = (end - start) / 60;
if(cost < 30){
cost = 0;
}
console.log('加班时长:' + cost);
total = total + cost;
}
console.log('加班总时长:' + total);
var study = 1800 - total;
alert('加班总时长:' + total + '\n还要努力:' + study + '\n详情按F12,查看console信息。\nPS:有些浏览器不支持统计未显示数据,因此会缩放页面后统计数据,点击"确定"后还原');
document.getElementsByTagName('body')[0].style.zoom=1;
},400);
}
run();