吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2283|回复: 15
收起左侧

[其他转载] 【油猴脚本】52pj帖子列表增强

[复制链接]
Cristy 发表于 2026-3-4 16:35
本帖最后由 Cristy 于 2026-3-5 10:20 编辑

52pj帖子列表增强集成设置面板,将原有多个弹窗菜单整合到一个直观的浮动窗口中,支持所有功能的可视化配置。

便捷安装地址:
https://scriptcat.org/scripts/code/5509/52pj%E5%B8%96%E5%AD%90%E5%88%97%E8%A1%A8%E5%A2%9E%E5%BC%BA.user.js



**2026-03-05**更新
根据坛友 xinchenmetx 的启发,让AI优化了设置面板 更加易于操作, 测试了ScriptCat 和 油猴插件 均正常展示。
image.png





下面为原文
---

## 效果:
b8684fa0-5ca4-46af-a23b-d862288d71f0.png

image.png

## 代码:

```javascript
// ==UserScript==
// @name         52pj撒币帖子更显眼(设置面板版)
// @match        https://www.52pojie.cn/*
// @version      2.0
// @description  实时监测并修改链接样式,集成可视化设置面板(支持回帖奖励、悬赏已解决、悬赏金额动态样式)
// @AuThor       aura service
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @license      ISC
// ==/UserScript==

(function() {
    'use strict';

    // ---------- 配置存储 ----------
    // 回帖奖励样式
    const defaultStyles = { fontWeight: 'bold', color: 'red', fontSize: '16px' };
    let styles = {
        fontWeight: GM_getValue('fontWeight', defaultStyles.fontWeight),
        color: GM_getValue('color', defaultStyles.color),
        fontSize: GM_getValue('fontSize', defaultStyles.fontSize)
    };

    // 悬赏已解决配置
    const defaultResolvedAction = 'mark';
    const defaultResolvedBgColor = '#f0f0f0';
    let resolvedAction = GM_getValue('resolvedAction', defaultResolvedAction);
    let resolvedBgColor = GM_getValue('resolvedBgColor', defaultResolvedBgColor);

    // 悬赏金额动态样式配置
    const REWARD_ENABLED_KEY = 'rewardEnabled';
    const REWARD_RULES_KEY = 'rewardRules';
    const defaultRewardRules = [
        { min: 1, max: 9, style: { color: 'green' } },
        { min: 10, max: 49, style: { color: 'orange', fontWeight: 'bold' } },
        { min: 50, max: 99, style: { color: 'red', fontWeight: 'bold', fontSize: '16px' } },
        { min: 100, max: null, style: { color: 'purple', fontWeight: 'bold', fontSize: '18px', backgroundColor: '#ffffcc' } }
    ];
    let rewardEnabled = GM_getValue(REWARD_ENABLED_KEY, false);
    let rewardRules = GM_getValue(REWARD_RULES_KEY, defaultRewardRules);

    // ---------- 辅助函数 ----------
    function getStyleForReward(amount) {
        if (!rewardEnabled) return null;
        for (const rule of rewardRules) {
            if (amount >= rule.min && (rule.max === null || amount <= rule.max)) {
                return rule.style;
            }
        }
        return null;
    }

    // ---------- 核心处理函数(同之前)----------
    function checkAndModify() {
        const rows = document.querySelectorAll('tbody tr');
        rows.forEach(row => {
            // 回帖奖励
            const ths = row.querySelectorAll('th.common, th.new');
            let hasReward = false;
            ths.forEach(th => {
                const span = th.querySelector('span');
                if (span && span.textContent.includes('回帖奖励')) hasReward = true;
            });
            if (hasReward) {
                const links = row.querySelectorAll('th.common a.s.xst, th.new a.s.xst');
                links.forEach(link => {
                    link.style.fontWeight = styles.fontWeight;
                    link.style.color = styles.color;
                    link.style.fontSize = styles.fontSize;
                });
            }

            // 悬赏已解决标记/隐藏
            const rewardIcon = row.querySelector('td.icn img[src*="rewardsmall.gif"]');
            if (rewardIcon) {
                const resolvedLink = Array.from(row.querySelectorAll('th a')).find(a => a.textContent.trim() === '[已解决]');
                if (resolvedLink) {
                    if (resolvedAction === 'mark') row.style.backgroundColor = resolvedBgColor;
                    else if (resolvedAction === 'hide') row.style.display = 'none';
                }
            }

            // 悬赏金额动态样式
            if (rewardEnabled && rewardIcon) {
                const rewardLink = row.querySelector('th a[href*="specialtype=reward"]');
                if (rewardLink) {
                    const amountSpan = rewardLink.querySelector('span.xw1');
                    if (amountSpan) {
                        const amount = parseInt(amountSpan.textContent.trim(), 10);
                        if (!isNaN(amount)) {
                            const style = getStyleForReward(amount);
                            if (style) {
                                const titleLink = row.querySelector('th.common a.s.xst, th.new a.s.xst');
                                if (titleLink) {
                                    for (const [prop, val] of Object.entries(style)) {
                                        titleLink.style[prop] = val;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    // ---------- 设置面板 ----------
    let settingsPanel = null;

    function createSettingsPanel() {
        if (settingsPanel) {
            settingsPanel.style.display = settingsPanel.style.display === 'none' ? 'block' : 'none';
            return;
        }

        // 创建面板容器
        const panel = document.createElement('div');
        panel.id = 'pj-settings-panel';
        Object.assign(panel.style, {
            position: 'fixed',
            top: '60px',
            right: '20px',
            width: '400px',
            maxHeight: '80vh',
            overflowY: 'auto',
            backgroundColor: '#fff',
            border: '1px solid #ccc',
            borderRadius: '8px',
            boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
            padding: '16px',
            zIndex: '9999',
            fontFamily: 'Arial, sans-serif',
            fontSize: '14px',
            display: 'block'
        });

        // 标题 + 关闭按钮
        const header = document.createElement('div');
        Object.assign(header.style, {
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            marginBottom: '16px',
            paddingBottom: '8px',
            borderBottom: '1px solid #eee'
        });
        header.innerHTML = '<h3 style="margin:0;">52pj 帖子增强设置</h3>';
        const closeBtn = document.createElement('button');
        closeBtn.textContent = '&#10005;';
        Object.assign(closeBtn.style, {
            background: 'none',
            border: 'none',
            fontSize: '18px',
            cursor: 'pointer',
            padding: '0 6px'
        });
        closeBtn.onclick = () => panel.style.display = 'none';
        header.appendChild(closeBtn);
        panel.appendChild(header);

        // ---------- 回帖奖励样式 ----------
        const section1 = document.createElement('div');
        section1.innerHTML = '<h4 style="margin:12px 0 8px;">回帖奖励样式</h4>';
        const form1 = document.createElement('div');
        form1.style.display = 'grid';
        form1.style.gridTemplateColumns = '80px 1fr';
        form1.style.gap = '8px';
        form1.style.marginBottom = '8px';

        // 字体粗细
        form1.appendChild(document.createTextNode('字体粗细:'));
        const inputWeight = document.createElement('input');
        inputWeight.type = 'text';
        inputWeight.value = styles.fontWeight;
        form1.appendChild(inputWeight);

        // 颜色
        form1.appendChild(document.createTextNode('颜色:'));
        const inputColor = document.createElement('input');
        inputColor.type = 'text';
        inputColor.value = styles.color;
        form1.appendChild(inputColor);

        // 字体大小
        form1.appendChild(document.createTextNode('字体大小:'));
        const inputSize = document.createElement('input');
        inputSize.type = 'text';
        inputSize.value = styles.fontSize;
        form1.appendChild(inputSize);

        section1.appendChild(form1);
        panel.appendChild(section1);

        // ---------- 悬赏已解决处理 ----------
        const section2 = document.createElement('div');
        section2.innerHTML = '<h4 style="margin:16px 0 8px;">悬赏已解决处理</h4>';
        const form2 = document.createElement('div');
        form2.style.marginBottom = '8px';

        // 处理方式单选
        const radioNone = document.createElement('input');
        radioNone.type = 'radio';
        radioNone.name = 'resolvedAction';
        radioNone.value = 'none';
        radioNone.checked = resolvedAction === 'none';
        const labelNone = document.createTextNode('无操作 ');

        const radioMark = document.createElement('input');
        radioMark.type = 'radio';
        radioMark.name = 'resolvedAction';
        radioMark.value = 'mark';
        radioMark.checked = resolvedAction === 'mark';
        const labelMark = document.createTextNode('标记背景 ');

        const radioHide = document.createElement('input');
        radioHide.type = 'radio';
        radioHide.name = 'resolvedAction';
        radioHide.value = 'hide';
        radioHide.checked = resolvedAction === 'hide';
        const labelHide = document.createTextNode('隐藏整行 ');

        form2.appendChild(radioNone);
        form2.appendChild(labelNone);
        form2.appendChild(radioMark);
        form2.appendChild(labelMark);
        form2.appendChild(radioHide);
        form2.appendChild(labelHide);
        form2.appendChild(document.createElement('br'));

        // 背景色
        const bgColorLabel = document.createTextNode('背景色: ');
        const inputBgColor = document.createElement('input');
        inputBgColor.type = 'text';
        inputBgColor.value = resolvedBgColor;
        inputBgColor.style.width = '100px';
        form2.appendChild(bgColorLabel);
        form2.appendChild(inputBgColor);

        section2.appendChild(form2);
        panel.appendChild(section2);

        // ---------- 悬赏金额动态样式 ----------
        const section3 = document.createElement('div');
        section3.innerHTML = '<h4 style="margin:16px 0 8px;">悬赏金额动态样式</h4>';
        const form3 = document.createElement('div');
        form3.style.marginBottom = '8px';

        // 启用开关
        const enableCheck = document.createElement('input');
        enableCheck.type = 'checkbox';
        enableCheck.checked = rewardEnabled;
        const enableLabel = document.createTextNode(' 启用');
        form3.appendChild(enableCheck);
        form3.appendChild(enableLabel);
        form3.appendChild(document.createElement('br'));

        // 规则编辑(JSON文本域)
        const rulesLabel = document.createTextNode('规则 (JSON):');
        form3.appendChild(rulesLabel);
        form3.appendChild(document.createElement('br'));

        const rulesTextarea = document.createElement('textarea');
        rulesTextarea.value = JSON.stringify(rewardRules, null, 2);
        Object.assign(rulesTextarea.style, {
            width: '100%',
            height: '150px',
            fontFamily: 'monospace',
            fontSize: '12px',
            marginTop: '4px'
        });
        form3.appendChild(rulesTextarea);

        // 重置默认规则按钮
        const resetBtn = document.createElement('button');
        resetBtn.textContent = '恢复默认规则';
        resetBtn.style.marginTop = '4px';
        resetBtn.onclick = () => {
            rulesTextarea.value = JSON.stringify(defaultRewardRules, null, 2);
        };
        form3.appendChild(resetBtn);

        section3.appendChild(form3);
        panel.appendChild(section3);

        // ---------- 保存/取消按钮 ----------
        const btnGroup = document.createElement('div');
        btnGroup.style.display = 'flex';
        btnGroup.style.justifyContent = 'flex-end';
        btnGroup.style.gap = '8px';
        btnGroup.style.marginTop = '20px';

        const saveBtn = document.createElement('button');
        saveBtn.textContent = '保存';
        Object.assign(saveBtn.style, {
            padding: '6px 16px',
            backgroundColor: '#4CAF50',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer'
        });
        saveBtn.onclick = () => {
            // 回帖奖励样式
            styles.fontWeight = inputWeight.value;
            styles.color = inputColor.value;
            styles.fontSize = inputSize.value;
            GM_setValue('fontWeight', styles.fontWeight);
            GM_setValue('color', styles.color);
            GM_setValue('fontSize', styles.fontSize);

            // 悬赏已解决
            const selectedAction = document.querySelector('input[name="resolvedAction"]:checked')?.value;
            if (selectedAction) {
                resolvedAction = selectedAction;
                GM_setValue('resolvedAction', resolvedAction);
            }
            resolvedBgColor = inputBgColor.value;
            GM_setValue('resolvedBgColor', resolvedBgColor);

            // 悬赏金额
            rewardEnabled = enableCheck.checked;
            GM_setValue(REWARD_ENABLED_KEY, rewardEnabled);
            try {
                const parsed = JSON.parse(rulesTextarea.value);
                if (Array.isArray(parsed) && parsed.every(r => typeof r.min === 'number' && r.style)) {
                    rewardRules = parsed;
                    GM_setValue(REWARD_RULES_KEY, rewardRules);
                } else {
                    alert('规则格式无效,请检查后重试');
                    return;
                }
            } catch (e) {
                alert('JSON 解析失败: ' + e.message);
                return;
            }

            alert('设置已保存!');
            panel.style.display = 'none';
            // 立即重新应用样式
            checkAndModify();
        };

        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = '关闭';
        Object.assign(cancelBtn.style, {
            padding: '6px 16px',
            backgroundColor: '#f44336',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer'
        });
        cancelBtn.onclick = () => panel.style.display = 'none';

        btnGroup.appendChild(saveBtn);
        btnGroup.appendChild(cancelBtn);
        panel.appendChild(btnGroup);

        document.body.appendChild(panel);
        settingsPanel = panel;
    }

    // ---------- 注册菜单命令 ----------
    GM_registerMenuCommand("&#9881;&#65039; 打开设置面板", createSettingsPanel);

    // ---------- 启动核心功能 ----------
    const observer = new MutationObserver(checkAndModify);
    observer.observe(document.body, { childList: true, subtree: true });
    checkAndModify();
    setInterval(checkAndModify, 1000);

})();
```

