- // ==UserScript==
- // @name 百合会漫画
- // @namespace https://bbs.yamibo.com/
- // @version 0.9.1
- // @description 百合会漫画阅读与下载
- // @author mooth
- // @match https://bbs.yamibo.com/forum-30*
- // @match https://bbs.yamibo.com/forum.php?mod=forumdisplay&fid=30*
- // @match https://bbs.yamibo.com/thread*
- // @match https://bbs.yamibo.com/forum.php?mod=viewthread&tid*
-
- // @icon https://www.google.com/s2/favicons?domain=yamibo.com
-
- // @require https://update.greasyfork.org/scripts/471654/1225059/vue3js.js
- // @require https://unpkg.com/fflate@0.8.2/umd/index.js
- // @require https://unpkg.com/axios@1.7.2/dist/axios.min.js
-
- // @grant GM_addStyle
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_xmlhttpRequest
- // @grant GM_addElement
-
- // @noframes
- // ==/UserScript==
-
-
- (function () {
- GM_addElement('link', {
- href: 'https://unpkg.com/element-plus/dist/index.css',
- rel: 'stylesheet'
- });
- GM_addElement('script', {
- src: 'https://unpkg.com/element-plus',
- type: 'text/javascript',
- id: "element"
- });
-
- const { createApp, computed, ref, reactive, onMounted, watch } = Vue;
-
- // 公用方法 ---------------------------------------------------------------------------
- const PubFun = {
- // 创建碎片
- Fragment: (id) => {
- const f = document.createDocumentFragment();
- f.appendChild(document.querySelector(id));
- return f;
- },
-
- // 解析地址 html_str 返回页面中解析的地址数组
- getUrls: (html) => {
- try {
- // 定义三个数组,分别存储三种不同目的的图片地址
- let urlCandidates = [new Array(), new Array(), new Array()];
-
- // 定义一个数组,用于存储最终解析出的图片地址
- let urls = [];
-
- // 使用正则表达式匹配三种不同格式的图片地址
- if (html.match(/zoomfile="(.*?)"/g)) {
- urlCandidates[2] = html.match(/zoomfile="(.*?)"/g);
- }
- if (html.match(/https:\/\/bbs\.yamibo\.com\/data.*?"/g)) {
- urlCandidates[1] = html.match(/https:\/\/bbs\.yamibo\.com\/data.*?"/g);
- }
- if (html.match(/<img.*?class="zoom".*?file="(.*?)"/g)) {
- urlCandidates[0] = html.match(/<img.*?class="zoom".*?file="(.*?)"/g);
- }
-
- // 将三个数组按照长度排序,优先处理匹配数量最多的情况
- urlCandidates.sort((a, b) => b.length - a.length);
-
- // 遍历三个数组,将匹配到的图片地址进行格式化后存储到 urls 数组中
- urlCandidates.forEach(list => {
- list.forEach(str => {
- if (str.match("bbs.yamibo.com")) {
- urls.push(str.match(/(https.*?)"/)[1]);
- // "zoomfile=\"data/attachment/forum/202406/06/120022lu22z92dtq3hedq9.jpg\""
- } else if (str.match(/zoomfile="(.*?)"/)) {
- urls.push("https:\/\/bbs.yamibo.com/" + str.match(/zoomfile="(.*?)"/)[1]);
- } else {
- urls.push(
- str.match(/<img.*?class="zoom".*?file="(.*?)"/)[1]
- .replace("http", "https")
- );
- }
- });
- });
-
- // 过滤不需要的图片 和错误匹配
- urls = [...new Set(urls.filter(url => {
- if (!url.endsWith('.gif') && !url.match('static')) {
- return url
- }
- }))];
-
- // 返回解析出的图片地址数组
- return urls;
- } catch (error) {
- console.log("html地址解析", error);
- }
- },
-
- // 获取图片生成本地地址 解决跨域 设置同源
- cross: async (url) => {
- return new Promise((resolve, reject) => {
- try {
- // 将 httpss 替换为 https
- url = url.replace("httpss", "https");
- // 定义一个变量,用于存储 blob URL
- let blobUrl = "";
- GM_xmlhttpRequest({
- method: "get",
- url: url,
- responseType: "blob",
- headers: {
- Referer: "https://bbs.yamibo.com/forum.php?"
- },
- onload: (res) => {
- try {
- // 将响应数据转换为 blob URL
- blobUrl = window.URL.createObjectURL(res.response);
- } catch (error) {
- reject(`PubFun.cross图片转本地地址 \n${url}\n ${error}`)
- }
-
- resolve(blobUrl);
- },
- onerror: () => {
- console.error("无法链接到该页面");
- reject("无法链接到该页面");
- }
- });
- } catch (error) {
- reject(`PubFun.cross\n${error}\n${url}`);
- }
-
- });
- },
-
- // 文件储存
- saveAs: (data, name, type) => {
- // 创建一个 a 标签
- const link = document.createElement("a");
- // 创建一个 blob URL
- const url = window.URL.createObjectURL(data);
- // 设置 a 标签的 href 属性为 blob URL
- link.href = url;
- // 设置 a 标签的 download 属性为文件名
- link.download = name + "." + type;
- // 模拟点击 a 标签,触发下载
- link.click();
- },
-
- // fflate打包
- fflate_zip: async (name, urlList, state) => {
- let num = 0;
- let file_b_list = {}
- await new Promise(async resolve => {
- for (let i = 0; i < urlList.length; i++) {
- const url = urlList[i];
- try {
- const res = await axios.get(url, { responseType: 'blob' });
- num++;
-
- if (state) {
- state.done = num;
- state.allTasks = urlList.length;
- }
-
- const file_blob = res.data;
- const file_type = file_blob.type.match(/\/(.*)/)?.[1];
- const file = new Uint8Array(await file_blob.arrayBuffer());
-
- file_b_list[`${i + 1}.${file_type}`] = file;
- } catch (error) {
- num++;
- if (state) {
- state.error++;
- }
- console.error("下载失败:", url, error);
- }
-
- // 完成
- if(i === urlList.length-1){
- resolve()
- }
- }
- });
-
- // 更新下载状态
- if (state) { state.pack = 1; }
- console.log(file_b_list);
- fflate.zip(file_b_list, { level: 0 }, (err, content) => {
- console.log(content);
- // 生成 zip 包并下载
- try {
- PubFun.saveAs(new Blob([content], { type: "application/zip" }), name, "zip")
- // 更新下载状态
- if (state) {
- state.pack = 2;
- }
- } catch (e) {
- // 更新下载状态
- if (state) {
- state.pack = 3;
- }
- // 打印错误信息
- console.error("打包失败:", e);
- }
- })
-
- },
-
- // 任务队列 a = new createTaskQueue(10), a.addTask(()=>fun())
- createTaskQueue: (concurrency = 10) => {
- const queue = [];
- let running = 0;
-
- const run = () => {
- while (running < concurrency && queue.length > 0) {
- const task = queue.shift();
- running++;
- task()
- .then(() => {
- running--;
- run();
- })
- .catch(() => {
- running--;
- run();
- });
- }
- };
-
- const addTask = (task) => {
- queue.push(task);
- run();
- };
-
- return {
- addTask
- }
- }
- };
-
- // 漫画列表组件 ---------------------------------------------------------------------------
- class MangaListComponent {
- static f = []
- static columns = 2
-
- constructor() {
- // 初始化 列数
- if (!GM_getValue("columns")) {
- GM_setValue("columns", 2)
- MangaListComponent.columns = 2
- } else {
- MangaListComponent.columns = GM_getValue("columns")
- }
-
- // 获取表格节点
- MangaListComponent.f = PubFun.Fragment("#threadlisttableid")
-
- // 模板样式
- MangaListComponent.style = `
- .columns_container{
- display: flex;
- gap: 10px;
- align-items: center;
- svg{
- /* height: 40px; */
- fill: burlywood;
- cursor: pointer;
- }
- }
- .columns_selected{
- fill: #551201 !important;
- }
- .mt_manga_message_container{
- display: grid;
- }
- .mt_manga_message {
- display: flex;
- height: 150px;
- padding: 10px 0;
- /* width: 50%; */
- float: left;
- overflow: auto;
- }
-
- .mt_manga_message::-webkit-scrollbar {
- /* 整体*/
- width: 5px;
- }
-
- .mt_manga_face {
- height: 100%;
- img{
- height: 100%;
- }
- }
-
- .mt_manga_info {
- padding: 0 10px;
- }
- `
- GM_addStyle(MangaListComponent.style)
-
- // 模板
- MangaListComponent.template = `
- <div class="columns_container">
- <svg @click="columns=1" :class="{'columns_selected':columns==1}" height="40px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1467" ><path d="M868.352 568.32q32.768 0 53.248 19.456t20.48 52.224l0 221.184q0 35.84-19.968 54.784t-52.736 18.944l-706.56 0q-33.792 0-56.832-22.528t-23.04-55.296l0-212.992q0-35.84 19.968-55.808t54.784-19.968l710.656 0zM868.352 90.112q32.768 0 53.248 18.944t20.48 52.736l0 220.16q0 35.84-19.968 54.784t-52.736 18.944l-706.56 0q-33.792 0-56.832-22.528t-23.04-55.296l0-211.968q0-35.84 19.968-55.808t54.784-19.968l710.656 0z" p-id="1468"></path></svg>
- <svg @click="columns=2" :class="{'columns_selected':columns==2}" height="47px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1618" ><path d="M433.1 480 174.9 480c-25.9 0-46.9-21-46.9-46.9L128 174.9c0-25.9 21-46.9 46.9-46.9l258.2 0c25.9 0 46.9 21 46.9 46.9l0 258.2C480 459 459 480 433.1 480z" p-id="1619"></path><path d="M433.1 896 174.9 896c-25.9 0-46.9-21-46.9-46.9L128 590.9c0-25.9 21-46.9 46.9-46.9l258.2 0c25.9 0 46.9 21 46.9 46.9l0 258.2C480 875 459 896 433.1 896z" p-id="1620"></path><path d="M849.1 480 590.9 480c-25.9 0-46.9-21-46.9-46.9L544 174.9c0-25.9 21-46.9 46.9-46.9l258.2 0c25.9 0 46.9 21 46.9 46.9l0 258.2C896 459 875 480 849.1 480z" p-id="1621"></path><path d="M849.1 896 590.9 896c-25.9 0-46.9-21-46.9-46.9L544 590.9c0-25.9 21-46.9 46.9-46.9l258.2 0c25.9 0 46.9 21 46.9 46.9l0 258.2C896 875 875 896 849.1 896z" p-id="1622"></path></svg>
- <svg @click="columns=3" :class="{'columns_selected':columns==3}" height="40px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1768" ><path d="M248.832 63.488q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-116.736 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l116.736 0zM572.416 63.488q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-118.784 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l118.784 0zM891.904 63.488q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-118.784 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l118.784 0zM248.832 385.024q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-116.736 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l116.736 0zM572.416 385.024q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-118.784 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l118.784 0zM891.904 385.024q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-118.784 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l118.784 0zM248.832 706.56q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-116.736 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l116.736 0zM572.416 706.56q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-118.784 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l118.784 0zM891.904 706.56q28.672 0 48.64 19.968t19.968 48.64l0 116.736q0 28.672-19.968 48.64t-48.64 19.968l-118.784 0q-28.672 0-48.64-19.968t-19.968-48.64l0-116.736q0-28.672 19.968-48.64t48.64-19.968l118.784 0z" p-id="1769"></path></svg>
- </div>
-
- <div class="mt_manga_message_container">
- <div v-for="(item, index) in comicList" :key="item.id" class="mt_manga_message" >
- <div class="mt_manga_face">
- <img :src="item.face" class="face" alt="封面">
- </div>
- <div v-html="item.innerHTML" class="mt_manga_info"></div>
- </div>
- </div>
-
- `
- // 创建
- createApp(
- {
- template: MangaListComponent.template,
- setup() {
- // 获取主题列表
- const fragment = MangaListComponent.f;
- // 定义主题链接
- const url = "https://bbs.yamibo.com/forum.php?mod=viewthread&tid=";
- // 列数
- const columns = ref(MangaListComponent.columns)
- // 定义漫画列表数据
- const comicList = ref([]);
- // 计算属性,为每个漫画项添加默认封面
- const computedComicList = computed(() => comicList.value.map((item) => ({
- ...item,
- face: item.face || "https://bbs.yamibo.com/data/attachment/forum/201504/01/110518de9s4qsd6qtzbn9m.jpg"
- })));
-
- ////////////////////////////////////////////////////////////////////////////////////
- // 获取漫画封面
- const getComicCover = async (url_0, index) => {
- return new Promise(async (resolve, reject) => {
- let url = url_0
-
- // 判断是否需要重定向
- let res = await axios.get(url)
- // 不需要,直接解析html
- if (res.data.match('html')) {
- console.log(`直接解析,${url}`);
- // 解析HTML获取图片地址
- const urls = PubFun.getUrls(res.data);
- // 将解析到的第一个图片地址设置为封面
- comicList.value[index].face = await PubFun.cross(urls[0]);
- resolve()
- return
- }
-
- // 需要重定向
- try {
- // 获取重定向地址
- url = await get_redirect_url_eval(url_0)
- // 通过iframe 获取重定向地址
- if (url == url_0) {
- url = await get_redirect_url_iframe(url_0)
- }
- } catch (error) {
- // 通过iframe 获取重定向地址
- url = await get_redirect_url_iframe(url_0)
- }
-
- // 发送请求获取对应漫画页面的HTML
- try {
- axios.get(url)
- .then(async (res) => {
-
- const data = res.data;
-
- // 是否重新加载
- if (!data.match('https')) {
- console.log("二次加载封面");
- getComicCover(url, index)
- return
- }
-
- let urls = []
- try {
- // 解析HTML获取图片地址
- urls = PubFun.getUrls(data);
- // 将解析到的第一个图片地址设置为封面
- comicList.value[index].face = await PubFun.cross(urls[0]);
-
- resolve()
- } catch (e) {
- console.error({
- "漫画页地址": url_0,
- "地址重定向转换": url,
- "封面地址": urls,
- "请求响应": res,
- e
- });
- resolve()
- }
- })
- .catch((error) => {
- // 打印错误信息
- console.error(`请求失败${url_0}:\n ${error}`);
- resolve()
- });
- } catch (error) {
- resolve()
- }
-
-
- })
- };
-
- // 获取重定向地址 通过eval直接执行地址重定向代码
- const get_redirect_url_eval = (url) => {
- return new Promise((resolve, reject) => {
- try {
- // 定义自定义 window 对象
- const myWindow = {
- window: {
- location: {
- og: url,
- href: url,
- assign: (newUrl) => { myWindow.window.location.href = newUrl },
- }
- },
- location: {
- href: url,
- assign: (newUrl) => { myWindow.location.href = newUrl },
- replace: (newUrl) => { myWindow.location.href = newUrl }
- },
- };
-
- // 定义eval上下文
- function evalWithContext(code, context) {
- return (function () {
- // 通过参数解构来获取上下文中的变量和函数
- const contextKeys = Object.keys(context);
- const contextValues = contextKeys.map(key => context[key]);
- // 创建一个新的函数,该函数的参数是上下文中的变量名,并在函数体中执行代码
- const func = new Function(...contextKeys, code);
- // 调用函数,并将上下文中的变量值作为参数传递给函数
- return func(...contextValues);
- })();
- }
-
- axios.get(url)
- .then(response => {
- // 获取跳转代码
- const scriptRegex = /<script\b[^>]*>([\s\S]*?)<\/script>/i;
- const match = response.data.match(scriptRegex);
-
- if (match && match[1]) {
- const scriptContent = match[1];
-
- // 执行跳转代码
- evalWithContext(scriptContent, myWindow);
-
- console.log(myWindow);
-
- if (myWindow.location.href.match("https")) {
- resolve(myWindow.location.href);
- } else {
- resolve("https://bbs.yamibo.com" + myWindow.location.href);
- }
- } else {
- reject(url);
- }
- })
- .catch(error => {
- console.error('get_redirect_url_eval错误:', myWindow, error);
- reject(url);
- });
- } catch (error) {
- reject(url)
- }
-
- });
- };
-
- // 在eval失败后 通过iframe直接执行地址重定向代码
- const get_redirect_url_iframe = (url) => {
- return new Promise((resolve, reject) => {
-
- // 创建一个 iframe 元素并设置其 src 属性
- const iframe = document.createElement('iframe');
- iframe.src = "";
- // iframe.sandbox = "allow-same-origin allow-scripts"
- iframe.style.display = "none"
- document.body.appendChild(iframe)
-
- iframe.onload = () => {
- console.log("get_redirect_url_iframe", iframe.contentDocument.location.href);
- resolve(iframe.contentDocument.location.href)
- document.body.removeChild(iframe)
- }
-
- iframe.contentDocument.location.href = url
- })
- }
-
- // 渐进式加载漫画封面
- const progressiveLoad = () => {
- // 10个10个加载
- const queue = PubFun.createTaskQueue(10);
- comicList.value.forEach((item, index) => {
- queue.addTask(() => getComicCover(item.url, index))
- })
- };
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // 通过原始网页数据初始化漫画列表数据 获取对应漫画地址
- const inti_manga_data = () => {
- for (let i in fragment.children[0].children) {
- const el = fragment.children[0].children[i];
- if (typeof el === "object" && el.id && el.id.match("normalthread")) {
- comicList.value.push({
- id: el.id,
- innerHTML: el.innerHTML,
- children: el.children,
- url: url + el.id.match("normalthread_(.*)")[1]
- });
- }
- }
- }
- // 组件挂载后执行
- onMounted(() => {
- // 初始化漫画列表数据
- inti_manga_data()
- // 开始渐进式加载漫画封面
- progressiveLoad();
- });
-
- ///////////////////////////////////////////////////////////////////////////////
- // 修改列数
- watch(columns, (new_val, old_val) => {
- const el = document.querySelector(".mt_manga_message_container")
- el.style.gridTemplateColumns = `repeat(${new_val}, 1fr)`;
-
- GM_setValue("columns", new_val)
- })
- onMounted(() => {
- const el = document.querySelector(".mt_manga_message_container")
- el.style.gridTemplateColumns = `repeat(${columns.value}, 1fr)`;
- })
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- return {
- comicList: computedComicList,
- columns
- };
- }
- }
- )
- .mount("#moderate")
- }
-
- };
-
-
- // 漫画页面组件 ---------------------------------------------------------------------------
- class MangaComponent {
- constructor() {
- console.log("漫画页面加载");
-
- // 用于 与vue通信,是否加载漫画模式
- MangaComponent.model_state = 1
-
- // 百合会»论坛›江湖›貼圖區›中文百合漫画区›【提灯喵汉化组】[金子ある]平良深姐妹都“病”得不轻 1 ...
- // 获取索要创建按钮的位置
- MangaComponent.pt = document.querySelector("#pt")
-
- // 创建 模式切换按钮
- MangaComponent.mt_cut = document.createElement("div")
- MangaComponent.mt_cut.id = "mt_cut"
- MangaComponent.mt_cut.innerText = "[漫画模式]"
- // 切换模式
- MangaComponent.mt_cut.addEventListener("click", () => {
- if (MangaComponent.model_state === 1) {
- document.querySelector("#mt_old").style.display = "none"
- document.querySelector("#mt_manga").style.display = "block"
- MangaComponent.mt_cut.innerText = "[原始模式]"
- MangaComponent.model_state = 2
- } else {
- document.querySelector("#mt_old").style.display = "block"
- document.querySelector("#mt_manga").style.display = "none"
- MangaComponent.mt_cut.innerText = "[漫画模式]"
- MangaComponent.model_state = 1
- }
- })
- // 添加
- MangaComponent.pt.appendChild(MangaComponent.mt_cut)
-
- // 定义自己el,用于存放两种模式
- MangaComponent.my_el = document.createElement("div")
- MangaComponent.my_el.id = "my_el"
- // 在他的下方插入自己的el
- MangaComponent.pt.parentNode.insertBefore(MangaComponent.my_el, MangaComponent.pt.nextSibling)
-
- // html模板
- MangaComponent.my_el.innerHTML = `
- <div id="mt_old"></div>
- <div id="mt_manga" style="display: none;">
- <div >
- <div v-if="urlsLoaded" id = "mt_manga_box" @dblclick="fullScreen = !fullScreen"
- :class="{is_one_p:onePage , not_one_p:!onePage , is_r_to_l:rightToLeft, is_w_bg:whiteBg}">
- <div id="mt_set" v-show="showSettings">
- <div class="block">
- <el-slider v-model="imageSize"></el-slider>
- <el-checkbox v-model="rightToLeft">从右向左</el-checkbox>
- <el-checkbox v-model="onePage">单开</el-checkbox>
- <el-checkbox v-model="whiteBg">白底</el-checkbox>
- <el-radio>
- <span @click="download()">{{downloadInfo}}</span>
- </el-radio>
- </div>
- </div>
-
- <img :style="{'width':imageSize +'%'}"
- :src="url" class="mt_manga_img" v-for="url in urlList"
- @click="showSettings = !showSettings"
- >
- </div>
- </div>
- </div>
- `
- // 样式
- MangaComponent.style = `
- #mt_cut{
- float: right;
- font-weight: bold;
- }
- .mt_manga_img{
- }
- #mt_manga_box{
- overflow: auto;
- display: flex;
- }
- .is_one_p{
- flex-direction: column;
- flex-wrap: nowrap;
- align-items: center
- }
- .not_one_p{
- flex-wrap: wrap;
- align-content: flex-start;
- justify-content: center
- }
- .is_r_to_l{
- flex-direction: row-reverse;
- }
- .is_w_bg{
- background-color: white;
- }
-
- #mt_manga_box::-webkit-scrollbar{ /* 整体*/
- width: 3px;
- height: 10px
- }
- #mt_manga_box::-webkit-scrollbar-thumb{ /* 滑动条*/
- background-color: rgb(208, 208, 208);
- border-radius: 1px;
- }
- #mt_set{
- width: 360px;
- height: 70px;
- background-color: rgb(235 179 82);
- position: fixed;
- border-radius: 5px;
- padding: 10px;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
- `
- GM_addStyle(MangaComponent.style)
-
- // 碎片 用户发布部分
- MangaComponent.f = PubFun.Fragment("#ct")
- document.querySelector("#mt_old").appendChild(MangaComponent.f)
-
-
- // 初始化数据
- // 解析页面中的图片地址
- MangaComponent.urls = PubFun.getUrls(document.querySelector("#mt_old").innerHTML);
-
- localStorage.getItem('size') ? null : localStorage.setItem('size', "100")
-
- // 创建
- createApp(
- {
- setup() {
- // 定义模式状态,1为默认模式,2为漫画模式
- const model_state = ref(MangaComponent.model);
- // 定义图片地址列表
- const urlList = MangaComponent.urls;
- // 定义图片地址是否加载完成状态
- const urlsLoaded = ref(true);
- // 定义是否全屏状态
- const fullScreen = ref(false);
- // 定义是否显示设置面板状态
- const showSettings = ref(false);
- // 定义下载按钮文字
- const downloadInfo = ref("下载");
- // 定义下载状态
- const downloadState = reactive({ done: 0, error: 0, allTasks: 0, pack: 0 });
- // 定义图片大小
- const imageSize = ref(localStorage.getItem('size') - 0);
- // 定义是否从右向左阅读
- const rightToLeft = ref(localStorage.getItem("rightToLeft") === "1");
- // 定义是否单页显示
- const onePage = ref(localStorage.getItem("onePage") === "1");
- // 定义是否使用白色背景
- const whiteBg = ref(localStorage.getItem("whiteBg") === "1");
-
- // 下载漫画
- const download = async () => {
- // 如果打包状态为0,则开始打包下载
- if (downloadState.pack === 0) {
- // 获取漫画名称
- const packName = document.getElementById("thread_subject").innerText;
- // 调用下载方法
- await PubFun.fflate_zip(packName, urlList, downloadState);
- }
- };
-
- // 监听图片大小变化
- watch(imageSize, (newSize) => {
- localStorage.setItem("size", newSize);
- });
- // 监听阅读方向变化
- watch(rightToLeft, (newValue) => {
- localStorage.setItem("rightToLeft", newValue ? "1" : "0");
- });
- // 监听单页显示状态变化
- watch(onePage, (newValue) => {
- localStorage.setItem("onePage", newValue ? "1" : "0");
- });
- // 监听白色背景状态变化
- watch(whiteBg, (newValue) => {
- localStorage.setItem("whiteBg", newValue ? "1" : "0");
- });
- // 监听下载状态变化
- watch(downloadState, () => {
- // 更新下载按钮文字
- downloadInfo.value = `${downloadState.done}/${downloadState.allTasks}`;
- if (downloadState.pack === 1) {
- downloadInfo.value = "开始打包,请等待...";
- }
- if (downloadState.pack === 2) {
- downloadInfo.value = "完成";
- }
- }, { deep: true });
- // 全屏
- watch(fullScreen, (new_val) => {
- const elem = document.documentElement;
- // 全屏模式的函数
- function full_screen() {
- if (elem.requestFullscreen) {
- elem.requestFullscreen();
- } else if (elem.mozRequestFullScreen) { // 兼容 Firefox
- elem.mozRequestFullScreen();
- } else if (elem.webkitRequestFullscreen) { // 兼容 Chrome, Safari 和 Opera
- elem.webkitRequestFullscreen();
- } else if (elem.msRequestFullscreen) { // 兼容 IE/Edge
- elem.msRequestFullscreen();
- }
- }
-
- // 退出全屏模式的函数
- function exit_fullscreen() {
- if (document.exitFullscreen) {
- document.exitFullscreen();
- } else if (document.mozCancelFullScreen) { // 兼容 Firefox
- document.mozCancelFullScreen();
- } else if (document.webkitExitFullscreen) { // 兼容 Chrome, Safari 和 Opera
- document.webkitExitFullscreen();
- } else if (document.msExitFullscreen) { // 兼容 IE/Edge
- document.msExitFullscreen();
- }
- }
-
- if (new_val) {
- full_screen()
- } else {
- exit_fullscreen()
- }
- })
-
-
- return {
- model_state,
- urlList,
- urlsLoaded,
- fullScreen,
- showSettings,
- downloadInfo,
- downloadState,
- imageSize,
- rightToLeft,
- onePage,
- whiteBg,
- download
- };
- }
- })
- .use(ElementPlus)
- .mount("#mt_manga")
- }
- };
-
- ///////////////////////////////////////////////////////////////////////////////////
- // 根据当前页面挂载组件
- // 主题页面
- if (window.location.href.match("https://bbs.yamibo.com/thread") || window.location.href.match(/forum.php\?mod=viewthread/)) {
- // 依赖加载完成
- document.querySelector("#element").onload = () => {
- new MangaComponent()
- }
- }
-
- // 主题列表页面
- else if (window.location.href.match("https://bbs.yamibo.com/forum")) {
- new MangaListComponent()
- }
- })();