前端Javascript脚本一键获取网页中的表格资源并导出为Excel文件

我们可能会遇到需要把网页中获取的表格资源转成excel下载,部分网站提供的下载内容可能不能满足你的需求,这时候就需要自定义一个网页表格数据下载的方法了。既然是网页资源嘛,我们最简单的考虑还是通过前端的js代码获取资源并下载,并且制作成油猴脚本可以方便他人使用。

思路一:逐页访问获取表格内容下载

这是第一个版本的,需要访问http://219.xx.xx.xx:8081/whoa/Index.aspx,这个表格数据写的比较简单,js代码没有经过匿名化,通过检查会引起数据刷新的按键绑定的点击事件,可以找到js代码里原本写的获取表格数据的方法,这就比较简单了,直接拿来就行了。

整个思路就是模翻页操作,一页页获取表格内容,拼接到一起。

主要遇到的问题是表格数据展示的页面是在一个新的<iframe>中的,网页本身的jquery不能访问,需要通过

    var x = document.getElementById("MFrame");
    var y = (x.contentWindow || x.contentDocument);
    var iJquery = y.jQuery;

的方法获取一个新的局域jquery来进行操作

最终的代码如下,当页面加载完毕后会在左下角放置一个比较隐蔽的start按键,点击后会获取表格所在的MFrame,模拟点击表头对时间进行排序,然后获取总页数,对每一页分别通过loopNext()函数获取内容。由于翻页需要时间,就设置了setInterval()循环去检测当前页页码是否是我们需要的下一页,并且当前的第一个case跟我们缓存的上一页的第一个case不同时才去把这个表的数据加入html字符串,加入的方式在addNewData()函数里,通过map函数实现。

复制代码
// ==UserScript==
// @name         hh1
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  xx
// @author       xx
// @match        http://219.xx.xx.xx:8081/whoa/Index.aspx
// @icon         https://www.google.com/s2/favicons?sz=64&domain=192.76
// @require      https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.5.1.min.js
// @grant        GM_addStyle
// ==/UserScript==
var start_css = ".egg_start_btn{outline:0;border:0;position:fixed;bottom:5px;left:5px;padding:12px 20px;border-radius:10px;cursor:pointer;background-color:#fff0;color:#d2d2d2;font-size:14px;text-align:center}";
GM_addStyle(start_css);
var html = '';
var sheetName = '';
var tmp_case_num = '';
var total_num = 0;
var total_page = 0;
var case_count = 0;
var speed = 5;
const thead = ['课程号', '课程时间', '课程内容'];

$(document).ready(function() {
    let ready = setInterval(function() {
        if (document.getElementsByClassName("m-top-box")[0]) {
            clearInterval(ready); //停止定时器
            //创建"开始"按钮
            createStartButton();
        }
    },
    800);
});

function downloadExcel() {
    // 将table添加到html中,在html中加入excel和sheet元素
    let template = '';
    template += '<html lang="" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel">';
    template += '<head><title></title>';
    template += '<xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>';
    template += '<x:Name>';
    template += sheetName;
    template += '</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions>';
    template += '</x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml>';
    template += '</head>';
    template += '<body><table>';
    template += html;
    template += '</table></body>';
    template += '</html>';

    // 将html编码为excel文件,并下载
    let url = 'data:application/vnd.ms-excel;base64,' + window.btoa(unescape(encodeURIComponent(template)));
    let a = document.createElement('a');
    a.href = url;
    a.download = sheetName + ".xls";
    a.click();
}

function createStartButton() {
    let body = document.getElementsByTagName("body")[0];
    let startButton = document.createElement("button");
    startButton.setAttribute("id", "startButton");
    startButton.innerText = "START";
    startButton.className = "egg_start_btn";
    //添加事件监听
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        startButton.addEventListener("click", start, false);
    } catch(e) {
        try { // IE8.0及其以下版本
            startButton.attachEvent('onclick', start);
        } catch(e) { // 早期浏览器
            console.log("error: 开始按钮绑定事件失败")
        }
    }
    //插入节点
    body.append(startButton);
    console.log(`%ctttttttttttttttttttttttttttttttttttttttfi;i1ttttttttttttttttttttttttttttttffffffffffffffLLLLLLLLLLLLLLLLLL
tttttttttttttttttttttttttttttttttttiiiiiiiii1tttttttttttttttttt1iiiiiiiiii1tffffffft1ffLLfLLLLLLLLLLLLLLLL
ttttttttttttttttttttttttttttttttttt11iiiiii1ttttttffftffftffffftt111111111tffffffffffffLLLLLLLLLLLLLLLLLLL
ttttttttttttttttttttttttttt111tt1ii1ttt1111tfLffffLGCCCLLGLLLLffft1111111tffffffLfLffLLLLLLLLLLLLLLLLLLLLL
ttttttttttttttttttttttttttttt1iiiii1tCLLfftLCCGGi,,:fLGGGGGGGLfttt1111111ttfGLGGLLLLfLLLLLLLLLLLLLLLLLLfLL
ttttttttttttfffffLffffftfttfft11111tf1::::::::::::::::,:::::::;fLLGLt111tLLLGGLL8CGGLLLLLLLLLLLLLLLLLLLLLL`,'color:#aaa;font-size:3px;');//字符画
}

function loopNext(tmp_case_num, next_page, iJquery){
    let timer = setInterval(() =>{
            let case_num = iJquery(".tdlist").data("ordertable").TABLE[0].课程号;
            if (case_num != tmp_case_num && iJquery("#txtPage").val()==next_page) {
                clearInterval(timer);
                tmp_case_num = case_num;
                console.log('Processing...');
                //console.log('Processing for page ' + next_page + '/' + total_page + ' ...');
                let tbody = iJquery(".tdlist").data("ordertable").TABLE;
                case_count += tbody.length;
                addNewData(tbody);
                if (iJquery("#NextPageBtn .btn_disabled").text() == "0") {
                    iJquery(".page-next").click();
                    setTimeout(()=>{
                        loopNext(tmp_case_num, next_page + 1, iJquery);
                    }, 1000 / speed + 100);
                } else {
                    setTimeout(()=>{
                        downloadExcel();
                        console.log("%c一共"+case_count+"/"+total_num+"份课程,请注意核对数量是否正确,内容是否重复!",'color:#ba0707;font-size:20px;font-weight: bold;');
                    }, 1000);
                }
            }
        },
        i * 1000 / speed);
}