---

## &#127919; 主要改进

### 1. 集成设置面板
- 通过油猴菜单命令 **&#9881;&#65039; 打开设置面板** 调出浮动窗口。
- 面板固定在页面右上角,可关闭,不干扰正常浏览。
- 所有配置项集中在一个界面中,告别多个弹窗。

### 2. 可视化控件
- **回帖奖励样式**:三个输入框分别控制字体粗细、颜色、大小。
- **悬赏已解决处理**:单选按钮选择处理方式(无操作/标记背景/隐藏),并支持自定义背景色。
- **悬赏金额动态样式**:
  - 复选框启用/禁用功能。
  - 文本域直接编辑 JSON 规则,带语法高亮(虽无高亮,但可手动调整)。
  - **恢复默认规则** 按钮一键填充默认配置。

### 3. 即时生效
- 点击 **保存** 后,所有配置通过 `GM_setValue` 持久化,并立即调用 `checkAndModify()` 刷新页面样式。
- 点击 **关闭** 仅隐藏面板,不丢失已保存的设置。

### 4. 保留原有核心功能
- 定时器 + MutationObserver 双重保障,确保动态加载内容(翻页、异步更新)也能应用样式。
- 所有处理逻辑(回帖奖励、已解决处理、金额样式)保持不变,仅将配置方式从 `prompt` 升级为面板。

