Greasy Fork

Greasy Fork is available in English.

Discord Midjourney 参数面板

在 Discord 中添加 Midjourney 参数设置面板,支持完整卡片式 UI 和最新参数功能(⚠️⚠️⚠️需开启开发者模式)

当前为 2025-05-17 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Discord Midjourney 参数面板
// @namespace    https://github.com/cwser
// @version      0.2.4
// @license      MIT
// @description  在 Discord 中添加 Midjourney 参数设置面板,支持完整卡片式 UI 和最新参数功能(⚠️⚠️⚠️需开启开发者模式)
// @author       cwser
// @match        https://discord.com/*
// @icon         https://www.midjourney.com/favicon.ico
// @grant        unsafeWindow
// @supportURL   https://github.com/cwser
// @homepageURL  https://github.com/cwser
// ==/UserScript==

(function() {
    'use strict';

    // 参数定义
    let params = {
        prompt: '', // 提示词参数
        ar: '1:1',
        stylize: 100,
        weird: 0,
        chaos: 0,
        mode: 'standard',
        version: 'v7',
        speed: 'relax',
        draft: false,
        noPrompt: '',
        cref: [],    // 格式: {url, 权重}
        sref: [],    // 格式: {url, 权重}
        oref: [],    // 格式: {url, 权重}
        iref: [],    // 这个参数在原始定义中存在,但未在UI或输出中使用,为保持一致性(如果未来计划使用)而保留
        directImages: [], // 格式: {url, 权重}
        // 新增参数
        tile: false,
        seed: '',
        quality: 1,
        stop: 100,
        visibility: '',
        // 新增个性化参数
        personalParams: '',
        // 新增批量任务参数
        r: 1
    };

    // 显示 Toast 提示
    function showToast(message) {
        const toast = document.createElement('div');
        toast.textContent = message;
        toast.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: rgba(0,0,0,0.8);
            color: white;
            padding: 10px 16px;
            border-radius: 6px;
            z-index: 99999;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            transform: translateY(-20px);
            opacity: 0;
            transition: all 0.3s ease;
        `;

        document.body.appendChild(toast);

        // 触发动画
        setTimeout(() => {
            toast.style.transform = 'translateY(0)';
            toast.style.opacity = '1';
        }, 10);

        // 自动消失
        setTimeout(() => {
            toast.style.transform = 'translateY(-20px)';
            toast.style.opacity = '0';
            setTimeout(() => {
                if (document.body.contains(toast)) { // 检查 toast 是否仍在 body 中
                    document.body.removeChild(toast);
                }
            }, 300);
        }, 2000);
    }

    // 创建设置按钮
    function createSettingButton() {
        const button = document.createElement('button');
        button.textContent = 'MJ设置';
        button.style.cssText = `
            position: fixed;
            right: 20px;
            bottom: 20px;
            padding: 10px 20px;
            background-color: #5865F2;
            color: white;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            z-index: 9999;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            transition: all 0.2s ease;
        `;

        button.addEventListener('click', toggleControlPanel);
        document.body.appendChild(button);

        button.addEventListener('mouseenter', () => {
            button.style.backgroundColor = '#4752C4';
            button.style.transform = 'scale(1.05)';
        });

        button.addEventListener('mouseleave', () => {
            button.style.backgroundColor = '#5865F2';
            button.style.transform = 'scale(1)';
        });
    }

    // 切换控制面板显示/隐藏
    function toggleControlPanel() {
        const panel = document.getElementById('mj-control-panel');
        if (panel) {
            if (panel.style.display === 'none') {
                panel.style.display = 'block';
                panel.style.opacity = '0';
                panel.style.transform = 'translateY(10px)';
                setTimeout(() => {
                    panel.style.opacity = '1';
                    panel.style.transform = 'translateY(0)';
                }, 10);
            } else {
                panel.style.opacity = '0';
                panel.style.transform = 'translateY(10px)';
                setTimeout(() => {
                    panel.style.display = 'none';
                }, 200); // 等待动画完成后再隐藏
            }
        }
    }

    // 重置参数
    function resetParams() {
        params = {
            prompt: '',
            ar: '1:1',
            stylize: 100,
            weird: 0,
            chaos: 0,
            mode: 'standard',
            version: 'v7',
            speed: 'relax',
            draft: false,
            noPrompt: '',
            cref: [],
            sref: [],
            oref: [],
            iref: [],
            directImages: [],
            tile: false,
            seed: '',
            quality: 1,
            stop: 100,
            visibility: '',
            personalParams: '',
            r: 1
        };
    }

    // 更新提示词参数
    function updatePromptParams() {
        const { prompt, ar, stylize, weird, chaos, mode, draft, noPrompt, version, cref, sref, speed, oref, /* iref 未在输出中使用 */ directImages, tile, seed, quality, stop, visibility, personalParams } = params;

        // 处理其他参数
        const otherParts = [
            `--ar ${ar}`,
            `--s ${stylize}`, // 修改:始终包含 --s,即使为 0
            weird !== 0 ? `--w ${weird}` : '',
            chaos !== 0 ? `--c ${chaos}` : '',
            mode !== 'standard' ? `--${mode}` : '', // 确保 'standard' 是默认值且不被添加
            draft ? '--draft' : '',
            noPrompt ? `--no ${noPrompt}` : '',
            version.startsWith('niji') ? `--niji ${version.replace('niji', '')}` : `--v ${version.replace('v', '')}`,
            speed !== 'relax' ? `--${speed}` : '', // 仅在速度不是默认的 relax 时添加
            tile ? '--tile' : '',
            seed ? `--seed ${seed}` : '',
            quality !== 1 ? `--q ${quality}` : '', // 仅在不是默认值 1 时添加
            stop !== 100 ? `--stop ${stop}` : '', // 仅在不是默认值 100 时添加
            visibility ? `--${visibility}` : '', // 将会是 --public 或 --stealth
            personalParams ? `--p ${personalParams}` : '',
            params.r > 1 ? `--r ${params.r}` : '' // 仅在 r > 1 时添加
        ];

        // 处理带权重的图像参考
        const formatImageWithWeight = (url, weight, prefix) => {
            let formatted = url;
            if (weight && weight.trim() !== '') { // 检查是否提供了权重且不为空
                formatted += ` ${prefix} ${weight.trim()}`;
            }
            return formatted;
        };

        const directImageUrls = directImages.map(item => formatImageWithWeight(item.url, item.weight, '--iw')).join(' ');

        const promptField = document.getElementById('prompt-params');
        if (promptField) {
            const allParts = [
                directImageUrls,
                prompt.trim(),
                ...cref.map(item => `--cref ${formatImageWithWeight(item.url, item.weight, '--cw')}`),
                ...sref.map(item => `--sref ${formatImageWithWeight(item.url, item.weight, '--sw')}`), // 修改:统一 sref 处理
                ...oref.map(item => `--oref ${formatImageWithWeight(item.url, item.weight, '--ow')}`),
                ...otherParts.filter(Boolean) // 过滤掉空字符串
            ].filter(Boolean); // 过滤掉任何完全为空的部分

            promptField.value = allParts.join(' ').trim();
        }
    }

    // 创建控制面板
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.id = 'mj-control-panel';
        panel.style.cssText = `
            display: none;
            position: fixed;
            right: 20px;
            bottom: 80px; /* 已调整,为设置按钮留出空间 */
            width: 1080px;
            max-width: calc(100% - 40px);
            background: white;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
            padding: 20px;
            z-index: 10000;
            border: 1px solid #E5E7EB;
            max-height: 90vh;
            overflow-y: auto;
            font-family: sans-serif;
            transition: opacity 0.2s ease, transform 0.2s ease; /* 为不透明度和变换添加了过渡效果 */
            color: #111827;
        `;

        panel.innerHTML = `
            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:20px;">
                <h3 style="margin:0; color:#111827; font-size:18px; font-weight:600;">Midjourney 参数设置</h3>
                <div style="flex:1; height:1px; background:#e5e7eb; margin:0 16px;"></div>
                <button id="theme-toggle" style="background:none; border:none; cursor:pointer; color:#6B7280; transition: color 0.2s ease; font-size: 16px;">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-moon-stars-fill" viewBox="0 0 16 16"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/><path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.312 6.19l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"/></svg>
                </button>
            </div>

            <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap:20px;">
                <div style="background:#f9fafb; padding:16px; border-radius:8px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">图片尺寸 (--ar)</p>
                    <div style="display:flex; align-items:center; gap:20px;">
                        <div style="position:relative; width:100px; height:100px;">
                            <div style="position:absolute; top:0; left:0; width:100px; height:100px; border:2px dashed #d1d5db; border-radius:12px;"></div>
                            <div id="ratio-preview" style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:100px; height:100px;">
                                <div style="width:100px; height:100px; border:2px dashed #d1d5db; border-radius:12px; position:absolute; top:0; left:0;"></div>
                                <div id="ratio-box" style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:#f3f4f6; border:2px solid #374151; border-radius:6px; display:flex; align-items:center; justify-content:center; font-size:12px; color:#374151; padding:2px 4px; min-width:20px; min-height:12px; box-sizing: border-box;">1:1</div>
                            </div>
                        </div>
                        <div style="flex:1;">
                            <div id="size-buttons" style="display:flex; gap:8px; margin-bottom:8px;"></div>
                            <input type="range" id="ratio-slider" min="0" max="10" value="5" style="width:100%;">
                        </div>
                    </div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">美学参数</p>
                    <div style="display:flex; flex-direction:column; gap:12px;">
                        <div style="display:flex; align-items:center; justify-content:space-between;">
                            <label for="stylize" style="flex:1; margin-right:12px;">风格化 (--s)</label>
                            <input type="range" id="stylize" name="stylize" min="0" max="1000" value="100" style="flex:3;">
                            <span id="stylize-value" style="width:40px; text-align:right;">100</span>
                        </div>
                        <div style="display:flex; align-items:center; justify-content:space-between;">
                            <label for="weird" style="flex:1; margin-right:12px;">奇特化 (--w)</label>
                            <input type="range" id="weird" name="weird" min="0" max="3000" value="0" style="flex:3;">
                            <span id="weird-value" style="width:40px; text-align:right;">0</span>
                        </div>
                        <div style="display:flex; align-items:center; justify-content:space-between;">
                            <label for="chaos" style="flex:1; margin-right:12px;">多样性 (--c)</label>
                            <input type="range" id="chaos" name="chaos" min="0" max="100" value="0" style="flex:3;">
                            <span id="chaos-value" style="width:40px; text-align:right;">0</span>
                        </div>
                    </div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px; display: flex; flex-direction: column; gap: 10px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">模型设置</p>
                    <div style="display:flex; gap:10px; align-items:center;">
                        <label style="flex:1;">速度
                            <div class="btn-group" style="display:flex; border-radius:6px; overflow:hidden; border:1px solid #d1d5db;">
                                <button data-value="relax" class="speed-btn active" style="flex:1; padding:6px; background:white; border:none; cursor:pointer;">标准</button>
                                <button data-value="fast" class="speed-btn" style="flex:1; padding:6px; background:white; border:none; cursor:pointer;">快速</button>
                                <button data-value="turbo" class="speed-btn" style="flex:1; padding:6px; background:white; border:none; cursor:pointer;">极速</button>
                            </div>
                        </label>
                        <label style="flex:1;">模式
                            <div class="btn-group" style="display:flex; border-radius:6px; overflow:hidden; border:1px solid #d1d5db;">
                                <button data-value="standard" class="mode-btn active" style="flex:1; padding:6px; background:white; border:none; cursor:pointer;">标准</button>
                                <button data-value="raw" class="mode-btn" style="flex:1; padding:6px; background:white; border:none; cursor:pointer;">原始</button>
                            </div>
                        </label>
                    </div>
                    <div style="display:flex; gap:10px; align-items:center;">
                        <label style="flex:1;">草稿 (--draft)
                            <div class="toggle-switch" id="draft-toggle-switch" style="position:relative; width:40px; height:20px; border-radius:10px; background:#e5e7eb; cursor:pointer;">
                                <div class="toggle-dot" style="position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:white; box-shadow:0 1px 3px rgba(0,0,0,0.2); transition:all 0.2s ease;"></div>
                            </div>
                        </label>
                        <label for="version-select" style="flex:2;">版本 (--v, --niji)
                            <select id="version-select" name="version-select" style="width:100%; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                                <option value="v7">v7</option>
                                <option value="v6.1">v6.1</option>
                                <option value="v6">v6</option>
                                <option value="v5.2">v5.2</option>
                                <option value="v5.1">v5.1</option>
                                <option value="v5">v5</option>
                                <option value="v4">v4</option>
                                <option value="v3">v3</option>
                                <option value="v2">v2</option>
                                <option value="v1">v1</option>
                                <option value="niji6">niji6</option>
                                <option value="niji5">niji5</option>
                                <option value="niji4">niji4</option>
                            </select>
                        </label>
                    </div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">角色参考 (--cref)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="cref-url" placeholder="粘贴角色图片URL" style="flex:3; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                        <input type="number" id="cref-weight" placeholder="权重 (--cw)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                    </div>
                    <button id="cref-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer; transition:all 0.2s ease;">添加</button>
                    <div id="cref-preview" style="margin-top:10px; display:flex; flex-wrap:wrap; gap:8px;"></div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">风格参考 (--sref)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="sref-url" placeholder="图片URL, 'random'或数字码" style="flex:3; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                        <input type="number" id="sref-weight" placeholder="权重 (--sw)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                    </div>
                    <button id="sref-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer; transition:all 0.2s ease;">添加</button>
                    <div id="sref-preview" style="margin-top:10px; display:flex; flex-wrap:wrap; gap:8px;"></div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">全方位参考 (--oref)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="oref-url" placeholder="粘贴全方位参考图片URL" style="flex:3; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                        <input type="number" id="oref-weight" placeholder="权重 (--ow)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                    </div>
                    <button id="oref-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer; transition:all 0.2s ease;">添加</button>
                    <div id="oref-preview" style="margin-top:10px; display:flex; flex-wrap:wrap; gap:8px;"></div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px;">
                    <p style="margin:0 0 8px 0; font-weight:500;">图像参考 (URL --iw)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="direct-image-url" placeholder="粘贴图像URL" style="flex:3; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                        <input type="number" id="direct-image-weight" placeholder="权重 (--iw)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                    </div>
                    <button id="direct-image-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer; transition:all 0.2s ease;">添加</button>
                    <div id="direct-image-preview" style="margin-top:10px; display:flex; flex-wrap:wrap; gap:8px;"></div>
                </div>

                <div style="background:#f9fafb; padding:16px; border-radius:8px; grid-column: span 2;">
                    <p style="margin:0 0 8px 0; font-weight:500;">更多参数</p>
                    <div style="display:grid; grid-template-columns: 1fr 1fr; gap:16px;">
                        <div>
                            <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                                <div class="toggle-switch" id="tile-toggle-switch" style="position:relative; width:40px; height:20px; border-radius:10px; background:#e5e7eb; cursor:pointer;">
                                    <div class="toggle-dot" style="position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:white; box-shadow:0 1px 3px rgba(0,0,0,0.2); transition:all 0.2s ease;"></div>
                                </div>
                                <label>重复图案 (--tile)</label>
                            </div>
                            <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                                <label for="seed-input">种子 (--seed)</label>
                                <input type="number" id="seed-input" name="seed-input" placeholder="0-4294967295" min="0" max="4294967295" style="width:120px; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                            </div>
                            <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                                <label for="personal-params">个性化 (--p)</label>
                                <input type="text" id="personal-params" name="personal-params" placeholder="输入个性化参数" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                            </div>
                        </div>
                        <div>
                            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
                                <label for="quality-slider">质量 (--q)</label>
                                <input type="range" id="quality-slider" name="quality-slider" min="0.25" max="1" step="0.25" value="1" style="flex:1; margin:0 10px;"> <span id="quality-value">1</span>
                            </div>
                            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
                                <label for="stop-slider">停止 (--stop)</label>
                                <input type="range" id="stop-slider" name="stop-slider" min="10" max="100" step="1" value="100" style="flex:1; margin:0 10px;">
                                <span id="stop-value">100</span>
                            </div>
                            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
                                <label for="r-slider">批量任务 (--r)</label>
                                <input type="range" id="r-slider" name="r-slider" min="1" max="10" value="1" style="flex:1; margin:0 10px;">
                                <span id="r-value">1</span>
                            </div>
                        </div>
                    </div>
                    <div style="margin-top:10px;">
                        <p style="margin:0 0 8px 0; font-weight:500;">可见性 (--public, --stealth)</p>
                        <div style="display:flex; gap:10px;">
                            <button data-value="" class="visibility-btn active" style="padding:6px 12px; border:1px solid #d1d5db; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">默认</button>
                            <button data-value="public" class="visibility-btn" style="padding:6px 12px; border:1px solid #d1d5db; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">公开</button>
                            <button data-value="stealth" class="visibility-btn" style="padding:6px 12px; border:1px solid #d1d5db; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">隐身</button>
                        </div>
                    </div>
                </div>
            </div>

            <div style="margin-top:20px; border-top:1px solid #e5e7eb; padding-top:16px;">
                <div style="display:flex; gap:10px;">
                    <div style="flex:1;">
                        <p style="margin:0 0 8px 0; font-weight:500;">提示词</p>
                        <textarea id="main-prompt" placeholder="输入主要提示词..." style="width:100%; height:80px; padding:10px; box-sizing:border-box; border-radius:6px; border:1px solid #d1d5db; transition:border-color 0.2s ease;"></textarea>
                    </div>
                    <div style="flex:1;">
                        <p style="margin:0 0 8px 0; font-weight:500;">排除词 (--no)</p>
                        <textarea id="no-prompt" placeholder="输入需要排除的元素,多个用空格分隔" style="width:100%; height:80px; padding:10px; box-sizing:border-box; border-radius:6px; border:1px solid #d1d5db; transition:border-color 0.2s ease;"></textarea>
                    </div>
                    <div style="flex:1;">
                        <p style="margin:0 0 8px 0; font-weight:500;">最终参数</p>
                        <textarea id="prompt-params" style="width:100%; height:80px; padding:10px; background:#f9fafb; border-radius:6px; border:1px solid #d1d5db; transition:border-color 0.2s ease; cursor:pointer;" readonly></textarea>
                    </div>
                </div>
            </div>

            <div style="margin-top:16px; display:flex; gap:10px;">
                <button id="copy-btn" style="flex:1; padding:8px; background:#4f46e5; color:white; border:none; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">拷贝参数</button>
                <button id="clear-btn" style="flex:1; padding:8px; background:#e5e7eb; color:#111827; border:none; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">清空参数</button>
            </div>
        `;

        document.body.appendChild(panel);
        bindControlEvents(); // 添加到DOM后绑定事件
    }

    function setInitialActiveButtons() {
        const buttonGroups = [
            { className: 'speed-btn', param: 'speed', defaultValue: 'relax' },
            { className: 'mode-btn', param: 'mode', defaultValue: 'standard' },
            { className: 'visibility-btn', param: 'visibility', defaultValue: '' }
        ];

        buttonGroups.forEach(group => {
            const buttons = document.querySelectorAll(`.${group.className}`);
            let currentParamValue = params[group.param] === undefined ? group.defaultValue : params[group.param];

            buttons.forEach(btn => {
                if (btn.dataset.value === currentParamValue) {
                    btn.classList.add('active');
                    btn.style.backgroundColor = '#4f46e5';
                    btn.style.color = 'white';
                } else {
                    btn.classList.remove('active');
                    btn.style.backgroundColor = 'white';
                    btn.style.color = '#111827';
                }
            });
        });
    }


    // 绑定控制面板事件
    function bindControlEvents() {
        const $ = id => document.getElementById(id);

        let isDarkMode = false;
        const themeToggleButton = $('theme-toggle');
        const sunIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-brightness-high-fill" viewBox="0 0 16 16"><circle cx="8" cy="8" r="4"/><path d="M8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 0a.5.5 0 0 1-.707.707l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707.707L2.343 3.757a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707z"/></svg>`;
        const moonIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-moon-stars-fill" viewBox="0 0 16 16"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/><path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.312 6.19l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"/></svg>`;

        themeToggleButton.addEventListener('click', () => {
            isDarkMode = !isDarkMode;
            const panel = $('mj-control-panel');
            const allButtons = panel.querySelectorAll('button'); // 如果需要,进行更具体的选择
            const inputsAndTextareas = panel.querySelectorAll('input, textarea, select');
            const bgElements = panel.querySelectorAll('[style*="background:#f9fafb"], .btn-group');
            const labels = panel.querySelectorAll('label, p, h3, span');


            if (isDarkMode) {
                panel.style.backgroundColor = '#2B2D31'; // Discord 暗色主题背景
                panel.style.color = '#DCDDDE';         // Discord 暗色主题文本
                panel.style.borderColor = '#202225';   // Discord 暗色主题边框

                labels.forEach(label => label.style.color = '#DCDDDE');
                themeToggleButton.innerHTML = sunIcon;
                themeToggleButton.style.color = '#DCDDDE';


                allButtons.forEach(btn => {
                     if (!btn.classList.contains('active') && !btn.id.startsWith('theme-toggle')) { // 保留激活按钮的样式
                        btn.style.backgroundColor = '#40444B'; // Discord 暗色按钮
                        btn.style.color = '#DCDDDE';
                        btn.style.borderColor = '#2D2F34'; // 按钮使用稍暗的边框
                    } else if (btn.classList.contains('active')) {
                        btn.style.backgroundColor = '#5865F2'; // 保留激活状态颜色
                        btn.style.color = 'white';
                    }
                });

                inputsAndTextareas.forEach(input => {
                    input.style.backgroundColor = '#202225'; // Discord 暗色输入框
                    input.style.color = '#DCDDDE';
                    input.style.borderColor = '#18191C'; // Discord 暗色输入框边框
                    if (input.type === 'range') {
                         input.style.setProperty('--thumb-bg', '#DCDDDE');
                         input.style.setProperty('--track-bg', '#40444B');
                    }
                });
                bgElements.forEach(el => el.style.backgroundColor = '#202225'); // 卡片背景

                // 为暗色模式更新比例框样式
                const ratioBox = $('ratio-box');
                if (ratioBox) {
                    ratioBox.style.background = '#40444B';
                    ratioBox.style.color = '#DCDDDE';
                    ratioBox.style.borderColor = '#DCDDDE';
                }


            } else { // 亮色模式
                panel.style.backgroundColor = 'white';
                panel.style.color = '#111827';
                panel.style.borderColor = '#E5E7EB';

                labels.forEach(label => label.style.color = '#111827'); // 重置标签颜色
                themeToggleButton.innerHTML = moonIcon;
                themeToggleButton.style.color = '#6B7280';


                allButtons.forEach(btn => {
                    if (!btn.classList.contains('active') && !btn.id.startsWith('theme-toggle')) {
                        btn.style.backgroundColor = 'white'; // 默认亮色模式按钮
                        btn.style.color = '#111827';
                        btn.style.borderColor = '#d1d5db';
                    } else if (btn.classList.contains('active')) {
                        btn.style.backgroundColor = '#4f46e5'; // 亮色模式下的激活颜色
                        btn.style.color = 'white';
                    }
                 });


                inputsAndTextareas.forEach(input => {
                    input.style.backgroundColor = 'white';
                    input.style.color = '#111827';
                    input.style.borderColor = '#d1d5db';
                     if (input.type === 'range') {
                         input.style.removeProperty('--thumb-bg');
                         input.style.removeProperty('--track-bg');
                    }
                });
                 bgElements.forEach(el => {
                    if(el.classList.contains('btn-group')) {
                        el.style.backgroundColor = 'transparent'; // 或者为按钮组指定特定的亮色模式
                    } else {
                        el.style.backgroundColor = '#f9fafb';
                    }
                });

                // 为亮色模式重置比例框样式
                const ratioBox = $('ratio-box');
                if (ratioBox) {
                    ratioBox.style.background = '#f3f4f6';
                    ratioBox.style.color = '#374151';
                    ratioBox.style.borderColor = '#374151';
                }
            }
            setInitialActiveButtons(); // 重新应用激活按钮样式以确保在主题更改后它们是正确的
        });


        $('main-prompt').oninput = e => { params.prompt = e.target.value; updatePromptParams(); };

        const bindSliderEvent = (id, property, displayId = null, isFloat = false) => {
            const slider = $(id);
            if (!slider) return;
            slider.oninput = e => {
                const value = isFloat ? parseFloat(e.target.value) : parseInt(e.target.value, 10);
                params[property] = value;
                if (displayId && $(displayId)) $(displayId).textContent = e.target.value; // 为确保精度,显示滑块的原始值
                updatePromptParams();
            };
        };

        bindSliderEvent('stylize', 'stylize', 'stylize-value');
        bindSliderEvent('weird', 'weird', 'weird-value');
        bindSliderEvent('chaos', 'chaos', 'chaos-value');
        bindSliderEvent('quality-slider', 'quality', 'quality-value', true); // 质量可以是浮点数
        bindSliderEvent('stop-slider', 'stop', 'stop-value');
        bindSliderEvent('r-slider', 'r', 'r-value');


        const bindRadioGroup = (groupClass, property, defaultValue) => {
            document.querySelectorAll(`.${groupClass}`).forEach(btn => {
                btn.addEventListener('click', () => {
                    document.querySelectorAll(`.${groupClass}`).forEach(b => {
                        b.classList.remove('active');
                        b.style.backgroundColor = isDarkMode ? '#40444B' : 'white';
                        b.style.color = isDarkMode ? '#DCDDDE' : '#111827';
                    });
                    btn.classList.add('active');
                    btn.style.backgroundColor = isDarkMode ? '#5865F2' : '#4f46e5'; // 使用适合主题的激活颜色
                    btn.style.color = 'white';
                    params[property] = btn.dataset.value;
                    updatePromptParams();
                });
            });
        };

        bindRadioGroup('speed-btn', 'speed', 'relax');
        bindRadioGroup('mode-btn', 'mode', 'standard');
        bindRadioGroup('visibility-btn', 'visibility', '');


        const bindToggleSwitch = (switchId, property) => {
            const switchEl = $(switchId);
            if (!switchEl) return;
            const dot = switchEl.querySelector('.toggle-dot');
            if (!dot) return;

            // 设置初始状态
            if (params[property]) {
                dot.style.transform = 'translateX(20px)';
                switchEl.style.backgroundColor = isDarkMode ? '#5865F2' : '#4f46e5';
            } else {
                dot.style.transform = 'translateX(0)';
                switchEl.style.backgroundColor = isDarkMode ? '#4E4F52' : '#e5e7eb';
            }

            switchEl.addEventListener('click', () => {
                params[property] = !params[property];
                if (params[property]) {
                    dot.style.transform = 'translateX(20px)';
                    switchEl.style.backgroundColor = isDarkMode ? '#5865F2' : '#4f46e5';
                } else {
                    dot.style.transform = 'translateX(0)';
                    switchEl.style.backgroundColor = isDarkMode ? '#4E4F52' : '#e5e7eb';
                }
                updatePromptParams();
            });
        };

        bindToggleSwitch('tile-toggle-switch', 'tile');
        bindToggleSwitch('draft-toggle-switch', 'draft'); // 已修正的草稿切换开关ID

        if ($('version-select')) {
            $('version-select').onchange = e => { params.version = e.target.value; updatePromptParams(); };
        }
        if ($('no-prompt')) {
            $('no-prompt').oninput = e => { params.noPrompt = e.target.value.trim(); updatePromptParams(); };
        }

        if ($('copy-btn')) {
            $('copy-btn').onclick = () => {
                const textarea = $('prompt-params');
                if (!textarea) return;
                textarea.select();
                try {
                    document.execCommand('copy');
                    showToast('参数已复制!');
                } catch (err) {
                    showToast('复制失败!');
                    console.error('Copy failed:', err);
                }
            };
        }

        if ($('clear-btn')) {
            $('clear-btn').onclick = () => {
                resetParams(); // 重置参数对象

                // 重置UI元素
                if ($('main-prompt')) $('main-prompt').value = params.prompt;
                if ($('stylize')) $('stylize').value = params.stylize;
                if ($('stylize-value')) $('stylize-value').textContent = params.stylize;
                if ($('weird')) $('weird').value = params.weird;
                if ($('weird-value')) $('weird-value').textContent = params.weird;
                if ($('chaos')) $('chaos').value = params.chaos;
                if ($('chaos-value')) $('chaos-value').textContent = params.chaos;
                if ($('version-select')) $('version-select').value = params.version;
                if ($('no-prompt')) $('no-prompt').value = params.noPrompt;
                if ($('ratio-slider')) {
                    const defaultRatioIndex = sizeMap.indexOf(params.ar);
                    $('ratio-slider').value = defaultRatioIndex !== -1 ? defaultRatioIndex : 5; // 如果未找到,则默认为 1:1
                    $('ratio-slider').dispatchEvent(new Event('input')); // 触发更新
                }

                ['cref-url', 'cref-weight', 'sref-url', 'sref-weight', 'oref-url', 'oref-weight', 'direct-image-url', 'direct-image-weight'].forEach(id => {
                    if ($(id)) $(id).value = '';
                });

                if ($('seed-input')) $('seed-input').value = params.seed;
                if ($('quality-slider')) $('quality-slider').value = params.quality;
                if ($('quality-value')) $('quality-value').textContent = params.quality;
                if ($('stop-slider')) $('stop-slider').value = params.stop;
                if ($('stop-value')) $('stop-value').textContent = params.stop;
                if ($('personal-params')) $('personal-params').value = params.personalParams;
                if ($('r-slider')) $('r-slider').value = params.r;
                if ($('r-value')) $('r-value').textContent = params.r;

                // 通过重新运行其绑定函数或手动设置来重置切换开关
                bindToggleSwitch('tile-toggle-switch', 'tile');
                bindToggleSwitch('draft-toggle-switch', 'draft');


                setInitialActiveButtons(); // 这将正确设置单选按钮的激活状态
                refreshPreviews();
                updatePromptParams(); // 更新最终的参数字符串
                showToast('所有参数已重置为默认值');
            };
        }


        const setupRefSection = (type) => {
            const addBtn = $(`${type}-add`);
            const urlInput = $(`${type}-url`);
            const weightInput = $(`${type}-weight`);
            const previewContainerId = `${type}-preview`;

            if (!addBtn || !urlInput || !weightInput) return;

            addBtn.onclick = () => {
                const url = urlInput.value.trim();
                const weight = weightInput.value.trim();

                if (!url) {
                    showToast(`请输入${type === 'sref' ? 'URL或代码' : 'URL'}`);
                    return;
                }

                const isImageUrl = /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url);
                const isSrefCode = type === 'sref' && (/^\d+$/.test(url) || url.toLowerCase() === 'random');

                if (type !== 'sref' && !isImageUrl) {
                    showToast('请输入有效的图片URL');
                    return;
                }
                if (type === 'sref' && !isImageUrl && !isSrefCode) {
                    showToast("请输入有效图片URL, 'random'或数字sref码");
                    return;
                }

                const targetArray = params[type === 'directImages' ? 'directImages' : type];
                const srefCodeToAdd = isSrefCode ? (url.toLowerCase() === 'random' ? 'random' : url) : url;
                const itemUrl = type === 'sref' ? srefCodeToAdd : url;


                if (!targetArray.some(item => item.url === itemUrl)) {
                    targetArray.push({ url: itemUrl, weight });
                    if (isSrefCode) {
                        addPreviewSrefCode(previewContainerId, itemUrl, weight);
                    } else {
                         const weightPrefix = {'cref': '--cw', 'sref': '--sw', 'oref': '--ow', 'directImages': '--iw'}[type];
                        addPreviewImage(previewContainerId, itemUrl, weight, type, weightPrefix);
                    }
                    urlInput.value = '';
                    weightInput.value = '';
                    updatePromptParams();
                } else {
                    showToast(`该${type === 'sref' && isSrefCode ? '码' : 'URL'}已添加`);
                }
            };
        };

        setupRefSection('cref');
        setupRefSection('sref');
        setupRefSection('oref');
        setupRefSection('directImages');


        const sizeMap = ['1:2', '9:16', '2:3', '3:4', '5:6', '1:1', '6:5', '4:3', '3:2', '16:9', '2:1'];
        const ratioPresets = { '1:2': { width: 50, height: 100 }, '9:16': { width: 56.25, height: 100 }, '2:3': { width: 66.67, height: 100 }, '3:4': { width: 75, height: 100 }, '5:6': { width: 83.33, height: 100 }, '1:1': { width: 100, height: 100 }, '6:5': { width: 100, height: 83.33 }, '4:3': { width: 100, height: 75 }, '3:2': { width: 100, height: 66.67 }, '16:9': { width: 100, height: 56.25 }, '2:1': { width: 100, height: 50 }};

        const ratioSlider = $('ratio-slider');
        if (ratioSlider) {
            ratioSlider.oninput = e => {
                const ratio = sizeMap[+e.target.value] || '1:1';
                params.ar = ratio;
                const box = $('ratio-box');
                const preset = ratioPresets[ratio] || { width: 100, height: 100 };
                if(box) {
                    box.style.width = `${preset.width}px`;
                    box.style.height = `${preset.height}px`;
                    box.textContent = ratio;
                }

                const presetMap = { '纵向': '1:2', '正方形': '1:1', '横向': '2:1' };
                document.querySelectorAll('#size-buttons button').forEach(btn => {
                    const btnRatio = presetMap[btn.textContent];
                    if (btnRatio === ratio) {
                        btn.classList.add('active');
                        btn.style.backgroundColor = isDarkMode ? '#5865F2' :'#4f46e5';
                        btn.style.color = 'white';
                    } else {
                        btn.classList.remove('active');
                        btn.style.backgroundColor = isDarkMode ? '#40444B' : 'white';
                        btn.style.color = isDarkMode ? '#DCDDDE' : '#111827';
                    }
                });
                updatePromptParams();
            };
            // 触发比例滑块的初始事件以设置预览
            const initialRatioIndex = sizeMap.indexOf(params.ar);
            ratioSlider.value = initialRatioIndex !== -1 ? initialRatioIndex : 5; // 默认为 1:1
            ratioSlider.dispatchEvent(new Event('input'));
        }


        const btnGroup = $('size-buttons');
        if (btnGroup) {
            const presetMap = { '纵向': '1:2', '正方形': '1:1', '横向': '2:1' };
            ['纵向', '正方形', '横向'].forEach((label, i) => {
                const btn = document.createElement('button');
                btn.textContent = label;
                btn.dataset.value = presetMap[label];
                btn.style.cssText = 'padding:4px 12px; border-radius:6px; border:1px solid #d1d5db; background:white; cursor:pointer; transition:all 0.2s ease;';
                if ((isDarkMode && params.ar === presetMap[label]) || (!isDarkMode && params.ar === presetMap[label]) ) {
                     btn.classList.add('active');
                     btn.style.backgroundColor = isDarkMode ? '#5865F2' : '#4f46e5';
                     btn.style.color = 'white';
                } else if (params.ar === presetMap[label]) { // 默认激活 1:1 (正方形)
                    btn.classList.add('active');
                    btn.style.backgroundColor = '#4f46e5';
                    btn.style.color = 'white';
                }


                btn.onclick = () => {
                    const ratio = presetMap[label];
                    const sliderIndex = sizeMap.indexOf(ratio);
                    if (sliderIndex !== -1 && ratioSlider) {
                        ratioSlider.value = sliderIndex;
                        ratioSlider.dispatchEvent(new Event('input'));
                    }
                };
                btnGroup.appendChild(btn);
            });
        }

        if ($('seed-input')) {
            $('seed-input').oninput = e => {
                const value = e.target.value.trim();
                if (/^\d*$/.test(value) && (value === '' || (parseInt(value) >= 0 && parseInt(value) <= 4294967295))) {
                    params.seed = value;
                } else {
                    e.target.value = params.seed;
                }
                updatePromptParams();
            };
        }
        if ($('personal-params')) {
            $('personal-params').oninput = e => { params.personalParams = e.target.value.trim(); updatePromptParams(); };
        }

        const promptParamsTextarea = $('prompt-params');
        if (promptParamsTextarea) {
            promptParamsTextarea.addEventListener('click', () => {
                promptParamsTextarea.select();
                 try {
                    document.execCommand('copy');
                    showToast('参数已复制!');
                } catch (err) {
                    showToast('复制失败!');
                    console.error('Copy failed:', err);
                }
            });
        }


        document.querySelectorAll('input, textarea, select').forEach(el => {
            el.addEventListener('focus', () => {
                el.style.borderColor = isDarkMode ? '#7289DA' : '#4f46e5'; // 暗色模式下的 Discord 焦点颜色,亮色模式下的应用紫色
            });
            el.addEventListener('blur', () => {
                el.style.borderColor = isDarkMode ? '#202225' : '#d1d5db';
            });
        });

        document.querySelectorAll('button').forEach(btn => {
            const originalBg = btn.style.backgroundColor;
            const originalTransform = btn.style.transform;
            const originalShadow = btn.style.boxShadow;

            btn.addEventListener('mouseenter', () => {
                if (!btn.classList.contains('active') && !btn.id.startsWith('theme-toggle')) {
                    btn.style.transform = 'translateY(-1px)';
                    btn.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
                    if (isDarkMode) btn.style.backgroundColor = '#4F545C'; // 暗色模式下悬停时略微变亮
                    // else btn.style.filter = 'brightness(0.95)'; // 如果需要,为亮色模式保留
                }
            });
            btn.addEventListener('mouseleave', () => {
                 if (!btn.classList.contains('active')) {
                    btn.style.transform = originalTransform || 'translateY(0)';
                    btn.style.boxShadow = originalShadow || 'none';
                    if (isDarkMode) btn.style.backgroundColor = '#40444B'; // 返回正常的暗色按钮
                    // else btn.style.filter = 'none';
                 }
            });
        });
    }

    function addPreviewImage(containerId, url, weight, paramType, weightPrefix) {
        const container = document.getElementById(containerId);
        if (!container) return;
        const imgContainer = document.createElement('div');
        imgContainer.style.cssText = 'position: relative; margin: 4px; animation: fadeIn 0.3s ease;';

        const img = document.createElement('img');
        img.src = url;
        img.style.width = '60px';
        img.style.height = '60px';
        img.style.objectFit = 'cover';
        img.style.borderRadius = '4px';
        img.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
        img.style.transition = 'all 0.2s ease';
        img.onerror = () => { // 处理损坏的图片链接
            imgContainer.innerHTML = `<div style="width:60px; height:60px; background:#eee; color:#999; display:flex; align-items:center; justify-content:center; border-radius:4px; font-size:10px; text-align:center;">无效图片</div>`;
        };


        img.addEventListener('mouseenter', () => { img.style.transform = 'scale(1.05)'; img.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)'; });
        img.addEventListener('mouseleave', () => { img.style.transform = 'scale(1)'; img.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)'; });

        const weightBadge = document.createElement('div');
        weightBadge.style.cssText = 'position: absolute; bottom: 0; left: 0; background: rgba(0,0,0,0.7); color: white; font-size: 10px; padding: 1px 3px; border-radius: 0 4px 0 0;';
        const wP = weightPrefix ? weightPrefix.replace('--', '') : '';
        weightBadge.textContent = weight && weight.trim() !== '' ? `${wP}:${weight}` : `${wP}:默认`;


        const deleteBtn = document.createElement('button');
        deleteBtn.style.cssText = 'position: absolute; top: -4px; right: -4px; background: rgba(239, 68, 68, 0.9); color: white; border: none; border-radius: 50%; width: 16px; height: 16px; font-size: 10px; line-height: 16px; text-align:center; cursor:pointer; transition:all 0.2s ease; opacity: 0.8; display:flex; align-items:center; justify-content:center;';
        deleteBtn.innerHTML = '&times;';
        deleteBtn.onclick = function(e) {
            e.stopPropagation();
            imgContainer.style.animation = 'fadeOut 0.2s ease forwards';
            setTimeout(() => {
                const targetArray = params[paramType === 'directImages' ? 'directImages' : paramType];
                const index = targetArray.findIndex(item => item.url === url);
                if (index !== -1) {
                    targetArray.splice(index, 1);
                    if (container.contains(imgContainer)) container.removeChild(imgContainer);
                    updatePromptParams();
                }
            }, 200);
        };
        deleteBtn.addEventListener('mouseenter', () => { deleteBtn.style.opacity = '1'; deleteBtn.style.transform = 'scale(1.1)'; });
        deleteBtn.addEventListener('mouseleave', () => { deleteBtn.style.opacity = '0.8'; deleteBtn.style.transform = 'scale(1)'; });

        imgContainer.appendChild(img);
        imgContainer.appendChild(weightBadge);
        imgContainer.appendChild(deleteBtn);
        container.appendChild(imgContainer);
    }

    function addPreviewSrefCode(containerId, code, weight) {
        const container = document.getElementById(containerId);
        if (!container) return;
        const codeContainer = document.createElement('div');
        codeContainer.style.cssText = 'position: relative; margin: 4px; background: #f3f4f6; border-radius: 4px; padding: 6px 10px; display: flex; align-items: center; font-family: monospace; font-size: 12px; color: #111827; animation: fadeIn 0.3s ease;';
        if (document.getElementById('mj-control-panel').style.backgroundColor === 'rgb(43, 45, 49)') { // 检查是否为暗色模式
             codeContainer.style.background = '#202225';
             codeContainer.style.color = '#DCDDDE';
        }


        const codeText = document.createElement('span');
        codeText.textContent = `sref:${code}`;

        const weightBadge = document.createElement('div');
        weightBadge.style.cssText = 'margin-left: 8px; background: rgba(79, 70, 229, 0.1); color: #4f46e5; font-size: 10px; padding: 2px 4px; border-radius: 3px;';
        weightBadge.textContent = weight && weight.trim() !== '' ? `sw:${weight}` : 'sw:默认';
        if (document.getElementById('mj-control-panel').style.backgroundColor === 'rgb(43, 45, 49)') { // 暗色模式
            weightBadge.style.background = 'rgba(88, 101, 242, 0.3)';
            weightBadge.style.color = '#B9BBBE';
        }


        const deleteBtn = document.createElement('button');
        deleteBtn.style.cssText = 'margin-left: 10px; background: rgba(239, 68, 68, 0.1); color: #ef4444; border: none; border-radius: 4px; padding: 2px 5px; font-size: 10px; line-height:1; cursor:pointer; transition:all 0.2s ease;';
        deleteBtn.innerHTML = '&times;';
        if (document.getElementById('mj-control-panel').style.backgroundColor === 'rgb(43, 45, 49)') { // 暗色模式
            deleteBtn.style.background = 'rgba(239, 68, 68, 0.3)';
            deleteBtn.style.color = '#FAA';
        }

        deleteBtn.onclick = function(e) {
            e.stopPropagation();
            codeContainer.style.animation = 'fadeOut 0.2s ease forwards';
            setTimeout(() => {
                const index = params.sref.findIndex(item => item.url === code);
                if (index !== -1) {
                    params.sref.splice(index, 1);
                    if (container.contains(codeContainer)) container.removeChild(codeContainer);
                    updatePromptParams();
                }
            }, 200);
        };
        deleteBtn.addEventListener('mouseenter', () => { deleteBtn.style.backgroundColor = 'rgba(239, 68, 68, 0.2)'; });
        deleteBtn.addEventListener('mouseleave', () => { deleteBtn.style.backgroundColor = 'rgba(239, 68, 68, 0.1)'; });
        if (document.getElementById('mj-control-panel').style.backgroundColor === 'rgb(43, 45, 49)') { // 暗色模式悬停
            deleteBtn.addEventListener('mouseenter', () => { deleteBtn.style.backgroundColor = 'rgba(239, 68, 68, 0.4)'; });
            deleteBtn.addEventListener('mouseleave', () => { deleteBtn.style.backgroundColor = 'rgba(239, 68, 68, 0.3)'; });
        }


        codeContainer.appendChild(codeText);
        codeContainer.appendChild(weightBadge);
        codeContainer.appendChild(deleteBtn);
        container.appendChild(codeContainer);
    }


    function refreshPreviews() {
        const refTypes = [
            { type: 'cref', previewId: 'cref-preview', weightPrefix: '--cw' },
            { type: 'sref', previewId: 'sref-preview', weightPrefix: '--sw' },
            { type: 'oref', previewId: 'oref-preview', weightPrefix: '--ow' },
            { type: 'directImages', previewId: 'direct-image-preview', weightPrefix: '--iw' }
        ];

        refTypes.forEach(ref => {
            const container = document.getElementById(ref.previewId);
            if (!container) return;
            container.innerHTML = ''; // 清除现有预览

            const items = params[ref.type];
            if (items && Array.isArray(items)) {
                items.forEach(item => {
                    if (ref.type === 'sref' && (item.url === 'random' || /^\d+$/.test(item.url))) {
                        addPreviewSrefCode(ref.previewId, item.url, item.weight);
                    } else {
                        addPreviewImage(ref.previewId, item.url, item.weight, ref.type, ref.weightPrefix);
                    }
                });
            }
        });
    }

    // 注入 FontAwesome 和一些用于动画的 CSS
    function injectStyles() {
        const styleSheet = document.createElement("style");
        styleSheet.type = "text/css";
        styleSheet.innerText = `
            @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
            @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(5px); } }
            input[type="range"] { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 100%;}
            input[type="range"]::-webkit-slider-runnable-track { background: #e5e7eb; height: 0.4rem; border-radius: 0.2rem; }
            input[type="range"]::-moz-range-track { background: #e5e7eb; height: 0.4rem; border-radius: 0.2rem; }
            input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; margin-top: -0.3rem; background-color: #4f46e5; height: 1rem; width: 1rem; border-radius: 50%; border: 1px solid #3730a3;}
            input[type="range"]::-moz-range-thumb { border: none; border-radius: 50%; background-color: #4f46e5; height: 1rem; width: 1rem; border: 1px solid #3730a3;}
        `;
        document.head.appendChild(styleSheet);

        const faLink = document.createElement('link');
        faLink.rel = 'stylesheet';
        faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css'; // 使用一个通用的 CDN
        document.head.appendChild(faLink);
    }


    function init() {
        injectStyles();       // 注入样式
        resetParams();        // 重置参数状态
        createSettingButton(); // 创建主按钮
        createControlPanel();  // 创建面板(初始隐藏)
        setInitialActiveButtons(); // 设置按钮的默认激活状态
        updatePromptParams();      // 计算初始提示字符串
    }

    // 脚本加载后立即初始化
    init();

})();