function addNewData(tbody) {
    tbody.map(item =>{
        html += '<tr>';
        thead.map(v =>{
            html += '<td style="text-align: center;">';
            html += (item[v] ? item[v] : '') + '\t';
            html += '</td>';
        });
        html += '</tr>';
    });
}

function start() {
    var x = document.getElementById("MFrame");
    var y = (x.contentWindow || x.contentDocument);
    var iJquery = y.jQuery;
    iJquery(".th_td:nth-child(6)").click(); // 寻找对应的表头进行点击排序,排序后翻页才能不重复
    //console.log(iJquery(".tdlist").html());
    total_num = iJquery(".tdlist").data("ordertable").COUNT;
    total_page = iJquery("#AllPageNum").html();

    let time = new Date();
    let Y = time.getFullYear();
    let M = time.getMonth();
    M = (M + 1) < 10 ? '0' + (M + 1) : (M + 1); //这里月份加1的原因是因为月份是从0开始的,0-11月,加1让月份从1-12月区间。
    let d = time.getDate();
    d = d < 10 ? '0' + d: d;
    let h = time.getHours();
    h = h < 10 ? '0' + h: h;
    let m = time.getMinutes();
    m = m < 10 ? '0' + m: m;
    sheetName = Y + "-" + M + "-" + d + "-" + h + "-" + m;

    html = '';
    html += '<tr>';
    thead.map(item => {
        html += '<th>';
        html += item + '\t';
        html += '</th>';
    });
    html += '</tr>';

    case_count = 0;
    tmp_case_num = '';
     $.ajax({
         type : "GET",
         url : 'http://api.tianapi.com/qingshi/index?key=xxxx',
         success : function(poem){
             //console.log(poem_str);
             //let poem = eval("("+poem_str+")"); //'{"code":200,"msg":"success","newslist":[{"content":"离愁渐远渐无穷,迢迢不断如春水。","source":"踏莎行","author":"欧阳修"}]}'
             poem = poem.newslist[0];
             console.log("%c❤❤❤Wish you happy everyday.❤❤❤",'color:#ba0707;text-align: center;font-size:20px;');
             console.log("%c"+poem.content+"\n\t\t\t\t\t%c——"+poem.author+"《"+poem.source+"》",'color:#740505;text-align: center;font-size:20px;','color:#740505;text-align: right;font-size:14px;');
             console.log("Waiting to be arranged in order...");
             setTimeout(()=>{
                 loopNext(tmp_case_num, 1, iJquery);
             },1000);
         },
         error: function (err) {
             console.log("%c❤❤❤You are everything when you are with me, and everything is you when you are not.",'color:#ba0707;font-size:20px;');
             console.log("Waiting to be arranged in order...");
             setTimeout(()=>{
                 loopNext(tmp_case_num, 1, iJquery);
             },1000);
         }
     });
}
思路一的代码
复制代码

 

思路二:根据网页的HTTP请求,模拟请求进行表格内容获取

后来经手了一个新的网页表格下载的需求,由于我不是网页制作的开发人员,无法获取人家的源代码,这个新网页的代码全部都进行了匿名化处理,导致去找按键绑定事件看的也是云里雾里。我就尝试了一个新的方法,通过chrome的http请求记录功能,去尝试模拟其对应的http请求,获取表格数据。

chrome打开http请求记录的方法为

  这样当网页进行了http请求时你就能看到请求的链接。但实际上这个方法看链接也只能看到请求网址,看不到请求载荷(就是?后面跟的参数)

我们可以通过查看chrome的“网络”页面,寻找我们需要的请求的详细参数,其中重要的为

  • 标头:告诉你对应的网址和请求方式,
  • 载荷:告诉你请求的详细参数(点击查看源代码才是原始链接形式),我之前就出过错,模拟请求没有带对应的参数,导致一直报错500,我还说这服务器这么智能识别了我的异常请求
  • 预览:我之前做的是内网的网页的插件,访问内网本身多了步代理的操作,代理的时候请求的方式是OPTION,正常的方式是GET和POST等,这时候就需要通过预览来快速查看正确返回值的网页

那我们在js脚本中如何捕获http请求呢,方法在于修改http请求的函数。比如下面的方式,将console.log()函数通过add()函数加进了http请求中。我们在第6行获取了本次请求的参数之后就可以任意做操作了,在我们这个例子中请求的参数arg是个列表,第一个是请求方式,第二个是请求url,我们可以针对url提取对应的token,为我们所用

复制代码
 1 function XMLHttpRequestBreak(fun=()=>false){
 2     let f = XMLHttpRequest.prototype.open;
 3  
 4     let add = function(){
 5         XMLHttpRequest.prototype.open = function(...args){
 6             check = fun(args);
 7             if(check){
 8                 throw check;
 9             }
10             f.apply(this,args)
11         }
12     };
13  
14     let remove = function(){
15         XMLHttpRequest.prototype.open = f
16     };
17  
18     return {add, remove}
19 }
20  
21 test = XMLHttpRequestBreak(console.log);
22 test.add()
23 test.remove()
复制代码

现在的问题就变得简单了,变为模拟获取数据操作的请求,主要的难点在于处理返回的数据,这里下载了两个表的内容,一个是todo,一个是end。

todo的内容就比较规整,主要是有的手机号中带了星号,需要再次访问一个url获取。

end的内容需要再次访问一个url获取处理的细节,处理的细节json中又有列表,我们将列表中的回复和满意度都用====进行了分割,放在一个单元格进行展示。

其中url请求的max_num是要先模拟一次请求,获取总共有多少个事件,这样比直接设定一个超级大的上限要更科学。

复制代码
// ==UserScript==
// @name         hh2
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  xx
// @author       xx
// @match        http://rafxxx.natappfree.cc/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=192.76
// @require      https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.5.1.min.js
// @grant        GM_addStyle
// ==/UserScript==
var start_css = ".egg_start_btn{outline:0;border:0;position:fixed;bottom:5px;left:5px;padding:12px 15px;border-radius:10px;cursor:pointer;background-color:#fff0;color:#e5eef8;z-index:999;font-size:12px;text-align:center}";
GM_addStyle(start_css);
var html_todo = '';
var html_end = '';
var sheetName = '';
var token = '';
var test = '';
const thead_todo = [
    //'事件ID',
    '事件号', '事件类型名', '规定完成时间', '电话'];
const thead_todo_en = [
    //'id',
    'caseNumber', 'eventType', 'regCompleteTime', 'reportPhone'];
