如意文档

所有文档平台免费文档下载

// ==UserScript==
// @name         如意文档
// @namespace    http://tampermonkey.net/
// @version      6.0
// @description  所有文档平台免费文档下载
// @author       ahonker999
// @match        https://jjg.spc.org.cn/resmea/view/stdonline
// @match        https://pro-img-brtm.baijiayun.com/*
// @match        https://hbba.sacinfo.org.cn/attachment/onlineRead/*
// @match        https://www.qzoffice.com/*
// @match        https://*.book118.com/*
// @match        https://*.renrendoc.com/*
// @match        https://*.docin.com/*
// @match        https://*.doc88.com/*
// @match        https://doc.mbalib.com/*
// @match        https://*.deliwenku.com/*
// @match        https://*.jinchutou.com/*
// @match        https://*.152files.goldhoe.com/*
// @match        https://www.nssi.org.cn/cssn/js/pdfjs/web/preview.jsp*
// @match        https://online.71nc.cn/*
// @match        http://114.251.111.103:18080/kfs/file/read/*
// @match        https://bulletin.cebpubservice.com/resource/ceb/js/pdfjs-dist/web/viewer.html*
// @match        http://121.36.94.83:9008/jsp/yishenqing/appladd/biaozhunfile/flash/previewImg.jsp*
// @match        http://rbtest.cnca.cn/cnca_kfs/file/read/*
// @match        https://*.mayiwenku.com/*
// @match        https://*.dugen.com/*
// @match        https://*.7cxk.com/*
// @match        https://ishare.iask.com/*
// @match        https://swf.iask.com/*
// @match        https://*.down.sina.com.cn/*
// @match        https://wenku.baidu.com/*
// @match        https://wkbjcloudbos.bdimg.com/*
// @match        https://wkretype.bdimg.com/*
// @match        https://*.chochina.com/*
// @match        https://*.weizhuannet.com/*
// @match        https://www.taodocs.com/*
// @match        https://wenku.so.com/*
// @match        https://*.360tres.com/*
// @match        https://www.wenkub.com/*
// @match        http://c.gb688.cn/*
// @match        http://www.nrsis.org.cn/mnr_kfs/file/read/*
// @match        https://*.feishu.cn/space/*
// @match        http://www.jtysbz.cn:8009/pdf/viewer/*
// @require      https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jspdf/2.4.0/jspdf.umd.min.js
// @require      https://unpkg.com/@zip.js/[email protected]/dist/zip.min.js
// @require      https://unpkg.com/[email protected]/dist/html2canvas.js
// @icon         https://dtking.cn/favicon.ico
// @run-at 		document-idle
// @grant       GM_getValue
// @grant       GM_deleteValue
// @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_speed{color: red;}';
	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,#nav-menu-wrap{display:none !important}}'
	const prefix = "MF_";
	// canvas 禁止重写 drawImage
	const canvasRenderingContext2DPrototype = CanvasRenderingContext2D.prototype;
	const originalDrawImage = canvasRenderingContext2DPrototype.drawImage;
	Object.defineProperty(canvasRenderingContext2DPrototype, 'drawImage', {
		value: originalDrawImage,
		writable: false,
		configurable: false
	});
 
 
	/**
	 * @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已添加:');
	}
	/**
	 * Url 地址拼接,无需预览直接从 HTML 中读取相应的参数即可
	 */
	const loadingUrls = (params) => {
		const _pageCount = Viewer._pageCount;
		console.log(_pageCount);
		let dp;
		if (params) {
			dp = u.query('#dp').value.replace('www', 'ww'); // 读根网特殊情况
		} else {
			dp = u.query('#dp').value;
		}
		const urls = [];
		for (var i = 1; i < _pageCount + 1; i++) {
			let u = dp + i + ".gif";
			urls.push(u);
		}
		MF_addURL(urls);
	}
 
	/**
	 * Url 地址拼接,无需预览直接从 HTML 中读取相应的参数即可
	 */
	const joinDownloadURL = (baseUrl) => {
		const size = Page.size;
		const urls = [];
		for (var i = 0; i < size; i++) {
			urls.push(baseUrl + '/' + i + '.png');
		}
		MF_addURL(urls);
	}
 
 
	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, val) {
			if (!val) {
				return e.getAttribute(key);
			} else {
				e.setAttribute(key, val);
			}
 
		}
 
		/**
		 *  追加样式
		 * @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];
				if (!item.id) continue;
				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);
					}
				}
				if (item.id === 'speed') {
					this.attr(el, 'contenteditable', true)
				}
				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',
		so: 'wenku.so.com',
		doc88: 'doc88.com',
		mbalib: 'doc.mbalib.com',
		deliwenku: 'deliwenku.com',
		cxk: '7cxk.com',
		jinchutou: 'jinchutou.com',
		mayiwenku: 'mayiwenku.com',
		dugen: 'ww.dugen.com',
		iask: 'ishare.iask.com',
		chochina: 'chochina.com',
		weizhuan: 'weizhuannet.com',
		taodocs: 'taodocs.com',
		wenkub: 'wenkub.com',
		gb688: 'gb688.cn',
		jjg: 'jjg.spc.org.cn',
		shengtongedu: 'pro-img-brtm.baijiayun.com',
		sacinfo: 'hbba.sacinfo.org.cn',
		qzoffice: 'www.qzoffice.com',
		nrsis: 'www.nrsis.org.cn',
		nea: '114.251.111.103:18080',
		nssi: 'www.nssi.org.cn',
		feishu: 'feishu.cn',
		jtysbz: 'jtysbz.cn',
		jsjlw: 'online.71nc.cn',
		mwr: '121.36.94.83:9008',
		cebpubservice: 'bulletin.cebpubservice.com',
		rbtest: 'rbtest.cnca.cn',
	};
	const {
		host,
		href,
		origin
	} = window.location;
	const jsPDF = jspdf.jsPDF;
	let zipWriter; // 声明全局变量
	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,
		loading = 500, // 毫秒
		pdf_ratio = 0.56,
		title = document.title,
		fileType = '',
		downType = 1, // 下载文件类型
		select = null,
		selectBox = null,
		dom = null,
		beforeFun = null,
		interval = null,
		startPageNo = 0,
		BASE_URL = 'https://wkretype.bdimg.com/retype',
		readerInfoBai = null, // 百度文档参数
		intervalBai = null; // 百度定时任务
	if (host.includes(domain.taodocs)) {
		iscopy = 'TRUE'; // taodocs copy flag
	}
 
	const params = new URLSearchParams(document.location.search.substring(1));
	if (params.size && params.get('custom')) {
		window.parent.postMessage({
			type: "onload",
			value: 'success'
		}, "*")
		u.log('子页面加载完成!');
	}
 
	// 百度拷贝文本
	const baiduCopy = () => {
		const observerOptions = {
			characterData: true,
			subtree: true
		};
		// dom 监听器
		const observer = new MutationObserver(function(mutationList, observer) {
			const mutation = mutationList[0];
			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');
				let style = {
					width: "100%",
					height: "200px",
					outline: "none",
					padding: "10px",
					boxSizing: "border-box",
					fontSize: "16px",
					border: "1px solid rgb(204, 204, 204)"
				}
				u.style(textarea, style)
				textarea.innerText = result;
				let box = u.query('#catalog-main') || u.query('.catalog-main') || u.query(
					'.related-doc-list')
				box.before(textarea);
			}
		});
		const targetNode2 = document.querySelector('.link')
		// 触发监听
		observer.observe(targetNode2, observerOptions);
	}
 
	// 监听页面卸载,移除百度定时删除广告等 DOM 定时器
	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) => {
		// console.log(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");
			let length = Number(localStorage.getItem("length") || "0");
			const {
				blob,
				uint8,
				width,
				height
			} = value;
			if (fileType.includes('ppt') || width > height) {
				doc.addPage([width * pdf_ratio, height * pdf_ratio], 'l');
				doc.addImage(uint8, 'JPEG', 0, 0, width * pdf_ratio, height * pdf_ratio, index, 'FAST')
			} else {
				doc.addPage();
				doc.addImage(uint8, 'JPEG', 0, 0, pdf_w, pdf_h, index, 'FAST')
			}
			if (index === 1) {
				doc.deletePage(1);
			}
			zipWriter.add(index + ".png", new zip.BlobReader(blob));
			localStorage.setItem('current', index + 1 + "");
			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) {
			u.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 init = () => {
		console.table({
			host,
			href,
			origin
		})
		dom = document.documentElement || document.body;
		if (host.includes(domain.renrendoc)) {
			if (!/.*renrendoc\.com\/.+$/.test(href)) {
				u.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)) {
				u.log('结束');
				return;
			}
			if (!href.includes('pptView.html') && !params.get("readpage")) {
				let node = u.query('h1')
				node = node ? node : u.query('h2');
				title = node.innerText.replaceAll(" ", "").replaceAll("VIP", "");
				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)) {
				u.log('结束');
				return;
			}
			select = "#contentcontainer canvas";
			const toImg = params.get('toImg');
			console.log('toImg', toImg);
			title = u.query('meta[property="og:title"]').content;
			fileType = u.attr(u.query('h1').children[0], 'title').toLowerCase();
			if (toImg && toImg === '1') {
				select = "#contentcontainer img"
			}
			console.log('toImg', select);
			if (isUserLogin === '1') { // 登录
				beforeFun = "let eb = u.query('.model-fold-show');if (eb) {eb.click();}";
			}
			if (fileType.includes('ppt') || (toImg && toImg === '1')) {
				btns.push(new Box('PPT', '获取地址', 'downtxt()'))
			}
 
		} else if (host.includes(domain.wenku)) {
			if (!/.+wenku\.baidu\.com\/(tfview|view).+$/.test(href)) {
				u.log('结束');
				return;
			}
			dom = u.query('.reader-wrap');
			beforeFun =
				"let eb = u.query('.unfold')?u.query('.unfold'):u.query('.read-all');if (eb) {eb.click();}";
			select = "#original-creader-root canvas";
			btns.push(new Box('print-pdf', '打印PDF', 'window.print()'))
			if (fileType.includes('ppt') || fileType.includes('pdf')) {
				btns.push(new Box('PPT', '获取地址', 'downtxt()'))
			} else {
				btns.push(new Box('get-text', '获取文本', 'fullText()'))
			}
		} else if (host.includes(domain.so)) {
			if (!/.+wenku\.so\.com\/.+$/.test(href)) {
				u.log('结束');
				return;
			}
			const {
				Title,
				DocType,
				Field03
			} = asyncData.DocInfo;
			title = Title;
			fileType = DocType.toLowerCase();;
			btns.splice(1, 2);
			btns.push(new Box('PPT', '获取地址', 'downtxt()'))
			MF_addURL(Field03);
		} else if (host.includes(domain.doc88)) {
			if (!/.+doc88\.com\/.+$/.test(href)) {
				u.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";
			btns.push(new Box('get-text', '获取文本', 'fullText()'))
		} else if (host.includes(domain.mbalib)) {
			if (!/doc\.mbalib\.com\/.+$/.test(href)) {
				u.log('结束');
				return;
			}
			dom = u.query('#scroll-m-box');
			title = u.query('h1 p').innerText;
			fileType = title.substring(title.indexOf('.') + 1).toLowerCase();
			select = "#viewer .page"
			btns.splice(1, 0, new Box('speed', '500'));
			btns.push(new Box('get-text', '获取文本', 'fullText()'))
		} else if (host.includes(domain.deliwenku) ||
			host.includes(domain.cxk) ||
			host.includes(domain.jinchutou) ||
			host.includes(domain.mayiwenku) ||
			host.includes(domain.dugen) ||
			host.includes(domain.chochina) ||
			host.includes(domain.weizhuan)
		) {
			if ((!/.+deliwenku\.com\/.+$/.test(href)) &&
				(!/.+7cxk\.com\/.+$/.test(href)) &&
				(!/.+jinchutou\.com\/.+$/.test(href)) &&
				(!/.+mayiwenku\.com\/.+$/.test(href)) &&
				(!/ww\.dugen\.com\/.+$/.test(href)) &&
				(!/.+chochina\.com\/.+$/.test(href)) &&
				(!/.+weizhuannet\.com\/.+$/.test(href))
			) {
				return;
			}
			// 蚂蚁需手动点击全文
			if (host.includes(domain.mayiwenku) || host.includes(domain.dugen)) {
				preview();
				loadingUrls(host.includes(domain.dugen));
			} else {
				loadingUrls();
			}
			if (host.includes(domain.chochina)) {
				title = u.query('h1').innerText;
				fileType = title.substring(title.indexOf('.') + 1).toLowerCase();
			} else {
				title = u.query('meta[property="og:title"]').content;
				fileType = u.query('meta[property="og:document:type"]').content.toLowerCase();
			}
			btns.splice(1, 2);
			btns.push(new Box('PPT', '获取地址', 'downtxt()'))
 
		} else if (host.includes(domain.iask)) {
			if (!/ishare\.iask\.com\/.+$/.test(href)) return;
			title = pageConfig.access.title;
			fileType = pageConfig.access.format.toLowerCase();;
			btns.splice(1, 2);
			btns.push(new Box('PPT', '获取地址', 'downtxt()'))
			MF_addURL(pageConfig.imgUrl);
		} else if (host.includes(domain.taodocs)) {
			if (!/www\.taodocs\.com\/.+$/.test(href)) return;
			title = u.query('h1').innerText;
			fileType = title.substring(title.indexOf('.') + 1).toLowerCase();
			beforeFun = "let eb = u.query('.fc2e');if (eb) {eb.click();}";
			select = "#canvas canvas";
			btns.push(new Box('get-text', '获取文本', 'fullText()'))
		} else if (host.includes(domain.wenkub)) {
			if (!/www\.wenkub\.com\/.+$/.test(href)) return;
			title = u.query('h1').innerText;
			fileType = title.substring(title.indexOf('.') + 1).toLowerCase();
			beforeFun = "let eb = u.query('.fc2e');if (eb) {eb.click();}";
			select = "#pageContainer img";
		} else if (host.includes(domain.gb688)) {
			if (u.query('#verifyCode')) return;
			fileType = 'pdf';
			select = "#viewer .page";
			btns.splice(1, 0, new Box('speed', '500'));
			btns.push(new Box('get-text', '获取文本', 'fullText()'))
		} else if (host.includes(domain.jjg)) {
			fileType = ".pdf";
			select = "#docViewer_ViewContainer .fwr-page-invisible";
			// select = "#docViewer_ViewContainer .fwr-page-image img";
		} else if (host.includes(domain.shengtongedu)) {
			fileType = "ppt";
		} else if (host.includes(domain.sacinfo)) {
			fileType = "pdf";
			const md5 = href.split('/').pop(); // 秘钥
			joinDownloadURL('https://hbba.sacinfo.org.cn/hbba_onlineRead_page/' + md5)
			btns.splice(1, 2);
			btns.push(new Box('PPT', '获取地址', 'downtxt()'))
		} else if (host.includes(domain.qzoffice)) {
			fileType = "pdf";
			title = params.get('content') || 'AI-PPT';
			btns.splice(1, 2);
			btns.splice(2, 1);
		} else if (host.includes(domain.nrsis)) {
			fileType = "pdf";
			select = ".page canvas";
		} else if (host.includes(domain.nea)) {
			fileType = "pdf";
			select = ".page canvas";
		} else if (host.includes(domain.nssi)) {
			title = document.title,
				fileType = "pdf";
			select = "#viewer .page";
			dom = u.query('#viewerContainer')
			btns.splice(1, 0, new Box('speed', '500'));
		} else if (host.includes(domain.feishu)) {
			fileType = "pdf";
			dom = u.query('#viewerContainer')
			fileType = 'pdf';
			select = "#viewer .page";
			if (title.includes('PDF')) {
				btns.splice(1, 0, new Box('speed', '500'));
				btns.push(new Box('get-text', '获取文本', 'fullText()'))
			} else {
				btns.splice(1, 5);
				btns.push(new Box('get-build', '打包下载', 'buildDown()'))
			}
		} else if (host.includes(domain.jtysbz) || host.includes(domain.cebpubservice)) {
			fileType = "pdf";
			select = "#viewer .page";
			btns.splice(1, 0, new Box('speed', '500'));
			btns.push(new Box('get-text', '获取文本', 'fullText()'))
		} else if (host.includes(domain.jsjlw)) {
			fileType = "pdf";
			select = "#ctn img";
			dom = u.query('#ctn');
		} else if (host.includes(domain.mwr)) {
			fileType = "pdf";
			select = "#imgdiv img";
			title = u.query('.left_titile').innerText;
		} else if (host.includes(domain.rbtest)) {
			fileType = "pdf";
			select = ".page canvas";
		}
		const query = u.query("#btn_ppt_front_pc"); // 原创
		if (!query) {
			u.gui(btns);
		} else {
			query.click();
		}
		console.log('文件名称:', title);
		console.log('文件类型:', fileType);
	}
 
 
	(function() {
		// 移除多余 iframe
		document.querySelectorAll('iframe').forEach(item => {
			item.remove()
		})
 
		// 清空系统缓存数据
		localStorage.removeItem('listData')
		localStorage.removeItem('length')
		localStorage.removeItem('current')
		localStorage.removeItem('pageData')
		localStorage.removeItem('down')
		localStorage.removeItem('SP_text')
 
		// 百度服务端渲染
		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');
			}
			setTimeout(() => {
				baiduCopy()
			}, 500)
			intervalBai = setInterval(() => {
				// 右侧侧边栏
				const vip = u.query('#app-right');
				if (vip) {
					vip.remove()
				}
				const chat = u.query('.wk-chat-modal');
				if (chat) {
					chat.remove()
				}
				// 左侧广告轮播
				const banner = u.query('.banner-wrapper');
				if (banner) {
					banner.remove()
				}
			}, 1000);
		}
 
	})();
 
	// load 事件
	(() => {
		// 在这里执行渲染完成后的操作
		console.log('HTML 渲染完成!');
		// 监听子页面加载完成,发送消息
		if (!params.size || !params.get('custom')) {
			init()
		}
	})();
 
 
	/**
	 * @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 (host.includes(domain.shengtongedu) && fileType.includes('ppt')) {
			localStorage.setItem('start', '1');
			await autoShengTongParsingPPT();
			return false;
		}
		if (host.includes(domain.mbalib) ||
			host.includes(domain.nssi) ||
			host.includes(domain.feishu) ||
			host.includes(domain.cebpubservice) ||
			host.includes(domain.jtysbz) || (host.includes(domain.gb688) && !u.query('#viewer').style
				.transform)) {
			localStorage.setItem('start', '1');
			localStorage.removeItem('SP_index')
			dom.scrollTop = 0;
			await scrollPreview()
			return false;
		}
 
		if (interval) return false;
		if (host.includes(domain.docin)) {
			// 起始页码
			startPageNo = document.querySelector("#page_cur").value - 1 || 0;
		} else {
			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()
			} else if (host.includes(domain.taodocs)) {
				scrollWinAreaTao()
			} else if (host.includes(domain.gb688)) {
				scrollPageAreaDocGB()
			} else if (host.includes(domain.jjg)) {
				scrollPageAreaJJG()
			} else if (host.includes(domain.nrsis) ||
				host.includes(domain.nea) ||
				host.includes(domain.mwr) ||
				host.includes(domain.jsjlw) ||
				host.includes(domain.rbtest)
			) {
				scrollWinArea()
			}
		}, 500);
	}
 
 
	/**
	 * @description 结束方法,停止预览
	 * @author Mr.Fang
	 * @time 2024年2月2日
	 */
	const stopPreview = async () => {
		console.log('---------->stopPreview');
		if (interval) {
			clearInterval(interval);
			interval = null;
		}
		localStorage.removeItem('start')
	}
 
	/**
	 * @description 结束方法,停止预览,前置方法
	 * @author Mr.Fang
	 * @time 2024年7月22日
	 */
	const stopBeforePreview = async () => {
		if (host.includes(domain.mwr)) {
			const page_index = u.query('.page_index').innerText;
			const page_total = u.query('.page_total').innerText;
			if (page_index === page_total) {
				stopPreview();
				u.preview(-1);
			} else { // 向上滚动一次
				dom.scrollTo({
					top: dom.scrollTop - 100,
					left: 0,
					behavior: "smooth",
				});
			}
		} else {
			stopPreview();
			u.preview(-1);
		}
	}
 
	/**
	 * @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)
		console.log('host', host)
		console.log('downType', downType)
		if (!down) {
			// 结束后续执行的方法
			if (host.includes(domain.book118) || host.includes(domain.shengtongedu)) {
				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 || display === 'none') {
					await downimg()
				}
			} else if (host.includes(domain.docin)) {
				if (params.get('toImg')) {
					await parseImage()
				} else {
					await imageToBase64()
					conditionDownload();
				}
			} else if (host.includes(domain.mbalib) ||
				host.includes(domain.feishu) ||
				host.includes(domain.nssi) ||
				host.includes(domain.cebpubservice) ||
				host.includes(domain.jtysbz)
			) {
				conditionDownload();
			} else if (
				host.includes(domain.doc88) ||
				host.includes(domain.taodocs) ||
				host.includes(domain.nrsis) ||
				host.includes(domain.nea) ||
				host.includes(domain.rbtest)
			) {
				await imageToBase64()
				conditionDownload();
			} else if (host.includes(domain.deliwenku) ||
				host.includes(domain.cxk) ||
				host.includes(domain.jinchutou) ||
				host.includes(domain.mayiwenku) ||
				host.includes(domain.dugen) ||
				host.includes(domain.iask) ||
				host.includes(domain.chochina) ||
				host.includes(domain.weizhuan) ||
				host.includes(domain.so) ||
				host.includes(domain.sacinfo)
			) {
				await downimg()
			} else if (host.includes(domain.gb688)) {
				if (u.query('#viewer').style.transform) { // bg
					await downloadGBImage();
				} else {
					conditionDownload();
				}
			} else if (host.includes(domain.jsjlw)) {
				await parseImage()
			} else if (host.includes(domain.jjg)) {
				await downloadElement()
				conditionDownload();
			} else if (host.includes(domain.qzoffice)) {
				await handleQzoffice();
				conditionDownload();
			} else if (host.includes(domain.mwr)) {
				await downloadImage();
				conditionDownload();
			}
		} else {
			conditionDownload();
		}
	}
	// 飞书打包下载
	const buildDown = async () => {
		const styles = [...u.queryAll('style')].map(div => div.outerHTML).join('\n');
		if (title.includes('excel')) {
			const container = u.query('.container').innerHTML;
			const content =
				`<!DOCTYPE html><html><head><meta charset="utf-8">${styles}</head><body style="overflow: auto;">${container}</body></html>`
			const htmlBlob = new Blob([content], {
				type: "text/html;charset=utf-8"
			});
			zipWriter.add('index.html', new zip.BlobReader(htmlBlob))
			zipWriter.add('index.txt', new zip.TextReader(u.query('.container').innerText))
		} else if (title.includes('txt')) {
			const container = u.query('#scroll-container').innerHTML;
			const content =
				`<!DOCTYPE html><html><head><meta charset="utf-8">${styles}</head><body>${container}</body></html>`
			const htmlBlob = new Blob([content], {
				type: "text/html;charset=utf-8"
			});
			zipWriter.add('index.html', new zip.BlobReader(htmlBlob))
			zipWriter.add('index.txt', new zip.TextReader(u.query('#scroll-container').innerText))
		}
		await u.sleep(500)
		downzip();
		u.preText('下载完成')
	}
 
	/**
	 * 根据指定条件下载文件
	 */
	const conditionDownload = () => {
		if (downType === 1) {
			downpdf()
			localStorage.setItem('down', '1')
		} else if (downType === 2) {
			downzip()
			if (!host.includes(domain.qzoffice)) // 排除 qz
				localStorage.setItem('down', '1')
		}
		u.preText('下载完成')
	}
 
	// 滚动指定 Window
	const scrollWinArea = () => {
		before();
		const scrollTop = dom.scrollTop;
		const height = dom.scrollHeight - dom.clientHeight;
		if (height <= scrollTop) {
			stopBeforePreview();
		} else {
			let top = scrollTop + 500;
			dom.scrollTo({
				top: top,
				left: 0,
				behavior: "smooth",
			});
			u.preview(top, height);
		}
	}
 
	/**
	 * @description 判断 dom 是否在可视范围内
	 * @author Mr.Fang
	 * @time 2024-6-25
	 * @param {HTMLElement} el
	 */
	const isElementInViewport = (el) => {
		const rect = el.getBoundingClientRect();
		return (
			rect.top >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight)
		);
	}
 
	/**
	 * @description 图片添加到 zip 或 pdf
	 * @author Mr.Fang
	 * @time 2024-6-25
	 * @see http://raw.githack.com/MrRio/jsPDF/master/docs/module-addImage.html#~addImage
	 * @param {HTMLImageElement | HTMLCanvasElement | Uint8Array | RGBAData} imageData
	 * @param {Blob} blob
	 * @param {Number} i 下标
	 * @param {Number} width 宽 
	 * @param {Number} height 高
	 * @param {Boolean} natural 原始高度宽度 true 原始尺寸 false A4
	 */
	const saveImageAndPDF = (imageData, blob, i, width, height, natural = false) => {
		let dir = 'p';
		let target_w = pdf_w;
		let target_h = pdf_h;
		if (width > height) {
			dir = 'l';
			target_h = pdf_w;
			target_w = pdf_h;
		}
		if (natural) {
			target_h = height * pdf_ratio;
			target_w = width * pdf_ratio;
		} else {
			target_h = target_h;
			target_w = target_w;
		}
 
		zipWriter.add(`${i}.png`, new zip.BlobReader(blob));
		doc.addPage([target_w, target_h], dir);
		doc.addImage(imageData, 'JPEG', 0, 0, target_w, target_h, i, 'FAST')
		if (doc.internal.pages[1].length === 2) {
			doc.deletePage(1); // 删除空白页
		}
	}
 
	/**
	 * @description 保存数据
	 * @author Mr.Fang
	 * @time 2024-6-25
	 * @param {Number} i 下标
	 * @param {HTMLElement} imageData 图片对象
	 * @param {HTMLElement} textLayer 文本对象
	 */
	const previewSave = async (i, imageData, textLayer) => {
		const {
			blob,
			width,
			height
		} = await MF_CanvasToBase64(imageData);
		saveImageAndPDF(imageData, blob, i, width, height, false)
		//获取文本内容
		let texts = JSON.parse(localStorage.getItem('SP_text')) || [];
		texts.push(fileType.includes('doc') ? textLayer.innerText : textLayer.textContent);
		localStorage.setItem('SP_text', JSON.stringify(texts))
		// 更新下标
		localStorage.setItem('SP_index', i + 1);
	}
 
	/**
	 * @description 预览&下载
	 * @author Mr.Fang
	 * @time 2024-6-25
	 */
	const scrollPreview = async () => {
		if (!localStorage.getItem("start")) {
			u.preview(-1, null, "已终止");
			return;
		}
		before();
		const i = Number(localStorage.getItem('SP_index')) || 0;
		const childrens = u.queryAll(select);
		const current = childrens[i];
		const length = childrens.length;
		// 如果当前对象在可视范围内,进行保存添加
		const imageData = current.querySelector('canvas');
		const textLayer = current.querySelector('.textLayer');
		if (isElementInViewport(current) && imageData && textLayer) {
			await previewSave(i, imageData, textLayer)
			if (i !== length - 1)
				childrens[i + 1].scrollIntoView({
					behavior: "smooth"
				});
		} else {
			current.scrollIntoView({
				behavior: "smooth"
			});
		}
		u.preview(i, length);
		if (i !== length - 1) {
			let speed = 500,
				MF_speed = Number(u.query('#MF_speed').innerText);
			if (MF_speed > 0) {
				speed = MF_speed
			} else {
				u.query('#MF_speed').innerText = 500
			}
			setTimeout(() => {
				console.log(speed, 'ms 后执行');
				scrollPreview()
			}, speed)
		} else {
			console.log('执行结束');
			u.preview(-1);
			localStorage.removeItem('SP_index')
			localStorage.removeItem('start')
		}
	}
 
	// 滚动指定 Window
	const scrollWinAreaTao = () => {
		const scrollTop = dom.scrollTop;
		const height = dom.scrollHeight - dom.clientHeight;
		const fc2e = u.query('.fc2e');
		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.width === 300 || item.height == 150) {
				end = 1;
				dom.scrollTo({
					top: dom.scrollTop + top,
					left: 0,
					behavior: "smooth",
				});
				u.preview(dom.scrollTop + top, height);
				break;
			}
		}
		if (end === 0) {
			if (!fc2e) {
				stopPreview();
				u.preview(-1);
			} else {
				before()
			}
		}
	}
	// 滚动指定区域
	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;
		const startNum = document.querySelector("#pageNumInput").value - 1 || 0;
		for (let i = startNum; 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 (t.length !== 0) {
				end = 1;
				item.scrollIntoView({
					behavior: "smooth"
				});
				u.preview(i + 1, length);
				break;
			}
		}
		if (end === 0) {
			u.preview(-1);
			stopPreview();
		}
	}
 
	const scrollPageAreaDocGB = () => {
		// 100% 预览
		if (u.query('#scaleSelect').selectedIndex < 9) {
			u.query('#zoomIn').click()
		}
 
		const clientHeight = dom.clientHeight;
		let end = 0;
		const els = u.queryAll(select);
		const length = els.length;
		for (let i = 0; i < length; i++) {
			let item = els[i];
			if (u.attr(item, 'bg')) {
				end = 1;
				item.scrollIntoView({
					behavior: "smooth"
				});
				u.preview(i + 1, length);
				break;
			}
		}
		if (end === 0) {
			u.preview(-1);
			stopPreview();
		}
	}
 
	const scrollPageAreaJJG = () => {
		let end = 0;
		// 放大
		if (u.query('.fwr-rb-zoom-box input').value === '100%') {
			u.query('.fwr-rb-bottom-zoomin').click();
			return;
		}
		const pages = u.query(".fwr-rb-bottom-tabs input").value.split('/');
		const els = u.queryAll(select);
		const length = els.length;
		for (let i = Number(pages[0].trim()) - 1; i < length; i++) {
			const item = els[i];
			const page = item.querySelector('.fwr-page-tile')
			if (!page) {
				end = 1;
				u.query('.fwr-rb-bottom-page-next').click();
				u.preview(i + 1, length);
				break;
			}
		}
		if (end === 0) {
			u.preview(-1);
			stopPreview();
		}
	}
 
	/**
	 * canvas 转 blob 对象
	 * 导出全部按 A4 格式导出,方便兼容大部分文档,支持横竖格式
	 */
	const imageToBase64 = async () => {
		const images = u.queryAll(select);
		const length = images.length;
		for (let i = 0; i < length; i++) {
			const item = images[i];
			if (host.includes(domain.doc88)) {
				let previousElementSibling = item.previousElementSibling.previousElementSibling;
				let t = previousElementSibling.innerText;
				if (t.length !== 0) {
					continue;
				}
			}
			let {
				blob,
				width,
				height
			} = await MF_CanvasToBase64(item);
			saveImageAndPDF(item, blob, i, width, height, host.includes(domain.doc88) || host.includes(
				domain.rbtest))
			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 = u.query("#view" + 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,
				logging: false,
			}).then(function(canvas) {
				let fileName = max_index + "_" + a_len + ".png";
				// 将canvas转换为图片并下载.
				canvas.toBlob(blob => {
						zipWriter.add(fileName, new zip.BlobReader(blob));
					},
					"image/png",
					1);
				// 添加PDF
				// 794px*1123px ;
				doc.addPage([canvas.width * pdf_ratio, canvas.height * pdf_ratio], 'l');
				doc.addImage(canvas, '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) {
			try {
				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));
			} catch (e) {
				console.error(e);
			}
		}
		u.preview(page, total);
		const pageNext = u.query('#pageNext');
		const btmRight = u.query('.btmRight');
 
		if (page !== total) {
			btmRight.click();
			await autoParsingPPT();
		}
	}
 
	/**
	 * 键盘事件 ←左 右→
	 */
	const triggerKeyEvent = (element, key = 'right', type) => {
		var event = new KeyboardEvent(type, {
			bubbles: true,
			cancelable: true,
			key: key,
			keyCode: key === 'letf' ? 37 : 39, // 37是左箭头,39是右箭头
			which: key === 'letf' ? 37 : 39
		});
		element.dispatchEvent(event);
	}
 
	/**
	 * @description 盛通教育 PPT 解析
	 * @author Mr.Fang
	 * @time 2024年5月10日
	 */
	const autoShengTongParsingPPT = async () => {
		if (!localStorage.getItem("start")) {
			u.preview(-1, null, "已终止");
			return;
		}
		const current = u.query('#playerView > div:nth-child(2)');
		current.style.transform = 'none'
		const {
			total,
			page
		} = await new Promise((resolve) => {
			const childNodes = document.querySelector(
				"#playerView > div:nth-child(2) > div:nth-child(1) > div").childNodes;
			const total = childNodes.length - 1;
			let page = 1;
			childNodes.forEach((item, index) => {
				if (item.childNodes.length > 0) {
					page = index;
				}
			})
			resolve({
				total,
				page
			})
		})
		const max_index = page - 1;
 
		// 动作数量
		let a_len = 0;
		if (max_index === Number(localStorage.getItem('currentPage'))) {
			a_len = Number(localStorage.getItem('currentPageIndex')) + 1;
		}
		if (a_len !== 0) {
			await u.sleep(1000);
		}
		const bgs = MF_RecursiveParsingImages(current);
		await new Promise((resolve) => {
			html2canvas(current, {
				useCORS: true,
				logging: false,
			}).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);
				}
				localStorage.setItem('currentPage', max_index);
				localStorage.setItem('currentPageIndex', a_len);
				resolve();
			});
		})
		if (a_len === 0) {
			try {
				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));
			} catch (e) {
				console.error(e);
			}
		}
		u.preview(page, total);
 
		if (page !== total) {
			triggerKeyEvent(document.body, 'right', 'keydown');
			triggerKeyEvent(document.body, 'right', 'keyup');
			await autoShengTongParsingPPT();
		}
	}
 
	/**
	 * @description 轻竹办公
	 * @author Mr.Fang
	 * @time 2024年5月17日
	 */
	const handleQzoffice = async () => {
		localStorage.removeItem('down')
		// 递归遍历 DOM 节点
		function traverseDOM(node, callback) {
			if (node.nodeType === Node.ELEMENT_NODE) {
				callback(node); // 调用回调函数处理当前节点
				node = node.firstChild; // 获取第一个子节点
				while (node) {
					traverseDOM(node, callback); // 递归遍历子节点
					node = node.nextSibling; // 获取下一个兄弟节点
				}
			}
		}
		// 查找具有指定属性的 <image> 元素
		function findImagesWithAttribute(node) {
			var images = [];
			traverseDOM(node, function(element) {
				if (element.tagName === 'image') {
					images.push(element);
				}
			});
			return images;
		}
		const template = document.getElementById("templateCanvas").cloneNode(true);
		template.style.display = 'block';
		template.style.height = '0px';
		template.style.position = 'relative';
		template.style.display = 'block';
		// 在整个文档中查找具有指定属性的 <image> 元素
		const images = findImagesWithAttribute(template);
		const imageArray = [];
		// 打印找到的元素
		const blobs = [];
		try {
			images.forEach(async (image, i) => {
				const animVal = image.href.animVal;
				let is = imageArray.filter(item => item.href === animVal);
				if (animVal && is.length === 0) {
					image.setAttribute('xlink:href', `./images/${i}.png`)
					imageArray.push({
						name: `./images/${i}.png`,
						href: animVal
					})
					const {
						blob,
						width,
						height
					} = await MF_ImageToBase64(animVal);
					zipWriter.add(`images/${i}.png`, new zip.BlobReader(blob));
				} else {
					image.setAttribute('xlink:href', is[0].name)
				}
			});
		} catch (e) {
			console.log(e);
		}
		const avgArray = document.querySelectorAll(".child-element svg");
		let content = [];
		const outerHTML = template.outerHTML;
		content.push(outerHTML);
		for (let i = 0; i < avgArray.length; i++) {
			const avgArrayElement = avgArray[i];
			const cloneNode = avgArrayElement.cloneNode(true);
			cloneNode.style.position = "static";
			cloneNode.style.width = "100%";
			cloneNode.style.height = "100%";
			cloneNode.style.transform = "none";
			const html = cloneNode.outerHTML;
			content.push(
				"<div classname=\"page-view\" style=\"width: 1200px; height: 820px;\">" +
				html + "</div>");
		}
		// 添加 html
		const htmlBlob = new Blob(['<!DOCTYPE html>' + content.join('\n\n')], {
			type: "text/html;charset=utf-8"
		});
		zipWriter.add('index.html', new zip.BlobReader(htmlBlob))
		zipWriter.add('index.txt', new zip.TextReader(document.querySelector('.texts').innerText))
	}
 
	/**
	 * @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:') && location.protocol === 'https') {
				src = src.replace("http:", "https:")
			} else if (src.startsWith("//")) {
				src = "https:" + src;
			}
			if (src) {
				const page = u.attr(item, 'data-page') || u.attr(item.parentElement, 'data-id');
				if (host.includes(domain.docin)) {
					const curr = Number(item.parentElement.id.split('_').pop());
					if (curr >= startPageNo + 1) {
						listData.push({
							page,
							src
						})
					}
				} else {
					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 {
					uint8,
					blob,
					width,
					height
				} = await MF_ImageToBase64(src);
				if (fileType.includes('ppt') || width > height) {
					doc.addPage([width * pdf_ratio, height * pdf_ratio], 'l');
					doc.addImage(uint8, 'JPEG', 0, 0, width * pdf_ratio, height * pdf_ratio, index,
						'FAST')
				} else {
					doc.addPage();
					doc.addImage(uint8, 'JPEG', 0, 0, pdf_w, pdf_h, index, 'FAST')
				}
				if (index === 1) {
					doc.deletePage(1);
				}
				zipWriter.add(index + ".png", new zip.BlobReader(blob));
				current = index;
				await u.preview(current, length);
			} 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 + "");
				u.preview(current, length);
				break;
			}
		}
		// 非当前域下载文件下标会多加一个数值
		if (localStorage.getItem("current")) {
			current -= 1;
		}
		console.log('current', current);
		if (current === length - 1) {
			conditionDownload();
		}
	}
 
	/**
	 * 图片下载 
	 */
	const downloadImage = async () => {
		const images = [...u.queryAll(select)];
		const len = images.length;
		for (let i = 0; i < len; i++) {
			const image = images[i]
			const canvas = await MF_ImageToCanvas(image);
			const {
				blob,
				width,
				height
			} = await MF_CanvasToBase64(canvas);
			saveImageAndPDF(canvas, blob, i, width, height, false);
			u.preview(i, len);
		}
	}
 
	const downloadElement = async () => {
		const nodes = u.queryAll(select + ' .fwr-page-tile');
		const len = nodes.length;
		for (let i = 0; i < len; i++) {
			const node = nodes[i]
			const {
				blob,
				canvas
			} = await MF_ImageStitchingToCanvas(node);
			saveImageAndPDF(canvas, blob, i, canvas.width, canvas.height, true);
			u.preview(i, len);
		}
	}
 
	const MF_ImageToCanvas = (image) => {
		return new Promise((resolve, reject) => {
			const canvas = u.createEl('', 'canvas');
			const {
				naturalWidth: width,
				naturalHeight: height
			} = image;
			canvas.width = width;
			canvas.height = height;
			let ctx = canvas.getContext('2d');
			ctx.fillStyle = '#FFFFFF';
			ctx.fillRect(0, 0, width, height);
			ctx.drawImage(image, 0, 0, width, height);
			resolve(canvas);
		})
	}
 
	/**
	 * bg pdf 下载
	 */
	const downloadGBImage = async () => {
		const els = u.queryAll(select);
		const length = els.length;
		for (let i = 0; i < length; i++) {
			let item = els[i];
			const {
				blob,
				canvas
			} = await MF_ImagePositionToBase64(item);
			if (!blob) {
				continue;
			}
			saveImageAndPDF(canvas, blob, i, canvas.width, canvas.height, true)
			await u.preview(i + 1, length);
		}
		// 非当前域下载文件下标会多加一个数值
		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 = '';
		if (host.includes(domain.wenku)) {
			const pageData = JSON.parse(localStorage.getItem('pageData'));
			if (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;
							}
						})
					}
				}
			} else {
				text = u.query('.ql-editor').innerText;
			}
 
		} else if (host.includes(domain.mbalib) ||
			host.includes(domain.feishu) ||
			host.includes(domain.cebpubservice) ||
			host.includes(domain.jtysbz)) {
			const texts = JSON.parse(localStorage.getItem("SP_text")) || []
			for (let i = 0; i < texts.length; i++) {
				let t = texts[i];
				text += `\n\n====第${i+1}页====\n\n` + t;
			}
			localStorage.removeItem('SP_text')
		} else if (host.includes(domain.doc88)) {
			// const texts = Core.api._VM;
			const texts = Core.api._bf;
			if (!texts) {
				alert('没有文本内容')
				return
			}
			for (let i = 0; i < texts.length; i++) {
				text += `\n\n====第${i+1}页====\n\n` + texts[i];
			}
		} else if (host.includes(domain.taodocs)) {
			const texts = u.queryAll('#canvas .textLayer');
			for (let i = 0; i < texts.length; i++) {
				let t = texts[i];
				text += `\n\n====第${i+1}页====\n\n`;
				text += t.innerText;
			}
		}
		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);
		}).catch(error => {
			console.error(error);
		});
	}
 
	/**
	 * @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' && bgi.includes('url')) {
							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 获取文件后缀名
	 * @author Mr.Fang
	 * @time 2024年6月17日16:31:05
	 * @param {name} data 文件名
	 * @returns {String} suffix 后缀 ,默认 pdf
	 */
	const getFileNameSuffix = (name) => {
		const last = name.lastIndexOf(".");
		return last > 0 ? name.substring(last + 1).toLocaleLowerCase() : 'pdf';
	};
 
	/**
	 * @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 {
						naturalWidth: width,
						naturalHeight: height
					} = image;
					canvas.width = width;
					canvas.height = height;
					let ctx = canvas.getContext('2d');
					ctx.fillStyle = '#FFFFFF';
					ctx.fillRect(0, 0, width, height);
					ctx.drawImage(image, 0, 0, width, height);
					canvas.toBlob(async blob => {
							// canvas 转 blob 对象
							// blob 转 uint8 、PDF 需要 uint8 对象
							const uint8 = await MF_BlobToUint8Array(blob)
							resolve({
								uint8,
								blob,
								width,
								height
							});
						},
						"image/png",
						1, );
				} catch (e) {
					reject(e);
				}
			}
			image.onerror = reject;
			image.src = src;
		})
	}
 
	/**
	 * @description 基于背景图片定位,转画布
	 * @author Mr.Fang
	 * @time 2024年3月13日
	 * @param src 图片地址
	 * @returns {Promise<unknown>}
	 */
	const MF_ImagePositionToBase64 = (el) => {
		const base_gb = "http://c.gb688.cn/bzgk/gb/";
		const style = el.style;
		const cw = Number(style.width.replace('px', ''));
		const ch = Number(style.height.replace('px', ''));
		// 所有子节点
		const childrens = el.children;
		// 背景图片地址处理
		if (childrens.length < 2) {
			return new Promise((resolve, reject) => {
				resolve({
					blob: null
				})
			})
		}
		const imageUrl = childrens[0].style.backgroundImage;
		const fullUrl = base_gb + imageUrl.substring(5, imageUrl.length - 2);
		if (!imageUrl) {
			return new Promise((resolve, reject) => {
				resolve({
					blob: null
				})
			})
		}
		return new Promise((resolve, reject) => {
			// 1、创建 Image 对象
			const image = new Image();
			// 2、onload 加载成功触发
			image.onload = function() {
				try {
					let canvas = u.createEl('', 'canvas');
					canvas.width = cw;
					canvas.height = ch;
					// 获取上下文对象
					const ctx = canvas.getContext('2d');
					ctx.fillStyle = "#fff";
					ctx.fillRect(0, 0, canvas.width, canvas.height);
					for (var i = 0; i < childrens.length; i++) {
						const child = childrens[i];
						const pos = child.style.backgroundPosition.split(' ');
						const coord = child.className.split('-');
						const dx = Number(coord[1]);
						const dy = Number(coord[2]);
						const sx = Math.abs(pos[0].replace('px', ''));
						const sy = Math.abs(pos[1].replace('px', ''));
						const rect = child.getBoundingClientRect();
						const {
							width: sw,
							height: sh
						} = rect;
						ctx.drawImage(image, sx, sy, sw, sh, dx * sw, dy * sh, sw, sh);
						if (i === childrens.length - 1) {
							// 转 base64 输出
							canvas.toBlob(
								(blob) => {
									resolve({
										blob,
										canvas
									});
								},
								"image/png",
								1,
							);
						}
					}
				} catch (e) {
					reject(e);
				}
			}
			image.onerror = reject;
			image.src = fullUrl;
		})
	}
 
	const MF_ImageStitchingToCanvas = (node) => {
 
		return new Promise((resolve, reject) => {
			try {
				// 获取最后一个分辨率 / tiles-layer-125 分辨率/ div/ 行 div [img]
				const children = node.lastElementChild.children;
				const firstNode = children[0];
				// 计算画布宽度
				const cwidth = [...firstNode.querySelectorAll('img')].reduce((start, item) => start +
					item.width, 0);
				const cheight = children.length * firstNode.querySelector('img').height;
				const canvas = u.createEl('', 'canvas');
				canvas.width = cwidth;
				canvas.height = cheight;
				// 获取上下文对象
				const ctx = canvas.getContext('2d');
				ctx.fillStyle = "#fff";
				ctx.fillRect(0, 0, canvas.width, canvas.height);
				// 拼接
				for (let i = 0; i < children.length; i++) {
					const chils = [...children[i].querySelectorAll('img')];
					let iw = 0;
					for (let j = 0; j < chils.length; j++) {
						const {
							width,
							height
						} = chils[j];
						ctx.drawImage(chils[j], iw, i * height, width, height);
						iw += width
					}
				}
				canvas.toBlob(
					(blob) => {
						resolve({
							blob,
							canvas,
						});
					},
					"image/png",
					1,
				);
			} catch (e) {
				//TODO handle the exception
				reject(e)
			}
 
		})
	}
 
	/**
	 * @description 图片拼接转 blob
	 * @author Mr.Fang
	 * @time 2024年6月5日
	 * @param el 节点对象
	 * @returns {Promise<blob>}
	 */
	const MF_ImageJoinToBlob = (el) => {
		return new Promise((resolve, reject) => {
			const children = el.children;
			const {
				naturalWidth,
				naturalHeight
			} = children[0];
			// 1、创建画布
			let canvas = u.createEl('', 'canvas');
			canvas.width = naturalWidth * 6;
			canvas.height = naturalHeight;
			const ctx = canvas.getContext('2d');
			ctx.fillStyle = "#fff";
			ctx.fillRect(0, 0, canvas.width, canvas.height);
			// 2、获取所有图片节点
			const listData = []
			for (var i = 0; i < children.length; i++) {
				const img = children[i];
				const left = img.style.left.replace('px', '')
				listData.push({
					index: i,
					left: Number(left)
				})
			}
			listData.sort((a, b) => a.left - b.left);
			// 3、遍历绘制画布
			for (var i = 0; i < listData.length; i++) {
				const img = children[listData[i].index];
				ctx.drawImage(img, i * naturalWidth, 0, naturalWidth, naturalHeight);
			}
			// 4、导出
			canvas.toBlob(
				(blob) => {
					resolve({
						blob,
						canvas,
					});
				},
				"image/png",
				1,
			);
		})
	}
 
	/**
	 * @description 将 blob 对象转 uint8Array
	 * @author Mr.Fang
	 * @time 2024年5月27日
	 * @param {Object} blob 图片对象
	 * @returns {Promise<Uint8Array>}
	 */
	const MF_BlobToUint8Array = (blob) => {
		return new Promise((resolve, reject) => {
			const fileReader = new FileReader();
			fileReader.onload = function() {
				resolve(new Uint8Array(this.result));
			};
			fileReader.onerror = function(error) {
				reject(error);
			};
			fileReader.readAsArrayBuffer(blob);
		});
	}
 
	/**
	 * @description 画布输出 blob 对象
	 * @author Mr.Fang
	 * @time 2024年1月20日18:05:49
	 * @param src 图片地址
	 * @returns {Promise<Object>}
	 */
	const MF_CanvasToBase64 = (canvas) => {
		return new Promise((resolve, reject) => {
			const {
				width,
				height
			} = canvas;
			canvas.toBlob(
				(blob) => {
					resolve({
						blob,
						width,
						height
					});
				},
				"image/png",
				1,
			);
		})
	}
})();