---

## &#128204; 使用说明
1. 安装脚本后,访问 52pojie.cn 任意页面。
2. 点击 Tampermonkey 图标 → 选择 **&#9881;&#65039; 打开设置面板**。
3. 在面板中调整各项参数,点击 **保存** 即可看到效果。
4. 如需修改,再次打开面板调整并保存。

---

## &#128295; 自定义扩展
- 您可以根据需要修改面板的样式(如宽度、颜色、位置)。
- 若希望规则编辑更友好,可替换文本域为可编辑表格,但 JSON 方式已足够灵活,且能完整保留原数据结构。


免费评分

参与人数 4吾爱币 +9 热心值 +4 收起 理由
jamescookers988 + 1 我很赞同!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
af8889 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
xinchenmetx + 1 + 1 热心回复!

查看全部评分

发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xinchenmetx 发表于 2026-3-4 17:55
本帖最后由 xinchenmetx 于 2026-3-6 01:16 编辑

用AI优化了界面
// ==UserScript==
// @name         52pj帖子列表增强
// @match        https://www.52pojie.cn/*
// @version      3.1
// @description  实时监测并修改链接样式,集成可视化设置面板(支持回帖奖励、悬赏已解决、悬赏金额动态样式)
// @author       aura service
// [url=home.php?mod=space&uid=609072]@grant[/url]        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @license      ISC
// ==/UserScript==

