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.7
// @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', // 模式:standard, raw
        version: 'v7',    // MJ 模型版本
        speed: 'relax',   // 速度:relax, fast, turbo
        draft: false,     // 是否为草稿模式
        noPrompt: '',     // 排除提示词
        cref: [],         // 角色参考 格式: {url, 权重}
        sref: [],         // 风格参考 格式: {url, 权重}
        oref: [],         // 全方位参考 格式: {url, 权重}
        iref: [],         // 图像参考(这个参数在原始定义中存在,但未在UI或输出中使用,为保持一致性而保留)
        directImages: [], // 直接图像URL作为提示词一部分 格式: {url, 权重}
        // 新增参数
        tile: false,      // 是否生成可平铺图案
        seed: '',         // 种子数
        quality: 1,       // 图像质量,默认质量为 1 (0.25, 0.5, 1, 2, 4)
        stop: 100,        // 停止生成百分比
        visibility: '',   // 可见性:public, stealth (或默认不设置)
        // 新增个性化参数
        personalParams: '', // 个性化后缀参数 (--p)
        // 新增批量任务参数
        r: 1              // 重复次数
    };
let isDarkMode = false; // 将 isDarkMode 移至更高作用域,默认为浅色模式启动时的状态
// 定义权重参数前缀的映射
    const weightPrefixes = {
        'cref': '--cw',
        'sref': '--sw',
        'oref': '--ow',
        'directImages': '--iw'
    };
// 显示 Toast 提示
    function showToast(message) {
        const toast = document.createElement('div');
        toast.textContent = message;

        // 根据当前主题设置 Toast 样式
        const toastBg = isDarkMode ? '#DCDDDE' : '#2B2D31'; // 深色模式用浅色背景,浅色模式用深色背景,以保证对比度
        const toastColor = isDarkMode ? '#2B2D31' : '#DCDDDE';
        const toastBoxShadow = isDarkMode ? '0 4px 12px rgba(0,0,0,0.3)' : '0 4px 12px rgba(0,0,0,0.15)';

        toast.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: ${toastBg};
            color: ${toastColor};
            padding: 10px 16px;
            border-radius: 6px;
            z-index: 99999;
            box-shadow: ${toastBoxShadow};
            transform: translateY(-20px);
            opacity: 0;
            transition: all 0.3s ease;
            font-family: sans-serif; /* 确保字体一致性 */
        `;
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; /* Discord 主题紫色 */
            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;
            font-family: sans-serif;
        `;
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}`,
            weird !== 0 ? `--w ${weird}` : '', // 仅当 weird 不为0时添加
            chaos !== 0 ? `--c ${chaos}` : '', // 仅当 chaos 不为0时添加
            mode !== 'standard' ? `--${mode}` : '', // 仅当 mode 不是 standard 时添加
            draft ? '--draft' : '', // 如果 draft 为 true,添加 --draft
            noPrompt ? `--no ${noPrompt}` : '', // 如果 noPrompt 不为空,添加 --no
            version.startsWith('niji') ? `--niji ${version.replace('niji', '')}` : `--v ${version.replace('v', '')}`, // 处理 niji 和普通版本
            speed !== 'relax' ? `--${speed}` : '', // 仅当 speed 不是 relax 时添加
            tile ? '--tile' : '', // 如果 tile 为 true,添加 --tile
            seed ? `--seed ${seed}` : '', // 如果 seed 不为空,添加 --seed
            quality !== 1 ? `--q ${quality}` : '', // 仅在质量不是默认值 1 时添加
            stop !== 100 ? `--stop ${stop}` : '', // 仅在 stop 不是默认值 100 时添加
            visibility ? `--${visibility}` : '', // 如果 visibility 不为空,添加对应参数
            personalParams ? `--p ${personalParams}` : '', // 如果 personalParams 不为空,添加 --p
            params.r > 1 ? `--r ${params.r}` : '' // 如果重复次数大于1,添加 --r
        ];
// 格式化带权重的图片URL
        const formatImageWithWeight = (url, weight, prefix) => {
            let formatted = url;
            if (weight && weight.trim() !== '') {
                formatted += ` ${prefix} ${weight.trim()}`;
            }
            return formatted;
        };
// 格式化直接图像URL列表
        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')}`),
                ...oref.map(item => `--oref ${formatImageWithWeight(item.url, item.weight, '--ow')}`),
                ...otherParts.filter(Boolean) // 过滤掉空字符串
            ].filter(Boolean);
promptField.value = allParts.join(' ').trim(); // 合并所有部分并去除首尾空格
        }
    }
