// ==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()
}
})();