// ==UserScript==
// @name 北师硕博论文下载器
// @version 1.0.5
// @namespace https://bnu.edu.cn
// @description 本程序仅因北师大在线pdf文档无法在线标记而制作,严格禁止下载文件外传,请务必配合
// @author None 佚名
// @antifeature 需要登录图书馆论文版权系统才能导出PDF
// @require https://cdn.bootcss.com/jquery/3.5.1/jquery.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.debug.js
// @require https://cdn.staticfile.org/html2canvas/1.4.1/html2canvas.min.js
// @match *://etdlib.bnu.edu.cn/read/*
// @license Apache-2.0
// @downloadURL none
// ==/UserScript==
(function () {
console.log('Thesis helper loaded');
'use strict';
$(function () {
console.log('Thesis helper loaded');
function addbutton() {
// 页面增加下载按钮
var topElement = document.querySelector('.pdf-top-con');
// 添加toolif
var newGroup = document.createElement('div');
newGroup.setAttribute('class', 'toolbar-lf');
// 添加分隔符
var fgElement = document.createElement('div');
fgElement.setAttribute('class', 'toolbar-separator');
// 添加下载button
var newAnchorElement = document.createElement('a');
newAnchorElement.setAttribute('class', 'downloadbutton');
newAnchorElement.setAttribute('onclick', 'download();');
var newParagraphElement = document.createElement('p');
newParagraphElement.innerHTML = '📩 下载PDF';
newAnchorElement.appendChild(newParagraphElement);
topElement.appendChild(newGroup);
newGroup.appendChild(fgElement);
newGroup.appendChild(newAnchorElement);
topElement.appendChild(newGroup);
}
// 显示提示的功能
function showtoast(msg, duration = 3000) {
var m = document.createElement('div');
m.innerHTML = msg;
m.setAttribute('id', 'msg');
m.style.cssText = "max-width:60%;min-width: 150px;padding:0 14px;min-height: 40px;color: rgb(255, 255, 255);line-height: 40px;text-align: center;border-radius: 4px;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 9999999999;background: rgba(0, 0, 0,.7);font-size: 16px;";
document.body.appendChild(m);
setTimeout(() => {
var d = 0.5;
m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
m.style.opacity = '0';
setTimeout(() => { document.body.removeChild(document.querySelector("#msg")) }, d * 1000);
}, duration);
}
const Controllerdocs = {
// 本部分代码参考 “文库下载器|百度网盘直链解析下载 http://www.zhihupe.com/”
// PDF 合并功能进度展示代码
addStatus:function(){
const statusOverlay = `
`;
const messageOverlay = ``;
document.body.insertAdjacentHTML('afterbegin', statusOverlay);
document.body.insertAdjacentHTML('afterbegin', messageOverlay);
document.head.appendChild(document.createElement('style')).innerHTML = `
.s-top{position: fixed;top: 0;left: 0;bottom: 0;right: 0;z-index: 99999999;padding-top: 40vh;display: none;}
.s-top.s-top-message{text-align: center;}
.s-message{background-color: #000000aa;color: white;padding: 8px 14px;text-align: center;font-size: 18px;border-radius: 6px;display: inline-block;}
.s-top.s-top-status{z-index: 99999998;cursor: wait;background-color: rgba(0, 0, 0, 0.4);backdrop-filter: blur(10px) saturate(1.8);}
.s-top.show{display: block;}
.s-panel{background: white;width: 90%;max-width: 480px;border-radius: 12px;padding: 14px 24px;margin: 0 auto;}
.s-progress-wrapper{height: 24px;border-radius: 12px;width: 100%;background-color: #eeeff3;overflow: hidden;margin-bottom: 12px;}
.s-progress{background-color: #54be99;height: 24px;width: 0;transition: width 0.2s ease;}
.s-status{display: flex;font-size: 14px;}
.s-text{flex-grow: 1;color: #5f5f5f;}
.s-progress-text{color: #54be99;font-weight: bold;}
.s-message{}
.swal2-actions{margin: 20px auto 0;}
.swal2-styled.swal2-cancel{border-radius: 5px;font-size: 16px;}
.swal2-styled.swal2-confirm{border-radius: 5px;font-size: 16px;}
.swal2-styled{margin: 5px;padding: 8px 16px;}
.none{display:none}
`;
},
showStatus:function(text='', progress=-1){
document.querySelector('.s-top.s-top-status').classList.add('show');
if(text) document.querySelector('.s-panel .s-text').innerHTML = text;
if (progress >= 0) {
progress = Math.min(progress, 100);
document.querySelector('.s-panel .s-progress').style.width = `${Math.floor(progress)}%`;
document.querySelector('.s-panel .s-progress-text').innerHTML = `${Math.floor(progress)}%`;
}
},
hideStatus:function(){
document.querySelector('.s-top.s-top-status').classList.remove('show');
},
}
function add_img_url() {
return new Promise((resolve) => {
showtoast('正在获取数据中,请勿操作',500)
document.getElementById('btnfirst').click(); // 返回首页
let checkImages = () => {
var img_database = document.querySelectorAll('img');
var TotalPage = parseInt((document.getElementById('totalPages').innerText).match(/\d+/)[0]);
// console.log('Number of images:', img_database.length);
// img_url 空值检查
var imgList = Array();
for (let i = 0; i < img_database.length; i++) {
imgList[i] = img_database[i].currentSrc;
}
if (img_database.length !== TotalPage || imgList.includes('')) {
setTimeout(() => {
showtoast('正在获取数据中,请勿操作',500);
document.getElementById('btnnext').click();
checkImages();
}, 500); // 间隔0.5秒翻页
} else {
document.getElementById('btnnext').click();
// console.log('准备制作PDF的IMG储备完毕');
// console.log(imgList);
resolve('图片链接加载成功');
}
};
checkImages();
});
}
function loadImage(url) {
// 图片加载
return new Promise((resolve, reject) => {
var img = new Image();
var data;
img.setAttribute("crossOrigin", "Anonymous");
img.src = url;
img.onError = function () {
throw new Error('Cannot load image: "' + url + '"');
};
img.onload = function () {
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Grab the image as a jpeg encoded in base64, but only the data
data = canvas
.toDataURL("image/jpeg")
.slice("data:image/jpeg;base64,".length);
// Convert the data to binary form
data = atob(data);
document.body.removeChild(canvas);
resolve(data);
};
});
}
async function download() {
// 加载img_url
await add_img_url();
Controllerdocs.addStatus();
// pdf 图片下载
var imgList = Array();
var img_database = document.querySelectorAll('img');
for (let i = 0; i < img_database.length; i++) {
imgList[i] = img_database[i].currentSrc;
}
var imgData = new Array();
for (var i = 0; i < imgList.length; i++) {
var link = imgList[i];
// console.log("获取第" + (i+1) + "张图片");
// console.log(link);
Controllerdocs.showStatus('准备合并为PDF文件中,请勿离开本页面', (i + 1) /imgList.length * 100);
await loadImage(link).then((data) => {
imgData.push(data);
});
}
// pdf 图片合并为pdf
// console.log("正在合并图片为PDF");
Controllerdocs.showStatus('正在合成图片为PDF文件');
var contentWidth = parseFloat(document.getElementById('PageContainer_0').style.width.replace('px', ''))
var contentHeight = parseFloat(document.getElementById('PageContainer_0').style.height.replace('px', ''))
const orientation = contentWidth > contentHeight ? 'l' : 'p';
var doc = new jsPDF({
orientation: orientation,
unit: "px",
format: [contentWidth, contentHeight],
});
const namepdf = document.getElementById('infoname').value
const output = namepdf + ".pdf";
let idx = 0;
imgData.forEach((e) => {
idx++;
doc.addImage(e, "JPG", 0, 0, contentWidth, contentHeight);
if (idx < imgData.length) {
doc.addPage();
}
});
doc.save(output);
Controllerdocs.hideStatus();
}
// 绑定下载按钮
$(document).ready(function () {
$(".downloadbutton").on("click", function () {
download();
});
});
addbutton();
})
})()