chrome插件实现页面报表数据统计

322 阅读1分钟

前言

最近不知道为什么换了个考勤系统,上下班用新的系统打卡,有个考勤报表页面没有计算加班时长功能,所以就想自己通过插件实现加班时长,说干就干。

思路

在目标页面注入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();

THE END