注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
?_=1
来访问最新页面。https://zh.moegirl.org.cn/User:%E5%85%AC%E7%9A%84%E9%A9%B1%E9%80%90%E8%88%B0/ak_index_supplement.js?_=1
/* global mw, $ */ "use strict"; window.RLQ = window.RLQ || []; window.RLQ.push(async () => { await mw.loader.using(["mediawiki.notification", "mw.Api"]); const api = new mw.Api(); const dic = {}; const eliteType = ["1+", "2", "3"]; const thumbCache = {}; //函数:检查半身像是否存在 const ifexist = async (opName, type) => { for (let retryTimes = 0; retryTimes < 3; retryTimes++) { try { const result = (await api.post({ action: "query", titles: `Media:半身像_${opName}_${type}.png`, prop: "info", })).query.pages["-1"]; return !("missing" in result || "invalid" in result); } catch (e) { console.error("ifexist", e); } } return false; }; //函数:获取指定的缩略图链接 const getThumb = async (files) => { const postInfo = {}; files.forEach(([filename, thumbWidth]) => { (postInfo[thumbWidth] = postInfo[thumbWidth] || new Set()).add(filename); }); return Object.fromEntries(await Promise.all(Object.entries(postInfo).map(async ([thumbWidth, filenames]) => { const result = {}; if (!(thumbWidth in thumbCache)) { thumbCache[thumbWidth] = {}; } for (const filename of filenames) { if (filename in thumbCache[thumbWidth]) { result[filename] = thumbCache[thumbWidth][filename]; filenames.delete(filename); } } if (filenames.size === 0) { return [thumbWidth, result]; } for (let retryTimes = 0; retryTimes < 3; retryTimes++) { try { const data = await api.post({ action: "query", titles: Array.from(filenames.values()).join("|"), prop: "imageinfo", iiprop: "url", iiurlwidth: thumbWidth, }); const normalized = Object.fromEntries(data.query.normalized.map(({ from, to }) => [to, from])); Object.entries(data.query.pages).forEach(([, { title, imageinfo: [{ thumburl }] }]) => { thumbCache[thumbWidth][normalized[title]] = result[normalized[title]] = thumburl; }); return [thumbWidth, result]; } catch (e) { console.info("getThumb", e, files); } } return [thumbWidth, result]; }))); }; //函数:初始化词典 const init = async (opName) => { if (!Array.isArray(dic[opName])) { dic[opName] = []; } //检查半身像词典是否包含无精;如果没有的话词典应当是空的,写词典 if (!dic[opName].includes("1")) { dic[opName].push("1"); if (await ifexist(opName, "1+")) { dic[opName].push("1+"); } if (await ifexist(opName, "2")) { dic[opName].push("2"); } //如果有精三、四,etc. 的话加在这里 for (let i = 1; await ifexist(opName, `skin${i}`); i++) { dic[opName].push(`skin${i}`); } } }; //函数:变更半身像的HTML元素(加载新半身像) const changeImage = async (root, opName, typeId) => { const layer2Filename = `File:半身像_${opName}_${typeId}.png`; const layer6Filename = `File:精英${eliteType.includes(typeId) ? typeId : "1"}_图标.png`; const thumbInfos = await getThumb([ [layer2Filename, 180], [layer6Filename, 67], ]); root.find(".akIllLayer2 > img").removeAttr("height srcset").attr("src", thumbInfos[180][layer2Filename]); root.find(".akIllLayer6 > img").removeAttr("height srcset").attr("src", thumbInfos[67][layer6Filename]); }; //函数:步进半身像 const change = async (root, opName, showBubble = true) => { root.data("supplement_running", true); dic[opName] = dic[opName] || []; if (showBubble) { mw.notify(`正在加载${opName}的下一张立绘……`, { title: "明日方舟:图鉴切换", tag: `akIll_supplement_${Object.keys(dic).indexOf(opName)}`, }); } await init(opName); const info = dic[opName]; const currentType = `${root.data("type") || "1"}`; if (info.length !== 1) { //下一个半身像的顺位 const nextId = (info.indexOf(currentType) + 1) % info.length; //准备下一套图片 const nextType = info[nextId]; await changeImage(root, opName, nextType); root.data({ supplement_running: false, type: nextType, }); } else { if (showBubble) { mw.notify(`${opName}只有这一张立绘……`, { title: "明日方舟:图鉴切换", tag: `akIll_supplement_${Object.keys(dic).indexOf(opName)}`, }); } root.data("supplement_running", false); } }; //函数:切换到指定半身像 const changeTo = async (root, opName, typeId, showBubble = true) => { root.data("supplement_running", true); dic[opName] = dic[opName] || []; //准备可读半身像类型,顺带检查type是否合法;不合法则强制bubble报错 let readableType; switch (typeId) { case "1": readableType = "无精英立绘"; break; case "1+": readableType = "精英一立绘"; break; case "2": readableType = "精英二立绘"; break; default: if (typeId.startsWith("skin")) { readableType = `时装 ${typeId.substring(4)}`; } else { mw.notify(`无法加载${opName}的图鉴“${typeId}”:图鉴名称不合法`, { title: "明日方舟:图鉴切换", tag: `akIll_supplement_${Object.keys(dic).indexOf(opName)}`, }); root.data("supplement_running", false); return false; } } if (showBubble) { mw.notify(`正在尝试加载${opName}的${readableType}……`, { title: "明日方舟:图鉴切换", tag: `akIll_supplement_${Object.keys(dic).indexOf(opName)}`, }); } await init(opName); const info = dic[opName]; //目标半身像的顺位 if (!info.includes(typeId)) { if (showBubble) { mw.notify(`无法加载${opName}的${readableType}:该图鉴不存在`, { title: "明日方舟:图鉴切换", tag: `akIll_supplement_${Object.keys(dic).indexOf(opName)}`, }); } root.data("supplement_running", false); return false; } //准备下一套图片 await changeImage(root, opName, typeId); root.data({ supplement_running: false, type: typeId, }); }; //点击一键无精按钮的事件 $("#button-IndexAllE0").css("cursor", "pointer").on("click", () => { console.log("AllE0 button triggered"); mw.notify("正在加载所有干员的无精英立绘……", { title: "明日方舟:图鉴切换", tag: "akIll_supplement_AllE0", }); $(".akIll").each((_, ele) => { changeTo($(ele), ele.dataset.operatorName, "1", false); }); }); //点击一键精二按钮的事件 $("#button-IndexAllE2").css("cursor", "pointer").on("click", () => { console.log("AllE2 button triggered"); mw.notify("正在加载四星及以上干员的精英二立绘……", { title: "明日方舟:图鉴切换", tag: "akIll_supplement_AllE2", }); $(".akIll").each((_, ele) => { changeTo($(ele), ele.dataset.operatorName, "2", false); }); }); //点击一键服装按钮的事件 $("#button-IndexAllSkin1").css("cursor", "pointer").on("click", () => { console.log("AllSkin1 button triggered"); mw.notify("正在加载拥有时装的干员的第一套时装……", { title: "明日方舟:图鉴切换", tag: "akIll_supplement_AllSkin1", }); $(".akIll").each((_, ele) => { changeTo($(ele), ele.dataset.operatorName, "skin1", false); }); }); //点击图鉴模板的事件 $(".akIll").css("cursor", "pointer").on("click", ({ target, }) => { if ($(target).closest(".akIll a").length > 0) { return true; } const root = $(target).closest(".akIll"); if (root.data("supplement_running")) { return false; } const opName = root.attr("data-operator-name"); change(root, opName); return false; }); });