TagBangumiUserPro 班固米用户备注

Based on AttachHowOldtoUserinPosts, to tag users in Bangumi. Now with clickable badges to edit notes.

目前為 2025-02-05 提交的版本,檢視 最新版本

// ==UserScript==
// @name         TagBangumiUserPro 班固米用户备注
// @version      2.8
// @description  Based on AttachHowOldtoUserinPosts, to tag users in Bangumi. Now with clickable badges to edit notes.
// @author       age_anime
// @match        https://bgm.tv/*
// @match        https://chii.in/*
// @match        https://bangumi.tv/*
// @grant        none
// @license      MIT
// @namespace https://gf.qytechs.cn/users/1426310
// ==/UserScript==
(function () {
    'use strict';

    // 默认颜色配置
    const defaultNoteColors = {
        "BGMER": "#40E0D0",
        "Wiki管理": "#BB44BB",
        "官方管理": "#000000",
        "大佬": "#DD6D22",
        "巨魔": "#CC3333",
        "大明星": "#DD6D22",
        "知名人士": "#3C3CC4"
    };
    let noteColors = JSON.parse(localStorage.getItem('userNoteColors_')) || defaultNoteColors;

    const defaultNote = "bgmer";
    const defaultColor = "rgba(102, 170, 85, 0.2)";

    function displayUserNote(userId, note) {
        const userAnchor = $("strong a.l[href='/user/" + userId + "']");
        if (userAnchor.length > 0 && userAnchor.next(".note-badge").length === 0) {
            const badgeColor = noteColors[note] || defaultColor;
            const badge = $(`
                <span class="note-badge" style="
                    background-color: ${badgeColor};
                    font-size: 11px;
                    padding: 2px 5px;
                    color: #FFF;
                    border-radius: 100px;
                    line-height: 150%;
                    display: inline-block;
                    cursor: pointer;
                " title="点击编辑备注">${note}</span>`);

            badge.click(function () {
                const newNote = prompt("请输入新的备注:", note);
                if (newNote !== null) {
                    const trimmedNote = newNote.trim();
                    if (trimmedNote === "") {
                        // 清空备注时移除缓存
                        localStorage.removeItem("userNote_" + userId);
                        badge.remove();
                    } else if (trimmedNote !== note) {
                        // 保存新备注到缓存
                        note = trimmedNote;
                        localStorage.setItem("userNote_" + userId, note);
                        badge.text(note);
                        const newBadgeColor = noteColors[note] || defaultColor;
                        badge.css("background-color", newBadgeColor);
                    }
                }
            });
            userAnchor.after(badge);
        }
    }

    function markUserNotes() {
        $("strong a.l:not(.avatar)").each(function () {
            const userLink = $(this).attr("href");
            const userId = userLink.split("/").pop();
            // 仅在缓存存在时使用,否则使用默认值(但不自动保存)
            const note = localStorage.getItem("userNote_" + userId) || defaultNote;
            displayUserNote(userId, note);
        });
    }

    function importUserNotes() {
        const input = document.createElement("input");
        input.type = "file";
        input.accept = "application/json";
        input.onchange = function (event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function (e) {
                    try {
                        const userNotes = JSON.parse(e.target.result);
                        Object.keys(userNotes).forEach(key => localStorage.setItem(key, userNotes[key]));
                        alert("导入成功");
                    } catch (error) {
                        alert("无效的JSON文件:" + error);
                    }
                };
                reader.readAsText(file);
            }
        };
        input.click();
    }

    function exportUserNotes() {
        const userNotes = {};
        Object.keys(localStorage).forEach(key => {
            if (key.startsWith("userNote_")) {
                userNotes[key] = localStorage.getItem(key);
            }
        });
        const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
        const entryCount = Object.keys(userNotes).length;
        const filename = `userNotes_${timestamp}_${entryCount}entries.json`;
        const blob = new Blob([JSON.stringify(userNotes, null, 2)], { type: "application/json" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = filename;
        a.click();
        URL.revokeObjectURL(url);
    }

    function openColorManager() {
        const modal = document.createElement('div');
        Object.assign(modal.style, {
            position: 'fixed',
            left: '50%',
            top: '50%',
            transform: 'translate(-50%, -50%)',
            backgroundColor: 'white',
            padding: '20px',
            borderRadius: '5px',
            boxShadow: '0 0 10px rgba(0,0,0,0.5)',
            zIndex: '9999',
            width: '450px'
        });

        // 添加颜色表单
        const form = document.createElement('div');
        form.style.marginBottom = '5px';

        const nameLabel = document.createElement('label');
        nameLabel.textContent = '名称:';
        nameLabel.style.color = '#333333';
        nameLabel.style.marginRight = '5px';

        const nameInput = document.createElement('input');
        nameInput.type = 'text';
        nameInput.style.minWidth = '240px';
        nameInput.style.width = 'auto';
        nameInput.style.height = '22px';
        nameInput.style.marginRight = '5px';
        nameInput.style.position = 'relative';
        nameInput.style.top = '-5px';

        const colorLabel = document.createElement('label');
        colorLabel.textContent = '颜色:';
        colorLabel.style.color = '#333333';
        colorLabel.style.marginRight = '5px';

        const colorInput = document.createElement('input');
        colorInput.type = 'color';
        colorInput.style.marginRight = '5px';

        const addButton = document.createElement('button');
        addButton.textContent = '添加';
        addButton.onclick = () => {
            const name = nameInput.value.trim();
            const color = colorInput.value;
            if (name && color) {
                noteColors[name] = color;
                textarea.value = JSON.stringify(noteColors, null, 4);
                nameInput.value = '';
                colorInput.value = '#000000';
            } else {
                alert('名称和颜色不能为空!');
            }
        };

        form.append(nameLabel, nameInput, colorLabel, colorInput, addButton);

        // JSON 编辑区域
        const textarea = document.createElement('textarea');
        textarea.style.cssText = 'width: 100%; height: 200px; margin-bottom: 10px;';
        textarea.value = JSON.stringify(noteColors, null, 4);

        // 按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = 'text-align: right;';

        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = '取消';
        cancelBtn.onclick = () => modal.remove();

        const saveBtn = document.createElement('button');
        saveBtn.textContent = '保存';
        saveBtn.style.marginLeft = '8px';
        saveBtn.onclick = () => {
            try {
                const newColors = JSON.parse(textarea.value);
                if (typeof newColors !== 'object' || newColors === null) {
                    throw new Error('请输入有效的JSON对象');
                }
                localStorage.setItem('userNoteColors_', JSON.stringify(newColors));
                noteColors = newColors;
                document.querySelectorAll('.note-badge').forEach(badge => {
                    const note = badge.textContent;
                    badge.style.backgroundColor = noteColors[note] || defaultColor;
                });
                modal.remove();
            } catch (error) {
                alert('错误: 请检查JSON格式(其他行的末尾是有英文逗号的,最后一行的末尾是没有逗号的!),还不会就把错误代码和JSON内容放在AI里面问问: ' + error.message);
            }
        };

        buttonContainer.append(cancelBtn, saveBtn);
        modal.append(form, textarea, buttonContainer);
        document.body.appendChild(modal);
    }

    function addButtonFunctions() {
        const badgeUserPanel = document.querySelector("ul#badgeUserPanel");
        if (badgeUserPanel) {
            // 导入按钮
            const importLi = document.createElement('li');
            const importBtn = document.createElement('a');
            importBtn.href = '#';
            importBtn.textContent = '导入用户数据';
            importBtn.onclick = (e) => { e.preventDefault(); importUserNotes(); };
            importLi.appendChild(importBtn);

            // 导出按钮
            const exportLi = document.createElement('li');
            const exportBtn = document.createElement('a');
            exportBtn.href = '#';
            exportBtn.textContent = '导出用户数据';
            exportBtn.onclick = (e) => { e.preventDefault(); exportUserNotes(); };
            exportLi.appendChild(exportBtn);

            // 颜色管理按钮
            const colorLi = document.createElement('li');
            const colorBtn = document.createElement('a');
            colorBtn.href = '#';
            colorBtn.textContent = '管理颜色配置';
            colorBtn.onclick = (e) => { e.preventDefault(); openColorManager(); };
            colorLi.appendChild(colorBtn);

            badgeUserPanel.append(importLi, exportLi, colorLi);
        }
    }

    if (document.body) {
        markUserNotes();
    } else {
        window.onload = markUserNotes;
    }

    setTimeout(addButtonFunctions, 1000);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址