引言
[fixed] BUG:20230104日历存在超出星期日的bug
每天写日报,感觉很烦躁,所以写了个helper
⚠️ 仅在TFS2013测试通过,因为公司用的就是这个版本
技术栈
- html css js
- jQuery (复用,无需引入)
功能
- 获取当前月的日报情况,可以直观的看到哪天的日报没有写
- 填写日报时,自动填写一些常规的文本
- 简化项目选择器,通过简称赋值到项目框
- 可以自由拖拽标题栏,以至移动TFS助手窗口的位置
截图

这里的日报信息来源为页面表格中的信息,通过document.getElementsByClassName("tbTileContent");获取到所有人的日报信息,根据姓名筛选出自己的工作报告。

当鼠标指向日报时,会更加详细的展示那天做了什么。

TFS助手缩小时的样子,如果主要目的并不是查看日报历史信息,可以缩小,节省页面空间。


我们公司要求日报格式为【yyyymmdd-内容】所以分割起来就很容易了,我每天有本地记录日报的习惯,因此复制粘贴过来就好

在代码中做好映射关系,简称和TFS中的项目关系,在这里输入简称即可

自动把一些改填写的填上,剩下的自己手动添加,或者修改代码,根据标题中的内容智能分析出技术栈
难点&解决
浏览器的CORB(没错,并不是CORS)策略,以至于页面无法注入进来,最后是通过jQuery的load和ajax注入到页面中的。
这里需要一个本地的WEB服务器,nginx,iis,apacheHttp都可以,因为TFS助手只用到了原生的js,不需要高级语言的介入,而tfs中默认引入了jQuery,注入后的代码复用了tfs的jQuery。
上面的那段代码放到书签里,在tfs的页面中打开这个书签,就可以注入到页面中了。
当然, 注意端口号。
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.calendar {
opacity: .99;
z-index: 99999999999999;
border: 2px solid #0066aa;
position: absolute;
display: inline-block;
background-color: rgba(210, 210, 210, .8);
}
.t_head {
border: 1px solid blue;
background-color: #53ace7;
color: white;
}
.t_body {
z-index: 100;
}
.day_div {
width: 80px;
height: 80px;
}
.now_day_div {
text-shadow: 0 0 10px black
}
.dayLog {
z-index: 1000;
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.dayLog:hover {
position: relative;
z-index: 10000;
color: yellow;
font-weight: bold;
background-color: rgba(0, 0, 0, .8);
width: 150px;
border: 3px solid black;
overflow: visible;
word-wrap: normal;
text-overflow: auto;
white-space: normal;
}
</style>
<body>
<div class="calendar">
<div id='title_bar' style="width: 100%; height:25px; background-color: #007acc">
<span style=" font-size:16px; margin-right:8px; cursor:pointer">TFS助手</span>
<span style="float:right; font-size:18px; margin-right:8px; cursor:pointer" onclick="closeDialog()">x</span>
</div>
<div>
<button onclick="getDayLog()">获取日报信息</button>
<button onclick="displayCal()">隐藏/显示日历</button>
<button onclick="setTFS()">自动化填报</button>
</div>
<table class="t_table" style=" display: none;" cellspacing="0" cellpadding="0" border="1">
<tr>
<th class="t_head">星期一</th>
<th class="t_head">星期二</th>
<th class="t_head">星期三</th>
<th class="t_head">星期四</th>
<th class="t_head">星期五</th>
<th class="t_head">星期六</th>
<th class="t_head">星期日</th>
</tr>
<tbody id="data-view">
<tr id="line1"></tr>
<tr id="line2"></tr>
<tr id="line3"></tr>
<tr id="line4"></tr>
<tr id="line5"></tr>
<tr id="line6"></tr>
</tbody>
</table>
<div id="message" style="background-color: #333333;color:darkorange"></div>
</div>
</body>
<script>
try {
$("body")
console.log("[#] 存在jQuery")
}
catch (e) {
console.log("[#] 不存在jQuery")
var oHead = document.getElementsByTagName("HEAD").item(0);
var oScript = document.createElement("script");
oScript.type = "text/javascript";
oScript.src = "dayLog.js";
oHead.appendChild(oScript);
}
</script>
</html>
<!--
最后的存在jQuery与否是为了判断是否在tfs页面,如果不在,就导入dayLog.js,如果存在,也就是在TFS页面中了,注入时不能使用script标签,也不能通过document.write()写入内容,因此只能出此下策。
let dialogMoveFlag = false;
let mousePointX = 0;
let yourName = "姓名"
let mousePointY = 0;
let cal = document.getElementById("data-view")
let point_day = 1;
let data = [
]
let now = new Date()
let now_day = now.getDate();
let template = '<td class="t_body "><div id="day{day}" class="day_div " style="text-align:center"><span >{day}<span></div></td>';
function message(text, code = 1) {
if (code === 1) {
document.getElementById("message").innerHTML = "[#] 信息:" + text;
} else if (code === 0) {
document.getElementById("message").innerHTML = "[x] 错误:" + text;
}
}
function getCountDays() {
let curDate = new Date(now);
var curMonth = now.getMonth();
curDate.setMonth(curMonth);
curDate.setDate(0);
return curDate.getDate();
}
function displayCal() {
obj = document.getElementsByClassName("t_table")[0]
if (obj.style.display == "none") {
obj.style.display = "block"
message("显示日历")
} else {
obj.style.display = "none"
message("隐藏日历")
}
}
function setCol() {
let line = 1;
let isFirst = true;
let finalDayWeek = 0;
if (isFirst) {
let a = new Date(now.setDate(1)).getDay()
if (a == 0) {
for (let i = 0; i < 6; i++) {
document.getElementById("line" + line).innerHTML += '<td ></td>'
}
} else {
for (let i = 0; i < a - 1; i++) {
document.getElementById("line" + line).innerHTML += '<td ></td>'
}
}
}
for (let i = 1; i <= getCountDays(); i++) {
let a = new Date(now.setDate(i)).getDay()
document.getElementById("line" + line).innerHTML += template.replaceAll("{day}", i < 10 ? "0" + i : i);
if (a == 0) {
line++;
}
finalDayWeek = 7 - a
}
for (let i = 0; i < finalDayWeek; i++) {
document.getElementById("line" + line).innerHTML += '<td ></td>'
}
document.getElementById("day" + (now_day < 10 ? "0" + now_day : now_day)).parentNode.className += "now_day_div";
}
function setTFS() {
try {
if ($("input").length < 8) {
message("自动化填报失败,尚未发现输入框", 0)
return 0;
}
let task = prompt("今日任务, 自动拼接年月")
let org = prompt("[简称]-全称\n[[简称]-全称\n[简称]-全称\nnull-自己选择")
switch (org) {
case "*简称*": $("input")[8].value = $("input")[8].title = '*全称*'; break;
case "*简称*": $("input")[8].value = $("input")[8].title = '*全称*'; break;
case "*简称*": $("input")[8].value = $("input")[8].title = '*全称*'; break;
default: break;
}
$("input")[8].focus()
if (task !== null) {
let dateOfNow = new Date()
task = dateOfNow.getUTCFullYear() + "" + (dateOfNow.getMonth() + 1) + task
}
$($("input")[3]).removeClass("watermark")
$("input")[3].value = $("input")[3].title = task
$("input")[3].focus()
$("input")[9].value = $("input")[9].title = '技术栈';
$("input")[9].focus()
$("input")[10].value = $("input")[10].title = 100;
$("input")[10].focus()
$("input")[11].value = $("input")[11].title = 8;
$("input")[11].focus()
$("input")[12].value = $("input")[12].title = 8;
$("input")[12].focus()
$("input")[13].value = $("input")[13].title = 8;
$("input")[13].focus()
$($($("body")[0]).find("iframe")[0]).contents().find('body').get(0).innerHTML = task
let invalidItem = $(".invalid")
for (let i = 0; i < invalidItem.length; i++) {
$(invalidItem[i]).removeClass("invalid")
}
$($($($("body")[0]).find("iframe")[0]).contents().find('body').get(0)).removeClass("invalid")
$($($($("body")[0]).find("iframe")[0]).contents().find('body').get(0)).focus()
message("自动化填报成功")
} catch (e) {
console.error(e)
message("自动化填报失败" + e, 0)
}
}
function setData() {
dayLogItems = document.getElementsByClassName("dayLog")
for (let i = dayLogItems.length - 1; i >= 0; i--) {
dayLogItems[i].parentNode.removeChild(dayLogItems[i])
}
for (let i = 0; i < data.length; i++) {
let day_log_item = data[i].split('-')
let log_day = day_log_item[0].substr(6, 2)
let log_item = day_log_item[1]
document.getElementById("day" + log_day).innerHTML += "<div class='dayLog' id='day_i" + log_day + "'>" + log_item + "</div>"
}
obj = document.getElementsByClassName("t_table")[0]
obj.style.display = "block"
}
title_bar.addEventListener('mousedown', function (e) {
dialogMoveFlag = true;
mousePointX = document.getElementsByClassName("calendar")[0].style.left.replaceAll("px", "") - e.x;
mousePointY = document.getElementsByClassName("calendar")[0].style.top.replaceAll("px", "") - e.y;
// console.log("down", mousePointX, mousePointY)
})
title_bar.addEventListener('mousemove', function (e) {
if (dialogMoveFlag) {
document.getElementsByClassName("calendar")[0].style.left = mousePointX + e.x + "px";
document.getElementsByClassName("calendar")[0].style.top = mousePointY + e.y + "px";
// console.log("move", document.getElementsByClassName("calendar")[0].style.left, document.getElementsByClassName("calendar")[0].style.top)
}
})
document.addEventListener('mouseup', function (e) {
// console.log("up")
dialogMoveFlag = false;
})
function closeDialog() {
document.getElementsByClassName("calendar")[0].style = 'display:none'
}
function getDayLog() {
let b = document.getElementsByClassName("tbTileContent");
data = []
for (let i = 0; i < b.length; i++) {
if (b[i].innerText.indexOf(yourName) == b[i].innerText.length - 2)
data.push(b[i].innerText)
}
data.sort();
setData()
message("重新获取日报信息成功")
}
function init() {
setCol();
}
init()
结语
虽然吧,这个代码很垃圾,我敢肯定有好多css是可以去掉的,js部分有冗余的代码,但是能用,并且效果看起来还不错,肝到了凌晨3点半,不优化了,如果TFS模板有变动,这个助手可能就不太好用了,但是原理是相通的主要是$("input")[n] 这里的n是第几个,算好就行,id每打开一次就会变化,我感觉只能这么做了。
以上
睡觉
评论 0
还没有评论,来说点什么吧。