本WIKI由旅行者酒馆于2021年10月05日申请开通。内容按CC BY-NC-SA 4.0协议提供,编辑权限开放。本WIKI仍在努力完善中,欢迎收藏。编辑组为非官方民间组织为爱发电,欢迎各路能人异士加入。

免责声明反馈留言收藏方法 • 交流群:1017604603
bugfix250107.1

全站通知:

Widget:ShowCount

来自崩坏:星穹铁道WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

<script> /**

* 传递给勾勾册的回调函数
* 勾选或者取消勾选后,Bikit 会调用一次本函数
*
* @param {string} listName
**/

function showCompute(listName) {

 const collectionSelector = "#CardSelectTr tr.bwiki-collection";
 const achievements = document.querySelectorAll(collectionSelector);
 let length = achievements.length;
 let sumCheck = 0;
 let remainingStella = 0;
 for (const achievement of achievements) {
   if (achievement.style.display === "none") {
     length -= 1;
     continue;
   }
   let checked = achievement.classList.contains("checked");
   if (checked) {
     sumCheck += 1;
   } else {
     const content = achievement.lastChild.textContent.trim().replace("星琼 x ", "");
     remainingStella += parseInt(content.trim());
   }
 }
 const totalNumClass = "bwiki-collection-totalnum-" + listName;
 for (let totalnum of document.getElementsByClassName(totalNumClass)) {
   totalnum.textContent = length;
 }
 const checkNumClass = "bwiki-collection-checknum-" + listName;
 for (let checknum of document.getElementsByClassName(checkNumClass)) {
   checknum.textContent = sumCheck;
 }
 const uncheckNumClass = "bwiki-collection-unchecknum-" + listName;
 for (let unchecknum of document.getElementsByClassName(uncheckNumClass)) {
   unchecknum.textContent = length - sumCheck;
 }
 for (let stellaNum of document.getElementsByClassName("stellaNum")) {
   stellaNum.textContent = `剩余可获取星琼:${remainingStella}个`;
 }

}

/**

* 勾勾册初始化执行完成之后,会设置几个 class 的 textContent 为统计数字
* 因此我们使用这个来判断勾勾册是否初始化成功
*
* Bikit 初始化阶段,首先会请求一次 mw.Api() 的 option 接口获取保存的勾选数据
* 根据保存数据对每一行进行判断是否已勾选,然后每一行都会调用一次 window.afterCollectionItemClick
* 而我们的回调函数又会扫一遍整张表然后更新成就完成数量,也就是如果提前设置回调函数,会导致初始化 O(N²) 时间复杂度
* 这就导致勾勾册初始化极其缓慢,因此为了避免空耗性能,我们必须等 Bikit 初始化完成后再设置回调
*
* @param {string} listName
*/

async function waitBikitInit(listName) {

 const indicatorClass = "bwiki-collection-unchecknum-achievement";
 const indicator = document.getElementsByClassName(indicatorClass);
 if (indicator.length === 0) return;
 while (isNaN(parseInt(indicator[0].textContent))) {
   await new Promise((resolve) => setTimeout(resolve, 100));
 }
 // 检测到初始化完成
 window.afterCollectionItemClick = showCompute;
 showCompute(listName);

}

document.addEventListener("DOMContentLoaded", async function () {

 const listName = "achievement"; // 勾勾册的自定义ID
 // 为成就筛选项增加事件监听以调用 showCompute 重新计算成就完成数量
 // 等 50ms 大概是为了等整个页面的 display: none 设置完成再执行,具体不清楚为什么当时这么写
 for (let button of document.getElementsByClassName("cardSelectOption")) {
   button.addEventListener("click", () =>
     setTimeout(showCompute, 50, listName),
   );
 }
 // 为「隐藏已完成成就」按钮增加事件监听以调用 showCompute 重新计算成就完成数量
 for (let button of document.getElementsByClassName("hideFinish")) {
   button.addEventListener("click", () =>
     setTimeout(showCompute, 50, listName),
   );
 }
 await waitBikitInit(listName);

}); </script>