在tab栏中添加跳转萌娘百科按钮。支持条目、人物与角色页面。可以自定义链接。
// ==UserScript==
// @name 快速跳转萌娘百科
// @namespace https://github.com/Zao-chen/Bangumi2Wiki
// @version 2.0.3
// @description 在tab栏中添加跳转萌娘百科按钮。支持条目、人物与角色页面。可以自定义链接。
// @match https://bangumi.tv/subject/*
// @match https://bangumi.tv/person/*
// @match https://bangumi.tv/character/*
// @match https://bgm.tv/subject/*
// @match https://bgm.tv/person/*
// @match https://bgm.tv/character/*
// @match https://chii.in/subject/*
// @match https://chii.in/person/*
// @match https://chii.in/character/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const LOCAL_KEY = 'moegirl_link_template';
const DEFAULT_TEMPLATE = 'https://zh.moegirl.org.cn/index.php?search={title}';
const titleLink = document.querySelector('h1.nameSingle a');
const isSubjectPage = location.pathname.includes('/subject/');
const isPersonPage = location.pathname.includes('/person/');
const isCharacterPage = location.pathname.includes('/character/');
let displayTitle = null;
if (isSubjectPage || isPersonPage || isCharacterPage) {
const tips = document.querySelectorAll('#infobox li span.tip');
for (const tip of tips) {
const text = tip.textContent.trim();
if (isSubjectPage && text.startsWith("中文名")) {
const li = tip.closest('li');
if (li) {
displayTitle = li.textContent.replace(/^中文名[::]\s*/, '').trim();
break;
}
}
if ((isPersonPage || isCharacterPage) && text.startsWith("简体中文名")) {
const li = tip.closest('li');
if (li) {
displayTitle = li.textContent.replace(/^简体中文名[::]\s*/, '').trim();
break;
}
}
}
}
// fallback:使用主标题本身
if (!displayTitle) {
displayTitle = titleLink?.textContent.trim() || '未知条目';
}
// 去除季数,例如“xxx 第1季”
displayTitle = displayTitle.replace(/第.*季/g, '').trim();
const navTabs = document.querySelector('.navTabs.clearit') || document.querySelector('.navTabs');
if (navTabs) {
const secondTab = navTabs.children[1] || navTabs.firstElementChild;
const newTab = document.createElement("li");
const link = document.createElement("a");
link.href = 'javascript:void(0)';
link.textContent = "萌百";
link.setAttribute('title', `点击跳转到“${displayTitle}”萌娘百科,长按可设置跳转模板`);
let pressTimer = null;
let longPressTriggered = false;
let pointerMoved = false;
let startX = 0;
let startY = 0;
function startPressTimer(e) {
longPressTriggered = false;
pointerMoved = false;
const touch = e.touches ? e.touches[0] : e;
startX = touch.clientX;
startY = touch.clientY;
pressTimer = setTimeout(() => {
longPressTriggered = true;
const current = localStorage.getItem(LOCAL_KEY) || DEFAULT_TEMPLATE;
const newTemplate = prompt("请输入跳转链接模板,使用 {title} 表示条目标题:", current);
if (newTemplate && newTemplate.includes('{title}')) {
localStorage.setItem(LOCAL_KEY, newTemplate);
alert("✅ 已保存新模板,刷新页面以生效!");
} else if (newTemplate) {
alert("⚠️ 模板格式无效,必须包含 {title} 作为占位符!");
}
}, 700);
}
function cancelPressTimer() {
clearTimeout(pressTimer);
}
function handlePointerMove(e) {
const touch = e.touches ? e.touches[0] : e;
const dx = Math.abs(touch.clientX - startX);
const dy = Math.abs(touch.clientY - startY);
if (dx > 10 || dy > 10) {
pointerMoved = true;
cancelPressTimer();
}
}
link.addEventListener("pointerdown", startPressTimer);
link.addEventListener("pointerup", cancelPressTimer);
link.addEventListener("pointercancel", cancelPressTimer);
link.addEventListener("pointermove", handlePointerMove);
// 防止手机端长按弹出默认菜单
link.addEventListener("contextmenu", (e) => e.preventDefault());
link.addEventListener("click", (e) => {
if (longPressTriggered) {
e.preventDefault(); // 如果是长按触发,不跳转
return;
}
const template = localStorage.getItem(LOCAL_KEY) || DEFAULT_TEMPLATE;
const finalUrl = template.replace(/{title}/g, encodeURIComponent(displayTitle));
window.open(finalUrl, "_blank");
});
newTab.appendChild(link);
navTabs.insertBefore(newTab, secondTab);
}
})();