// 创建控制面板HTML结构
    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; /* 默认浅色模式文本颜色 */
        `;
// 面板内部HTML结构
        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 class="panel-section" 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 id="ratio-preview-bg" 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 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 class="panel-section" 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 class="panel-section" 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; border-right: 1px solid #d1d5db; cursor:pointer;">标准</button>
                                <button data-value="fast" class="speed-btn" style="flex:1; padding:6px; background:white; border:none; border-right: 1px solid #d1d5db;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; border-right: 1px solid #d1d5db; 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; margin-top: 4px;">
                                <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; box-sizing: border-box;">
                                <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 class="panel-section" 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; box-sizing: border-box;">
                        <input type="number" id="cref-weight" placeholder="权重 (--cw)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db; box-sizing: border-box;">
                    </div>
                    <button id="cref-add" class="action-button" 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 class="panel-section" 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; box-sizing: border-box;">
                        <input type="number" id="sref-weight" placeholder="权重 (--sw)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db; box-sizing: border-box;">
                    </div>
                    <button id="sref-add" class="action-button" 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 class="panel-section" 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; box-sizing: border-box;">
                        <input type="number" id="oref-weight" placeholder="权重 (--ow)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db; box-sizing: border-box;">
                    </div>
                    <button id="oref-add" class="action-button" 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 class="panel-section" 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; box-sizing: border-box;">
                        <input type="number" id="direct-image-weight" placeholder="权重 (--iw)" style="flex:1; padding:6px; border-radius:6px; border:1px solid #d1d5db; box-sizing: border-box;">
                    </div>
                    <button id="direct-image-add" class="action-button" 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 class="panel-section" 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; box-sizing: border-box;">
                            </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; box-sizing: border-box;">
                            </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" max="4" step="1" value="2" 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 class="btn-group" 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; resize: vertical;"></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; resize: vertical;"></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; resize: vertical;" readonly></textarea>
                    </div>
                </div>
            </div>
            <div style="margin-top:16px; display:flex; gap:10px;">
                <button id="copy-btn" class="action-button-primary" style="flex:1; padding:8px; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">拷贝参数</button>
                <button id="clear-btn" class="action-button-secondary" style="flex:1; padding:8px; 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: '' }
            // 尺寸预设按钮的激活状态由 ratioSlider 的 input 事件处理
        ];
buttonGroups.forEach(group => {
            const buttons = document.querySelectorAll(`.${group.className}`);
            let currentParamValue = params[group.param] === undefined ? group.defaultValue : params[group.param];
buttons.forEach(btn => {
                const isActive = btn.dataset.value === currentParamValue;
                btn.classList.toggle('active', isActive);
                if (isActive) {
                    btn.style.backgroundColor = isDarkMode ? '#5865F2' : '#4f46e5'; // 深色紫 / 浅色靛蓝
                    btn.style.color = 'white';
                    btn.style.borderColor = isDarkMode ? '#5865F2' : '#4f46e5';
                } else {
                    btn.style.backgroundColor = isDarkMode ? '#40444B' : 'white'; // 深色灰 / 浅色白
                    btn.style.color = isDarkMode ? '#DCDDDE' : '#374151'; // 深色浅灰 / 浅色深灰
                    btn.style.borderColor = isDarkMode ? '#2D2F34' : '#D1D5DB'; // 深色更深灰 / 浅色浅灰
                }
            });
        });
    }
// 更新拨动开关的视觉样式
    function updateToggleVisuals(switchId, property) {
        const switchEl = document.getElementById(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'; // 深色灰 / 浅色更浅灰
        }
    }
// 设置参考图片/代码区域 (cref, sref, oref, directImages)
    const setupRefSection = (idPrefix, paramKey) => { // idPrefix 用于HTML元素ID, paramKey 用于 params 对象的键名
        const $ = id => document.getElementById(id);
        const addBtn = $(`${idPrefix}-add`);
        const urlInput = $(`${idPrefix}-url`);
        const weightInput = $(`${idPrefix}-weight`);
        const previewContainerId = `${idPrefix}-preview`;
if (!addBtn || !urlInput || !weightInput) {
            // console.error(`初始化 ${idPrefix} 区域失败:缺少元素。请确保HTML中的ID匹配: ${idPrefix}-add, ${idPrefix}-url, ${idPrefix}-weight`);
            return;
        }
addBtn.onclick = () => {
            const url = urlInput.value.trim();
            const weight = weightInput.value.trim();
let toastMessage = `请输入${paramKey === 'sref' ? 'URL或代码' : 'URL'}`;
            if (!url) {
                showToast(toastMessage);
                return;
            }
// 验证URL是否为有效的图片格式
            const isImageUrl = /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url);
            // 验证sref是否为数字代码或 'random'
            const isSrefCode = paramKey === 'sref' && (/^\d+$/.test(url) || url.toLowerCase() === 'random');
if (paramKey !== 'sref' && !isImageUrl) {
                showToast('请输入有效的图片URL');
                return;
            }
            if (paramKey === 'sref' && !isImageUrl && !isSrefCode) {
                showToast("sref请输入有效图片URL, 'random'或数字代码");
                return;
            }
const targetArray = params[paramKey]; // 使用 paramKey 访问 params 中的对应数组
            if (!Array.isArray(targetArray)) {
                // console.error(`params.${paramKey} 不是一个数组。`);
                return;
            }
const itemUrl = (paramKey === 'sref' && isSrefCode) ? (url.toLowerCase() === 'random' ? 'random' : url) : url;
if (!targetArray.some(item => item.url === itemUrl)) { // 避免重复添加
                targetArray.push({ url: itemUrl, weight });
                const currentWeightPrefix = weightPrefixes[paramKey]; // 使用 paramKey 获取对应的权重前缀
if (paramKey === 'sref' && isSrefCode) { // 如果是 sref 代码
                    addPreviewSrefCode(previewContainerId, itemUrl, weight);
                } else { // 如果是图片URL
                    addPreviewImage(previewContainerId, itemUrl, weight, paramKey, currentWeightPrefix);
                }
                urlInput.value = ''; // 清空输入框
                weightInput.value = ''; // 清空权重输入框
                updatePromptParams(); // 更新最终参数显示
            } else {
                showToast(`该${(paramKey === 'sref' && isSrefCode) ? '代码' : 'URL'}已添加`);
            }
        };
    };
// 绑定控制面板中的各种事件
    function bindControlEvents() {
        const $ = id => document.getElementById(id);
        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 panelSections = panel.querySelectorAll('.panel-section'); // 所有区块背景
            const btnGroups = panel.querySelectorAll('.btn-group'); // 按钮组
            const labels = panel.querySelectorAll('label, p, h3, span'); // 所有文本元素
            const divider = panel.querySelector('div[style*="height:1px; background"]'); // 分割线
            const ratioBox = $('ratio-box'); // 比例预览框
            const ratioPreviewBg = $('ratio-preview-bg'); // 比例预览背景虚线框

            // 特定按钮
            const copyButton = $('copy-btn');
            const clearButton = $('clear-btn');
            const refAddButtons = panel.querySelectorAll('#cref-add, #sref-add, #oref-add, #direct-image-add');


if (isDarkMode) { // ------------------ 深色模式 ------------------
                panel.style.backgroundColor = '#2B2D31'; // Discord 深灰色背景
                panel.style.color = '#DCDDDE';           // Discord 浅灰色文本
                panel.style.borderColor = '#202225';     // Discord 更深边框
                if (divider) divider.style.background = '#40444B'; // 分割线颜色

labels.forEach(label => label.style.color = '#DCDDDE');
                themeToggleButton.innerHTML = sunIcon; // 切换为太阳图标
                themeToggleButton.style.color = '#DCDDDE';

inputsAndTextareas.forEach(input => {
                    input.style.backgroundColor = '#202225'; // 输入框背景
                    input.style.color = '#DCDDDE';           // 输入框文本颜色
                    input.style.borderColor = '#18191C';     // 输入框边框颜色
                    if (input.placeholder) input.classList.add('dark-placeholder'); else input.classList.remove('dark-placeholder');
                    if (input.type === 'range') {
                         input.style.setProperty('--thumb-bg', '#DCDDDE'); // 滑块颜色
                         input.style.setProperty('--track-bg', '#40444B');  // 滑道颜色
                    }
                });
panelSections.forEach(el => el.style.backgroundColor = '#202225'); // 区块背景
btnGroups.forEach(el => {
                    el.style.borderColor = '#40444B'; // 按钮组边框
                    el.querySelectorAll('button:not(:last-child)').forEach(b => b.style.borderRightColor = '#40444B'); // 按钮组内分割线
                });

                if (ratioBox) {
                    ratioBox.style.background = '#40444B';
                    ratioBox.style.color = '#DCDDDE';
                    ratioBox.style.borderColor = '#70747A';
                }
                if(ratioPreviewBg) ratioPreviewBg.style.borderColor = '#40444B'; // 比例预览虚线框

                // 特定按钮的深色模式样式
                if (copyButton) {
                    copyButton.style.backgroundColor = '#5865F2'; // 主要操作按钮颜色 (Discord 紫)
                    copyButton.style.color = 'white';
                    copyButton.style.border = '1px solid #5865F2';
                }
                if (clearButton) {
                    clearButton.style.backgroundColor = '#40444B'; // 次要操作按钮颜色
                    clearButton.style.color = '#DCDDDE';
                    clearButton.style.border = '1px solid #2D2F34';
                }
                refAddButtons.forEach(btn => {
                    btn.style.backgroundColor = '#5865F2'; // 添加按钮颜色
                    btn.style.color = 'white';
                    btn.style.border = '1px solid #5865F2';
                });

// 为其他按钮(非特殊处理的)应用深色模式样式
allButtons.forEach(btn => {
                    if (btn === copyButton || btn === clearButton || btn.id.startsWith('theme-toggle') || Array.from(refAddButtons).includes(btn)) return;

                    if (!btn.classList.contains('active')) { // 非激活按钮
                        btn.style.backgroundColor = '#40444B';
                        btn.style.color = '#DCDDDE';
                        btn.style.borderColor = btn.closest('.btn-group') ? 'transparent' : '#2D2F34'; // 按钮组内按钮通常无独立边框
                    } else { // 激活按钮 (如速度、模式、可见性、尺寸预设中的激活项)
                        btn.style.backgroundColor = '#5865F2';
                        btn.style.color = 'white';
                        btn.style.borderColor = btn.closest('.btn-group') ? 'transparent' : '#5865F2';
                    }
                });

} else { // ------------------ 浅色模式 ------------------
                panel.style.backgroundColor = 'white';
                panel.style.color = '#111827';           // 深色文本
                panel.style.borderColor = '#E0E0E0';     // 浅灰色边框 (比 D1D5DB 稍柔和)
                if (divider) divider.style.background = '#E5E7EB';

labels.forEach(label => label.style.color = '#1F2937'); // 文本颜色调整为更深的灰色,提高对比度
                themeToggleButton.innerHTML = moonIcon; // 切换为月亮图标
                themeToggleButton.style.color = '#6B7280'; // 图标颜色

inputsAndTextareas.forEach(input => {
                    input.style.backgroundColor = 'white';
                    input.style.color = '#111827';
                    input.style.borderColor = '#D1D5DB'; // 标准浅色边框
                    if (input.placeholder) input.classList.remove('dark-placeholder');
                     if (input.type === 'range') { // 移除深色模式的自定义属性,恢复到 injectStyles 中的默认浅色样式
                         input.style.removeProperty('--thumb-bg');
                         input.style.removeProperty('--track-bg');
                    }
                });
panelSections.forEach(el => el.style.backgroundColor = '#F9FAFB'); // 区块背景用非常浅的灰色
btnGroups.forEach(el => {
                    el.style.borderColor = '#D1D5DB'; // 按钮组边框
                    el.querySelectorAll('button:not(:last-child)').forEach(b => b.style.borderRightColor = '#D1D5DB'); // 按钮组内分割线
                });

                if (ratioBox) {
                    ratioBox.style.background = '#F3F4F6';    // 预览框背景
                    ratioBox.style.color = '#374151';      // 预览框文字颜色
                    ratioBox.style.borderColor = '#6B7280'; // 预览框边框颜色 (中度灰色,更清晰)
                }
                if(ratioPreviewBg) ratioPreviewBg.style.borderColor = '#CBD5E1'; // 比例预览虚线框 (更清晰的浅灰)

                // 特定按钮的浅色模式样式
                if (copyButton) {
                    copyButton.style.backgroundColor = '#4f46e5'; // 主要操作按钮颜色 (靛蓝)
                    copyButton.style.color = 'white';
                    copyButton.style.border = '1px solid #4f46e5';
                }
                if (clearButton) {
                    clearButton.style.backgroundColor = '#E5E7EB'; // 次要操作按钮背景 (浅灰)
                    clearButton.style.color = '#374151';           // 次要操作按钮文字 (深灰)
                    clearButton.style.border = '1px solid #D1D5DB';
                }
                 refAddButtons.forEach(btn => {
                    btn.style.backgroundColor = '#4f46e5'; // 添加按钮颜色
                    btn.style.color = 'white';
                    btn.style.border = '1px solid #4f46e5';
                });

// 为其他按钮(非特殊处理的)应用浅色模式样式
allButtons.forEach(btn => {
                    if (btn === copyButton || btn === clearButton || btn.id.startsWith('theme-toggle') || Array.from(refAddButtons).includes(btn)) return;

                    if (!btn.classList.contains('active')) { // 非激活按钮
                        btn.style.backgroundColor = 'white';
                        btn.style.color = '#374151'; // 文字颜色改为深灰
                        btn.style.borderColor = btn.closest('.btn-group') ? 'transparent' : '#D1D5DB';
                    } else { // 激活按钮
                        btn.style.backgroundColor = '#4f46e5';
                        btn.style.color = 'white';
                        btn.style.borderColor = btn.closest('.btn-group') ? 'transparent' : '#4f46e5';
                    }
                 });
            }
            setInitialActiveButtons(); // 根据新主题刷新所有按钮组的激活状态和样式
            updateToggleVisuals('tile-toggle-switch', 'tile'); // 更新 "重复图案" 开关样式
            updateToggleVisuals('draft-toggle-switch', 'draft'); // 更新 "草稿" 开关样式
            refreshPreviews(); // 刷新所有参考图预览的样式
        });
// 绑定主要提示词输入事件
        if ($('main-prompt')) {
            $('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('stop-slider', 'stop', 'stop-value');
        bindSliderEvent('r-slider', 'r', 'r-value');
// 特殊处理质量滑块 (quality),因为它的值不是连续的
        const qualitySlider = $('quality-slider');
        const qualityValueDisplay = $('quality-value');
        const qualityMap = [0.25, 0.5, 1, 2, 4]; // 质量滑块对应的实际值
if (qualitySlider && qualityValueDisplay) {
            const initialQualityValue = params.quality;
            const initialSliderIndex = qualityMap.indexOf(initialQualityValue);
if (initialSliderIndex !== -1) { // 如果初始值在映射中
                qualitySlider.value = initialSliderIndex;
                qualityValueDisplay.textContent = initialQualityValue;
            } else { // 默认值处理
                params.quality = 1; // 重置为默认值
                qualitySlider.value = qualityMap.indexOf(1); // 滑块也重置
                qualityValueDisplay.textContent = params.quality;
            }
qualitySlider.oninput = e => {
                const sliderIndex = parseInt(e.target.value, 10);
                if (sliderIndex >= 0 && sliderIndex < qualityMap.length) {
                    params.quality = qualityMap[sliderIndex];
                    if (qualityValueDisplay) qualityValueDisplay.textContent = params.quality;
                    updatePromptParams();
                }
            };
        }
// 辅助函数:绑定单选按钮组事件 (如速度、模式、可见性)
        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' : '#374151';
                        b.style.borderColor = isDarkMode ? (b.closest('.btn-group > div > button') ? '#2D2F34' : 'transparent') : (b.closest('.btn-group > div > button') ? '#D1D5DB' : 'transparent');
                         // 对于非按钮组内的独立按钮组(如可见性按钮),它们有自己的边框
                        if (!b.closest('.btn-group')) {
                           b.style.borderColor = isDarkMode ? '#2D2F34' : '#D1D5DB';
                        }
                    });
                    // 设置当前点击按钮的激活状态和样式
                    btn.classList.add('active');
                    btn.style.backgroundColor = isDarkMode ? '#5865F2' : '#4f46e5';
                    btn.style.color = 'white';
                    btn.style.borderColor = isDarkMode ? (btn.closest('.btn-group > div > button') ? '#5865F2' : 'transparent') : (btn.closest('.btn-group > div > button') ? '#4f46e5' : 'transparent');
                     if (!btn.closest('.btn-group')) {
                           btn.style.borderColor = isDarkMode ? '#5865F2' : '#4f46e5';
                     }

                    params[property] = btn.dataset.value;
                    updatePromptParams();
                });
            });
        };
bindRadioGroup('speed-btn', 'speed', 'relax');
        bindRadioGroup('mode-btn', 'mode', 'standard');
        bindRadioGroup('visibility-btn', 'visibility', '');
// 辅助函数:绑定拨动开关的事件 (仅处理逻辑,视觉更新由 updateToggleVisuals 完成)
        const bindToggleSwitchEvent = (switchId, property) => {
            const switchEl = $(switchId);
            if (!switchEl) return;
            switchEl.addEventListener('click', () => {
                params[property] = !params[property];
                updateToggleVisuals(switchId, property); // 调用视觉更新函数
                updatePromptParams();
            });
        };
bindToggleSwitchEvent('tile-toggle-switch', 'tile');
        bindToggleSwitchEvent('draft-toggle-switch', 'draft');
// 初始化时设置拨动开关的视觉状态
        updateToggleVisuals('tile-toggle-switch', 'tile');
        updateToggleVisuals('draft-toggle-switch', 'draft');
// 绑定版本选择下拉框事件
        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 || !textarea.value) {
                    showToast('没有参数可以拷贝');
                    return;
                }
                textarea.select(); // 选中内容
                try {
                    // 优先使用现代的 Clipboard API
                    if (navigator.clipboard && navigator.clipboard.writeText) {
                        navigator.clipboard.writeText(textarea.value).then(() => {
                            showToast('参数已复制!');
                        }).catch(err => {
                            showToast('复制失败!请尝试手动复制。');
                            console.error('异步复制失败:', err);
                            // 如果 Clipboard API 失败 (例如非安全上下文),尝试旧方法
                            legacyCopy(textarea);
                        });
                    } else {
                       legacyCopy(textarea); // 回退到旧方法
                    }
                } catch (err) { // 捕获 legacyCopy 中同步 execCommand 可能的错误
                    // legacyCopy 内部会显示自己的 toast,这里主要记录错误
                    console.error('外层复制尝试失败:', err);
                }
            };
        }

        // 辅助函数:用于旧版浏览器的复制操作
        function legacyCopy(textareaElement) {
            textareaElement.select();
            try {
                const successful = document.execCommand('copy');
                if (successful) {
                    showToast('参数已复制 (兼容模式)!');
                } else {
                    showToast('复制失败 (兼容模式)!请手动复制。');
                }
            } catch (err) {
                showToast('复制异常 (兼容模式)!请手动复制。');
                console.error('兼容模式复制失败:', err);
            }
        }

// 图片尺寸预设值和滑块映射
const sizeMap = ['1:2', '9:16', '2:3', '3:4', '5:6', '1:1', '6:5', '4:3', '3:2', '16:9', '2:1'];
// 绑定清空参数按钮事件
        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; // 5 对应 '1:1'
                    $('ratio-slider').dispatchEvent(new Event('input')); // 触发input事件来更新预览和按钮
                }
// 清空所有参考图URL和权重输入框
                ['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') && qualityMap) { // 重置质量滑块
                    const resetSliderIndex = qualityMap.indexOf(params.quality); // params.quality 此时是 1
                    $('quality-slider').value = resetSliderIndex !== -1 ? resetSliderIndex : qualityMap.indexOf(1);
                }
                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;

                // 重新应用主题相关的视觉样式
                updateToggleVisuals('tile-toggle-switch', 'tile');
                updateToggleVisuals('draft-toggle-switch', 'draft');
setInitialActiveButtons(); // 重置按钮组的激活状态和样式
                refreshPreviews(); // 清空并刷新参考图预览区
                updatePromptParams(); // 更新最终参数显示
                showToast('所有参数已重置为默认值');
            };
        }
// 初始化各个参考图/代码区域
        setupRefSection('cref', 'cref');
        setupRefSection('sref', 'sref');
        setupRefSection('oref', 'oref');
        setupRefSection('direct-image', 'directImages'); // idPrefix 是 'direct-image', paramKey 是 'directImages'
// 比例预设值对应的预览框尺寸
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;
                }
// 更新尺寸预设按钮的激活状态
                document.querySelectorAll('#size-buttons button').forEach(btn => {
                    const btnRatio = btn.dataset.value; // 获取按钮代表的比例
                    const isActive = btnRatio === ratio;
                    btn.classList.toggle('active', isActive);
                    // 根据主题和激活状态设置样式 (与 setInitialActiveButtons 逻辑类似)
                    if (isActive) {
                        btn.style.backgroundColor = isDarkMode ? '#5865F2' :'#4f46e5';
                        btn.style.color = 'white';
                        btn.style.borderColor = isDarkMode ? '#5865F2' : '#4f46e5';
                    } else {
                        btn.style.backgroundColor = isDarkMode ? '#40444B' : 'white';
                        btn.style.color = isDarkMode ? '#DCDDDE' : '#374151';
                        btn.style.borderColor = isDarkMode ? '#2D2F34' : '#D1D5DB';
                    }
                });
                updatePromptParams(); // 更新最终参数显示
            };
            // 初始化滑块值 (在按钮创建和主题应用之后再触发首次事件)
        }
// 创建尺寸预设按钮 (纵向, 正方形, 横向)
const sizeButtonGroup = $('size-buttons');
        if (sizeButtonGroup) {
            const presetMap = { '纵向': '1:2', '正方形': '1:1', '横向': '2:1' };
            ['纵向', '正方形', '横向'].forEach((label) => {
                const btn = document.createElement('button');
                btn.textContent = label;
                btn.dataset.value = presetMap[label]; // 将比例值存储在 dataset 中

                // 初始化按钮样式 (后续由主题切换或滑块事件更新)
                btn.style.padding = '4px 12px';
                btn.style.borderRadius = '6px';
                btn.style.cursor = 'pointer';
                btn.style.transition = 'all 0.2s ease';
                // 初始样式基于浅色模式非激活状态
                btn.style.backgroundColor = 'white';
                btn.style.color = '#374151';
                btn.style.borderColor = '#D1D5DB';

                // 如果当前参数的ar值与此按钮匹配,则设为激活 (初始加载时)
                if (params.ar === presetMap[label]) {
                    btn.classList.add('active');
                    // 激活样式会在后续 themeToggleButton 点击或 setInitialActiveButtons 中正确设置
                }

btn.onclick = () => { // 点击预设按钮时,更新滑块并触发其input事件
                    const ratio = presetMap[label];
                    const sliderIndex = sizeMap.indexOf(ratio);
                    if (sliderIndex !== -1 && ratioSlider) {
                        ratioSlider.value = sliderIndex;
                        ratioSlider.dispatchEvent(new Event('input')); // 触发滑块事件以统一更新
                    }
                };
                sizeButtonGroup.appendChild(btn);
            });
        }
// 绑定种子数输入事件,带验证
        if ($('seed-input')) {
            $('seed-input').oninput = e => {
                const value = e.target.value.trim();
                // 验证输入是否为数字,且在0到4294967295之间,或为空
                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', () => {
                if (!promptParamsTextarea.value) {
                    showToast('没有参数可以拷贝');
                    return;
                }
                // 复用拷贝按钮的逻辑
                if (navigator.clipboard && navigator.clipboard.writeText) {
                    navigator.clipboard.writeText(promptParamsTextarea.value).then(() => {
                        showToast('参数已复制!');
                    }).catch(err => {
                        showToast('复制失败!请尝试手动复制。');
                        console.error('从文本框异步复制失败:', err);
                        legacyCopy(promptParamsTextarea); // 回退
                    });
                } else {
                   legacyCopy(promptParamsTextarea); // 旧版浏览器
                }
            });
        }
// 为所有输入控件添加焦点和失焦时的边框样式变化
document.querySelectorAll('input[type="text"], input[type="number"], textarea, select').forEach(el => {
            el.addEventListener('focus', () => {
                // 焦点颜色:深色模式用Discord紫色强调,浅色模式用主题靛蓝强调
                el.style.borderColor = isDarkMode ? '#7289DA' : '#4f46e5';
            });
            el.addEventListener('blur', () => {
                // 失焦时恢复到当前主题的标准边框颜色
                el.style.borderColor = isDarkMode ? '#18191C' : '#D1D5DB';
            });
        });
// 为面板内的按钮添加更细致的悬停效果 (不包括主题切换按钮和已激活的按钮组内按钮)
document.querySelectorAll('#mj-control-panel button').forEach(btn => {
    let originalBg, originalColor, originalBorder; // 用于存储原始样式以便恢复

btn.addEventListener('mouseenter', () => {
        // 排除主题切换按钮、已激活按钮、按钮组内的非激活按钮(它们通常没有独立边框或特殊背景)
        if (btn.id === 'theme-toggle' || btn.classList.contains('active') || btn.closest('.btn-group button:not(.active)')) {
            return;
        }
originalBg = btn.style.backgroundColor;
        originalColor = btn.style.color;
        originalBorder = btn.style.borderColor;

        // 特殊按钮(拷贝、清空、添加)的悬停效果
        const isPrimaryAction = btn.classList.contains('action-button-primary') || btn.id.endsWith('-add');
        const isSecondaryAction = btn.classList.contains('action-button-secondary');

        if (isPrimaryAction) {
            btn.style.backgroundColor = isDarkMode ? '#4752C4' : '#4338CA'; // 深色主题用更深的紫,浅色主题用更深的靛蓝
        } else if (isSecondaryAction) {
            btn.style.backgroundColor = isDarkMode ? '#4F545C' : '#D1D5DB'; // 深色主题用中度灰,浅色主题用更深的浅灰
        } else if (!btn.closest('.btn-group')) { // 普通按钮(非按钮组内),例如可见性按钮
            btn.style.backgroundColor = isDarkMode ? '#4F545C' : '#F3F4F6'; // 深色用中灰,浅色用极浅灰
        }
        // 通用悬停效果:轻微上移和阴影
        if(!btn.closest('.btn-group button')) { // 按钮组内的按钮通常不需要额外阴影和位移
           btn.style.transform = 'translateY(-1px)';
           btn.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
        }
    });
btn.addEventListener('mouseleave', () => {
        if (btn.id === 'theme-toggle' || btn.classList.contains('active') || btn.closest('.btn-group button:not(.active)')) {
            return;
        }
        // 恢复原始样式,除非它们是特殊按钮且未激活
        const isPrimaryAction = btn.classList.contains('action-button-primary') || btn.id.endsWith('-add');
        const isSecondaryAction = btn.classList.contains('action-button-secondary');

        if ( (isPrimaryAction || isSecondaryAction || !btn.closest('.btn-group')) && !btn.classList.contains('active')) {
            btn.style.backgroundColor = originalBg;
            btn.style.color = originalColor;
            btn.style.borderColor = originalBorder;
        }
        if(!btn.closest('.btn-group button')) {
            btn.style.transform = 'translateY(0)';
            btn.style.boxShadow = 'none';
        }
    });
});
// 确保ratioSlider在按钮和主题应用后初始化其显示
        if (ratioSlider) {
            const initialRatioIndex = sizeMap.indexOf(params.ar);
            ratioSlider.value = initialRatioIndex !== -1 ? initialRatioIndex : 5;
            ratioSlider.dispatchEvent(new Event('input')); // 现在触发,确保UI已准备好
        }

        // 首次加载时,根据 isDarkMode 的初始值(默认为 false)应用一次主题
        // 通过模拟点击主题切换按钮,然后再切换回来,确保所有样式基于初始状态正确应用
        // 这是一个确保初始样式正确的技巧
        const initialThemeState = isDarkMode;
isDarkMode = !initialThemeState; // 临时反转
        themeToggleButton.click();       // 应用反转后的主题,并使 isDarkMode 变回 initialThemeState
                                         // 此时 isDarkMode 是 initialThemeState,且对应样式已应用
    }
// 添加图片预览到容器
function addPreviewImage(containerId, url, weight, paramKey, currentWeightPrefix) { // paramKey 用于删除操作时定位参数数组
        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.cssText = `
            width: 60px; height: 60px; object-fit: cover; border-radius: 4px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
            border: 1px solid ${isDarkMode ? '#40444B' : '#E5E7EB'}; /* 根据主题调整边框 */
            transition: all 0.2s ease;
        `;
img.onerror = () => { // 图片加载失败处理
            const errorDiv = document.createElement('div');
            errorDiv.textContent = '无效图';
            errorDiv.style.cssText = `width:60px; height:60px; display:flex; align-items:center; justify-content:center; border-radius:4px; font-size:10px; text-align:center;`;
            if(isDarkMode) {
                errorDiv.style.background = '#40444B'; // 深色背景
                errorDiv.style.color = '#aaa';        // 浅色文字
                errorDiv.style.border = '1px solid #555';
            } else {
                errorDiv.style.background = '#F3F4F6'; // 浅色背景
                errorDiv.style.color = '#757575';      // 深色文字
                errorDiv.style.border = '1px solid #E5E7EB';
            }
            imgContainer.innerHTML = ''; // 清空原内容 (可能是img标签)
            imgContainer.appendChild(errorDiv);
        };
img.addEventListener('mouseenter', () => { img.style.transform = 'scale(1.05)'; img.style.boxShadow = `0 2px 6px ${isDarkMode ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.15)'}`; });
        img.addEventListener('mouseleave', () => { img.style.transform = 'scale(1)'; img.style.boxShadow = `0 1px 3px ${isDarkMode ? 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.1)'}`; });
