根据公司的规定,每月八小时,弹性工作制。所以大家平时来的不太准时,如果有事,下班也就早些回去了。所以一个月下来工作时间可能不够,但是公司的考勤日历是这样的:

除了请假和法定节假日外,其他样式显示都是一样的,每次都要一个个估算这个月的大概工作时间,十分不方便。后来看到公司有人在用一个Chrome扩展程序,可以计算出一个月的工作时间,但是我觉得还是没有看到我想看的东西,因为除了每个月的累计工作时间外,我还想看到:平均每天工作时长、每一天的工作时长、20点以后的天数(20点以后下班的可以报销晚饭的,哈哈……)、22点以后下班的天数(报销打车费)……所以我决定还是自己写一个吧。

  第一步,我先写了一个JS方法,然后通过F12开发者工具的Console复制粘贴运行。

  公司用的OA系统没有引用jQuery库,所以我刚开始的想法是想动态引用jQuery类库,如下:

var script = document.createElement("script");
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js";
document.body.appendChild(script);

但是遇到了问题:一个是$被占用,二是HR系统采用iframe嵌套,并且还有frame嵌套,结构很复杂。而console运行的代码是在最顶层运行的,后期的chrome扩展插件是运行在内部frame中的,可能这里的JS后面不能直接使用。虽然$被占用的问题可以通过jQuery.noConflict();来解决,但是jquery库和原来系统的JS库存在调用顺序的问题,而且在内部的frame中死活访问不到jQuery这个对象。最后我决定放弃使用jQuery,该用原生JavaScript。

JS代码如下:

/*
* author:清明雨上
* date:2016-1-5
*/
var mydate = function() {
//time2-time1
function getTimeDiff(time1, time2) {
var st1 = time1.split(':');
var st2 = time2.split(':');
return ((st2[0] | 0) * 60 + (st2[1] | 0)) - ((st1[0] | 0) * 60 + (st1[1] | 0) * 1);
} var timeList = [];
var mymain = window.parent.frames['Main'].document.getElementById('ctl00_cphMain_CalendarAC');
var listAC = mymain.getElementsByClassName('listAC');
for (var i = 0; i < listAC.length; i++) {
var item = listAC[i];
var t = {};
t.timeSpan = item.getElementsByTagName('td')[1].innerText;
t.remark = item.getElementsByTagName('td')[2].innerText;
timeList.push(t);
}; var totalMin = 0;
var noworkDays = 0; //请假天数
var workDays = 0; //实际上班天数
var workHourEveryday = [];
var no8h = 0; //未满8小时天数
var over20 = 0; //20点以后下班天数
var over21 = 0; //21点以后下班天数
var over22 = 0; //22点以后下班天数
var over23 = 0; //23点以后下班天数
for (var i = 0; i < timeList.length; i++) {
var time = timeList[i];
if (time.remark != '无') {
noworkDays++;
continue;
}
if (time.timeSpan == '无刷卡记录')
continue; var splitTime = time.timeSpan.split('~');
if (splitTime.length == 2) {
//正常上下班
var begin = splitTime[0];
var end = splitTime[1];
var thisMin = getTimeDiff(begin, end);
totalMin += thisMin;
workDays++;
if (thisMin / 60 < 8) {
workHourEveryday.push('<font color="red"><b style="font-size:15px">' + parseInt(thisMin / 60) + '</b>.' + thisMin % 60 + '</font>');
no8h++;
} else {
workHourEveryday.push('<b style="font-size:15px">' + parseInt(thisMin / 60) + '</b>.' + thisMin % 60);
var offworkHour = parseInt(end.split(':')[0]);
if (offworkHour >= 20) {
over20++;
}
if (offworkHour >= 21) {
over21++;
}
if (offworkHour >= 22) {
over22++;
}
if (offworkHour >= 23) {
over23++;
}
}
}
};
var myHour = parseInt(totalMin / 60); //本月工作累计小时数
var otherMin = totalMin % 60; //本月工作出小时部分外的分钟数
var avgHourOneDay = workDays == 0 ? '0.0' : '<b style="font-size:15px">'+(parseInt(myHour / workDays) + '</b>.' + (parseInt((myHour % workDays) * 60 / workDays) + parseInt(otherMin / workDays))); //平均每天工作时长 var html = '<div class="alectest" style="background: #cbebfb;padding:7px;">\
<div>出勤时间:<b style="font-size:15px;color:red">' + myHour + '</b>小时<font color="red">' + otherMin + '</font>分钟(平均<font color="red">' + avgHourOneDay + '</font>小时/天)</div>\
<div>参考时间:' + workDays * 8 + '小时【' + workDays + '天】(除去请假和节假日,实际有打卡记录的天数)</div>\
<div>请假/外出天数:' + noworkDays + '天</div>\
<div>每天工作时间(格式:小时.分钟):' + workHourEveryday.join(',') + '</div>\
<div>未满8小时天数:<b style="font-size:15px">' + no8h + '</b>天</div>\
<div>20点以后下班天数:<b style="font-size:15px">' + over20 + '</b>天</div>\
<div>21点以后下班天数:<b style="font-size:15px">' + over21 + '</b>天</div>\
<div>22点以后下班天数:<b style="font-size:15px">' + over22 + '</b>天</div>\
<div>23点以后下班天数:<b style="font-size:15px">' + over23 + '</b>天</div>\
</div>'
var alectest = mymain.parentNode.getElementsByClassName('alectest');
if (alectest.length > 0) {
// mymain.parentNode.removeChild(alectest[0]);
alectest[0].innerHTML = html;
} else {
var div = document.createElement("div");
div.innerHTML = html;
var fragement = document.createDocumentFragment();
while (div.childNodes[0]) {
fragement.appendChild(div.childNodes[0]);
}
mymain.parentNode.insertBefore(fragement, mymain);
}
bindBtnClick();
}
var bindBtnClick = function() {
window.parent.frames['Main'].document.getElementById('ctl00_cphTop_BtnQuery').addEventListener('click', function() {
var inter = setInterval(function() {
if (window.parent.frames['Main'].document.getElementById('ctl00_cphMain_CalendarAC') &&
window.parent.frames['Main'].document.getElementById('ctl00_UpMaster').style.display == 'none') {
clearInterval(inter);
mydate();
}
}, 500);
}, false);
}
bindBtnClick();