const thead_end = [
    //'事件ID',
    '事件号', '事件类型名', '规定完成时间','经办处室', '实际完成时间', '处理结果', '是否满意'];
const thead_end_en = [
    //'id',
    'caseNumber', 'eventType', 'eventRegCompleteTime'];//handleDeptName,createTime,message,satisfactionType
const http_pre = "http://10.xx.xx.xx:9000/";

function XMLHttpRequestBreak(fun=()=>false){
    let f = XMLHttpRequest.prototype.open;
    let remove = function(){
        XMLHttpRequest.prototype.open = f
    };
    let add = function(){
        XMLHttpRequest.prototype.open = function(...args){
            if (args[0] == "POST"){
                let check = fun(args[1]);
                token = getParams(args[1], 'accessToken');
                if (token){
                    console.log("%cGet ready for token="+token,'color:#ba0707;text-align: center;font-size:20px;');
                    remove();
                }
                if (check){
                    throw check;
                }
            }
            f.apply(this,args);
        }
    };
    return {add, remove};
}


$(document).ready(function() {
    let ready = setInterval(function() {
        if (document.getElementsByClassName("el-container")[0]) {
            //如果找到了这个,就认为加载完毕
            clearInterval(ready); //停止定时器
            //创建"开始学习"按钮
            createStartButton();
            console.log(`%ctttttttttttttttttttttttttttttttttttttttfi;i1ttttttttttttttttttttttttttttttffffffffffffffLLLLLLLLLLLLLLLLLL
tttttttttttttttttttttttttttttttttttiiiiiiiii1tttttttttttttttttt1iiiiiiiiii1tffffffft1ffLLfLLLLLLLLLLLLLLLL
ttttttttttttttttttttttttttttttttttt11iiiiii1ttttttffftffftffffftt111111111tffffffffffffLLLLLLLLLLLLLLLLLLL
ttttttttttttttttttttttttttt111tt1ii1ttt1111tfLffffLGCCCLLGLLLLffft1111111tffffffLfLffLLLLLLLLLLLLLLLLLLLLL
ttttttttttttttttttttttttttttt1iiiii1tCLLfftLCCGGi,,:fLGGGGGGGLfttt1111111ttfGLGGLLLLfLLLLLLLLLLLLLLLLLLfLL`,'color:#aaa;font-size:3px;');//抽象画
        }
    },
    800);
});

function downloadExcel(html,suffix) {
    // 将table添加到html中,在html中加入excel和sheet元素
    let template = '';
    template += '<html lang="" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel">';
    template += '<head><title></title>';
    template += '<xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>';
    template += '<x:Name>';
    template += sheetName + "-" + suffix;
    template += '</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions>';
    template += '</x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml>';
    //html转excel中的\n换行符不管用,需要用<br/>。通过加css,控制<br/>在同一个单元格换行,否则会分割一个单元格。
    template += '<style type="text/css">br {mso-data-placement:same-cell;}</style>';
    template += '</head>';
    template += '<body><table>';
    template += html;
    template += '</table></body>';
    template += '</html>';

    // 将html编码为excel文件,并下载
    let url = 'data:application/vnd.ms-excel;base64,' + window.btoa(unescape(encodeURIComponent(template)));
    let a = document.createElement('a');
    a.href = url;
    a.download = sheetName + "-" + suffix +".xls";
    a.click();
}

function getParams(url, params){
    // 获取url中某个参数的值
      var res = new RegExp("(?:&|/?)" + params + "=([^&$]+)").exec(url);
      return res ? res[1] : '';
}

function createStartButton() {
    let body = document.getElementsByTagName("body")[0];
    let startButton = document.createElement("button");
    startButton.setAttribute("id", "startButton");
    startButton.innerText = "S\nT\nA\nR\nT";
    startButton.className = "egg_start_btn";
    //添加事件监听
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        startButton.addEventListener("click", start, false);
    } catch(e) {
        try { // IE8.0及其以下版本
            startButton.attachEvent('onclick', start);
        } catch(e) { // 早期浏览器
            console.log("error: 开始按钮绑定事件失败")
        }
    }
    //插入节点
    body.append(startButton);
    //监听请求
    test = XMLHttpRequestBreak(console.log);
    test.add();
}

function downloadTodo(){
    let max_num_todo = 2;
    let url_todo = http_pre + "distribute/disEventInfo/toDoList?accessToken="+token+"&boxType=1&pageNumber=1&pageSize="+max_num_todo+"&searchConditionJson=%5B%7B%22";
    console.log(url_todo);
    $.ajax({
         type : "POST",
         url : url_todo,
         success : function(res){
             //{state: true, msg: '', data: Array(2), code: 200, total: 499, …}
             max_num_todo = res.total+88;
             url_todo = http_pre + "distribute/disEventInfo/toDoList?accessToken="+token+"&boxType=1&pageNumber=1&pageSize="+max_num_todo+"&searchConditionJson=%5B%7B%22";
             $.ajax({
                 type : "POST",
                 url : url_todo,
                 success : function(res){
                     //{state: true, msg: '', data: Array(499), code: 200, total: 499, …}
                     let data = res.data;
                     console.log(data);
                     addNewDataTodo(data);
                     //console.log(html_todo);
                     downloadExcel(html_todo,"todo");
                     downloadEnd();
                 },
                 error: function (err) {
                     console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                     console.log(err);
                 },async:false
             });
         },
         error: function (err) {
             console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
             console.log(err);
         },async:false
     });
}

function downloadEnd(){
    let max_num_end = 2;
    let url_end = http_pre + "distribute/disEventInfo/EndList?accessToken="+token+"&pageNumber=1&pageSize="+max_num_end+"&searchConditionJson=%5B%7B%22";
    $.ajax({
         type : "POST",
         url : url_end,
         success : function(res){
             //{state: true, msg: '', data: Array(2), code: 200, total: 1169, …}
             max_num_end = res.total+88;
             url_end = http_pre + "distribute/disEventInfo/EndList?accessToken="+token+"&pageNumber=1&pageSize="+max_num_end+"&searchConditionJson=%5B%7B%22";
             $.ajax({
                 type : "POST",
                 url : url_end,
                 success : function(res){
                     //{state: true, msg: '', data: Array(1169), code: 200, total: 1169, …}
                     let data = res.data;
                     console.log(data);
                     addNewDataEnd(data);
                     //console.log(html_end);
                     downloadExcel(html_end,"end");
                 },
                 error: function (err) {
                     console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                     console.log(err);
                 },async:false
             });
         },
         error: function (err) {
             console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
             console.log(err);
         },async:false
     });
}