// 权重徽章
const weightBadge = document.createElement('div');
        weightBadge.style.cssText = `
            position: absolute; bottom: 0; left: 0;
            background: ${isDarkMode ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.8)'};
            color: ${isDarkMode ? 'white' : '#374151'};
            font-size: 10px; padding: 1px 3px; border-radius: 0 4px 0 0;
            border-top: 1px solid ${isDarkMode ? '#5865F2' : '#4f46e5'}; /* 强调边框 */
            border-right: 1px solid ${isDarkMode ? '#5865F2' : '#4f46e5'};
        `;
        const wP = currentWeightPrefix ? currentWeightPrefix.replace('--', '') : ''; // 简化权重前缀显示
        weightBadge.textContent = weight && weight.trim() !== '' ? `${wP}:${weight}` : `${wP}:默认`;
// 删除按钮
const deleteBtn = document.createElement('button');
        deleteBtn.style.cssText = `
            position: absolute; top: -5px; right: -5px;
            background: ${isDarkMode ? 'rgba(239, 68, 68, 0.7)' : 'rgba(239, 68, 68, 0.85)'}; /* 轻微调整透明度 */
            color: white; border: none; border-radius: 50%;
            width: 18px; height: 18px; font-size: 12px; line-height: 18px; /* 增大一点方便点击 */
            text-align:center; cursor:pointer; transition:all 0.2s ease; opacity: 0.8;
            display:flex; align-items:center; justify-content:center;
            box-shadow: 0 1px 2px rgba(0,0,0,0.2);
        `;
        deleteBtn.innerHTML = '&times;'; // 关闭图标
        deleteBtn.onclick = function(e) { // 点击删除
            e.stopPropagation(); // 阻止事件冒泡
            imgContainer.style.animation = 'fadeOut 0.2s ease forwards'; // 播放淡出动画
            setTimeout(() => {
                const targetArray = params[paramKey]; // 根据 paramKey 获取正确的参数数组
                if (Array.isArray(targetArray)) {
                    const index = targetArray.findIndex(item => item.url === url); // 找到要删除的项
                    if (index !== -1) {
                        targetArray.splice(index, 1); // 从数组中移除
                        if (container.contains(imgContainer)) container.removeChild(imgContainer); // 从DOM中移除
                        updatePromptParams(); // 更新最终参数显示
                    }
                }
            }, 200); // 等待动画完成
        };
        deleteBtn.addEventListener('mouseenter', () => { deleteBtn.style.opacity = '1'; deleteBtn.style.transform = 'scale(1.1)'; deleteBtn.style.background = isDarkMode ? 'rgb(239, 68, 68)' : 'rgb(220, 38, 38)'; });
        deleteBtn.addEventListener('mouseleave', () => { deleteBtn.style.opacity = '0.8'; deleteBtn.style.transform = 'scale(1)'; deleteBtn.style.background = isDarkMode ? 'rgba(239, 68, 68, 0.7)' : 'rgba(239, 68, 68, 0.85)';});