代码说明:监听考勤查询按钮的click事件,考勤信息加载完成后,执行我的JS方法。

  第二步,开发Chrome扩展程序

  参考资料:http://open.chrome.360.cn/extension_dev/content_scripts.html (查询manifest.json的content_scripts节点的各个属性说明)

  manifest.json是必须的,最终内容如下:

{
"manifest_version":2,
"name": "Extension Name",
"version": "0.1.0",
"description": "插件描述",
"icons": { "48": "icon.png" },
"content_scripts": [
{
"all_frames" : true,
"matches": ["http://*"],
"js": ["haha.js"],
"run_at": "document_end"
}
]
}

另外,在同目录下放入一个icon.png图片,至此,所有文件都准备完毕,目录如下:

打开Chrome的扩展程序列表的开发者模式》大包扩展程序...,在扩展程序根目录中输入上面三个文件所在的父目录。

点击【打包扩展程序】即可。

说明:如果点击该按钮长时间未能反映,可以能是你的chrome不允许第三方非认证的扩展程序,解决方案是,点击chrome快捷方式右键》属性》目标输入框后面追加“ enable-easy-off-store-extension-install”,注意前面的空格。

然后再尝试以上步骤就行了。

  第三步,防止Chrome屏蔽非官方扩展程序 设置

  Chrome会提示暂停非官方扩展程序,每次启动就有提示,很烦人。

  查找资料:http://www.itechzero.com/prevent-chrome-shielding-unofficial-extensions-tutorial.html (防止Chrome屏蔽非官方扩展程序教程)

根据以上资料说明,可以轻松解决这个问题。

  

  至此,该可扩展程序全部完成,结果图如下:

  