function addNewDataTodo(tbody) {
    let count = 1;
    tbody.map(item =>{
        if (count%10 == 0 || count==1|| count==tbody.length){
            console.log("Preparing Todo data: ["+ count +"/"+tbody.length+"]");
        }
        let url_event = http_pre + "distribute/disEventInfo/"+item.id+"?accessToken="+token;//to get reportPhone
        html_todo += '<tr>';
        thead_todo_en.map(v =>{
            html_todo += '<td style="text-align: center;">';
            if (v == 'reportPhone'){
                let phone = item[v];
                if (phone.indexOf("*") != -1){
                    //手机号中存在星号
                    $.ajax({
                        type : "GET",
                        url : url_event,
                        success : function(res){
                            //{state: true, msg: '', data: {reportPhone:"189xx",..}, code: 200}
                            phone = res.data.reportPhone;
                        },
                        error: function (err) {
                            console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                            console.log(err);
                        },async:false
                    });
                }
                if (phone.indexOf(",") != -1) {
                    phone = phone.replaceAll(",","<br/>")
                }
                html_todo += (phone ? phone : item[v]) + '\t';
            }else{
                html_todo += (item[v] ? item[v] : '') + '\t';
            }
            html_todo += '</td>';
        });
        html_todo += '</tr>';
        count++;
    });
}

function CompareDate(d1, d2) {
    //比较日期,d1比d2晚则返回true
    return ((new Date(d1.replace(/-/g, "/"))) > (new Date(d2.replace(/-/g, "/"))));
}


function maxDate(datelist){
    // 接受列表 返回最大日期
    //datelist eg: ['2019-1-2','2019-3-4','2019-5-7']
    var newDateList = datelist.map((x) => new Date(x).getTime());  // 获取Date对象的秒数
    var maxdate = Math.max(...newDateList);  // 获取最大秒数
    var maxdateindex = newDateList.indexOf(maxdate); // 最大秒数索引
    var maxdatestring = datelist[maxdateindex];// 通过索引取出datelist中最大日期字符串
    return maxdatestring;
}

function addNewDataEnd(tbody) {
    let count = 1;
    tbody.map(item =>{
        if (count%10 == 0 || count==1|| count==tbody.length){
            console.log("Preparing End data: ["+ count +"/"+tbody.length+"]");
        }
        let url_dispose = http_pre + "distribute/disDisposeMsgList?accessToken="+token+"&processInstId="+item.processInstId+"&processType="+item.processType+"&businessid="+item.businessId;//to get handleDeptName list, message list, last createTime, last disReviewSituationModels.satisfactionType
        html_end += '<tr>';
        thead_end_en.map(v =>{
            html_end += '<td style="text-align: center;">';
            if (v == 'reportPhone' && item[v].indexOf(",") != -1){
                html_end += item[v].replaceAll(",","<br/>") + '\t';
            }else{
                html_end += (item[v] ? item[v] : '') + '\t';
            }
            html_end += '</td>';
        });
        $.ajax({//获取handleDeptName,createTime, message, satisfactionType
             type : "GET",
             url : url_dispose,
             success : function(res){
                     /*[{
                        "handleDeptName": "精神卫生中心",
                        "message": "尊敬的X先生...",
                        "createTime": "2021-10-12 17:26:36",
                        "disReviewSituationModels": [
                            {
                                "satisfactionType": "1",
                            }
                        ]
                    }, {...}]*/
                let data_list = res.data;
                //console.log(data_list);
                let handleDeptName_list = [];
                let createTime_list = [];
                let message_list = [];
                let satisfactionType_list = [];
                data_list.map(d => {
                    handleDeptName_list.push(d.handleDeptName);
                    createTime_list.push(d.createTime);
                    message_list.push(d.message);
                    let drsm = d.disReviewSituationModels;
                    if (drsm){
                        let dsType = drsm[drsm.length-1].satisfactionType;
                        if(dsType){
                            //值为1
                            satisfactionType_list.push("满意");
                        }else{
                            //值为0或null
                            satisfactionType_list.push(parseInt(dsType)==0?"不满意":"未反馈");
                        }
                    }else{
                        //没有回访记录
                        satisfactionType_list.push("未回访");
                    }
                });
                html_end += '<td style="text-align: center;">';
                let handleDeptNames = handleDeptName_list.join('<br/>=====<br/>');
                html_end += (handleDeptNames ? handleDeptNames : '') + '\t';
                html_end += '</td>';
                html_end += '<td style="text-align: center;">';
                let last_time = maxDate(createTime_list);
                html_end += (last_time ? last_time : '') + '\t';
                html_end += '</td>';
                html_end += '<td style="text-align: center;">';
                let messages = message_list.join('<br/>===========<br/>');
                html_end += (messages ? messages : '') + '\t';
                html_end += '</td>';
                html_end += '<td style="text-align: center;">';
                 let satisfactions = satisfactionType_list.join('<br/>=====<br/>');
                 html_end += (satisfactions ? satisfactions : '') + '\t';
                html_end += '</td>';
             },
             error: function (err) {
                 console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                 console.log(err);
             },async:false
         });
        html_end += '</tr>';
        count++;
    });
}

function start() {
    if (!token){
        console.log("%c!!!请先访问某个事件,获取Token后再点击开始!!!",'color:#ba0707;text-align: center;font-size:20px;');
        return;
    }
    test.remove();
    console.log("Starting!...");

    let time = new Date();
    let Y = time.getFullYear();
    let M = time.getMonth();
    M = (M + 1) < 10 ? '0' + (M + 1) : (M + 1); //这里月份加1的原因是因为月份是从0开始的,0-11月,加1让月份从1-12月区间。
    let d = time.getDate();
    d = d < 10 ? '0' + d: d;
    let h = time.getHours();
    h = h < 10 ? '0' + h: h;
    let m = time.getMinutes();
    m = m < 10 ? '0' + m: m;
    sheetName = Y + "-" + M + "-" + d + "-" + h + "-" + m;

    html_todo = '';
    html_todo += '<tr>';
    thead_todo.map(item => {
        html_todo += '<th>';
        html_todo += item + '\t';
        html_todo += '</th>';
    });
    html_todo += '</tr>';
    html_end = '';
    html_end += '<tr>';
    thead_end.map(item => {
        html_end += '<th>';
        html_end += item + '\t';
        html_end += '</th>';
    });
    html_end += '</tr>';

     $.ajax({
         type : "GET",
         url : 'http://api.tianapi.com/qingshi/index?key=xxx',
         success : function(poem){
             //console.log(poem_str);
             //let poem = eval("("+poem_str+")"); //'{"code":200,"msg":"success","newslist":[{"content":"离愁渐远渐无穷,迢迢不断如春水。","source":"踏莎行","author":"欧阳修"}]}'
             poem = poem.newslist[0];
             console.log("%c❤❤❤Wish you happy everyday.❤❤❤",'color:#ba0707;text-align: center;font-size:20px;');
             console.log("%c"+poem.content+"\n\t\t\t\t\t%c——"+poem.author+"《"+poem.source+"》",'color:#740505;text-align: center;font-size:20px;','color:#740505;text-align: right;font-size:14px;');
             downloadTodo();
         },
         error: function (err) {
             console.log("%c❤❤❤You are everything when you are with me, and everything is you when you are not.",'color:#ba0707;font-size:20px;');
             downloadTodo();
         }
     });
}
思路二的代码
复制代码

 并行请求获取表格数据