imgContainer.appendChild(img);
        imgContainer.appendChild(weightBadge);
        imgContainer.appendChild(deleteBtn);
        container.appendChild(imgContainer);
    }
// 添加Sref代码预览到容器
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; border-radius: 4px; padding: 6px 10px;
            display: inline-flex; align-items: center; /* 改为 inline-flex 使其内容包裹 */
            font-family: monospace; font-size: 12px; animation: fadeIn 0.3s ease;
            transition: background-color 0.2s, border-color 0.2s, color 0.2s; /* 平滑过渡 */
        `;
        // 根据主题设置样式
        if (isDarkMode) {
             codeContainer.style.background = '#202225'; // 深色背景
             codeContainer.style.color = '#DCDDDE';      // 浅色文字
             codeContainer.style.border = '1px solid #2D2F34'; // 深色边框
        } else {
             codeContainer.style.background = '#F3F4F6'; // 浅色背景
             codeContainer.style.color = '#111827';      // 深色文字
             codeContainer.style.border = '1px solid #E0E0E0'; // 浅色边框
        }
const codeText = document.createElement('span');
        codeText.textContent = `sref:${code}`;
// 权重徽章
const weightBadge = document.createElement('div');
        weightBadge.style.cssText = 'margin-left: 8px; font-size: 10px; padding: 2px 4px; border-radius: 3px; transition: background-color 0.2s, color 0.2s;';
        weightBadge.textContent = weight && weight.trim() !== '' ? `sw:${weight}` : 'sw:默认';
        if (isDarkMode) {
            weightBadge.style.background = 'rgba(88, 101, 242, 0.3)'; // 深色主题强调色背景
            weightBadge.style.color = '#B9BBBE';                     // 深色主题强调色文字
        } else {
            weightBadge.style.background = 'rgba(79, 70, 229, 0.1)';  // 浅色主题强调色背景
            weightBadge.style.color = '#4f46e5';                      // 浅色主题强调色文字
        }
// 删除按钮
const deleteBtn = document.createElement('button');
        deleteBtn.style.cssText = 'margin-left: 10px; border: none; border-radius: 4px; padding: 2px 5px; font-size: 10px; line-height:1; cursor:pointer; transition:all 0.2s ease;';
        if (isDarkMode) {
            deleteBtn.style.background = 'rgba(239, 68, 68, 0.3)'; // 深色主题删除按钮背景
            deleteBtn.style.color = '#FAA';                     // 深色主题删除按钮文字
        } else {
            deleteBtn.style.background = 'rgba(239, 68, 68, 0.1)'; // 浅色主题删除按钮背景
            deleteBtn.style.color = '#ef4444';                     // 浅色主题删除按钮文字
        }
        deleteBtn.innerHTML = '&times;';
deleteBtn.onclick = function(e) { // 点击删除
            e.stopPropagation();
            codeContainer.style.animation = 'fadeOut 0.2s ease forwards';
            setTimeout(() => {
                const index = params.sref.findIndex(item => item.url === code); // sref是特定的,直接用
                if (index !== -1) {
                    params.sref.splice(index, 1);
                    if (container.contains(codeContainer)) container.removeChild(codeContainer);
                    updatePromptParams();
                }
            }, 200);
        };
// 删除按钮的悬停效果
        const originalDeleteBg = deleteBtn.style.backgroundColor; // 保存原始背景色
        deleteBtn.addEventListener('mouseenter', () => {
            deleteBtn.style.backgroundColor = isDarkMode ? 'rgba(239, 68, 68, 0.5)' : 'rgba(239, 68, 68, 0.25)';
        });
        deleteBtn.addEventListener('mouseleave', () => { deleteBtn.style.backgroundColor = originalDeleteBg; });
codeContainer.appendChild(codeText);
        codeContainer.appendChild(weightBadge);
        codeContainer.appendChild(deleteBtn);
        container.appendChild(codeContainer);
    }
// 刷新所有参考图片/代码的预览区域
function refreshPreviews() {
        // paramKey 对应 params 对象中的键名和 weightPrefixes 映射的键名
        const refTypes = [
            { idPrefix: 'cref', paramKey: 'cref', previewId: 'cref-preview' },
            { idPrefix: 'sref', paramKey: 'sref', previewId: 'sref-preview' },
            { idPrefix: 'oref', paramKey: 'oref', previewId: 'oref-preview' },
            { idPrefix: 'direct-image', paramKey: 'directImages', previewId: 'direct-image-preview' }
        ];
refTypes.forEach(ref => {
            const container = document.getElementById(ref.previewId);
            if (!container) return;
            container.innerHTML = ''; // 清除现有预览内容
const items = params[ref.paramKey]; // 获取对应的参数数组
            if (items && Array.isArray(items)) {
                items.forEach(item => {
                    const currentWeightPrefix = weightPrefixes[ref.paramKey]; // 获取权重前缀
                    // 如果是 sref 且为 'random' 或数字代码
                    if (ref.paramKey === 'sref' && (item.url === 'random' || /^\d+$/.test(item.url))) {
                        addPreviewSrefCode(ref.previewId, item.url, item.weight);
                    } else { // 否则为图片URL
                        addPreviewImage(ref.previewId, item.url, item.weight, ref.paramKey, currentWeightPrefix);
                    }
                });
            }
        });
    }
// 注入自定义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;}

            /* 深色模式滑块轨道和滑块样式 (通过JS设置CSS变量来改变) */
            input[type="range"]:is([style*="--track-bg"])::-webkit-slider-runnable-track { background: var(--track-bg); }
            input[type="range"]:is([style*="--track-bg"])::-moz-range-track { background: var(--track-bg); }
            input[type="range"]:is([style*="--thumb-bg"])::-webkit-slider-thumb { background-color: var(--thumb-bg); border-color: #B0B3B8; /* 深色模式下为滑块使用稍浅的边框 */ }
            input[type="range"]:is([style*="--thumb-bg"])::-moz-range-thumb { background-color: var(--thumb-bg); border-color: #B0B3B8; }

            /* 按钮组内按钮的样式 */
            .btn-group button { border: none; } /* 移除独立边框,由父级 .btn-group 控制整体边框 */
            .btn-group > button:not(:last-child), /* 直接子按钮 */
            .btn-group > div > button:not(:last-child) { /* 兼容 label > div > button 结构 */
                 border-right: 1px solid #d1d5db; /* 浅色模式分隔线,会被JS按主题覆盖 */
            }
            /* 深色模式下按钮组分隔线 - 会被JS按主题覆盖 */
            /* html[data-theme='dark'] .btn-group button:not(:last-child),
            body[style*="background-color: rgb(43, 45, 49)"] .btn-group button:not(:last-child) {
                 border-right-color: #40444B;
            } */

            /* 深色模式下的 placeholder 颜色 */
            .dark-placeholder::placeholder { color: #72767d; opacity: 1; }

            /* 使 textarea 可以垂直调整大小 */
            textarea { resize: vertical; }
        `;
        document.head.appendChild(styleSheet);
