快速跳转萌娘百科

在tab栏中添加跳转萌娘百科按钮。支持条目、人物与角色页面。可以自定义链接。

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);
    }

})();