参考https://blog.51cto.com/u_15490526/5302370

http://t.zoukankan.com/damowangM-p-10135903.html

由于end任务的数据量太大了,且每个数据都要重新请求获取满意度等内容,想通过并行来加速,但又要限制同一时间访问请求数量不能太大,所以通过递归promise来实现:

  通过给multiRequest()一个url列表,返回获取数据的列表,在获取的同时也进行了一些处理,之后addNewDataEnd(tbody)可以直接拼接表格。

  由于返回的是Promise对象,所以可以通过接续then()进行下载任务。

下面的代码把下载todo和end两个表的任务分成了两个按钮进行绑定,点哪个下哪个。

复制代码
// ==UserScript==
// @name         v2
// @namespace    http://tampermonkey.net/
// @version      xx
// @description  xx
// @author       xx
// @match        http://xxxx/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=192.76
// @require      https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.5.1.min.js
// @grant        GM_addStyle
// ==/UserScript==
var start_css = ".start_btn_todo{outline:0;border:0;position:fixed;bottom:55px;left:5px;padding:12px 15px;border-radius:10px;cursor:pointer;background-color:#fff0;color:#e5eef8;z-index:999;font-size:12px;text-align:center}.start_btn_end{outline:0;border:0;position:fixed;bottom:5px;left:5px;padding:12px 15px;border-radius:10px;cursor:pointer;background-color:#fff0;color:#e5eef8;z-index:999;font-size:12px;text-align:center}";
GM_addStyle(start_css);
var html_todo = '';
var html_end = '';
var sheetName = '';
var token = '';
var test = '';
const MAX_CON = 20; //最大并发数
const thead_todo = [
    //'事件ID',
    '事件号', '事件类型名', '规定完成时间', '电话'];
const thead_todo_en = [
    //'id',
    'caseNumber', 'eventType', 'regCompleteTime', 'reportPhone'];
const thead_end = [
    //'事件ID',
    '事件号', '事件类型名', '规定完成时间','经办处室', '实际完成时间', '处理结果', '是否满意'];
const thead_end_en = [
    //'id',
    'caseNumber', 'eventType', 'eventRegCompleteTime'];//handleDeptName,createTime,message,satisfactionType
const http_pre = "http://10.xx.xx.xx:9000/";

function XMLHttpRequestBreak(fun=()=>false){
    let f = XMLHttpRequest.prototype.open;
    let remove = function(){
        XMLHttpRequest.prototype.open = f
    };
    let add = function(){
        XMLHttpRequest.prototype.open = function(...args){
            if (args[0] == "POST"){
                let check = fun(args[1]);
                token = getParams(args[1], 'accessToken');
                if (token){
                    console.log("%cGet ready for token="+token,'color:#ba0707;text-align: center;font-size:20px;');
                    remove();
                }
                if (check){
                    throw check;
                }
            }
            f.apply(this,args);
        }
    };
    return {add, remove};
}


$(document).ready(function() {
    let ready = setInterval(function() {
        if (document.getElementsByClassName("el-container")[0]) {
            //如果找到了这个,就认为加载完毕
            clearInterval(ready); //停止定时器
            //创建"开始学习"按钮
            createStartButton();
            console.log(`%ctttttttttttttttttttttttttttttttttttttttfi;i1ttttttttttttttttttttttttttttttffffffffffffffLLLLLLLLLLLLLLLLLL
tttttttttttttttttttttttttttttttttttiiiiiiiii1tttttttttttttttttt1iiiiiiiiii1tffffffft1ffLLfLLLLLLLLLLLLLLLL`,'color:#aaa;font-size:3px;');
        }
    },
    800);
});

function downloadExcel(html,suffix) {
    // 将table添加到html中,在html中加入excel和sheet元素
    let template = '';
    template += '<html lang="" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel">';
    template += '<head><title></title>';
    template += '<xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>';
    template += '<x:Name>';
    template += sheetName + "-" + suffix;
    template += '</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions>';
    template += '</x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml>';
    //html转excel中的\n换行符不管用,需要用<br/>。通过加css,控制<br/>在同一个单元格换行,否则会分割一个单元格。
    template += '<style type="text/css">br {mso-data-placement:same-cell;}</style>';
    template += '</head>';
    template += '<body><table>';
    template += html;
    template += '</table></body>';
    template += '</html>';

    // 将html编码为excel文件,并下载
    let url = 'data:application/vnd.ms-excel;base64,' + window.btoa(unescape(encodeURIComponent(template)));
    let a = document.createElement('a');
    a.href = url;
    a.download = sheetName + "-" + suffix +".xls";
    console.log("%c!Finished for "+suffix,'color:#ba0707;font-size:20px;');
    a.click();
}

function getParams(url, params){
    // 获取url中某个参数的值
      var res = new RegExp("(?:&|/?)" + params + "=([^&$]+)").exec(url);
      return res ? res[1] : '';
}

