Greasy Fork

百度-原创力-人人-豆丁-道客-豆丁建筑

你能看见多少我能下载多少。下载公开免费的 PPTX、PDF、DOCX、TXT等文件。

目前为 2024-02-21 提交的版本。查看 最新版本

// ==UserScript==
// @name         百度-原创力-人人-豆丁-道客-豆丁建筑
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  你能看见多少我能下载多少。下载公开免费的 PPTX、PDF、DOCX、TXT等文件。
// @author       Mr.Fang
// @match        https://*.book118.com/*
// @match        https://*.renrendoc.com/*
// @match        https://*.docin.com/*
// @match        https://*.doc88.com/*
// @match        https://wenku.baidu.com/*
// @match        https://wkbjcloudbos.bdimg.com/*
// @match        https://wkretype.bdimg.com/*
// @require      https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jspdf/2.4.0/jspdf.umd.min.js
// @require      https://cdn.jsdelivr.net/npm/@zip.js/[email protected]/dist/zip.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
// @icon         https://dtking.cn/favicon.ico
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_download
// @grant       GM_notification
// @grant        unsafeWindow
// @license      Apache-2.0
// ==/UserScript==

(function () {
    'use strict';
    let MF =
        '#MF_fixed{position:fixed;top:50%;transform:translateY(-50%);right:20px;gap:20px;flex-direction:column;z-index:2147483647;display:flex}';
    MF +=
        '.MF_box{padding:10px;cursor:pointer;border-color:rgb(0,102,255);border-radius:5px;background-color:white;color:rgb(0,102,255);margin-right:10px;box-shadow:rgb(207,207,207) 1px 1px 9px 3px}.MF_active{color: green;}';
    MF +=
        '@media print{html{height:auto !important}body{display:block !important}#app-left{display:none !important}#app-right{display:none !important}#MF_fixed{display:none !important}.menubar{display:none !important}.top-bar-right{display:none !important}.user-guide{display:none !important}#app-reader-editor-below{display:none !important}.no-full-screen{display:none !important}.comp-vip-pop{display:none !important}.center-wrapper{width:auto !important}.reader-thumb,.related-doc-list,.fold-page-content,.try-end-fold-page,.lazy-load,#MF_textarea{display:none !important}}'
    const prefix = "MF_";
    /**
     * @description 添加 URL 到本地缓存
     * @author Mr.Fang
     * @time 2024年2月4日
     * @param {Array} urls 数据
     * @param key
     */
    const MF_addURL = (urls, key = 'listData') => {
        let listData = JSON.parse(localStorage.getItem(key)) || [];
        let index = 0;
        let length = listData.length;
        urls.forEach((url) => {
            if (!listData.some(item => item.src === url)) {
                // 添加新的URL对象
                listData.push({
                    src: url,
                    page: length + index
                });
                index++;
            }
        })
        // 将更新后的URL数组存储回localStorage
        localStorage.setItem(key, JSON.stringify(listData));
        GM_setValue(key, JSON.stringify(listData))
        console.log('URL已添加:');
    }

    class Box {
        id = ""; // id
        label = ""; // 按钮文本
        fun = ""; // 执行方法
        constructor(id, label, fun) {
            this.id = id;
            this.label = label;
            this.fun = fun;
        }
    }

    class Utility {
        debug = true;

        /**
         * 添加 css 样式
         * @param e 节点
         * @param data JSON 格式样式
         */
        style(e, data) {
            Object.keys(data).forEach(key => {
                e.style[key] = data[key]
            })
        }

        attr(e, key) {
            return e.getAttribute(key)
        }

        /**
         *  追加样式
         * @param css  格式样式
         */
        appendStyle(css) {
            let style = this.createEl('', 'style');
            style.textContent = css;
            style.type = 'text/css';
            let dom = document.head || document.documentElement;
            dom.appendChild(style);
        }

        /**
         * @description 创建 dom
         * @param id 必填
         * @param elType
         * @param data
         */
        createEl(id, elType, data) {
            const el = document.createElement(elType);
            el.id = id || '';
            if (data) {
                this.style(el, data);
            }
            return el;
        }

        query(el) {
            return document.querySelector(el);
        }

        queryAll(el) {
            return document.querySelectorAll(el);
        }

        update(el, text) {
            const elNode = this.query(el);
            if (!elNode) {
                console.log('节点不存在');
            } else {
                elNode.innerHTML = text;
            }
        }

        /**
         * 进度
         * @param current 当前数量 -1预览结束
         * @param total 总数量
         * @param content 内容
         */
        preview(current, total, content) {
            return new Promise(async (resolve, reject) => {
                if (current === -1) {
                    this.update('#' + prefix + 'text', content ? content : "已完成");
                } else {
                    let p = (current / total) * 100;
                    let ps = p.toFixed(0) > 100 ? 100 : p.toFixed(0);
                    console.log('当前进度', ps)
                    this.update('#' + prefix + 'text', '进度' + ps + '%');
                    await this.sleep(500);
                    resolve();
                }
            })

        }

        preText(content) {
            this.update('#' + prefix + 'text', content);
        }

        gui(boxs) {
            const box = this.createEl(prefix + "fixed", 'div');
            for (let x in boxs) {
                let item = boxs[x];
                let el = this.createEl(prefix + item.id, 'button');
                el.append(new Text(item.label));
                if (x === '0') {
                    el.classList = prefix + 'box ' + prefix + "active";
                } else {
                    el.className = prefix + "box";
                }
                if (item.fun) {
                    el.onclick = function () {
                        eval(item.fun);
                    }
                }
                box.append(el);
            }
            document.body.append(box);
        }

        sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }

        log(msg) {
            if (this.debug) {
                console.log(msg);
            }
        }

        logt(msg) {
            if (this.debug) {
                console.table(msg);
            }
        }
    }

    const u = new Utility();
    u.appendStyle(MF);


    const btns = [
        new Box('text', '状态 0 %'),
        new Box('start', '自动预览', 'autoPreview()'),
        new Box('stop', '停止预览', 'stopPreview()'),
        new Box('down', '下载图片', 'executeDownload(2)'),
        new Box('pdf', '下载PDF', 'executeDownload(1)')
    ]

    const domain = {
        renrendoc: "renrendoc.com",
        book118: 'book118.com',
        docin: 'docin.com',
        wenku: 'wenku.baidu.com',
        doc88: 'doc88.com',
    };
    const {
        host,
        href,
        origin
    } = window.location;
    const jsPDF = jspdf.jsPDF;
    const zipWriter = new zip.ZipWriter(new zip.BlobWriter("application/zip"), {
        bufferedWrite: true,
        useCompressionStream: false
    });
    const doc = new jsPDF({
        orientation: 'p',
        unit: 'px',
        compress: true
    });
    let pdf_w = 446,
        pdf_h = 631,
        pdf_ratio = 0.56,
        title = document.title,
        fileType = '',
        downType = 1, // 下载文件类型
        select = null,
        dom = null,
        beforeFun = null,
        interval = null,
        BASE_URL = 'https://wkretype.bdimg.com/retype',
        readerInfoBai = null, // 百度文档参数
        intervalBai = null; // 百度定时任务

    const params = new URLSearchParams(document.location.search.substring(1));
    console.log(params);
    if (params.size && params.get('custom')) {
        window.parent.postMessage({
            type: "onload",
            value: 'success'
        }, "*")
        u.log('子页面加载完成!');
    }

    /**
     * 人人监听侧边栏点击切换问题
     */
    const renObserve = () => {
        const targetNode = u.query(".center-wrap");
        if (targetNode) {
            const observerOptions = {
                childList: true,
                attributes: false,
                subtree: false
            };
            // dom 监听器
            const observer = new MutationObserver(function (mutationList, observer) {
                mutationList.forEach((mutation) => {
                    const addedNodes = mutation.addedNodes;
                    if (addedNodes.length) {
                        addedNodes.forEach(item => {
                            if (item.className === 'main-content') {
                                dom = item;
                                let node = u.query('h1');
                                title = node.innerText.replaceAll(" ", "");
                                node.nextElementSibling.children
                                let innerText = node.nextElementSibling.children[6].innerText;
                                fileType = innerText.split(":")[1].toLowerCase();
                                localStorage.removeItem('down')
                            }
                        })
                    }
                });
            });
            // 触发监听
            observer.observe(targetNode, observerOptions);
        }
    }

    // 监听页面加载完成事件
    window.onload = function () {
        // 移除多余 iframe
        document.querySelectorAll('iframe').forEach(item => {
            item.remove()
        })
        // 在这里执行渲染完成后的操作
        console.log('HTML 渲染完成!');
        // 清空系统缓存数据
        localStorage.removeItem('listData')
        localStorage.removeItem('length')
        localStorage.removeItem('current')
        localStorage.removeItem('pageData')
        localStorage.removeItem('down')
        // 百度服务端渲染
        if (host.includes(domain.wenku)) {
            const {
                readerInfo,
                viewBiz
            } = pageData;
            fileType = viewBiz.docInfo.fileType;
            title = viewBiz.docInfo.aiQueryTitle;
            readerInfoBai = readerInfo;
            const htmlUrls = readerInfo.htmlUrls;
            if (htmlUrls) {
                if (fileType.includes('ppt')) {
                    MF_addURL(htmlUrls);
                } else if (fileType.includes('pdf')) {
                    let images = [];
                    if (htmlUrls.png) {
                        images = htmlUrls.png.map(item => {
                            return item.pageLoadUrl
                        })
                    } else {
                        images = htmlUrls;
                    }
                    MF_addURL(images);
                }
                // 文本内容地址保存
                if (htmlUrls.json) {
                    let pageLoadUrl = htmlUrls.json.map(item => {
                        return item.pageLoadUrl
                    })
                    MF_addURL(pageLoadUrl, 'pageData');
                }
            }
            // 纯文本类型文件
            if (fileType === "txt") { // 纯文本类型
                let urls = [];
                const {
                    docId,
                    freePage,
                    rsign,
                    showPage,
                    md5sum
                } = readerInfoBai;
                for (var i = 1; i < showPage + 1; i++) {
                    let x = md5sum.substring(1);
                    let n = ["pn=" + i, "rn=1", "type=txt", "spr=0", "rsign=" + rsign,
                        "callback=wenku_" + i
                    ].join("&");
                    let url = BASE_URL + "/text/" + docId + "?" + x + "&" + n;
                    urls.push(url)
                }
                MF_addURL(urls, 'pageData');
            }
            // let switchBtn = document.querySelector('.switch-btn');
            // if (!switchBtn?.className.includes('quit')) { // 编辑模式
            //     switchBtn.click();
            // }
            // URL地址
            console.log('htmlUrls:' + JSON.stringify(htmlUrls))
            // 封面
            console.log('coverUrl:' + viewBiz.docInfo.coverUrl)
            // 页码
            console.log('page:' + viewBiz.docInfo.page)
            setTimeout(() => {
                baiduCopy()
            }, 500)
            intervalBai = setInterval(() => {
                const chat = u.query('#wk-chat');
                if (chat) {
                    chat.remove()
                }
                const vip = u.query('.vip-privilege');
                if (vip) {
                    vip.remove()
                }

            }, 1000);
        }
        // 监听子页面加载完成,发送消息
        const params = new URLSearchParams(document.location.search.substring(1));
        if (!params.size || !params.get('custom')) {
            init()
        }
    };

    const baiduCopy = () => {
        const observerOptions = {
            characterData: true,
            subtree: true
        };
        // dom 监听器
        const observer = new MutationObserver(function (mutationList, observer) {
            const mutation = mutationList[0];
            console.log('mutation: ', mutation);
            let data = mutation.target.data;
            let result = data.substring(data.indexOf('“') + 1, data.lastIndexOf('”'));
            let textarea = u.query('#MF_textarea');
            if (textarea) {
                textarea.innerText = result;
            } else {
                textarea = u.createEl('MF_textarea', 'textarea');
                textarea.style.width = "100%"
                textarea.style.height = "200px"
                textarea.style.outline = "none";
                textarea.style.padding = "10px";
                textarea.style.boxSizing = "border-box";
                textarea.style.fontSize = "16px"
                textarea.style.border = "1px solid rgb(204, 204, 204)"
                textarea.innerText = result;
                let box = u.query('#catalog-main') || u.query('.catalog-main')|| u.query('.related-doc-list')
                box.before(textarea);
            }
            console.log(textarea);
        });
        const targetNode2 = document.querySelector('.link')
        // 触发监听
        observer.observe(targetNode2, observerOptions);
    }


    window.onunload = function () {
        if (intervalBai) {
            clearInterval(intervalBai);
            intervalBai = null;
        }
    }


    // 百度 xhr 数据监听
    if (host.includes(domain.wenku)) {
        const _r_text = window.Response.prototype.text;
        window.Response.prototype.text = function () {
            return new Promise((resolve, reject) => {
                _r_text.call(this).then((text) => {
                    resolve(text);
                }).catch(reject);
            });
        }
        const _open = window.XMLHttpRequest.prototype.open;
        window.XMLHttpRequest.prototype.open = function (...args) {
            this.addEventListener("load", () => {
                try {
                    let content = this.responseText;
                    const url = args[1];
                    if (url.includes('ndocview/readerinfo')) {
                        const {
                            data
                        } = JSON.parse(content);
                        const htmlUrls = data.htmlUrls;
                        let list = htmlUrls.png;
                        let images = [];
                        if (list) {
                            images = htmlUrls.png.map(item => {
                                return item.pageLoadUrl
                            });
                        } else {
                            images = htmlUrls;
                        }
                        // 文本内容地址保存
                        if (htmlUrls.json) {
                            let pageLoadUrl = htmlUrls.json.map(item => {
                                return item.pageLoadUrl
                            })
                            MF_addURL(pageLoadUrl, 'pageData');
                        }
                        // 纯文本类型文件
                        if (fileType === "txt") { // 纯文本类型
                            let urls = [];
                            const {
                                docId,
                                freePage,
                                rsign,
                                md5sum
                            } = data;
                            for (var i = readerInfoBai.showPage + 1; i < freePage + 1; i++) {
                                let x = md5sum.substring(1);
                                let n = ["pn=" + i, "rn=1", "type=txt", "spr=0", "rsign=" + rsign,
                                    "callback=wenku_" + i
                                ].join("&");
                                let url = BASE_URL + "/text/" + docId + "?" + x + "&" + n;
                                urls.push(url)
                            }
                            MF_addURL(urls, 'pageData');
                        }
                        MF_addURL(images);
                    }
                } catch {
                }
            });
            return _open.apply(this, args);
        }
    }

    const childMessage = (message) => {
        window.parent.postMessage({
            type: "child",
            value: message ? message : ''
        }, "*")
    }
    const parentMessage = (message, attr) => {
        const ifarme = document.getElementById(attr);
        let _window = ifarme.contentWindow;
        _window.postMessage({
            type: 'parent',
            value: message ? message : ''
        }, "*")
    }
    // 监听页面消息事件
    window.addEventListener("message", (e) => {
        const {
            type,
            value
        } = e.data;
        if (type === 'parent') { // 父级-子页面消息
            if (value.includes(origin)) {
                MF_ImageToBase64(value).then(data => {
                    childMessage(data);
                })
            }
        } else if (type === 'child') { // 子页面-到父页面消息
            let index = Number(localStorage.getItem("current") || "0");
            const {
                data,
                width,
                height
            } = value;
            if (fileType.includes('ppt') || width > height) {
                doc.addPage([width * pdf_ratio, height * pdf_ratio], 'l');
                doc.addImage(data, 'JPEG', 0, 0, width * pdf_ratio, height * pdf_ratio, index, 'FAST')
            } else {
                doc.addPage();
                doc.addImage(data, 'JPEG', 0, 0, pdf_w, pdf_h, index, 'FAST')
            }
            if (index === 1) {
                doc.deletePage(1);
            }
            localStorage.setItem('current', index + 1 + "");
            zipWriter.add(index + ".png", new zip.Data64URIReader(data));
            downimg();
        } else if (type === 'onload') {
            const url = new URL(e.origin);
            const attrId = url.host.replaceAll(".", "");
            const query = document.getElementById('#' + attrId);
            if (query) {
                downimg();
            }
        }
    })


    /**
     * @description 前置方法
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const before = () => {
        if (beforeFun) {
            console.log('---------->beforeFun');
            eval(beforeFun)
        }
        // 画布添加监听事件,当数据加载完成删除 id,防止数据被清空
        if (host.includes(domain.wenku)) {
            const els = u.queryAll('canvas');
            for (var i = 0; i < els.length; i++) {
                let eNode = els[i];
                const intersectionObserver = new IntersectionObserver((entries) => {
                    let isIntersecting = entries[0].isIntersecting
                    if (isIntersecting && eNode.width && eNode.height) {
                        eNode.id = '';
                    }
                });
                // 开始监听
                intersectionObserver.observe(eNode);
            }
        }
    }


    /**
     * @description 后置方法
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const after = () => {

    }

    /**
     * @description 初始化方法
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const init = () => {
        console.table({
            host,
            href,
            origin
        })
        dom = document.documentElement || document.body;
        if (host.includes(domain.renrendoc)) {
            if (!/.*renrendoc\.com\/.+$/.test(href)) {
                console.log('结束');
                return;
            }
            const node = u.query('h1');
            title = node.innerText.replaceAll(" ", "");
            node.nextElementSibling.children
            const innerText = node.nextElementSibling.children[6].innerText;
            fileType = innerText.split(":")[1].toLowerCase();
            dom = u.query('.main-content');
            beforeFun =
                "let er = u.query('#load_preview_btn');if (er && er.style.display !== 'none') {er.click()}";
            select = "#page img";
            btns.push(new Box('PPT', '获取地址', 'downtxt()'))
        } else if (host.includes(domain.book118)) {
            if (!/.+book118\.com\/.+$/.test(href)) {
                console.log('结束');
                return;
            }
            if (!href.includes('pptView.html')) {
                const node = u.query('h1');
                title = node.innerText.replaceAll(" ", "");
                const number = title.lastIndexOf(".");
                fileType = title.substring(number + 1).toLowerCase();
                GM_setValue('title', title);
                if (fileType.includes('ppt')) {
                    beforeFun = "let eb = u.query('#btn_ppt_front_pc');if (eb) {eb.click();}";
                } else {
                    beforeFun = "let eb = u.query('#btn_preview_remain');if (eb) {eb.click();}";
                }
            } else {
                fileType = 'ppt';
                title = GM_getValue('title');
            }
            select = ".webpreview-item img";
            btns.push(new Box('PPT', '获取地址', 'downtxt()'))
        } else if (host.includes(domain.docin)) {
            if (!/.+docin\.com\/.+$/.test(href)) {
                console.log('结束');
                return;
            }
            title = u.query('meta[property="og:title"]').content;
            fileType = u.attr(u.query('h1').children[0], 'title').toLowerCase();
            select = "#contentcontainer canvas";
            if (isUserLogin === '1') {
                beforeFun = "let eb = u.query('.model-fold-show');if (eb) {eb.click();}";
            }
            if (fileType.includes('ppt')) {
                btns.push(new Box('PPT', '获取地址', 'downtxt()'))
            }
        } else if (host.includes(domain.wenku)) {
            if (!/.+wenku\.baidu\.com\/(tfview|view).+$/.test(href)) {
                console.log('结束');
                return;
            }
            dom = u.query('.reader-wrap');
            beforeFun = "let eb = u.query('.unfold');if (eb) {eb.click();}";
            select = "#original-creader-root canvas";
            btns.push(new Box('print-pdf', '打印PDF', 'window.print()'))
            btns.push(new Box('get-text', '获取文本', 'fullText()'))
            if (fileType.includes('ppt') || fileType.includes('pdf')) {
                btns.push(new Box('PPT', '获取地址', 'downtxt()'))
            }
        } else if (host.includes(domain.doc88)) {
            if (!/.+doc88\.com\/.+$/.test(href)) {
                console.log('结束');
                return;
            }
            title = u.query('meta[property="og:title"]').content;
            fileType = u.query("#box1 .attribute").innerText.split(" ")[0].split(":")[1].toLowerCase();
            beforeFun = "let eb = u.query('#continueButton');if (eb) {eb.click();}";
            select = "#pageContainer .inner_page";
        }
        const query = u.query("#btn_ppt_front_pc"); // 原创
        if (!query) {
            u.gui(btns);
        } else {
            query.click();
        }

        console.log('文件名称:', title);
        console.log('文件类型:', fileType);
    }

    /**
     * @description 开始方法,自动预览
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const autoPreview = async () => {
        if (host.includes(domain.book118) && fileType.includes('ppt')) {
            localStorage.setItem('start', '1');
            await autoParsingPPT();
            return false;
        }
        if (interval) return false;
        dom.scrollTop = 0;
        interval = setInterval(() => {
            if (host.includes(domain.book118)) {
                scrollPageArea()
            } else if (host.includes(domain.renrendoc)) {
                scrollPageArea()
            } else if (host.includes(domain.docin)) {
                scrollWinArea()
            } else if (host.includes(domain.wenku)) {
                scrollWinArea()
            } else if (host.includes(domain.doc88)) {
                scrollPageAreaDoc88()
            }
        }, 500);
    }

    /**
     * @description 结束方法,停止预览
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const stopPreview = async () => {
        console.log('---------->stopPreview');
        if (interval) {
            clearInterval(interval);
            interval = null;
        }
        if (host.includes(domain.book118) && fileType.includes('ppt')) {
            localStorage.removeItem('start')
        }
    }

    /**
     * @description 执行文件下载
     * @author Mr.Fang
     * @time 2024年2月20日
     * @param type 文件类型
     */
    const executeDownload = async (type) => {
        downType = type;
        const down = localStorage.getItem('down');
        console.log('down', down)
        if (!down) {
            // 结束后续执行的方法
            if (host.includes(domain.book118)) {
                if (fileType.includes('ppt')) {
                    conditionDownload();
                } else {
                    await parseImage()
                }
            } else if (host.includes(domain.renrendoc)) {
                await parseImage()
            } else if (host.includes(domain.wenku)) {
                const display = u.query('#app-top-right-tool')?.style.display;
                if (display === 'none') {
                    await downimg()
                }
            } else if (host.includes(domain.docin)) {
                await imageToBase64()
                conditionDownload();
            } else if (host.includes(domain.doc88)) {
                await imageToBase64()
                conditionDownload();
            }
        } else {
            conditionDownload();
        }
    }

    /**
     * 根据指定条件下载文件
     */
    const conditionDownload = () => {
        if (downType === 1) {
            downpdf()
            localStorage.setItem('down', '1')
        } else if (downType === 2) {
            downzip()
            localStorage.setItem('down', '1')
        }
        u.preText('下载完成')
    }

    // 滚动指定 Window
    const scrollWinArea = () => {
        before();
        const scrollTop = dom.scrollTop;
        const height = dom.scrollHeight - dom.clientHeight;
        if (height <= scrollTop) {
            stopPreview();
            u.preview(-1);
        } else {
            let top = scrollTop + 500;
            dom.scrollTo({
                top: top,
                left: 0,
                behavior: "smooth",
            });
            u.preview(top, height);
        }
    }
    // 滚动指定区域
    const scrollPageArea = () => {
        before();
        const clientHeight = dom.clientHeight;
        let end = 0;
        const images = u.queryAll(select);
        const length = images.length;
        for (let i = 0; i < length; i++) {
            let item = images[i];
            const {
                top
            } = item.getBoundingClientRect();
            if (item instanceof HTMLImageElement) {
                if (!item.src && !item.getAttribute('data-src')) {
                    end = 1;
                    dom.scrollTo({
                        top: dom.scrollTop + top,
                        left: 0,
                        behavior: "smooth",
                    });
                    u.preview(i + 1, length);
                    break;
                }
            } else if (item instanceof HTMLDivElement) {
                end = 1;
                dom.scrollTo({
                    top: dom.scrollTop + top,
                    left: 0,
                    behavior: "smooth",
                });
                u.preview(i + 1, length);
                break;
            }
        }
        if (end === 0) {
            u.preview(-1);
            stopPreview();
        }
    }

    const scrollPageAreaDoc88 = () => {
        before();
        const clientHeight = dom.clientHeight;
        let end = 0;
        const images = u.queryAll(select);
        const length = images.length;
        for (let i = 0; i < length; i++) {
            let item = images[i];
            const {
                top
            } = item.getBoundingClientRect();
            let previousElementSibling = item.previousElementSibling.previousElementSibling;
            let fs = u.attr(item, 'fs');
            let t = previousElementSibling.innerText;
            if (!fs || t.length) {
                end = 1;
                dom.scrollTo({
                    top: dom.scrollTop + top,
                    left: 0,
                    behavior: "smooth",
                });
                u.preview(i + 1, length);
                break;
            }
        }
        if (end === 0) {
            u.preview(-1);
            stopPreview();
        }
    }

    const imageToBase64 = async () => {
        const images = u.queryAll(select);
        const length = images.length;
        for (let i = 0; i < length; i++) {
            let {
                data,
                width,
                height
            } = await MF_CanvasToBase64(images[i]);
            let fileName = i + ".png";
            zipWriter.add(fileName, new zip.Data64URIReader(data));
            if (fileType.includes('ppt')) {
                doc.addPage([width * pdf_ratio, height * pdf_ratio], 'l');
                doc.addImage(data, 'JPEG', 0, 0, width * pdf_ratio, height * pdf_ratio, i, 'FAST')
            } else {
                doc.addPage();
                doc.addImage(data, 'JPEG', 0, 0, pdf_w, pdf_h, i, 'FAST')
            }
            if (i === 1) {
                doc.deletePage(1);
            }
            await u.preview(i + 1, length);
        }
        console.log('处理完成', length);
    }

    /**
     * @description 原创力 PPT 解析
     * @author Mr.Fang
     * @time 2024年2月21日
     */
    const autoParsingPPT = async () => {
        if (!localStorage.getItem("start")) {
            u.preview(-1, null, "已终止");
            return;
        }
        const page = Number(u.query('#PageIndex').innerText);
        const total = Number(u.query('#PageCount').innerText);
        const childNodes = u.query("#view").childNodes;
        const count = childNodes.length;
        const max_index = page - 1;
        const current = childNodes[max_index];
        // 动作数量
        const a_len = u.queryAll(`#view${max_index} #animt${max_index}>div`).length;
        if (a_len !== 0) {
            await u.sleep(1000);
        }
        const bgs = MF_RecursiveParsingImages(current);
        await new Promise((resolve) => {
            html2canvas(current, {
                useCORS: true
            }).then(function (canvas) {
                // 将canvas转换为图片并下载.
                let data = canvas.toDataURL();
                let fileName = max_index + "_" + a_len + ".png";
                zipWriter.add(fileName, new zip.Data64URIReader(data));
                // 添加PDF
                // 794px*1123px ;
                doc.addPage([canvas.width * pdf_ratio, canvas.height * pdf_ratio], 'l');
                doc.addImage(data, 'JPEG', 0, 0, canvas.width * pdf_ratio, canvas.height *
                    pdf_ratio, max_index + "_" + a_len, 'FAST')
                if (max_index === 1) {
                    doc.deletePage(1);
                }
                resolve();
            });
        })
        if (a_len === 0) {
            const detail = bgs.map((item, i) => {
                return zipWriter.add(max_index + "/" + i + ".png", new zip.HttpReader(item));
            });
            await Promise.all(detail);
            zipWriter.add(max_index + "/" + "文本描述.txt", new zip.TextReader(current.innerText));
        }
        u.preview(page, total);
        const pageNext = u.query('#pageNext');
        const btmRight = u.query('.btmRight');

        if (page !== total) {
            btmRight.click();
            await autoParsingPPT(zipWriter);
        }
    }

    /**
     * @description 解析图片 [src]
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const parseImage = async () => {
        const images = u.queryAll(select);
        if (!images.length) {
            u.log('------>parseImage 暂无数据');
            return;
        }
        const listData = [];
        images.forEach((item) => {
            let src = u.attr(item, 'data-src') || item.src;
            if (src.includes('http:')) {
                src = src.replace("http:", "https:")
            } else if (src.startsWith("//")) {
                src = "https:" + src;
            }
            const page = u.attr(item, 'data-page') || u.attr(item.parentElement, 'data-id');
            listData.push({
                page,
                src
            })
        })
        const store = JSON.stringify(listData);
        u.logt(listData)
        u.log('size:' + images.length);
        GM_setValue('listData', store);
        localStorage.setItem('listData', store)
        u.log('--------->downimg');
        localStorage.removeItem('current')
        downimg()
    }

    /**
     * @description 下载图片
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const downimg = async () => {
        const images = JSON.parse(GM_getValue('listData'));
        const length = images.length;
        localStorage.setItem('length', length);
        let current = Number(localStorage.getItem("current")) || 0;
        u.log('downimg----------->current:' + current)
        for (let index = current; index < length; index++) {
            const image = images[index];
            const src = image.src;
            if (src.includes(host)) { // 当前域
                const {
                    data,
                    width,
                    height
                } = await MF_ImageToBase64(src);
                if (fileType.includes('ppt') || width > height) {
                    doc.addPage([width * pdf_ratio, height * pdf_ratio], 'l');
                    doc.addImage(data, 'JPEG', 0, 0, width * pdf_ratio, height * pdf_ratio, index, 'FAST')
                } else {
                    doc.addPage();
                    doc.addImage(data, 'JPEG', 0, 0, pdf_w, pdf_h, index, 'FAST')
                }
                if (index === 1) {
                    doc.deletePage(1);
                }
                zipWriter.add(index + ".png", new zip.Data64URIReader(data));
            } else {
                const url = new URL(src);
                const attrId = url.host.replaceAll(".", "")
                const query = document.getElementById('#' + attrId);
                if (query) { // 框架是否存在
                    parentMessage(src, "#" + attrId);
                } else {
                    const el = u.createEl("#" + attrId, 'iframe');
                    el.src = url.origin + '?custom=true';
                    el.style.visibility = "hidden";
                    document.body.append(el);
                }
                localStorage.setItem('current', index + "");
                break;
            }
            current = index;
        }
        u.preview(current, length);
        if (current === length - 1) {
            conditionDownload();
        }
    }

    /**
     * @param {String} url 请求地址
     */
    const requestGet = (url) => {
        return new Promise((resolve, reject) => {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", url, true);
            // xhr.setRequestHeader("Content-Type", "application/json");
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 206 || xhr.status === 200) {
                        try {
                            let responseText = xhr.responseText;
                            let result = responseText.substring(responseText.indexOf('\(') + 1,
                                responseText.length - 1);
                            u.log(result)
                            resolve(JSON.parse(result));
                        } catch (e) {
                            reject(e);
                        }
                    } else {
                        reject(new Error(`HTTP status code ${xhr.status}`));
                    }
                }
            };
            xhr.onerror = function () {
                reject(new Error("Network error"));
            };
            xhr.send();
        });
    }

    /**
     * 复制到剪切板
     * @param text
     */
    const copyToClipboard = (text) => {
        var input = document.createElement("textarea");
        input.value = text;
        document.body.appendChild(input);
        input.select();
        document.execCommand("copy");
        document.body.removeChild(input);
    }

    /**
     * @description 通过接口获取文本内容
     * @author Mr.Fang
     * @time 2024年2月20日
     */
    const fullText = async () => {
        let text = '';
        const pageData = JSON.parse(localStorage.getItem('pageData'));
        for (var i = 0; i < pageData.length; i++) {
            let url = pageData[i].src;
            let resultData = await requestGet(url);
            if (resultData instanceof Array) {
                text += resultData[0].parags[0].c;
            } else {
                resultData.body.forEach(item => {
                    if (typeof item.c === "string") {
                        text += item.c;
                    }
                })
            }
        }
        MF_ExportTxt(text, `${title}.txt`);
    }

    /**
     * @description 下载压缩包,包含图片
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const downzip = () => {
        zipWriter.close().then((blob => {
            GM_download(URL.createObjectURL(blob), `${title}.zip`);
            URL.revokeObjectURL(blob);
        }));
    }

    /**
     * @description 下载 PDF
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const downpdf = () => {
        // 下载 PDF 文件
        doc.save(`${title}.pdf`, {
            returnPromise: true
        });
    }


    /**
     * @description 下载 txt 文本
     * @author Mr.Fang
     * @time 2024年2月2日
     */
    const downtxt = () => {
        const images = JSON.parse(GM_getValue('listData'));
        const text = images.map(item => {
            return item.src
        }).join("\n");
        MF_ExportTxt(text, `${title}.txt`);
    }

    /**
     * @description 递归加载子节点,获取子节点背景,img 属性值
     * @author Mr.Fang
     * @time 2024年1月20日18:05:49
     * @param children
     * @returns {*[]}
     */
    const MF_RecursiveParsingImages = (children) => {
        const list = [];
        if (children.childNodes.length) {
            children.childNodes.forEach(item => {
                if (item || item instanceof HTMLImageElement) {
                    if (item instanceof HTMLImageElement) { // 图片
                        let src = item.src;
                        list.push(src);
                    } else if (item.style) {
                        let bgi = item.style.backgroundImage;
                        if (bgi && bgi !== 'initial') {
                            let src = bgi.substring(bgi.indexOf("\"") + 1, bgi.lastIndexOf("\""));
                            src = src.indexOf("/") === 0 ? src : "/" + src;
                            list.push(origin + src);
                        }
                    }
                    if (item.childNodes.length) {
                        const images = MF_RecursiveParsingImages(item);
                        list.push(...images);
                    }
                }
            })
        }
        return list;
    }

    /**
     * @description 导出 txt 文件
     * @author Mr.Fang
     * @time 2024年1月20日18:05:49
     * @param {Object} data 数据
     * @param {Object} filename 文件名
     */
    const MF_ExportTxt = (data, filename) => {
        const csvContent = "data:text/txt;charset=utf-8," + data;
        const encodedUri = encodeURI(csvContent);
        const link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", filename);

        // 点击链接以下载文件
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }

    /**
     * @description 加载图片
     * @author Mr.Fang
     * @time 2024年1月20日18:05:49
     * @param src 图片地址
     * @returns {Promise<unknown>}
     */
    const MF_ImageToBase64 = (src) => {
        return new Promise((resolve, reject) => {
            // 1、创建 Image 对象
            const image = new Image();
            // 2、onload 加载成功触发
            image.onload = function () {
                try {
                    let canvas = u.createEl('', 'canvas');
                    const {
                        width,
                        height
                    } = image;
                    canvas.width = width;
                    canvas.height = height;
                    let context = canvas.getContext('2d');
                    context.drawImage(image, 0, 0, width, height);
                    const data = canvas.toDataURL();
                    resolve({
                        data,
                        width,
                        height
                    });
                } catch (e) {
                    reject(e);
                }
            }
            image.onerror = reject;
            image.src = src;
        })
    }

    /**
     * @description 画布输出 base64
     * @author Mr.Fang
     * @time 2024年1月20日18:05:49
     * @param src 图片地址
     * @returns {Promise<unknown>}
     */
    const MF_CanvasToBase64 = (canvas) => {
        return new Promise((resolve, reject) => {
            const {
                width,
                height
            } = canvas;
            const data = canvas.toDataURL();
            resolve({
                data,
                width,
                height
            });
        })
    }
})();