您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show what isn't done and display uploaded files.
// ==UserScript== // @name Almascript - Alma Start Process List Helper // @namespace https://gf.qytechs.cn/en/users/8332-sreyemnayr // @version 2019.8.6.1 // @description Show what isn't done and display uploaded files. // @author Ryan Meyers // @match https://*.getalma.com/workflows/processes/*/review // @require https://gf.qytechs.cn/scripts/388114-pdf-js/code/PDFjs.js?version=721820 // @require https://gf.qytechs.cn/scripts/388210-html2pdf-js/code/html2pdfjs.js?version=722443 // @require https://unpkg.com/[email protected]/dist/pdf-lib.min.js // @require https://unpkg.com/[email protected]/dist/FileSaver.min.js // @grant unsafeWindow // ==/UserScript== // Loaded via <script> tag, create shortcut to access PDF.js exports. var pdfjsLib = window["pdfjs-dist/build/pdf"]; // The workerSrc property shall be specified. pdfjsLib.GlobalWorkerOptions.workerSrc = "//gf.qytechs.cn/scripts/388115-pdf-js-worker/code/PDFjs%20Worker.js?version=721821"; const readBlobAsArrayBuffer = (blob) => { const temporaryFileReader = new FileReader(); return new Promise((resolve, reject) => { temporaryFileReader.onerror = () => { temporaryFileReader.abort(); reject(new DOMException("Problem parsing input file.")); }; temporaryFileReader.onload = () => { resolve(temporaryFileReader.result); }; temporaryFileReader.readAsArrayBuffer(blob); }); }; function clearBody(body) { body = body.replace(/src=/g,"data-src="); body = body.replace(/<link/g, "nolink"); return body; } function fetchAndUpdate(node) { const updateNode = node; fetch(node.href) .then(function(response) { return response.text(); }) .then(function(body) { body = clearBody(body); var parser = new DOMParser(); var doc = parser.parseFromString(body, "text/html"); var xpath = "//li[contains(@class,'task')][not(contains(@class,'task-complete'))]"; var result = document.evaluate( xpath, doc, null, XPathResult.ANY_TYPE, null ); //console.log(result); var node, nodes = []; while ((node = result.iterateNext())) { //console.log(node.textContent.trim()); var newNode = document.createElement("div"); newNode.classList.add("pill"); newNode.innerHTML = '<i class="far fa-times-circle" style="color:#eb6841;"></i>' + node.textContent.trim(); updateNode.parentElement.parentElement.children[4].append(newNode); } }); } function fetchHealthForm(node) { var updateNode = node; var pdfIcon = document.createElement("div"); pdfIcon.classList.add( "pure-button", "pure-button-pdf", "pure-button-large", "image-icon-button" ); var iconElement = document.createElement("i"); iconElement.classList.add("far", "fa-images", "fa-1x", "pdfIcon"); pdfIcon.append(iconElement); var studentName, processName = ""; updateNode.parentElement.parentElement.children[0].append(pdfIcon); pdfIcon.onclick = async function() { iconElement.classList.add("lds-circle"); fetch(node.href) .then(function(response) { return response.text(); }) .then(function(body) { //console.log(body); body = clearBody(body); var parser = new DOMParser(); var doc = parser.parseFromString(body, "text/html"); var xpath = "//li[contains(@class,'task')]"; var result = document.evaluate( xpath, doc, null, XPathResult.ANY_TYPE, null ); //console.log(result); var node, nodes = []; var numFiles = 0; var filesDone = 0; while ((node = result.iterateNext())) { var taskUri = node.dataset.href; var formUri = taskUri.replace("task-details", "form"); let headers = new Headers({ Accept: "application/json", "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest" }); fetch(formUri, { method: "GET", headers: headers }) .then(function(response) { return response.json(); }) .then(function(myJson) { //console.log(myJson); var jsonHTML = myJson.Message.html; jsonHTML = jsonHTML.replace(/form-section/g, "form-section-off"); jsonHTML = jsonHTML.replace( /<ul class/g, '<ul style="display:none;" class' ); //console.log(jsonHTML); //var files = jsonHTML.match(/<a href="(\/workflows\/processes\/.*\/get-file\?id=[a-zA-z0-9]*)">/g); var files = jsonHTML.match( /\/workflows\/processes\/.*\/get-file\?id=[a-zA-z0-9]*/g ); if (files) { numFiles += files.length; iconElement.classList.add("lds-circle"); for (var file of files) { fetch(file) .then(function(response) { return response.blob(); }) .then(async function(blob) { console.log(blob.type); let reader = new FileReader(); reader.readAsArrayBuffer(blob); reader.onload = async function() { var newImg; //blob.arrayBuffer().then(async function(myBuffer){ if (blob.type === "application/pdf") { newImg = document.createElement("canvas"); var loadingTask = pdfjsLib.getDocument(file); loadingTask.promise.then( function(pdf) { console.log("PDF loaded"); // Fetch the first page var pageNumber = 1; pdf.getPage(pageNumber).then(function(page) { console.log("Page loaded"); var scale = 0.25; var viewport = page.getViewport(scale); // Prepare canvas using PDF page dimensions var canvas = newImg; var context = canvas.getContext("2d"); canvas.height = 230; canvas.width = 160; // Render PDF page into canvas context var renderContext = { canvasContext: context, viewport: viewport }; var renderTask = page.render(renderContext); renderTask.promise.then(function() { console.log("Page rendered"); }); }); }, function(reason) { // PDF loading error console.error(reason); } ); //newImg = document.createElement('a'); //newImg.href = file; //newImg.innerHTML = "Download"; updateNode.append(newImg); } else { newImg = document.createElement("img"); newImg.src = file; newImg.width = 160; updateNode.append(newImg); } filesDone += 1; if (filesDone === numFiles) { iconElement.classList.remove("lds-circle"); } }; }); } } }); } }) .then(function() {}); }; } function doIncomplete() { var xpath = "//tr[td[text()='Active (in progress)']]/td[2]/a"; var result = document.evaluate( xpath, document, null, XPathResult.ANY_TYPE, null ); var node, nodes = []; while ((node = result.iterateNext())) { nodes.push(node); //console.log(node.href); fetchAndUpdate(node); } } function clickAllImageButtons() { var node; for (node of document.getElementsByClassName("image-icon-button")) { node.click(); } } function downloadAllPDFs() { var node; for (node of document.getElementsByClassName("pdf-icon-button")) { node.click(); } } function doCompletePDFButtons() { var xpath = "//tr[td[text()='Active (complete)' or text()='Complete']]/td[2]/a"; var result = document.evaluate( xpath, document, null, XPathResult.ANY_TYPE, null ); //var result = document.evaluate(xpath,document.cloneNode(true)) var node, nodes = []; while ((node = result.iterateNext())) { nodes.push(node); //console.log(node.href); } for (node of nodes) { generatePDF(node); generatePDF(node, true); fetchHealthForm(node); } } function generatePDF(node, justHealth = false) { const onlyHealth = justHealth; var updateNode = node; var pdfIcon = document.createElement("div"); var iconElement = document.createElement("i"); if (onlyHealth) { pdfIcon.classList.add( "pure-button", "pure-button-pdf", "pure-button-large", "health-icon-button" ); iconElement.classList.add("fas", "fa-notes-medical", "fa-1x", "pdfIcon"); } else { pdfIcon.classList.add( "pure-button", "pure-button-pdf", "pure-button-large", "pdf-icon-button" ); iconElement.classList.add("fas", "fa-file-pdf", "fa-1x", "pdfIcon"); } pdfIcon.append(iconElement); var studentName, processName = ""; updateNode.parentElement.parentElement.children[0].append(pdfIcon); pdfIcon.onclick = async function() { iconElement.classList.add("lds-circle"); const bigPdf = await PDFLib.PDFDocument.create(); var allHTML = []; const bigFetch = await fetch(node.href); var body = await bigFetch.text(); body = clearBody(body); //console.log(body); var parser = new DOMParser(); var doc = parser.parseFromString(body, "text/html"); var xpath; studentName = doc.getElementsByClassName("fn")[0].innerText.trim(); if (onlyHealth) { processName = "HEALTH " + doc.getElementById("page-header").innerText.trim(); xpath = "//li[contains(@class,'task')][div/h5[contains(text(),'Health' ) or contains(text(), 'Medi')]]"; } else { processName = doc.getElementById("page-header").innerText.trim(); xpath = "//li[contains(@class,'task')]"; } var result = document.evaluate( xpath, doc, null, XPathResult.ANY_TYPE, null ); var numDone = 0; var task; while ((task = result.iterateNext())) { var taskUri = task.dataset.href; var formUri = taskUri.replace("task-details", "form"); let headers = new Headers({ Accept: "application/json", "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest" }); var taskNum = parseInt(taskUri.match(/task=([0-9]+)/)[1]); console.log(taskNum); var fetchResponse = await fetch(formUri, { method: "GET", headers: headers }); var myJson = await fetchResponse.json(); console.log(myJson); var jsonHTML = myJson.Message.html; jsonHTML = jsonHTML.replace(/form-section/g, "form-section-off"); jsonHTML = jsonHTML.replace( /<ul class/g, '<ul style="display:none;" class' ); console.log(jsonHTML); //var files = jsonHTML.match(/<a href="(\/workflows\/processes\/.*\/get-file\?id=[a-zA-z0-9]*)">/g); var files = jsonHTML.match( /\/workflows\/processes\/.*\/get-file\?id=[a-zA-z0-9]*/g ); if (files) { for (var file of files) { var fileResponse = await fetch(file); var blob = await fileResponse.blob(); console.log(blob.type); const blobArrayBuffer = await readBlobAsArrayBuffer(blob); //blob.arrayBuffer().then(async function(myBuffer){ if (blob.type === "application/pdf") { const pdf = await PDFLib.PDFDocument.load( blobArrayBuffer ); console.log(pdf); const numPages = pdf.getPages().length; const copiedPages = await bigPdf.copyPages( pdf, Array.from(Array(numPages).keys()) ); copiedPages.forEach(page => { bigPdf.addPage(page); }); } else if (blob.type === "image/jpeg") { // Embed the JPG image bytes and PNG image bytes const jpgImage = await bigPdf.embedJpg(blobArrayBuffer); // Get the width/height of the JPG image scaled down to 25% of its original size const jpgDims = jpgImage.scale(0.5); // Add a blank page to the document const page = bigPdf.addPage([ jpgDims.width, jpgDims.height ]); // Draw the JPG image in the center of the page page.drawImage(jpgImage, { x: page.getWidth() / 2 - jpgDims.width / 2, y: page.getHeight() / 2 - jpgDims.height / 2, width: jpgDims.width, height: jpgDims.height }); } else if (blob.type === "image/png") { // Embed the JPG image bytes and PNG image bytes const jpgImage = await bigPdf.embedPng(blobArrayBuffer); // Get the width/height of the JPG image scaled down to 25% of its original size const jpgDims = jpgImage.scale(0.5); // Add a blank page to the document const page = bigPdf.addPage([ jpgDims.width, jpgDims.height ]); // Draw the JPG image in the center of the page page.drawImage(jpgImage, { x: page.getWidth() / 2 - jpgDims.width / 2, y: page.getHeight() / 2 - jpgDims.height / 2, width: jpgDims.width, height: jpgDims.height }); } //bigPdf.addPage(pdf); // console.log(pdf); //var objectURL = URL.createObjectURL(myBlob); //let reader = new FileReader(); //reader.readAsDataURL(myBlob); //reader.onload = function() { // console.log(myBlob); //allHTML += "<embed src=\""+reader.result+"\" width=\"850\" height=\"1100\" class=\"page-break\" type=\"application/pdf\">"; //numDone += 1; // pdfButtonProgress.innerHTML = parseInt(100 * (numDone / (totalTasks + 3) )).toString() + "%"; //}; } } console.log(files); var jsonHeader = myJson.Message.header; allHTML[taskNum] = "<h1>" + jsonHeader + "</h1>" + jsonHTML; // numDone += 1; // pdfButtonProgress.innerHTML = parseInt(100 * (numDone / (totalTasks + 3))).toString() + "%"; // <a href="/workflows/processes/5d0a73db7b86eb6fe20f6092/5d1a18b97b86eb0a7532e0f9/5d1a18b97b86eb39037d417d/get-file?id=5d372340a814e42a0d1872e1"> } html2pdf() .set({ html2canvas: { scale: 2 }, pagebreak: { before: ".page-break", avoid: ["div", "h1", ".form-section-offs"] } }) .from('<div style="padding:100px;">' + allHTML.join(" ") + "</div>") .output("datauristring") .then(async function(pdfAsString) { //pdfButtonProgress.innerHTML = parseInt(100 * (numDone / (totalTasks + 2))).toString() + "%"; const htmlPdf = await PDFLib.PDFDocument.load(pdfAsString); //pdfButtonProgress.innerHTML = parseInt(100 * (numDone / (totalTasks + 1.5))).toString() + "%"; const numPages = bigPdf.getPages().length; const copiedPages = await htmlPdf.copyPages( bigPdf, Array.from(Array(numPages).keys()) ); //pdfButtonProgress.innerHTML = parseInt(100 * (numDone / (totalTasks + 1.2))).toString() + "%"; copiedPages.forEach(page => { htmlPdf.addPage(page); }); //pdfButtonProgress.innerHTML = parseInt(100 * (numDone / (totalTasks + 1))).toString() + "%"; //const pdfUrl = URL.createObjectURL( // new Blob([await htmlPdf.save()], { type: 'application/pdf' }), //); saveAs( new Blob([await htmlPdf.save()]), studentName + " - " + processName + ".pdf" ); //pdfButtonProgress.innerHTML = parseInt(100 * (numDone / totalTasks)).toString() + "%"; iconElement.classList.remove("lds-circle"); //pdfButtonText.innerHTML = "Saved"; //pdfButtonProgress.innerHTML = ""; //htmlPdf.save(); }); } //saveAs(await htmlPdf.save(), "Form.pdf"); //window.open(pdfUrl, '_blank'); //htmlPdf.save(); // }); // console.log(allHTML); } (async function() { "use strict"; var newStyle = document.createElement("style"); newStyle.innerHTML = ` .pill { background-color: #fff; padding: .5em; border-radius: 5px; display: inline-block; cursor: default; margin-top: 1em; font-size: 8pt; } .pure-button-pdf { color: #eb6841; background: #fff; padding: 0.1em;} .pdfIcon { margin-left:2px; margin-right:2px;} .lds-circle { display: inline-block; transform: translateZ(1px); } .lds-circle { display: inline-block; animation: lds-circle 2.4s cubic-bezier(0, 0.2, 0.8, 1) infinite; } @keyframes lds-circle { 0%, 100% { animation-timing-function: cubic-bezier(0.5, 0, 1, 0.5); } 0% { transform: rotateY(0deg); } 50% { transform: rotateY(1800deg); animation-timing-function: cubic-bezier(0, 0.5, 0.5, 1); } 100% { transform: rotateY(3600deg); } } `; document.getElementsByTagName("head")[0].append(newStyle); var showFormsButton = document.createElement("button"); showFormsButton.onclick = clickAllImageButtons; showFormsButton.innerHTML = '<i class="far fa-images"></i> Show Thumbnails for All Uploads'; showFormsButton.classList.add("pure-button"); document.getElementById("page-header").append(showFormsButton); var allPDFsButton = document.createElement("button"); allPDFsButton.onclick = downloadAllPDFs; allPDFsButton.innerHTML = '<i class="far fa-file-pdf"></i> Download all Completed as PDFs'; allPDFsButton.classList.add("pure-button"); document.getElementById("page-header").append(allPDFsButton); doIncomplete(); doCompletePDFButtons(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址