function createStartButton() {
    let body = document.getElementsByTagName("body")[0];
    let startButton1 = document.createElement("button");
    startButton1.setAttribute("id", "startButton1");
    startButton1.innerText = "待\n处\n理";
    startButton1.className = "start_btn_todo";
    //添加事件监听
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        startButton1.addEventListener("click", start_todo, false);
    } catch(e) {
        try { // IE8.0及其以下版本
            startButton1.attachEvent('onclick', start_todo);
        } catch(e) { // 早期浏览器
            console.log("error: 开始按钮绑定事件失败")
        }
    }
    //插入节点
    body.append(startButton1);
    let startButton2 = document.createElement("button");
    startButton2.setAttribute("id", "startButton2");
    startButton2.innerText = "已\n完\n成";
    startButton2.className = "start_btn_end";
    //添加事件监听
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        startButton2.addEventListener("click", start_end, false);
    } catch(e) {
        try { // IE8.0及其以下版本
            startButton2.attachEvent('onclick', start_end);
        } catch(e) { // 早期浏览器
            console.log("error: 开始按钮绑定事件失败")
        }
    }
    //插入节点
    body.append(startButton2);
    //监听请求
    test = XMLHttpRequestBreak(console.log);
    test.add();
}

function downloadTodo(){
    let max_num_todo = 2;
    let url_todo = http_pre + "distribute/disEventInfo/toDoList?accessToken="+token+"&boxType=1&pageNumber=1&pageSize="+max_num_todo+"&searchConditionJson=%5B%7B%22";
    console.log(url_todo);
    $.ajax({
         type : "POST",
         url : url_todo,
         success : function(res){
             //{state: true, msg: '', data: Array(2), code: 200, total: 499, …}
             max_num_todo = res.total+88;
             url_todo = http_pre + "distribute/disEventInfo/toDoList?accessToken="+token+"&boxType=1&pageNumber=1&pageSize="+max_num_todo+"&searchConditionJson=%5B%7B%22";
             $.ajax({
                 type : "POST",
                 url : url_todo,
                 success : function(res){
                     //{state: true, msg: '', data: Array(1169), code: 200, total: 1169, …}
                     let data = res.data;
                     console.log(data);
                     addNewDataTodo(data);
                     //console.log(html_todo);
                     downloadExcel(html_todo,"todo");
                     //downloadEnd();
                 },
                 error: function (err) {
                     console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                     console.log(err);
                 },async:false
             });
         },
         error: function (err) {
             console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
             console.log(err);
         },async:false
     });
}

function downloadEnd(){
    let max_num_end = 2;
    let url_end = http_pre + "distribute/disEventInfo/EndList?accessToken="+token+"&pageNumber=1&pageSize="+max_num_end+"&searchConditionJson=%5B%7B%22";
    $.ajax({
         type : "POST",
         url : url_end,
         success : function(res){
             //{state: true, msg: '', data: Array(2), code: 200, total: 1169, …}
             max_num_end = res.total+88;
             url_end = http_pre + "distribute/disEventInfo/EndList?accessToken="+token+"&pageNumber=1&pageSize="+max_num_end+"&searchConditionJson=%5B%7B%22";
             $.ajax({
                 type : "POST",
                 url : url_end,
                 success : function(res){
                     //{state: true, msg: '', data: Array(1169), code: 200, total: 1169, …}
                     let data = res.data;
                     console.log(data);
                     addNewDataEnd(data);
                     //console.log(html_end);
                     //downloadExcel(html_end,"end");
                 },
                 error: function (err) {
                     console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                     console.log(err);
                 },async:false
             });
         },
         error: function (err) {
             console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
             console.log(err);
         },async:false
     });
}

function addNewDataTodo(tbody) {
    let count = 1;
    tbody.map(item =>{
        if (count%10 == 0 || count==1|| count==tbody.length){
            console.log("Preparing Todo data: ["+ count +"/"+tbody.length+"]");
        }
        let url_event = http_pre + "geosocial-flowable-distribute/disEventInfo/"+item.id+"?accessToken="+token;//to get reportPhone
        html_todo += '<tr>';
        thead_todo_en.map(v =>{
            html_todo += '<td style="text-align: center;">';
            if (v == 'reportPhone'){
                let phone = item[v];
                if (phone.indexOf("*") != -1){
                    //手机号中存在星号
                    $.ajax({
                        type : "GET",
                        url : url_event,
                        success : function(res){
                            //{state: true, msg: '', data: {reportPhone:"189xx",..}, code: 200}
                            phone = res.data.reportPhone;
                        },
                        error: function (err) {
                            console.log("%c!WARNING!",'color:#ba0707;font-size:20px;');
                            console.log(err);
                        },async:false
                    });
                }
                if (phone.indexOf(",") != -1) {
                    phone = phone.replaceAll(",","<br/>")
                }
                html_todo += (phone ? phone : item[v]) + '\t';
            }else{
                html_todo += (item[v] ? item[v] : '') + '\t';
            }
            html_todo += '</td>';
        });
        html_todo += '</tr>';
        count++;
    });
}

function CompareDate(d1, d2) {
    //比较日期,d1比d2晚则返回true
    return ((new Date(d1.replace(/-/g, "/"))) > (new Date(d2.replace(/-/g, "/"))));
}


function maxDate(datelist){
    // 接受列表 返回最大日期
    //datelist eg: ['2019-1-2','2019-3-4','2019-5-7']
    var newDateList = datelist.map((x) => new Date(x).getTime());  // 获取Date对象的秒数
    var maxdate = Math.max(...newDateList);  // 获取最大秒数
    var maxdateindex = newDateList.indexOf(maxdate); // 最大秒数索引
    var maxdatestring = datelist[maxdateindex];// 通过索引取出datelist中最大日期字符串
    return maxdatestring;
}

function addNewDataEnd(tbody) {
    let urls = [];
    tbody.map(item =>{
        let url_dispose = http_pre + "distribute/disDisposeMsgList?accessToken="+token+"&processInstId="+item.processInstId+"&processType="+item.processType+"&businessid="+item.businessId;//to get handleDeptName list, message list, last createTime, last disReviewSituationModels.satisfactionType
        urls.push(url_dispose);
    });
    multiRequest(urls, MAX_CON).then(function(request_result) {
        let count = 0;
        tbody.map(item =>{
            if (count%10 == 9 || count==0|| count==tbody.length-1){
                console.log("Preparing End data: ["+ (count+1) +"/"+tbody.length+"]");
            }
            html_end += '<tr>';
            thead_end_en.map(v =>{
                html_end += '<td style="text-align: center;">';
                if (v == 'reportPhone' && item[v].indexOf(",") != -1){
                    html_end += item[v].replaceAll(",","<br/>") + '\t';
                }else{
                    html_end += (item[v] ? item[v] : '') + '\t';
                }
                html_end += '</td>';
            });
            html_end += '<td style="text-align: center;">';
            let handleDeptNames = request_result[count].handleDeptNames;
            html_end += (handleDeptNames ? handleDeptNames : '') + '\t';
            html_end += '</td>';
            html_end += '<td style="text-align: center;">';
            let last_time = request_result[count].last_time;
            html_end += (last_time ? last_time : '') + '\t';
            html_end += '</td>';
            html_end += '<td style="text-align: center;">';
            let messages = request_result[count].messages;
            html_end += (messages ? messages : '') + '\t';
            html_end += '</td>';
            html_end += '<td style="text-align: center;">';
            let satisfactions = request_result[count].satisfactions;
            html_end += (satisfactions ? satisfactions : '') + '\t';
            html_end += '</td>';
            html_end += '</tr>';
            count++;
        });
    }).then(()=>{
        downloadExcel(html_end,"end");
    }).catch((err) => {
        console.log(err);
    });
}

