// ==UserScript== // @name Bangumi Super Enhancer // @namespace https://tampermonkey.net/ // @version 2.2.2 // @description Bangumi 增强套件 // @author Bios // @match *://bgm.tv/subject/* // @match *://chii.in/subject/* // @match *://bangumi.tv/subject* // @match *://bgm.tv/character/* // @match *://chii.in/character/* // @match *://bangumi.tv/character/* // @match *://bgm.tv/person/* // @match *://chii.in/person/* // @match *://bangumi.tv/person/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @license MIT // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js // @downloadURL none // ==/UserScript== (function () { "use strict"; // 样式增强 GM_addStyle(` .btnCustom { margin: 5px 0; background-color: #1E90FF !important; color: white !important; border-radius: 10px !important; padding: 5px 15px !important; border: none !important; cursor: pointer !important; transition: opacity 0.2s; } .btnCustom:hover { opacity: 0.8; } .enhancer-textarea { width: 100%; min-height: 60px; max-height: 300px; border: 1px solid #ddd; border-radius: 10px; padding: 8px; margin: 8px 0; resize: vertical; font-size: 13px; box-sizing: border-box; } .enhancer-panel { margin: 6px 0; /* 减少外边距 */ border-radius: 6px; /* 调小圆角 */ padding: 5px; /* 减少内边距 */ background: #f8f8f8; border: 1px solid #e0e0e0; } #coverUploadForm { text-align: center; padding: 3px; /* 减少表单内边距 */ } #coverUploadForm input[type="file"] { margin: 3px auto; /* 缩小文件输入框边距 */ width: 90%; /* 调宽输入框减少留白 */ display: block; } /* 进一步缩小按钮尺寸 */ #coverUploadForm input[type="submit"] { padding: 4px 8px !important; /* 更紧凑的按钮尺寸 */ font-size: 14px !important; /* 更小的字号 */ margin: 8px auto 2px !important; /* 调整按钮间距 */ } `); /* Wiki 按钮模块 */ function initWikiButton() { // 排除编辑页面 if (/(edit_detail|edit)$/.test(location.pathname)) return; // 排除 add_related 和 upload_img 页面 if (/add_related|upload_img/.test(location.pathname)) return; const matchSubject = location.pathname.match(/\/subject\/(\d+)/); const matchPerson = location.pathname.match(/\/person\/(\d+)/); const matchCharacter = location.pathname.match(/\/character\/(\d+)/); const nav = document.querySelector(".subjectNav .navTabs, .navTabs"); if (!nav || nav.querySelector(".wiki-button")) return; const li = document.createElement("li"); li.className = "wiki-button"; let wikiUrl = ""; if (matchSubject) { wikiUrl = `${location.origin}/subject/${matchSubject[1]}/edit_detail`; } else if (matchPerson) { wikiUrl = `${location.origin}/person/${matchPerson[1]}/edit`; } else if (matchCharacter) { wikiUrl = `${location.origin}/character/${matchCharacter[1]}/edit`; } if (wikiUrl) { li.innerHTML = `Wiki`; nav.appendChild(li); } } // 监听 URL 变化 function observeURLChanges() { let lastURL = location.href; new MutationObserver(() => { if (location.href !== lastURL) { lastURL = location.href; initWikiButton(); } }).observe(document, { subtree: true, childList: true }); } /* 封面上传模块 */ async function initCoverUpload() { if (document.querySelector("img.cover")) return; const infoBox = document.querySelector("#bangumiInfo"); if (!infoBox) return; const links = document.querySelectorAll(".tip_i p a.l"); if (links.length < 2) return; try { const res = await fetch(links[1].href); const doc = new DOMParser().parseFromString(await res.text(), "text/html"); const form = doc.querySelector("#columnInSubjectA .text form"); if (form) { const container = document.createElement("div"); container.className = "enhancer-panel"; const clone = form.parentElement.cloneNode(true); const uploadForm = clone.querySelector("form"); uploadForm.id = "coverUploadForm"; const fileInput = uploadForm.querySelector("input[type=file]"); fileInput.style.width = "100%"; const submitBtn = uploadForm.querySelector("input[type=submit]"); submitBtn.className = "btnCustom"; submitBtn.style.width = "120px"; submitBtn.style.margin = "10px auto 0"; container.appendChild(uploadForm); infoBox.parentNode.insertBefore(container, infoBox); } } catch (e) { console.error("封面加载失败:", e); } } /* 章节批量编辑 */ function enhanceEpisodes() { if (!location.pathname.includes("/ep")) return; const formHash = document.querySelector("[name=formhash]")?.value; if (!formHash) return; document.querySelector("[name=edit_ep_batch]")?.addEventListener("submit", async (e) => { e.preventDefault(); const episodes = [...document.querySelectorAll('[name="ep_mod[]"]:checked')].map(el => el.value); let batchSize = 100; while (batchSize >= 50 && episodes.length > 0) { try { const data = new URLSearchParams(); data.append("formhash", formHash); data.append("chkall", "on"); data.append("submit", "批量修改"); episodes.splice(0, batchSize).forEach(ep => data.append("ep_mod[]", ep)); const res = await fetch(location.pathname + "/edit_batch", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: data }); if (!res.ok) throw new Error(); alert(`成功提交 ${batchSize} 个章节`); return; } catch { batchSize = Math.floor(batchSize / 2); } } alert("提交失败,请减少选中数量!"); }); } /* 获取当前页面的 ID(即 URL 里的 subject/xxx、character/xxx、person/xxx)*/ function getCurrentPageID() { const match = window.location.pathname.match(/\/(subject|character|person)\/(\d+)/); return match ? parseInt(match[2], 10) : null; } const currentPageID = getCurrentPageID(); /* 获取当前条目 ID */ /* 批量关联模块 */ function initBatchRelation() { if (!document.getElementById("indexCatBox")) return; const panelHTML = `