禅道任务统计(自用)

统计禅道任务的工时

目前為 2023-06-09 提交的版本,檢視 最新版本

// ==UserScript==
// @name         禅道任务统计(自用)
// @namespace    http://tampermonkey.net/
// @version      0.31
// @description  统计禅道任务的工时
// @author       zyb
// @match        http://zentao.ngarihealth.com/index.php?m=my&f=task*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=ngarihealth.com
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // Your code here...

    setTimeout(init, 2000)

    // 初始化函数
    function init() {

        // 数据处理,以便于后续操作
        // 获取需求列表的dom节点,请将每页选项调整到40或更多
        let trListDom = Array.from(document.querySelectorAll('#main #mainContent tbody tr')) || [];
        // 任务需求数组
        let requirementsList = trListDom.map(itemDom => {
            // id
            const id = itemDom.querySelectorAll('.c-id')[0].querySelectorAll('.checkbox-primary input')[0].value;
            // 预计开始日期
            const dateStr = itemDom.querySelectorAll('td:nth-child(6)')[0].innerText || '';
            // 预计工时
            const estimateTime = +itemDom.querySelectorAll('td:nth-child(10)')[0].innerText || 0;
            // 消耗工时
            const consumeTime = +itemDom.querySelectorAll('td:nth-child(11)')[0].innerText || 0;

            return { dateStr, estimateTime, consumeTime, id }
        }) || [];

        // 处理异步请求,兼容不需要请求接口的数据
        const promiseList = requirementsList.map(async (item) => {
            let promise;
            if (!item.dateStr) {
                // item.dateStr为空,表示是被分配的需求

                // 设置请求的url
                let url = `http://zentao.ngarihealth.com/index.php?m=task&f=view&taskID=${item.id}`
                // 将异步请求转为同步,目的是减少服务器压力,以免被检测后封锁ip
                promise = await ajaxAsyncFuc({ url });

            } else {
                // item.dateStr不为空,表示是自己创建的需求,不需要额外调用接口获取日期

                // 新建Promise对象,返回值为空
                promise = await new Promise((resolve, reject) => {
                    resolve();
                })
            }

            return { data: promise, object: item };

        })

        // 等待所有请求完成后,对不同月份的数据进行处理
        Promise.all(promiseList).then(res => {
            // 是否统计被分配的需求的工时标识
            let tipsFlag = true;

            // 处理完后存储的数据
            let dataForMonthObj = {
                // 本月的月份
                nowMonthStr: '',
                // 本月预计工时
                estimateTime: 0,
                // 本月实际消耗工时
                consumeTime: 0,
                // 上个月的月份
                preMonthStr: '',
                // 上个月预计工时
                preEstimateTime: 0,
                // 上个月实际消耗工时
                preConsumeTime: 0,
                // 这周消耗的工时
                thisWeekConsumeTime: 0,
                // 上周消耗的工时
                lastWeekConsumeTime: 0,
            };

            // 遍历返回值
            res.map(item => {
                let obj = {};

                if (item.data) {
                    // data字段有数据,说明是被分配的需求

                    // 创建一个div的Dom节点,将接口返回的HTML字符串转为Dom节点
                    let div = document.createElement('div');
                    div.innerHTML = item.data;
                    const trDom = div.querySelectorAll('#legendLife tbody tr:nth-child(2)')[0];
                    const value = trDom.querySelectorAll('td')[0].innerText || '';
                    // 创建正则规则,匹配yyyy-MM-dd或yyyy/MM/dd时间格式
                    const regex = /\d{4}[-/]\d{2}[-/]\d{2}/g;

                    obj = {
                        ...item.object,
                        // 截取符合正则规则的字符串,即任务日期
                        dateStr: value.match(regex) && value.match(regex)[0] || '',
                    };

                    // data字段有数据,说明是被分配的需求,所以不需要提示文案
                    tipsFlag = false;

                } else {
                    // data字段无数据,说明是自己创建的需求

                    obj = { ...item.object };
                }

                // 日期处理
                // 本月的月份
                let nowMonth = new Date().getMonth() + 1;
                // 上个月的月份
                let previousMonth = (nowMonth === 1) ? 12 : (nowMonth - 1);
                // 本周周一的日期
                let mondayDate = new Date().getLastWeekday();
                // 上周一的日期
                let lastMondayDate = new Date(mondayDate.getTime() - 1000).getLastWeekday();


                // 如果dateStr为空,说明此任务还没完成
                if (obj.dateStr) {

                    // 当前数据的开始时间
                    let date = new Date(obj.dateStr);
                    // 当前数据的开始时间月份
                    let month = date.getMonth() + 1;

                    // 如果是本月数据
                    if (month === nowMonth) {
                        dataForMonthObj.nowMonthStr = month;
                        dataForMonthObj.estimateTime += obj.estimateTime;
                        dataForMonthObj.consumeTime += obj.consumeTime;
                    }
                    // 如果是上月数据
                    if (month === previousMonth) {
                        dataForMonthObj.preMonthStr = month;
                        dataForMonthObj.preEstimateTime += obj.estimateTime;
                        dataForMonthObj.preConsumeTime += obj.consumeTime;
                    }

                    // 如果是这周的数据
                    if (date.getTime() > mondayDate.getTime()) {
                        dataForMonthObj.thisWeekConsumeTime += obj.consumeTime;
                    }
                    // 如果是上周的数据
                    if (date.getTime() < mondayDate.getTime() && date.getTime() > lastMondayDate.getTime()) {
                        dataForMonthObj.lastWeekConsumeTime += obj.consumeTime;
                    }
                }


                return obj
            })
            // 将处理完的数据显示到页面上
            setDivValueFuc(dataForMonthObj, tipsFlag);
        });

    }

    // 将处理完的数据显示到页面上
    function setDivValueFuc(dataForMonthObj, tipsFlag) {
        let mainMenuDom = document.querySelectorAll('#mainMenu')[0];
        let divDom = document.createElement('div');
        divDom.style = 'height:33px;display:flex;align-items: center;padding:10px'
        divDom.innerHTML = `
		  <!--<span>${dataForMonthObj.nowMonthStr}月预计时间:<span style="color:red">${dataForMonthObj.estimateTime}</span>工时;</span>-->
		  <span>${dataForMonthObj.nowMonthStr}月消耗时间:<span style="color:red">${dataForMonthObj.consumeTime}</span>工时;</span>
		  <!--<span>${dataForMonthObj.preMonthStr}月预计时间:<span style="color:red">${dataForMonthObj.preEstimateTime}</span>工时;</span>-->
		  <span>${dataForMonthObj.preMonthStr}月消耗时间:<span style="color:red">${dataForMonthObj.preConsumeTime}</span>工时;</span>
		  <span>上周消耗时间:<span style="color:red">${dataForMonthObj.lastWeekConsumeTime}</span>工时;</span>
		  <span>本周消耗时间:<span style="color:red">${dataForMonthObj.thisWeekConsumeTime}</span>工时;</span>
          ${tipsFlag ? ('<span style="color:red">注意!未统计被分配的需求的工时</span>') : ('<span></span>')}
		`;
        mainMenuDom.appendChild(divDom);

        console.log('dataForMonthObj', dataForMonthObj)
        console.log('estimateTime', dataForMonthObj.estimateTime)
        console.log('consumeTime', dataForMonthObj.consumeTime)
        console.log('preEstimateTime', dataForMonthObj.preEstimateTime)
        console.log('preConsumeTime', dataForMonthObj.preConsumeTime)
    }

    // 发送ajax数据
    async function ajaxAsyncFuc(obj = {}) {
        return new Promise(function (resolve, reject) {
            // 发送数据
            const xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象
            const url = obj.url || ''; // 要访问的URL地址
            const contentType = obj.contentType || 'application/x-www-form-urlencoded'; // 设置请求头
            const type = obj.type || "GET"; // 定义请求方法
            const data = obj.data;

            xhr.open(type, url); // 定义请求方法和URL
            xhr.setRequestHeader('Content-type', contentType); // 设置请求头

            // 处理请求响应
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // console.log(xhr.responseText); // 响应内容将会被打印到控制台
                        resolve(xhr.responseText);
                    } else {
                        reject();
                    }
                }
            }

            // 发送POST请求
            xhr.send(data); // 动态添加请求数据
        })
    }

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址