function multiRequest(urls = [], maxNum) {
  // 请求总数量
  const len = urls.length;
  // 根据请求数量创建一个数组来保存请求的结果
  const result = new Array(len).fill(false);
  // 当前完成的数量
  let count = 0;

  return new Promise((resolve, reject) => {
    // 请求maxNum个
    while (count < maxNum) {
      next();
    }
    function next() {
      let current = count++;
      // 处理边界条件
      if (current >= len) {
        // 请求全部完成就将promise置为成功状态, 然后将result作为promise值返回
        !result.includes(false) && resolve(result);
        return;
      }
      const url = urls[current];
      console.log(`开始 ${current}`, new Date().toLocaleString());
      fetch(url)
        .then((res) => {
          return res.json();
        })
        .then((res) => {
                     /*[{
                        "handleDeptName": "精神卫生中心",
                        "message": "尊敬的X先生...",
                        "createTime": "2021-10-12 17:26:36",
                        "disReviewSituationModels": [
                            {
                                "satisfactionType": "1",
                            }
                        ]
                    }, {...}]*/
          // 保存请求结果
          let data_list = res.data;
          //console.log(data_list);
          let handleDeptName_list = [];
          let createTime_list = [];
          let message_list = [];
          let satisfactionType_list = [];
          data_list.map(d => {
              handleDeptName_list.push(d.handleDeptName);
              createTime_list.push(d.createTime);
              message_list.push(d.message);
              let drsm = d.disReviewSituationModels;
              if (drsm){
                  let dsType = drsm[drsm.length-1].satisfactionType;
                  if(dsType){
                      //值为1
                      satisfactionType_list.push("满意");
                  }else{
                      //值为0或null
                      satisfactionType_list.push(parseInt(dsType)==0?"不满意":"未反馈");
                  }
              }else{
                  //没有回访记录
                  satisfactionType_list.push("未回访");
              }
          });
          let handleDeptNames = handleDeptName_list.join('<br/>=====<br/>');
          let last_time = maxDate(createTime_list);
          let messages = message_list.join('<br/>===========<br/>');
          let satisfactions = satisfactionType_list.join('<br/>=====<br/>');
          result[current] = {
              'handleDeptNames': handleDeptNames,
              'last_time': last_time,
              'messages': messages,
              'satisfactions': satisfactions,
          };
          //console.log(`完成 ${current}`, new Date().toLocaleString());
          // 请求没有全部完成, 就递归
          if (current < len) {
            next();
          }
        })
        .catch((err) => {
          console.log(`结束 ${current}`, new Date().toLocaleString());
          result[current] = err;
          // 请求没有全部完成, 就递归
          if (current < len) {
            next();
          }
        });
    }
  });
}

function start_todo() {
    if (!token){
        console.log("%c!!!请先访问某个案件,获取Token后再点击开始!!!",'color:#ba0707;text-align: center;font-size:20px;');
        return;
    }
    test.remove();
    console.log("Starting!...");

    let time = new Date();
    let Y = time.getFullYear();
    let M = time.getMonth();
    M = (M + 1) < 10 ? '0' + (M + 1) : (M + 1); //这里月份加1的原因是因为月份是从0开始的,0-11月,加1让月份从1-12月区间。
    let d = time.getDate();
    d = d < 10 ? '0' + d: d;
    let h = time.getHours();
    h = h < 10 ? '0' + h: h;
    let m = time.getMinutes();
    m = m < 10 ? '0' + m: m;
    sheetName = Y + "-" + M + "-" + d + "-" + h + "-" + m;

    html_todo = '';
    html_todo += '<tr>';
    thead_todo.map(item => {
        html_todo += '<th>';
        html_todo += item + '\t';
        html_todo += '</th>';
    });
    html_todo += '</tr>';

     $.ajax({
         type : "GET",
         url : 'http://api.tianapi.com/qingshi/index?key=xxx',
         success : function(poem){
             //console.log(poem_str);
             //let poem = eval("("+poem_str+")"); //'{"code":200,"msg":"success","newslist":[{"content":"离愁渐远渐无穷,迢迢不断如春水。","source":"踏莎行","author":"欧阳修"}]}'
             poem = poem.newslist[0];
             console.log("%c❤❤❤Wish you happy everyday.❤❤❤",'color:#ba0707;text-align: center;font-size:20px;');
             console.log("%c"+poem.content+"\n\t\t\t\t\t%c——"+poem.author+"《"+poem.source+"》",'color:#740505;text-align: center;font-size:20px;','color:#740505;text-align: right;font-size:14px;');
             downloadTodo();
         },
         error: function (err) {
             console.log("%c❤❤❤You are everything when you are with me, and everything is you when you are not.",'color:#ba0707;font-size:20px;');
             downloadTodo();
         }
     });
}

