Greasy Fork

Greasy Fork is available in English.

北师硕博论文下载器

本程序仅因北师大在线pdf文档无法在线标记而制作,严格禁止下载文件外传,请务必配合

当前为 2024-01-06 提交的版本,查看 最新版本

// ==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
// ==/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 = `<div class="s-top s-top-status"><div class="s-panel"><div class="s-progress-wrapper"><div class="s-progress"></div></div><div class="s-status" style=""><div class="s-text" style="">正在加载...</div><div class="s-progress-text">0%<div></div></div></div></div></div>`;
                const messageOverlay = `<div class="s-top s-top-message"><div class="s-message">testtest</div></div>`;
                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();

    })
})()