Loading... # 引言 <div class="tip inlineBlock share"> [fixed] BUG:20230104日历存在超出星期日的bug </div> 每天写日报,感觉很烦躁,所以写了个helper ⚠️ 仅在TFS2013测试通过,因为公司用的就是这个版本 # 技术栈 - html css js - jQuery (复用,无需引入) # 功能 - 获取当前月的日报情况,可以直观的看到哪天的日报没有写 - 填写日报时,自动填写一些常规的文本 - 简化项目选择器,通过简称赋值到项目框 - 可以自由拖拽标题栏,以至移动TFS助手窗口的位置 # 截图 ![日报信息](https://www.zunmx.top/usr/uploads/2022/11/2739605993.png) 这里的日报信息来源为页面表格中的信息,通过`document.getElementsByClassName("tbTileContent");`获取到所有人的日报信息,根据姓名筛选出自己的工作报告。 ![显示详细日志](https://www.zunmx.top/usr/uploads/2022/11/3821547583.png) 当鼠标指向日报时,会更加详细的展示那天做了什么。 ![TFS助手缩小](https://www.zunmx.top/usr/uploads/2022/11/3237503671.png) TFS助手缩小时的样子,如果主要目的并不是查看日报历史信息,可以缩小,节省页面空间。 ![日报标题](https://www.zunmx.top/usr/uploads/2022/11/2714959200.png) ![本地日报](https://www.zunmx.top/usr/uploads/2022/11/3281224814.png) 我们公司要求日报格式为【yyyymmdd-内容】所以分割起来就很容易了,我每天有本地记录日报的习惯,因此复制粘贴过来就好 ![项目选择](https://www.zunmx.top/usr/uploads/2022/11/2157365276.png) 在代码中做好映射关系,简称和TFS中的项目关系,在这里输入简称即可 ![自动化填报](https://www.zunmx.top/usr/uploads/2022/11/2581264774.png) 自动把一些改填写的填上,剩下的自己手动添加,或者修改代码,根据标题中的内容智能分析出技术栈 # 难点&解决 <div class="tip inlineBlock info"> 浏览器的CORB(没错,并不是CORS)策略,以至于页面无法注入进来,最后是通过jQuery的load和ajax注入到页面中的。 ```js javascript:$("body").append("<div id = 'inject'></div>");$("#inject").load("http://localhost:89/dayLog/dayLog.html");setTimeout(function(){$.ajax("http://localhost:89/dayLog/dayLog.js")},100); ``` 这里需要一个本地的WEB服务器,nginx,iis,apacheHttp都可以,因为TFS助手只用到了原生的js,不需要高级语言的介入,而tfs中默认引入了jQuery,注入后的代码复用了tfs的jQuery。 上面的那段代码放到书签里,在tfs的页面中打开这个书签,就可以注入到页面中了。 当然, 注意端口号。 </div> # 代码 ```html <!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()`写入内容,因此只能出此下策。 ```Javascript 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每打开一次就会变化,我感觉只能这么做了。 以上 睡觉 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