Google Chrome 扩展程序开发的更多相关文章

  1. 了解Chrome扩展程序开发--摘抄

    了解Chrome扩展程序开发 2018-01-11 边城到此莫若 鸡蛋君说前端 首先,我尝试来用简单几句话描述一下Chrome扩展程序: Chrome扩展主要用于对浏览器功能的增强,它强调与浏览器相结 ...

  2. 解决高版本 Google Chrome 扩展程序强制停用问题 -摘自网络

    1]前往这里下载你喜欢的语言的组策略模板 后缀为.adm (其他的文件自己看 https://docs.google.com/viewer?a=v&pid=sites&srcid=Y2 ...

  3. chrome扩展程序开发

    首先,明确两个概念的区别:chrome扩展程序和Web Apps.具体参考:http://www.chromi.org/archives/10106 本文只讨论chrome扩展程序. 最好的开发教程莫 ...

  4. chrome扩展程序开发之在目标页面运行自己的JS

    大家都知道JS是运行在客户端的,所以,如果我们自己写一个浏览器的话,是一定可以往下载下来的网页源代码中加入js的.可惜我们没有这个能力.不过幸运的是,chrome的扩展程序可以帮我们做到这件事. 本文 ...

  5. chrome扩展程序开发之在目标页面执行自己的JS

    大家都知道JS是执行在client的.所以,假设我们自己写一个浏览器的话.是一定能够往下载下来的网页源码中加入js的.可惜我们没有这个能力.只是幸运的是,chrome的扩展程序能够帮我们做到这件事. ...

  6. 如何将已经安装从chrome扩展程序导出备份为.CRX文件?

    之前介绍过CRX Extractor可以从chrome应用商店下载备份扩展程序,有读者朋友问说:如果 Google Chrome扩展程序已经从 Chrome应用商店下架,还有没有方法下载呢?通常网路上 ...

  7. Chrome扩展程序的二次开发:把它改得更适合自己使用

    我当然知道未经作者允许修改别人程序是不道德的了,但作为学习研究之用还是无可厚非,这里仅供交流. 一切都是需求驱动的 话说某天我在网上猎奇的时候无意间发现这么一款神奇的谷歌浏览器插件:Extension ...

  8. Web 开发人员必备的12款 Chrome 扩展程序

    之前已经分享过一些帮助 Web 开发人员和设计师的 Chrome 扩展,这次我们继续展示一组很有用的 Chrome 应用程序.这些免费的 Chrome 应用程序可以简化您的工作流程,为了加快您的工作流 ...

  9. Chrome浏览器扩展开发系列之一:初识Google Chrome扩展

    1.       Google Chrome扩展简介 Google Chrome扩展是一种软件,以增强Chrome浏览器的功能. Google Chrome扩展使用HTML.JavaScript.CS ...

随机推荐

  1. 关于解决keil4和mdk共存后51不能使用go to definition Of 'XXXXXX'问题

    自己安装keil4和mdk共存后,(我是先安装的keil 后安装的 MDK),在51单片机工程里不能使用go to definition Of 'XXXXXX'问题, 类似的如图 已经困扰了好长时间, ...

  2. 记录js的一些小技巧

    1.取数组最大值,最小值 Math.max.apply(null,[1,2,3,32,3]); Math.min.apply(null,[1,2,3,32,3]); 2.旧版IE setTimeout ...

  3. celery与mangodb搭配应用

    写作背景介绍 在celery简单应用中已经介绍了如何去配置一个celery应用,也知道怎么分离任务逻辑代码与客户端代码了.我们现在的任务是怎么把计算结果保存到数据库中,这种数据持久化是非常重要的.你一 ...

  4. Atitit WebDriver技术规范原理与概念

    Atitit WebDriver技术规范原理与概念 1. Book haosyo ma1 2. WebDriver是W3C的一个标准,由Selenium主持.1 3. WebDriver如何工作 (z ...

  5. atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换

    atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...

  6. Leetcode 231 Power of Two 数论

    同样是判断数是否是2的n次幂,同 Power of three class Solution { public: bool isPowerOfTwo(int n) { ) && ((( ...

  7. windows地址转发

    netsh interface portproxy add v4tov4 listenport=8080 connectaddress=192.168.8.108 connectport=8080 把 ...

  8. 鸡和蛋的OO设计

    一个题目:用类图表示出鸡和蛋的关系. 第一版: 第二版: 一个鸡可以下N个蛋,一个蛋可以浮出0或者1个鸡. 问题是公鸡不会下单,第三版:

  9. java 调用 .net webservice 示例

    String url="http://IP:端口/LisService.asmx"; String methodName="GetLisResultForBlood&qu ...

  10. 内部通信服务Factory(WCF)

    WCF,很好,却又麻烦,很多时候不想用WCF的原因就是:用这个真麻烦... 麻烦的地方,比如: 一堆一堆的服务配置,散落在一个一个的folder下,更新系统时容易出错 客户端除了要知道WCF Cont ...