// 检查是否已加载 Font Awesome,避免重复加载 (如果其他脚本也用它)
// Font Awesome 在此脚本中似乎并未直接使用其图标类,主要是SVG图标。如果需要,可以取消注释。
        /*
        if (!document.querySelector('link[href*="font-awesome"]')) {
            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'; // 可以考虑使用特定版本或 SRI
            document.head.appendChild(faLink);
        }
        */
    }
// 初始化脚本
function init() {
        injectStyles();    // 注入CSS样式
        resetParams();     // 初始化参数对象为默认值
        createSettingButton(); // 创建“MJ设置”按钮
        createControlPanel();  // 创建控制面板DOM结构并绑定基础事件

        // 控制面板创建后,手动触发一次主题设置,确保初始状态正确显示
        // (bindControlEvents 内部的 themeToggleButton 事件监听器会处理实际的样式切换)
        // `isDarkMode` 默认为 false, 所以第一次点击会应用浅色模式 (如果当前是深色则切换)
        // 再次点击会应用深色模式。我们需要确保初始加载时面板根据 `isDarkMode` 的默认值正确渲染。
        // `bindControlEvents` 末尾的 themeToggleButton.click() 调用会完成这个任务。
        updatePromptParams(); // 初始化时填充一次最终参数文本框
    }
// 等待 Discord 应用挂载后再执行初始化
const discordAppMount = document.getElementById('app-mount');
    if (discordAppMount) {
        // 短暂延迟有时有助于确保 Discord 自身的样式已稳定
        setTimeout(init, 500);
    } else {
        // 如果 app-mount 还未加载,则监听 window load 事件
        window.addEventListener('load', () => setTimeout(init, 500), { once: true });
    }
})();