您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
这是一个tagww.com网站的文件导出脚本
// ==UserScript== // @name tagww 导出文件脚本 // @namespace http://tampermonkey.net/ // @version 1.0.1 // @description 这是一个tagww.com网站的文件导出脚本 // @author 21克的爱情提供技术支持 // @match *.tagww.com/* // @require https://cdnjs.cloudflare.com/ajax/libs/axios/1.7.7/axios.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.js // @require https://cdnjs.cloudflare.com/ajax/libs/exceljs/4.4.0/exceljs.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @grant GM_registerMenuCommand // @grant GM_openInTab // @license MIT // ==/UserScript== (function() { 'use strict'; const menu_command_id = GM_registerMenuCommand("其他工具", function(event) { console.log("Menu item selected"); // 打开新标签页 // GM_openInTab('https://tool.civiccloud.cn/#/finance'); GM_openInTab('https://tool.civiccloud.cn/#/finance', { active: true, // 新标签页将被激活 insert: true, // 新标签页将在当前标签页旁边插入 setParent: true // 新标签页将设置当前标签页为父标签页 }); // 宿主页面的Tampermonkey脚本 window.addEventListener('message', function(event) { // 确保消息来源是可信的 if (event.origin === "https://example.com") { console.log("接收到消息:", event.data); // 处理接收到的消息 } }, false); // window.opener.postMessage('这是来自子页面的消息', 'https://example.com'); }); console.log('Tagww 插件加载成功'); // 自定义拦截请求操作 function addXMLRequestCallback(callback){ var oldSend, i; if( XMLHttpRequest.callbacks ) { // we've already overridden send() so just add the callback XMLHttpRequest.callbacks.push( callback ); } else { // create a callback queue XMLHttpRequest.callbacks = [callback]; // store the native send() oldSend = XMLHttpRequest.prototype.send; // override the native send() XMLHttpRequest.prototype.send = function(){ // process the callback queue // the xhr instance is passed into each callback but seems pretty useless // you can't tell what its destination is or call abort() without an error // so only really good for logging that a request has happened // I could be wrong, I hope so... // EDIT: I suppose you could override the onreadystatechange handler though for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) { XMLHttpRequest.callbacks[i]( this ); } // call the native send() oldSend.apply(this, arguments); } } } // e.g. addXMLRequestCallback( function( xhr ) { xhr.addEventListener("load", function(){ if ( xhr.readyState == 4 && xhr.status == 200 ) { console.dir(xhr); if (xhr.responseURL.includes("includes/jobAjaxReqs.csp") || xhr.responseURL.includes("/apps/Dashboard/%25CSP.Broker.cls")) { formatHtml(); } } }); }); // axios 解决下载PDF 302 错误 const request = axios.create({ baseURL: 'https://sourcing.di.tagww.com', withCredentials: true, }) // PDF 类 const PDF = { workbook: null, async start (data, isExcel, progress, doneBlack) { const zip = new JSZip() const ids = JSON.parse(localStorage.getItem('downloadIds') || '{}') const excelData = [] for (let i = 0; i < data.length; i++) { progress && progress(i + 1) const job = data[i]; ids[job.id] = true console.log('开始下载', job) const purchaseOrdersUrl = await this.getViewByUrl(job.url, 0) console.log('获取到订单链接以及项目名称', purchaseOrdersUrl) const orderListUrl = await this.getViewByUrl(purchaseOrdersUrl.url, 1) console.log('获取到表格链接', orderListUrl) const tableListUrl = await this.getViewByUrl(orderListUrl, 2) console.log('获取到表格链接', tableListUrl) const tableList = await this.getViewByUrl(tableListUrl, 3) console.log('获取到表格数据列表链接', tableList) for (let index = 0; index < tableList.length; index++) { const item = tableList[index]; const printViewUrl = await this.getViewByUrl(item.url, 4) console.log('获取到打印链接', printViewUrl) const downloadUrl = await this.getViewByUrl(printViewUrl, 5, item) console.log('获取到下载链接', downloadUrl) const fileBlob = await this.downloadFile(downloadUrl, `PO_${item.id}`) console.log('获取到下载的文件数据', fileBlob, purchaseOrdersUrl, item) const total = item.data.replace(/[a-zA-Z\s]/g, '') const projectName = purchaseOrdersUrl.projectName excelData.push({ orderId: item.id, jobsId: job.id, projectName, total: total.replace(',', '') * 1 }) const name = `(${projectName})${total}` zip.file(`${fileBlob.name.replace(/\.[pdf|PDF]+/, name + '.pdf')}`, fileBlob.data) } } console.log(excelData) if (isExcel) { this.workbook = new ExcelJS.Workbook(); const sheet = this.workbook.addWorksheet('My Sheet'); sheet.columns = [ { header: 'JobsId', key: 'jobsId', width: 15 }, { header: 'OrderId', key: 'orderId', width: 32 }, { header: 'ProjectName', key: 'projectName', width: 40 }, { header: 'Total Money', key: 'total', width: 20 } ]; sheet?.addRows(excelData); // 写入 buffer const buffer = await this.workbook.xlsx.writeBuffer(); zip.file(`JOBS统计数据.xlsx`, buffer) } zip.generateAsync({ type: "blob" }).then(function (content) { localStorage.setItem('downloadIds', JSON.stringify(ids)) doneBlack && doneBlack() saveAs(content, `${new Date().getTime()}.zip`); //Photo.zip为生成zip后的文件名 }) }, getViewByUrl (url, status, params={}) { return new Promise((resolve) => { if (!url) { resolve('') } if (url.indexOf(location.origin) == -1) { url = `${location.origin}/${url}`; } request({ url: url, method: 'GET', }).then(({ data }) => { let resultUrl = '' if (status === 5) { const downRegExp = new RegExp(/JbPurchaseOrderPrintView.csp\?(.?)+&/i) console.log('是否含有locationHref链接', downRegExp.test(data)) if (downRegExp.test(data)) { let viewUrl = downRegExp.exec(data)[0] || '' viewUrl = viewUrl.replace("CSPCHD","CACHELOGINDATA") const fileRegExp = new RegExp(/CoDownloadPDF.csp\?(.?)+&/i) console.log('是否含有CoDownloadPDF链接', fileRegExp.test(data)) if (fileRegExp.test(data)) { const oId = url.replace(/\D/g, '') // https://sourcing.di.tagww.com/apps/CoDownloadPDF.csp?CSPToken=1_kbP44ZX4I9t$EXhtUFUvzZ9T2F6Iy0MR35zfFFkFaZumbzYv1LD1LG4sw$dguP1zIbX8K98nnH7Wh0s4vc7w--&locationHref=https://sourcing.di.tagww.com/apps/JbPurchaseOrderPrintView.csp?CSPSHARE=1&CACHELOGINDATA=000001020000mHg7cH0TIiFd9zz6ShNvs0iPT1BnxjoE1Un6qz&OID=129678&PARAMNAMES=CACHELOGINDATA,OID,st_forPrint,OID&TYPE=PO&st_forPrint=1&number=2100129678&OID=129678 resultUrl = `${fileRegExp.exec(data)[0] || ''}locationHref=https://sourcing.di.tagww.com/apps/${viewUrl}OID=${oId}&PARAMNAMES=CACHELOGINDATA,OID,st_forPrint,OID&TYPE=PO&st_forPrint=1&number=${params.id}&OID=${oId}` } } } else { let div = document.createElement("div") div.style.display = "none" div.innerHTML = data.replaceAll("img", "imgg") if (status === 0) { // 获取导航列表 const purchaseOrders = div.querySelector("#main-nav .sfhover") const projectName = div.querySelector(".titlearea .titlewithbuttons").innerText resolve({ url: 'apps/' + purchaseOrders.querySelector("a").getAttribute("href"), projectName }) } else if (status === 1) { const orderDiv = div.querySelector("#main-nav").lastChild.previousElementSibling; const orderList = orderDiv.querySelector('a') resultUrl = orderList.getAttribute('href') } else if (status === 2) { resultUrl = div.querySelector("#JbPurchaseOrderList").getAttribute('src') // resultUrl = orderList.attr('src') } else if (status === 3) { const tr = div.querySelectorAll('table tr[class]') || [] const trData = Array.from(tr).map(item => ({ id: item.querySelectorAll('td')[1].innerText.trim(), url: 'apps/' + item.querySelectorAll('td')[1].querySelector('a').getAttribute("href"), data: item.querySelectorAll('td')[6].innerText, })) resolve(trData) // resultUrl = orderList.attr('src') } else if (status === 4) { const printRegExp = new RegExp(/JbPurchaseOrderPrintView.csp\?OID=[\d]+/) if (printRegExp.test(data)) { resultUrl = printRegExp.exec(data)[0] || '' } } } resolve('apps/' + resultUrl) }) }) }, downloadFile(url, name){ return new Promise((resolve) => { if (!url) { resolve('') } if (url.indexOf(location.origin) == -1) { url = `${location.origin}/${url}`; } request({ url: url, method: 'GET', responseType: "blob", }).then((res) => { const name = (res.headers['content-disposition'] || '').substr((res.headers['content-disposition'] || '').indexOf('=') + 1) resolve({ name, data: res.data }) }) }) } } function formatHtml(){ if (location.pathname === "/apps/Dashboard/DbJobs.csp") { const ids = JSON.parse(localStorage.getItem('downloadIds') || '{}') console.log(ids) // 设置下载的excel按钮 const excel = document.querySelector('#jobRows thead th:last-child') if (excel) { excel.innerHTML = `<button class="downloadEXCEL" style="background:#28dfff;color:#fff;border:none;width:83px;padding:1px 0;margin:0 auto;display:block;cursor:pointer;">EXCEL</button>` } // 设置下载PDF按钮 const list = document.querySelectorAll('#jobRows tbody td:last-child') list.forEach((item) => { const id = item.parentElement?.querySelector('a')?.outerText || '' const url = item.parentElement?.querySelector('a')?.href item.innerHTML = `<button class="downloadPDF" data-id="${id}" data-url="${url}" style="background:${ids[id] ? 'grey' : '#28dfff'};color:#fff;border:none;width:83px;padding:1px 10px;cursor:pointer;">${ids[id] ? 'retry' : 'down'} PDF</button>` }) document.querySelectorAll('.downloadEXCEL').forEach((ele) => { ele.addEventListener('click', ( e ) => { const { target } = e e.preventDefault() e.stopPropagation() // 获取所有的选中框 const checkData = document.querySelectorAll('table tr[class] input[type=checkbox]') const list = Array.from(checkData).filter((item) => item.checked).map((item) => { const tr = item.parentElement.parentElement return { id: tr.querySelector('tr > td > a').outerText.trim(), url: tr.querySelector('tr > td > a').href, status: tr.querySelector('#jobStatusUpdateTd').outerText.trim(), } }).filter((item) => !'Cancelled'.includes(item.status)) if (list.length === 0) { return alert('select data is empty') } PDF.start( list, true, (index) => { console.log(index) target.innerHTML = `EXCEL${index}/${list.length}` target.disabled = true target.style.background = "#5d5d5d" }, () => { target.innerHTML = `EXCEL` target.disabled = false target.style.background = "#28dfff" } ) }) }) document.querySelectorAll('.downloadPDF').forEach((ele) => { ele.addEventListener('click', ( e ) => { const { target } = e e.preventDefault() e.stopPropagation() ids[target?.dataset.id] = true localStorage.setItem('downloadIds', JSON.stringify(ids)) target.innerHTML = "Download..." target.disabled = true target.style.background = "#808080" console.log(target?.dataset) PDF.start( [target?.dataset], false, () => {}, () => { target.innerHTML = `retry PDF` target.disabled = false target.style.background = "grey" } ) }) }) } } })();