您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
gadgets 页面无刷新切换启用/停用,并添加“全部停用”按钮
// ==UserScript== // @name 班固米组件当页启用停用 // @namespace https://bgm.tv/ // @version 1.3.1 // @description gadgets 页面无刷新切换启用/停用,并添加“全部停用”按钮 // @author you // @match https://bgm.tv/settings/gadgets // @match https://bangumi.tv/settings/gadgets // @match https://chii.in/settings/gadgets // @run-at document-idle // @license MIT // ==/UserScript== (function () { 'use strict'; /** 提示 */ function toast(message, success = true) { if (window.chiiLib?.ukagaka?.presentSpeech) { window.chiiLib.ukagaka.presentSpeech(message, success); } } /** gadgetId: 从 href 里提取数字 */ function getGadgetId(href) { const m = href.match(/\/dev\/app\/(\d+)\//); return m ? m[1] : null; } /** 判断是启用还是停用 */ function isEnableLink(href) { return /\/enable(\?|$)/.test(href); } /** 设置按钮 loading/恢复 */ function setLoading(a, loading) { if (!a) return; const span = a.querySelector('span') || a; if (loading) { span.textContent = '处理中…'; a.classList.add('disabled'); a.style.opacity = '0.6'; a.style.pointerEvents = 'none'; } else { // 根据 href 决定按钮文本 span.textContent = isEnableLink(a.href) ? '启用' : '停用'; a.classList.remove('disabled'); a.style.opacity = ''; a.style.pointerEvents = ''; } } /** 切换一组 gadget 的按钮(所有同 id 的按钮) */ function flipButtons(gadgetId, toEnable) { document.querySelectorAll(`a[href*="/dev/app/${gadgetId}/"]`).forEach(a => { const span = a.querySelector('span') || a; if (toEnable) { // gadget 启用 → 显示“停用” a.href = a.href.replace('/enable', '/disable'); a.classList.remove('btnGreenSmall'); a.classList.add('btnRedSmall'); } else { // gadget 停用 → 显示“启用” a.href = a.href.replace('/disable', '/enable'); a.classList.remove('btnRedSmall'); a.classList.add('btnGreenSmall'); } }); } /** 发起请求 */ function toggleRequest(a) { const href = a.getAttribute('href'); const gadgetId = getGadgetId(href); if (!gadgetId) return; const enabling = isEnableLink(href); setLoading(a, true); return fetch(href, { method: 'GET', credentials: 'same-origin' }) .then(res => { if (res.ok || (res.status >= 300 && res.status < 400)) { flipButtons(gadgetId, enabling); toast(enabling ? '启用成功!' : '停用成功!', true); } else { toast('操作失败!', false); } }) .catch(() => toast('操作失败!', false)) .finally(() => setLoading(a, false)); } /** 绑定按钮 */ function bindButtons() { document.querySelectorAll('a.btnGreenSmall, a.btnRedSmall').forEach(a => { if (!getGadgetId(a.href)) return; a.addEventListener('click', e => { e.preventDefault(); // 如果正在处理中就不再响应 if (a.classList.contains('disabled')) return; toggleRequest(a); }); }); } /** 添加“全部停用”按钮 */ function addDisableAllButton() { const firstLi = document.querySelector('#columnA .tml_item, .tml_item'); if (!firstLi) return; const a = document.createElement('a'); a.href = 'javascript:void(0)'; a.className = 'btnRedSmall'; const span = document.createElement('span'); span.textContent = '全部停用'; a.appendChild(span); a.addEventListener('click', async e => { e.preventDefault(); if (a.classList.contains('disabled')) return; // 找到所有处于启用状态的 gadget 按钮(红色=启用中) const activeButtons = [...document.querySelectorAll('a.btnRedSmall')] .filter(btn => getGadgetId(btn.href)); // 去重(同 gadgetId 只操作一次) const ids = [...new Set(activeButtons.map(b => getGadgetId(b.href)))]; setLoading(a, true); for (const id of ids) { const btn = activeButtons.find(b => getGadgetId(b.href) === id); if (btn) await toggleRequest(btn); } setLoading(a, false); toast('全部停用完成!', true); }); firstLi.parentNode.insertBefore(a, firstLi); } // 初始化 bindButtons(); addDisableAllButton(); })();