(function() {
    'use strict';

    // ---------- 配置存储 ----------
    const defaultStyles = { fontWeight: 'bold', color: '#ff0000', fontSize: '16px' };
    let styles = {
        fontWeight: GM_getValue('fontWeight', defaultStyles.fontWeight),
        color: GM_getValue('color', defaultStyles.color),
        fontSize: GM_getValue('fontSize', defaultStyles.fontSize)
    };

    const defaultResolvedAction = 'mark';
    const defaultResolvedBgColor = '#f0f0f0';
    let resolvedAction = GM_getValue('resolvedAction', defaultResolvedAction);
    let resolvedBgColor = GM_getValue('resolvedBgColor', defaultResolvedBgColor);

    const REWARD_ENABLED_KEY = 'rewardEnabled';
    const REWARD_RULES_KEY = 'rewardRules';
    const defaultRewardRules = [
        { min: 1, max: 9, style: { color: '#008000' } },
        { min: 10, max: 49, style: { color: '#ffa500', fontWeight: 'bold' } },
        { min: 50, max: 99, style: { color: '#ff0000', fontWeight: 'bold', fontSize: '16px' } },
        { min: 100, max: null, style: { color: '#800080', fontWeight: 'bold', fontSize: '18px', backgroundColor: '#ffffcc' } }
    ];
    let rewardEnabled = GM_getValue(REWARD_ENABLED_KEY, false);
    let rewardRules = GM_getValue(REWARD_RULES_KEY, defaultRewardRules);

    // ---------- 辅助函数 ----------
    function getStyleForReward(amount) {
        if (!rewardEnabled) return null;
        for (const rule of rewardRules) {
            if (amount >= rule.min && (rule.max === null || amount <= rule.max)) {
                return rule.style;
            }
        }
        return null;
    }

    // ---------- 核心处理函数 ----------
    function checkAndModify() {
        const rows = document.querySelectorAll('#threadlisttableid tbody tr, tbody tr');
        rows.forEach(row => {
            // 回帖奖励
            const ths = row.querySelectorAll('th.common, th.new');
            let hasReward = false;
            ths.forEach(th => {
                const span = th.querySelector('span');
                if (span && span.textContent.includes('回帖奖励')) hasReward = true;
            });
            if (hasReward) {
                const links = row.querySelectorAll('th.common a.s.xst, th.new a.s.xst');
                links.forEach(link => {
                    link.style.fontWeight = styles.fontWeight;
                    link.style.color = styles.color;
                    link.style.fontSize = styles.fontSize;
                });
            }

            // 悬赏已解决标记/隐藏
            const rewardIcon = row.querySelector('td.icn img[src*="rewardsmall.gif"]');
            if (rewardIcon) {
                const resolvedLink = Array.from(row.querySelectorAll('th a')).find(a => a.textContent.trim() === '[已解决]');
                if (resolvedLink) {
                    if (resolvedAction === 'mark') row.style.backgroundColor = resolvedBgColor;
                    else if (resolvedAction === 'hide') row.style.display = 'none';
                }
            }

            // 悬赏金额动态样式
            if (rewardEnabled && rewardIcon) {
                const rewardLink = row.querySelector('th a[href*="specialtype=reward"]');
                if (rewardLink) {
                    const amountSpan = rewardLink.querySelector('span.xw1');
                    if (amountSpan) {
                        const amount = parseInt(amountSpan.textContent.trim(), 10);
                        if (!isNaN(amount)) {
                            const style = getStyleForReward(amount);
                            if (style) {
                                const titleLink = row.querySelector('th.common a.s.xst, th.new a.s.xst');
                                if (titleLink) {
                                    for (const [prop, val] of Object.entries(style)) {
                                        titleLink.style[prop] = val;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    // ---------- 设置面板 ----------
    let settingsPanel = null;
    let overlay = null;

    function createSettingsPanel() {
        if (settingsPanel) {
            settingsPanel.style.display = settingsPanel.style.display === 'none' ? 'flex' : 'none';
            if (overlay) overlay.style.display = settingsPanel.style.display === 'none' ? 'none' : 'block';
            return;
        }

        // 创建遮罩层
        overlay = document.createElement('div');
        overlay.id = 'pj-settings-overlay';
        Object.assign(overlay.style, {
            position: 'fixed',
            top: '0',
            left: '0',
            width: '100%',
            height: '100%',
            backgroundColor: 'rgba(0,0,0,0.5)',
            zIndex: '9998',
            display: 'none'
        });
        overlay.onclick = () => {
            settingsPanel.style.display = 'none';
            overlay.style.display = 'none';
        };
        document.body.appendChild(overlay);

        // 主面板容器
        const panel = document.createElement('div');
        panel.id = 'pj-settings-panel';
        Object.assign(panel.style, {
            position: 'fixed',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            width: '520px',
            maxHeight: '85vh',
            backgroundColor: '#ffffff',
            borderRadius: '12px',
            boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
            zIndex: '9999',
            fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
            fontSize: '14px',
            display: 'flex',
            flexDirection: 'column',
            overflow: 'hidden'
        });

        // 标题栏
        const header = document.createElement('div');
        Object.assign(header.style, {
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            padding: '20px 24px',
            backgroundColor: '#f8f9fa',
            borderBottom: '1px solid #e9ecef'
        });

        const title = document.createElement('h3');
        title.textContent = '⚙️ 52pj 帖子增强设置';
        Object.assign(title.style, {
            margin: '0',
            fontSize: '18px',
            fontWeight: '600',
            color: '#212529'
        });

        const closeBtn = document.createElement('button');
        closeBtn.innerHTML = '✕';
        Object.assign(closeBtn.style, {
            background: 'none',
            border: 'none',
            fontSize: '20px',
            color: '#6c757d',
            cursor: 'pointer',
            padding: '4px 8px',
            borderRadius: '4px',
            transition: 'all 0.2s'
        });
        closeBtn.onmouseover = () => closeBtn.style.backgroundColor = '#e9ecef';
        closeBtn.onmouseout = () => closeBtn.style.backgroundColor = 'transparent';
        closeBtn.onclick = () => {
            panel.style.display = 'none';
            overlay.style.display = 'none';
        };

        header.appendChild(title);
        header.appendChild(closeBtn);
        panel.appendChild(header);

        // 标签页导航
        const tabNav = document.createElement('div');
        Object.assign(tabNav.style, {
            display: 'flex',
            borderBottom: '1px solid #dee2e6',
            backgroundColor: '#fff',
            padding: '0 24px'
        });

        const tabs = [
            { id: 'reply', label: '💬 回帖奖励', icon: '' },
            { id: 'resolved', label: '✅ 悬赏已解决', icon: '' },
            { id: 'reward', label: '💰 悬赏金额', icon: '' }
        ];

        let activeTab = 'reply';
        const tabButtons = {};
        const tabContents = {}; // 提前定义

        function switchTab(tabId) {
            activeTab = tabId;
            // 更新按钮样式
            Object.keys(tabButtons).forEach(key => {
                const btn = tabButtons[key];
                if (key === tabId) {
                    btn.style.color = '#0d6efd';
                    btn.style.borderBottomColor = '#0d6efd';
                } else {
                    btn.style.color = '#6c757d';
                    btn.style.borderBottomColor = 'transparent';
                }
            });
            // 显示对应内容
            Object.keys(tabContents).forEach(key => {
                tabContents[key].style.display = key === tabId ? 'block' : 'none';
            });
        }

        tabs.forEach(tab => {
            const btn = document.createElement('button');
            btn.textContent = tab.label;
            Object.assign(btn.style, {
                padding: '12px 16px',
                border: 'none',
                background: 'none',
                cursor: 'pointer',
                fontSize: '14px',
                fontWeight: '500',
                color: '#6c757d',
                borderBottom: '2px solid transparent',
                transition: 'all 0.2s',
                marginRight: '8px'
            });

            btn.onclick = () => switchTab(tab.id);
            tabButtons[tab.id] = btn;
            tabNav.appendChild(btn);
        });

        panel.appendChild(tabNav);

        // 内容区域
        const contentArea = document.createElement('div');
        Object.assign(contentArea.style, {
            flex: '1',
            overflowY: 'auto',
            padding: '24px'
        });

        // ========== 标签页 1: 回帖奖励样式 ==========
        const replyTab = document.createElement('div');
        tabContents.reply = replyTab;

        // 预览区域
        const previewBox1 = createPreviewBox();
        const previewText1 = document.createElement('a');
        previewText1.textContent = '这是一个回帖奖励帖子的预览';
        previewText1.href = '#';
        Object.assign(previewText1.style, {
            textDecoration: 'none',
            cursor: 'default'
        });
        previewBox1.appendChild(previewText1);

        // 表单
        const form1 = document.createElement('div');
        Object.assign(form1.style, {
            display: 'flex',
            flexDirection: 'column',
            gap: '16px'
        });

        // 颜色选择
        const colorGroup = createFormGroup('文字颜色');
        const colorWrapper = document.createElement('div');
        Object.assign(colorWrapper.style, {
            display: 'flex',
            alignItems: 'center',
            gap: '8px'
        });

        const colorInput = document.createElement('input');
        colorInput.type = 'color';
        colorInput.value = rgbToHex(styles.color) || styles.color;
        Object.assign(colorInput.style, {
            width: '50px',
            height: '36px',
            border: '1px solid #ced4da',
            borderRadius: '4px',
            cursor: 'pointer'
        });

        const colorText = document.createElement('input');
        colorText.type = 'text';
        colorText.value = styles.color;
        Object.assign(colorText.style, {
            flex: '1',
            padding: '8px 12px',
            border: '1px solid #ced4da',
            borderRadius: '4px',
            fontSize: '14px'
        });

        colorInput.oninput = (e) => {
            colorText.value = e.target.value;
            updatePreview1();
        };
        colorText.oninput = (e) => {
            colorInput.value = rgbToHex(e.target.value) || e.target.value;
            updatePreview1();
        };

        colorWrapper.appendChild(colorInput);
        colorWrapper.appendChild(colorText);
        colorGroup.appendChild(colorWrapper);
        form1.appendChild(colorGroup);

        // 字体粗细
        const weightGroup = createFormGroup('字体粗细');
        const weightSelect = document.createElement('select');
        const weights = [
            { value: 'normal', label: '正常 (Normal)' },
            { value: 'bold', label: '粗体 (Bold)' },
            { value: 'bolder', label: '更粗 (Bolder)' },
            { value: 'lighter', label: '更细 (Lighter)' },
            { value: '100', label: '100 - Thin' },
            { value: '400', label: '400 - Regular' },
            { value: '700', label: '700 - Bold' },
            { value: '900', label: '900 - Black' }
        ];
        weights.forEach(w => {
            const opt = document.createElement('option');
            opt.value = w.value;
            opt.textContent = w.label;
            if (w.value === styles.fontWeight) opt.selected = true;
            weightSelect.appendChild(opt);
        });
        Object.assign(weightSelect.style, {
            width: '100%',
            padding: '8px 12px',
            border: '1px solid #ced4da',
            borderRadius: '4px',
            fontSize: '14px',
            backgroundColor: '#fff'
        });
        weightSelect.onchange = updatePreview1;
        weightGroup.appendChild(weightSelect);
        form1.appendChild(weightGroup);

        // 字体大小
        const sizeGroup = createFormGroup('字体大小');
        const sizeWrapper = document.createElement('div');
        Object.assign(sizeWrapper.style, {
            display: 'flex',
            alignItems: 'center',
            gap: '12px'
        });

        const sizeInput = document.createElement('input');
        sizeInput.type = 'range';
        sizeInput.min = '12';
        sizeInput.max = '24';
        sizeInput.value = parseInt(styles.fontSize) || 16;
        Object.assign(sizeInput.style, {
            flex: '1',
            cursor: 'pointer'
        });

        const sizeValue = document.createElement('span');
        sizeValue.textContent = styles.fontSize;
        Object.assign(sizeValue.style, {
            minWidth: '50px',
            textAlign: 'center',
            fontWeight: '600',
            color: '#495057'
        });

        sizeInput.oninput = (e) => {
            sizeValue.textContent = e.target.value + 'px';
            updatePreview1();
        };

        sizeWrapper.appendChild(sizeInput);
        sizeWrapper.appendChild(sizeValue);
        sizeGroup.appendChild(sizeWrapper);
        form1.appendChild(sizeGroup);

        replyTab.appendChild(previewBox1);
        replyTab.appendChild(form1);

        function updatePreview1() {
            previewText1.style.color = colorText.value;
            previewText1.style.fontWeight = weightSelect.value;
            previewText1.style.fontSize = sizeValue.textContent;
        }
        updatePreview1();

        // ========== 标签页 2: 悬赏已解决 ==========
        const resolvedTab = document.createElement('div');
        tabContents.resolved = resolvedTab;
        resolvedTab.style.display = 'none';

        const form2 = document.createElement('div');
        Object.assign(form2.style, {
            display: 'flex',
            flexDirection: 'column',
            gap: '20px'
        });

        // 操作方式卡片
        const actionGroup = createFormGroup('处理方式');
        const actionCards = document.createElement('div');
        Object.assign(actionCards.style, {
            display: 'grid',
            gridTemplateColumns: 'repeat(3, 1fr)',
            gap: '12px'
        });

        const actions = [
            { value: 'none', label: '无操作', desc: '保持原样', icon: '⭕' },
            { value: 'mark', label: '标记背景', desc: '改变背景色', icon: '🎨' },
            { value: 'hide', label: '隐藏整行', desc: '完全隐藏', icon: '🙈' }
        ];

        let selectedAction = resolvedAction;
        const actionCardEls = {};

        actions.forEach(action => {
            const card = document.createElement('div');
            Object.assign(card.style, {
                padding: '16px',
                border: '2px solid ' + (action.value === selectedAction ? '#0d6efd' : '#dee2e6'),
                borderRadius: '8px',
                cursor: 'pointer',
                textAlign: 'center',
                transition: 'all 0.2s',
                backgroundColor: action.value === selectedAction ? '#f8f9ff' : '#fff'
            });

            const icon = document.createElement('div');
            icon.textContent = action.icon;
            Object.assign(icon.style, {
                fontSize: '24px',
                marginBottom: '8px'
            });

            const label = document.createElement('div');
            label.textContent = action.label;
            Object.assign(label.style, {
                fontWeight: '600',
                marginBottom: '4px',
                color: '#212529'
            });

            const desc = document.createElement('div');
            desc.textContent = action.desc;
            Object.assign(desc.style, {
                fontSize: '12px',
                color: '#6c757d'
            });

            card.appendChild(icon);
            card.appendChild(label);
            card.appendChild(desc);

            card.onclick = () => {
                selectedAction = action.value;
                Object.keys(actionCardEls).forEach(key => {
                    const el = actionCardEls[key];
                    if (key === action.value) {
                        el.style.borderColor = '#0d6efd';
                        el.style.backgroundColor = '#f8f9ff';
                    } else {
                        el.style.borderColor = '#dee2e6';
                        el.style.backgroundColor = '#fff';
                    }
                });
                bgColorGroup.style.opacity = action.value === 'mark' ? '1' : '0.5';
                bgColorGroup.style.pointerEvents = action.value === 'mark' ? 'auto' : 'none';
            };

            actionCards.appendChild(card);
            actionCardEls[action.value] = card;
        });

        actionGroup.appendChild(actionCards);
        form2.appendChild(actionGroup);

        // 背景色选择
        const bgColorGroup = createFormGroup('标记背景色');
        Object.assign(bgColorGroup.style, {
            opacity: selectedAction === 'mark' ? '1' : '0.5',
            pointerEvents: selectedAction === 'mark' ? 'auto' : 'none',
            transition: 'opacity 0.2s'
        });

        const bgColorWrapper = document.createElement('div');
        Object.assign(bgColorWrapper.style, {
            display: 'flex',
            alignItems: 'center',
            gap: '12px'
        });

        const bgColorInput = document.createElement('input');
        bgColorInput.type = 'color';
        bgColorInput.value = rgbToHex(resolvedBgColor) || resolvedBgColor;
        Object.assign(bgColorInput.style, {
            width: '60px',
            height: '40px',
            border: '1px solid #ced4da',
            borderRadius: '4px',
            cursor: 'pointer'
        });

        const bgColorPreview = document.createElement('div');
        Object.assign(bgColorPreview.style, {
            flex: '1',
            height: '40px',
            borderRadius: '4px',
            border: '1px solid #ced4da',
            backgroundColor: resolvedBgColor
        });

        bgColorInput.oninput = (e) => {
            bgColorPreview.style.backgroundColor = e.target.value;
        };

        bgColorWrapper.appendChild(bgColorInput);
        bgColorWrapper.appendChild(bgColorPreview);
        bgColorGroup.appendChild(bgColorWrapper);
        form2.appendChild(bgColorGroup);

        resolvedTab.appendChild(form2);

        // ========== 标签页 3: 悬赏金额动态样式 ==========
        const rewardTab = document.createElement('div');
        tabContents.reward = rewardTab;
        rewardTab.style.display = 'none';

        // 启用开关
        const enableGroup = document.createElement('div');
        Object.assign(enableGroup.style, {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            padding: '16px',
            backgroundColor: '#f8f9fa',
            borderRadius: '8px',
            marginBottom: '20px'
        });

        const enableLabel = document.createElement('div');
        enableLabel.innerHTML = '<strong>启用悬赏金额高亮</strong><br><span style="font-size:12px;color:#6c757d;">根据悬赏金额自动设置不同样式</span>';

        const enableSwitch = createToggleSwitch(rewardEnabled);
        // 修复:使用 querySelector 获取 input 元素绑定事件
        enableSwitch.querySelector('input').addEventListener('change', (e) => {
            rulesContainer.style.opacity = e.target.checked ? '1' : '0.5';
            rulesContainer.style.pointerEvents = e.target.checked ? 'auto' : 'none';
        });

        enableGroup.appendChild(enableLabel);
        enableGroup.appendChild(enableSwitch);
        rewardTab.appendChild(enableGroup);

        // 规则容器
        const rulesContainer = document.createElement('div');
        Object.assign(rulesContainer.style, {
            opacity: rewardEnabled ? '1' : '0.5',
            pointerEvents: rewardEnabled ? 'auto' : 'none',
            transition: 'opacity 0.2s'
        });

        const rulesHeader = document.createElement('div');
        rulesHeader.innerHTML = '<strong>金额区间规则</strong><span style="float:right;font-size:12px;color:#6c757d;">优先级从上到下</span>';
        Object.assign(rulesHeader.style, {
            marginBottom: '12px',
            paddingBottom: '8px',
            borderBottom: '1px solid #dee2e6'
        });
        rulesContainer.appendChild(rulesHeader);

        const rulesList = document.createElement('div');
        Object.assign(rulesList.style, {
            display: 'flex',
            flexDirection: 'column',
            gap: '12px'
        });

        let ruleEditors = [];

        function createRuleEditor(rule, index) {
            const editor = document.createElement('div');
            Object.assign(editor.style, {
                padding: '16px',
                backgroundColor: '#f8f9fa',
                borderRadius: '8px',
                border: '1px solid #e9ecef',
                position: 'relative'
            });

            // 头部:范围
            const header = document.createElement('div');
            Object.assign(header.style, {
                display: 'flex',
                alignItems: 'center',
                gap: '8px',
                marginBottom: '12px'
            });

            const rangeLabel = document.createElement('span');
            rangeLabel.textContent = '金额范围:';

            const minInput = document.createElement('input');
            minInput.type = 'number';
            minInput.value = rule.min;
            Object.assign(minInput.style, {
                width: '70px',
                padding: '6px',
                border: '1px solid #ced4da',
                borderRadius: '4px'
            });

            const sep = document.createElement('span');
            sep.textContent = '-';

            const maxInput = document.createElement('input');
            maxInput.type = 'text';
            maxInput.value = rule.max === null ? '∞' : rule.max;
            maxInput.placeholder = '无上限';
            Object.assign(maxInput.style, {
                width: '70px',
                padding: '6px',
                border: '1px solid #ced4da',
                borderRadius: '4px'
            });

            header.appendChild(rangeLabel);
            header.appendChild(minInput);
            header.appendChild(sep);
            header.appendChild(maxInput);

            // 删除按钮
            if (index > 0) {
                const deleteBtn = document.createElement('button');
                deleteBtn.innerHTML = '🗑️';
                Object.assign(deleteBtn.style, {
                    marginLeft: 'auto',
                    background: '#dc3545',
                    border: 'none',
                    color: 'white',
                    padding: '4px 8px',
                    borderRadius: '4px',
                    cursor: 'pointer',
                    fontSize: '12px'
                });
                deleteBtn.onclick = () => {
                    editor.remove();
                    ruleEditors = ruleEditors.filter(e => e !== editor);
                };
                header.appendChild(deleteBtn);
            }

            editor.appendChild(header);

            // 样式设置
            const styleGrid = document.createElement('div');
            Object.assign(styleGrid.style, {
                display: 'grid',
                gridTemplateColumns: 'repeat(2, 1fr)',
                gap: '12px'
            });

            // 文字颜色
            const colorCtrl = createColorControl('文字颜色', rule.style.color || '#000000');
            styleGrid.appendChild(colorCtrl);

            // 背景颜色
            const bgCtrl = createColorControl('背景颜色', rule.style.backgroundColor || 'transparent', true);
            styleGrid.appendChild(bgCtrl);

            // 字体粗细
            const weightCtrl = createSelectControl('字体粗细', 
                ['normal', 'bold', 'bolder', 'lighter', '100', '400', '700', '900'],
                rule.style.fontWeight || 'normal'
            );
            styleGrid.appendChild(weightCtrl);

            // 字体大小
            const sizeCtrl = createSelectControl('字体大小',
                ['12px', '14px', '16px', '18px', '20px', '24px'],
                rule.style.fontSize || '14px'
            );
            styleGrid.appendChild(sizeCtrl);

            editor.appendChild(styleGrid);

            // 预览
            const previewDiv = document.createElement('div');
            Object.assign(previewDiv.style, {
                marginTop: '12px',
                padding: '8px',
                backgroundColor: '#fff',
                borderRadius: '4px',
                textAlign: 'center'
            });

            const previewLink = document.createElement('a');
            previewLink.textContent = `悬赏 $${rule.min} 金币的帖子标题`;
            previewLink.href = '#';
            Object.assign(previewLink.style, {
                textDecoration: 'none',
                color: rule.style.color || '#000',
                fontWeight: rule.style.fontWeight || 'normal',
                fontSize: rule.style.fontSize || '14px',
                backgroundColor: rule.style.backgroundColor || 'transparent',
                padding: '2px 8px',
                borderRadius: '4px'
            });

            // 实时更新预览
            function updatePreview() {
                previewLink.style.color = colorCtrl.value;
                previewLink.style.backgroundColor = bgCtrl.value === 'transparent' ? 'transparent' : bgCtrl.value;
                previewLink.style.fontWeight = weightCtrl.value;
                previewLink.style.fontSize = sizeCtrl.value;
            }

            colorCtrl.addEventListener('input', updatePreview);
            colorCtrl.addEventListener('change', updatePreview);
            bgCtrl.addEventListener('input', updatePreview);
            bgCtrl.addEventListener('change', updatePreview);
            weightCtrl.addEventListener('change', updatePreview);
            sizeCtrl.addEventListener('change', updatePreview);

            previewDiv.appendChild(previewLink);
            editor.appendChild(previewDiv);

            // 存储引用以便保存时读取
            editor.getData = () => ({
                min: parseInt(minInput.value) || 0,
                max: maxInput.value === '∞' || maxInput.value === '' ? null : parseInt(maxInput.value),
                style: {
                    color: colorCtrl.value,
                    backgroundColor: bgCtrl.value === 'transparent' ? undefined : bgCtrl.value,
                    fontWeight: weightCtrl.value === 'normal' ? undefined : weightCtrl.value,
                    fontSize: sizeCtrl.value === '14px' ? undefined : sizeCtrl.value
                }
            });

            return editor;
        }

        // 初始化现有规则
        rewardRules.forEach((rule, idx) => {
            const editor = createRuleEditor(rule, idx);
            rulesList.appendChild(editor);
            ruleEditors.push(editor);
        });

        rulesContainer.appendChild(rulesList);

        // 添加规则按钮
        const addRuleBtn = document.createElement('button');
        addRuleBtn.innerHTML = '+ 添加金额区间';
        Object.assign(addRuleBtn.style, {
            marginTop: '12px',
            width: '100%',
            padding: '10px',
            backgroundColor: '#e9ecef',
            border: '2px dashed #adb5bd',
            borderRadius: '8px',
            cursor: 'pointer',
            color: '#495057',
            fontWeight: '500',
            transition: 'all 0.2s'
        });
        addRuleBtn.onmouseover = () => {
            addRuleBtn.style.backgroundColor = '#dee2e6';
            addRuleBtn.style.borderColor = '#6c757d';
        };
        addRuleBtn.onmouseout = () => {
            addRuleBtn.style.backgroundColor = '#e9ecef';
            addRuleBtn.style.borderColor = '#adb5bd';
        };
        addRuleBtn.onclick = () => {
            const newRule = { min: 0, max: null, style: { color: '#000000' } };
            const editor = createRuleEditor(newRule, ruleEditors.length);
            rulesList.appendChild(editor);
            ruleEditors.push(editor);
        };
        rulesContainer.appendChild(addRuleBtn);

        // 重置按钮
        const resetRulesBtn = document.createElement('button');
        resetRulesBtn.textContent = '恢复默认规则';
        Object.assign(resetRulesBtn.style, {
            marginTop: '8px',
            width: '100%',
            padding: '8px',
            backgroundColor: 'transparent',
            border: '1px solid #dc3545',
            color: '#dc3545',
            borderRadius: '4px',
            cursor: 'pointer',
            fontSize: '13px'
        });
        resetRulesBtn.onclick = () => {
            if (confirm('确定要恢复默认规则吗?当前自定义规则将丢失。')) {
                rulesList.innerHTML = '';
                ruleEditors = [];
                defaultRewardRules.forEach((rule, idx) => {
                    const editor = createRuleEditor(rule, idx);
                    rulesList.appendChild(editor);
                    ruleEditors.push(editor);
                });
            }
        };
        rulesContainer.appendChild(resetRulesBtn);

        rewardTab.appendChild(rulesContainer);

        // 组装内容区
        Object.values(tabContents).forEach(content => {
            contentArea.appendChild(content);
        });
        panel.appendChild(contentArea);

        // 底部按钮
        const footer = document.createElement('div');
        Object.assign(footer.style, {
            display: 'flex',
            justifyContent: 'flex-end',
            gap: '12px',
            padding: '16px 24px',
            backgroundColor: '#f8f9fa',
            borderTop: '1px solid #e9ecef'
        });

        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = '取消';
        Object.assign(cancelBtn.style, {
            padding: '8px 20px',
            backgroundColor: '#6c757d',
            color: 'white',
            border: 'none',
            borderRadius: '6px',
            cursor: 'pointer',
            fontSize: '14px',
            fontWeight: '500'
        });
        cancelBtn.onclick = () => {
            panel.style.display = 'none';
            overlay.style.display = 'none';
        };

        const saveBtn = document.createElement('button');
        saveBtn.textContent = '保存设置';
        Object.assign(saveBtn.style, {
            padding: '8px 24px',
            backgroundColor: '#0d6efd',
            color: 'white',
            border: 'none',
            borderRadius: '6px',
            cursor: 'pointer',
            fontSize: '14px',
            fontWeight: '500',
            boxShadow: '0 2px 4px rgba(13,110,253,0.3)'
        });
        saveBtn.onmouseover = () => saveBtn.style.backgroundColor = '#0b5ed7';
        saveBtn.onmouseout = () => saveBtn.style.backgroundColor = '#0d6efd';

        saveBtn.onclick = () => {
            // 保存回帖奖励样式
            styles.color = colorText.value;
            styles.fontWeight = weightSelect.value;
            styles.fontSize = sizeValue.textContent;
            GM_setValue('color', styles.color);
            GM_setValue('fontWeight', styles.fontWeight);
            GM_setValue('fontSize', styles.fontSize);

            // 保存悬赏已解决
            resolvedAction = selectedAction;
            resolvedBgColor = bgColorInput.value;
            GM_setValue('resolvedAction', resolvedAction);
            GM_setValue('resolvedBgColor', resolvedBgColor);

            // 保存悬赏金额规则
            rewardEnabled = enableSwitch.querySelector('input').checked;
            GM_setValue(REWARD_ENABLED_KEY, rewardEnabled);

            const newRules = ruleEditors.map(editor => editor.getData());
            // 清理 undefined 值
            newRules.forEach(rule => {
                Object.keys(rule.style).forEach(key => {
                    if (rule.style[key] === undefined) delete rule.style[key];
                });
            });
            rewardRules = newRules;
            GM_setValue(REWARD_RULES_KEY, rewardRules);

            // 显示成功提示
            showToast('设置已保存!');
            panel.style.display = 'none';
            overlay.style.display = 'none';

            checkAndModify();
        };

        footer.appendChild(cancelBtn);
        footer.appendChild(saveBtn);
        panel.appendChild(footer);

        document.body.appendChild(panel);
        settingsPanel = panel;

        // 初始化标签页
        switchTab('reply');
        overlay.style.display = 'block';

        // 辅助函数:创建表单组
        function createFormGroup(labelText) {
            const group = document.createElement('div');
            const label = document.createElement('label');
            label.textContent = labelText;
            Object.assign(label.style, {
                display: 'block',
                marginBottom: '6px',
                fontWeight: '500',
                color: '#495057',
                fontSize: '14px'
            });
            group.appendChild(label);
            return group;
        }

        // 辅助函数:创建预览框
        function createPreviewBox() {
            const box = document.createElement('div');
            Object.assign(box.style, {
                padding: '20px',
                backgroundColor: '#f8f9fa',
                borderRadius: '8px',
                marginBottom: '20px',
                textAlign: 'center',
                border: '1px dashed #dee2e6'
            });
            const label = document.createElement('div');
            label.textContent = '👁️ 实时预览';
            Object.assign(label.style, {
                fontSize: '12px',
                color: '#6c757d',
                marginBottom: '8px',
                textTransform: 'uppercase',
                letterSpacing: '1px'
            });
            box.appendChild(label);
            return box;
        }

        // 辅助函数:创建颜色选择控件
        function createColorControl(label, defaultValue, allowTransparent = false) {
            const group = document.createElement('div');
            const lbl = document.createElement('div');
            lbl.textContent = label;
            Object.assign(lbl.style, {
                fontSize: '12px',
                color: '#6c757d',
                marginBottom: '4px'
            });

            const wrapper = document.createElement('div');
            Object.assign(wrapper.style, {
                display: 'flex',
                gap: '6px'
            });

            const colorInput = document.createElement('input');
            colorInput.type = 'color';
            colorInput.value = defaultValue === 'transparent' ? '#ffffff' : (rgbToHex(defaultValue) || defaultValue);
            Object.assign(colorInput.style, {
                width: '36px',
                height: '32px',
                border: '1px solid #ced4da',
                borderRadius: '4px',
                padding: '0',
                cursor: 'pointer'
            });

            const textInput = document.createElement('input');
            textInput.type = 'text';
            textInput.value = defaultValue;
            Object.assign(textInput.style, {
                flex: '1',
                padding: '6px',
                border: '1px solid #ced4da',
                borderRadius: '4px',
                fontSize: '12px'
            });

            let transparentBtn = null;
            if (allowTransparent) {
                transparentBtn = document.createElement('button');
                transparentBtn.textContent = '无';
                Object.assign(transparentBtn.style, {
                    padding: '6px 10px',
                    backgroundColor: defaultValue === 'transparent' ? '#0d6efd' : '#e9ecef',
                    color: defaultValue === 'transparent' ? 'white' : '#495057',
                    border: 'none',
                    borderRadius: '4px',
                    cursor: 'pointer',
                    fontSize: '12px'
                });
                transparentBtn.onclick = () => {
                    textInput.value = 'transparent';
                    colorInput.value = '#ffffff';
                    transparentBtn.style.backgroundColor = '#0d6efd';
                    transparentBtn.style.color = 'white';
                    // 触发自定义事件
                    textInput.dispatchEvent(new Event('input'));
                };
                wrapper.appendChild(transparentBtn);
            }

            colorInput.oninput = (e) => {
                textInput.value = e.target.value;
                if (allowTransparent && transparentBtn) {
                    transparentBtn.style.backgroundColor = '#e9ecef';
                    transparentBtn.style.color = '#495057';
                }
                textInput.dispatchEvent(new Event('input'));
            };
            textInput.oninput = (e) => {
                const hex = rgbToHex(e.target.value);
                if (hex) colorInput.value = hex;
            };

            Object.defineProperty(group, 'value', {
                get: () => textInput.value,
                set: (v) => {
                    textInput.value = v;
                    const hex = rgbToHex(v);
                    if (hex) colorInput.value = hex;
                    if (allowTransparent && transparentBtn) {
                        transparentBtn.style.backgroundColor = v === 'transparent' ? '#0d6efd' : '#e9ecef';
                        transparentBtn.style.color = v === 'transparent' ? 'white' : '#495057';
                    }
                }
            });

            // 自定义事件监听接口
            group.addEventListener = (type, fn) => {
                colorInput.addEventListener(type, fn);
                textInput.addEventListener(type, fn);
            };

            wrapper.appendChild(colorInput);
            wrapper.appendChild(textInput);
            group.appendChild(lbl);
            group.appendChild(wrapper);

            return group;
        }

        // 辅助函数:创建下拉控件
        function createSelectControl(label, options, defaultValue) {
            const group = document.createElement('div');
            const lbl = document.createElement('div');
            lbl.textContent = label;
            Object.assign(lbl.style, {
                fontSize: '12px',
                color: '#6c757d',
                marginBottom: '4px'
            });

            const select = document.createElement('select');
            options.forEach(opt => {
                const option = document.createElement('option');
                option.value = opt;
                option.textContent = opt;
                if (opt === defaultValue) option.selected = true;
                select.appendChild(option);
            });
            Object.assign(select.style, {
                width: '100%',
                padding: '6px',
                border: '1px solid #ced4da',
                borderRadius: '4px',
                fontSize: '13px'
            });

            Object.defineProperty(group, 'value', {
                get: () => select.value,
                set: (v) => select.value = v
            });

            group.addEventListener = (type, fn) => select.addEventListener(type, fn);

            group.appendChild(lbl);
            group.appendChild(select);
            return group;
        }

        // 辅助函数:创建开关
        function createToggleSwitch(checked) {
            const label = document.createElement('label');
            Object.assign(label.style, {
                position: 'relative',
                display: 'inline-block',
                width: '50px',
                height: '26px',
                cursor: 'pointer'
            });

            const input = document.createElement('input');
            input.type = 'checkbox';
            input.checked = checked;
            Object.assign(input.style, {
                opacity: '0',
                width: '0',
                height: '0'
            });

            const slider = document.createElement('span');
            Object.assign(slider.style, {
                position: 'absolute',
                cursor: 'pointer',
                top: '0',
                left: '0',
                right: '0',
                bottom: '0',
                backgroundColor: checked ? '#0d6efd' : '#ccc',
                transition: '.3s',
                borderRadius: '26px'
            });

            const knob = document.createElement('span');
            Object.assign(knob.style, {
                position: 'absolute',
                content: '""',
                height: '20px',
                width: '20px',
                left: checked ? '26px' : '3px',
                bottom: '3px',
                backgroundColor: 'white',
                transition: '.3s',
                borderRadius: '50%',
                boxShadow: '0 1px 3px rgba(0,0,0,0.3)'
            });

            input.onchange = (e) => {
                slider.style.backgroundColor = e.target.checked ? '#0d6efd' : '#ccc';
                knob.style.left = e.target.checked ? '26px' : '3px';
            };

            label.appendChild(input);
            label.appendChild(slider);
            label.appendChild(knob);

            Object.defineProperty(label, 'checked', {
                get: () => input.checked,
                set: (v) => {
                    input.checked = v;
                    slider.style.backgroundColor = v ? '#0d6efd' : '#ccc';
                    knob.style.left = v ? '26px' : '3px';
                }
            });

            return label;
        }

        // 辅助函数:RGB转Hex
        function rgbToHex(rgb) {
            if (!rgb || typeof rgb !== 'string') return null;
            if (rgb.startsWith('#')) return rgb;
            const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$$/);
            if (!match) return null;
            const r = parseInt(match[1]);
            const g = parseInt(match[2]);
            const b = parseInt(match[3]);
            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        }

        // 辅助函数:显示提示
        function showToast(message) {
            // 检查是否已存在样式
            if (!document.getElementById('pj-toast-style')) {
                const style = document.createElement('style');
                style.id = 'pj-toast-style';
                style.textContent = `
                    @keyframes slideDown {
                        from { transform: translate(-50%, -100%); opacity: 0; }
                        to { transform: translate(-50%, 0); opacity: 1; }
                    }
                `;
                document.head.appendChild(style);
            }

            const toast = document.createElement('div');
            toast.textContent = message;
            Object.assign(toast.style, {
                position: 'fixed',
                top: '20px',
                left: '50%',
                transform: 'translateX(-50%)',
                backgroundColor: '#28a745',
                color: 'white',
                padding: '12px 24px',
                borderRadius: '6px',
                boxShadow: '0 4px 12px rgba(0,0,0,0.2)',
                zIndex: '10000',
                fontWeight: '500',
                animation: 'slideDown 0.3s ease'
            });

            document.body.appendChild(toast);
            setTimeout(() => {
                toast.style.opacity = '0';
                toast.style.transition = 'opacity 0.3s';
                setTimeout(() => toast.remove(), 300);
            }, 2000);
        }
    }

    // ---------- 注册菜单命令 ----------
    GM_registerMenuCommand("⚙️ 打开设置面板", createSettingsPanel);

    // ---------- 启动核心功能 ----------
    const observer = new MutationObserver(checkAndModify);
    observer.observe(document.body, { childList: true, subtree: true });
    checkAndModify();
    setInterval(checkAndModify, 1000);
})();

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
Cristy + 1 + 1 用心讨论,共获提升!
af8889 + 1 + 1 谢谢@Thanks!

查看全部评分

AiniWang 发表于 2026-3-4 17:25
af8889 发表于 2026-3-4 18:10
cgbchen 发表于 2026-3-4 18:37
这个好玩,以后找自己关心的帖子方便了。手动点赞!
zxinyun 发表于 2026-3-4 18:41
为啥我设置了都不生效呢,奇怪。
zzq90322 发表于 2026-3-4 19:38
已安装,好用,感谢分享这个好玩,以后找自己关心的帖子方便了。手动点赞!
anranleixia 发表于 2026-3-4 20:02
已收藏,感谢大佬的分享
picoyiyi 发表于 2026-3-4 20:48
能标记那些我已经回答过的帖么?
icho 发表于 2026-3-4 21:33
给楼主点赞
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-11-4 07:15

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表