function start_end() {
    if (!token){
        console.log("%c!!!请先访问某个案件,获取Token后再点击开始!!!",'color:#ba0707;text-align: center;font-size:20px;');
        return;
    }
    test.remove();
    console.log("Starting!...");

    let time = new Date();
    let Y = time.getFullYear();
    let M = time.getMonth();
    M = (M + 1) < 10 ? '0' + (M + 1) : (M + 1); //这里月份加1的原因是因为月份是从0开始的,0-11月,加1让月份从1-12月区间。
    let d = time.getDate();
    d = d < 10 ? '0' + d: d;
    let h = time.getHours();
    h = h < 10 ? '0' + h: h;
    let m = time.getMinutes();
    m = m < 10 ? '0' + m: m;
    sheetName = Y + "-" + M + "-" + d + "-" + h + "-" + m;

    html_end = '';
    html_end += '<tr>';
    thead_end.map(item => {
        html_end += '<th>';
        html_end += item + '\t';
        html_end += '</th>';
    });
    html_end += '</tr>';

     $.ajax({
         type : "GET",
         url : 'http://api.tianapi.com/qingshi/index?key=xxx',
         success : function(poem){
             //console.log(poem_str);
             //let poem = eval("("+poem_str+")"); //'{"code":200,"msg":"success","newslist":[{"content":"离愁渐远渐无穷,迢迢不断如春水。","source":"踏莎行","author":"欧阳修"}]}'
             poem = poem.newslist[0];
             console.log("%c❤❤❤Wish you happy everyday.❤❤❤",'color:#ba0707;text-align: center;font-size:20px;');
             console.log("%c"+poem.content+"\n\t\t\t\t\t%c——"+poem.author+"《"+poem.source+"》",'color:#740505;text-align: center;font-size:20px;','color:#740505;text-align: right;font-size:14px;');
             downloadEnd();
         },
         error: function (err) {
             console.log("%c❤❤❤You are everything when you are with me, and everything is you when you are not.",'color:#ba0707;font-size:20px;');
             downloadEnd();
         }
     });
}
思路二代码V2
复制代码

 上面这些map函数里面套push的,最好可以改成https://www.cnblogs.com/zaishiyu/p/13967240.html里最后这样的直接赋值的情况,虽然说确实是按顺序的,但改一下还是保险一些。

const dateList=res.list.map(item => ({
    name:item.name,
    age:item.age
    })
);

使用这样的方式,就不需要一个map里那么多push了,可以把多个列表元素并为一个列表里的object,这样每次索引的时候同一个object里的内容可以确保是对应的。

组织成表格html字符串,自动导出下载为Excel文件

将打包好的html字符串,发送到下面的函数即可

复制代码
function downloadExcel(html,sheetName) {
    // 将table添加到html中,在html中加入excel和sheet元素
    let template = '';
    template += '<html lang="" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel">';
    template += '<head><title></title>';
    template += '<xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>';
    template += '<x:Name>';
    template += sheetName;
    template += '</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions>';
    template += '</x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml>';
    //html转excel中的\n换行符不管用,需要用<br/>。通过加css,控制<br/>在同一个单元格换行,否则会分割一个单元格。
    template += '<style type="text/css">br {mso-data-placement:same-cell;}</style>';
    template += '</head>';
    template += '<body><table>';
    template += html;
    template += '</table></body>';
    template += '</html>';

    // 将html编码为excel文件,并下载
    let url = 'data:application/vnd.ms-excel;base64,' + window.btoa(unescape(encodeURIComponent(template)));
    let a = document.createElement('a');
    a.href = url;
    a.download = sheetName + ".xls";
    a.click();
}
复制代码

这里会遇到一个问题,如果想要导出的内容里有换行符‘\n’,在excel里是不识别的,需要换成对应的html语言的<br />。但问题是<br />会拆分单元格,把换行后的内容放到另一个单元格了,如果想要在同一个单元格内换行,需要在css中加入以下内容控制<br/>在同一个单元格换行,否则会分割一个单元格。

br {mso-data-placement:same-cell;}

关于时间的操作

获取当前时间作为表名

使用Date()然后格式化字符串

复制代码
    let time = new Date();
    let Y = time.getFullYear();
    let M = time.getMonth();
    M = (M + 1) < 10 ? '0' + (M + 1) : (M + 1); //这里月份加1的原因是因为月份是从0开始的,0-11月,加1让月份从1-12月区间。
    let d = time.getDate();
    d = d < 10 ? '0' + d: d;
    let h = time.getHours();
    h = h < 10 ? '0' + h: h;
    let m = time.getMinutes();
    m = m < 10 ? '0' + m: m;
    sheetName = Y + "-" + M + "-" + d + "-" + h + "-" + m;
复制代码

比较时间的大小,返回最大的时间

复制代码
function maxDate(datelist){
    // 接受列表 返回最大日期
    //datelist eg: ['2019-1-2','2019-3-4','2019-5-7']
    var newDateList = datelist.map((x) => new Date(x).getTime());  // 获取Date对象的秒数
    var maxdate = Math.max(...newDateList);  // 获取最大秒数
    var maxdateindex = newDateList.indexOf(maxdate); // 最大秒数索引
    var maxdatestring = datelist[maxdateindex];// 通过索引取出datelist中最大日期字符串
    return maxdatestring;
}
复制代码

判断两个时间的先后

function CompareDate(d1, d2) {
    //比较日期,d1比d2晚则返回true
    return ((new Date(d1.replace(/-/g, "/"))) > (new Date(d2.replace(/-/g, "/"))));
}

 获取url中某个参数的值

function getParams(url, params){
    // 获取url中某个参数的值
      var res = new RegExp("(?:&|/?)" + params + "=([^&$]+)").exec(url);
      return res ? res[1] : '';
}

 

console界面交互

输出字符串勾勒的图片

为了增加一些交互感,在console界面输出了一个字符串图片,你可以把你想展示的图片通过网站(图片转ascii字符画)转成字符串,用console的%c格式化输出,注意键盘左上角的波浪线那个按键一起的``按键可以使换行的字符串被认为是同一个字符串的组成部分。

通过api获取随机的诗句

http://api.tianapi.com/qingshi/index?key=xxxxxx,方法为GET,返回json如下

'{"code":200,"msg":"success","newslist":[{"content":"离愁渐远渐无穷,迢迢不断如春水。","source":"踏莎行","author":"欧阳修"}]}'

 何时插入开始按钮?

寻找你认为代表网页准备完成的那个元素,设置个定时器检测到这个元素就判断为网页加载完成

复制代码
$(document).ready(function() {
    let ready = setInterval(function() {
        if (document.getElementsByClassName("m-top-box")[0]) {
            clearInterval(ready); //停止定时器
            //创建"开始"按钮
            createStartButton();
        }
    },
    800);
});
复制代码

安装到浏览器

如何安装油猴脚本呢?参考教程https://www.cnblogs.com/jdq-123/p/16272121.html安装插件,然后参考“三、2.如何将本地的脚本文件配置至浏览器”把js内容复制进去保存

由于要对接油猴脚本,其中的设置css效果就可以使用官方提供的GM_addStyle方式进行注入,这也就是上面的代码之中的那些内容

 

posted @   evtricks  阅读(2287)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2018-10-16 斐讯K2 PSG1218 刷机教程 基于Breed互刷 清除配置
点击右上角即可分享
微信分享提示
瞬光斩黯黮,昭明破晦夜。