Greasy Fork

Greasy Fork is available in English.

Discord Midjourney 参数面板

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Discord Midjourney 参数面板
// @namespace    https://github.com/cwser
// @version      0.1.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, weight}
        sref: [],    // 格式: {url, weight}
        oref: [],    // 格式: {url, weight}
        iref: [],
        directImages: [], // 格式: {url, weight}
        // 新增参数
        tile: false,
        seed: '',
        quality: 1,
        stop: 100,
        visibility: '',
        // 新增个性化参数
        personalParams: ''
    };

    // 显示 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(() => 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';
                    panel.style.opacity = '1';
                    panel.style.transform = 'translateY(0)';
                }, 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: ''
        };
    }

    // 更新提示词参数
    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}`,
            stylize !== 0 ? `--s ${stylize}` : '',
            weird !== 0 ? `--w ${weird}` : '',
            chaos !== 0 ? `--c ${chaos}` : '',
            mode !== 'standard' ? `--${mode}` : '',
            draft ? '--draft' : '',
            noPrompt ? `--no ${noPrompt}` : '',
            version.startsWith('niji') ? `--niji ${version.replace('niji', '')}` : `--v ${version.replace('v', '')}`,
            `--${speed}`,
            // 新增参数处理
            tile ? '--tile' : '',
            seed ? `--seed ${seed}` : '',
            quality !== 1 ? `--q ${quality}` : '',
            stop !== 100 ? `--stop ${stop}` : '',
            visibility ? `--${visibility}` : '',
            // 新增个性化参数处理
            personalParams ? `--p ${personalParams}` : ''
        ];

        // 处理带权重的图像参考
        const formatImageWithWeight = (url, weight, prefix) => {
            return weight ? `${url} ${prefix} ${weight}` : url;
        };

        // 直接图像参考不使用参数标识,直接添加到提示词中
        const directImageUrls = directImages.map(item => formatImageWithWeight(item.url, item.weight, '--iw')).join(' ');

        const promptField = document.getElementById('prompt-params');
        if (promptField) {
            // 构建完整提示词:图像参考URL + 主提示词 + --cref/--sref/--oref + 其他参数
            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();
        }
    }

    // 创建控制面板
    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: all 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;">
                    <i class="fa-regular fa-moon"></i>
                </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;">图片尺寸</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 style="flex:1; margin-right:12px;">风格化</label>
                            <input type="range" id="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 style="flex:1; margin-right:12px;">奇特化</label>
                            <input type="range" id="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 style="flex:1; margin-right:12px;">多样性</label>
                            <input type="range" id="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;">草稿
                            <div class="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 style="flex:2;">版本
                            <select id="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="权重" 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" style="flex:3; padding:6px; border-radius:6px; border:1px solid #d1d5db;">
                        <input type="number" id="sref-weight" placeholder="权重" 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="权重" 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;">图像参考</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="权重" 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>种子 --seed</label>
                                <input type="number" id="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>个性化 --p</label>
                                <input type="text" id="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>质量 --q</label>
                                <input type="range" id="quality-slider" min="0" max="4" 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>停止 --stop</label>
                                <input type="range" id="stop-slider" min="10" max="100" step="1" value="100" style="flex:1; margin:0 10px;">
                                <span id="stop-value">100</span>
                            </div>
                        </div>
                    </div>
                    <div style="margin-top:10px;">
                        <p style="margin:0 0 8px 0; font-weight:500;">可见性</p>
                        <div style="display:flex; gap:10px;">
                            <button id="stealth-btn" class="visibility-btn active" style="padding:6px 12px; border:1px solid #d1d5db; border-radius:6px; cursor:pointer; transition:all 0.2s ease;">隐身</button>
                            <button id="public-btn" 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;">排除词</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();
    }

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

    buttonGroups.forEach(group => {
        const buttons = document.querySelectorAll(`.${group.className}`);
        buttons.forEach(btn => {
            if (btn.dataset.value === params[group.param]) {
                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;
        $('theme-toggle').addEventListener('click', () => {
            isDarkMode = !isDarkMode;
            const panel = $('mj-control-panel');
            const buttons = document.querySelectorAll('button:not(.visibility-btn):not(.speed-btn):not(.mode-btn)');
            const inputs = document.querySelectorAll('input, textarea');
            const sliders = document.querySelectorAll('input[type="range"]');
            const toggleSwitches = document.querySelectorAll('.toggle-switch');
            const bgElements = document.querySelectorAll('.btn-group, [style*="background:#f9fafb"]');

            if (isDarkMode) {
                panel.style.backgroundColor = '#2B2D31';
                panel.style.color = '#E4E6EB';
                panel.style.borderColor = '#4E4F52';

                buttons.forEach(btn => {
                    btn.style.backgroundColor = '#4E4F52';
                    btn.style.color = '#E4E6EB';
                });

                inputs.forEach(input => {
                    input.style.backgroundColor = '#1E1F22';
                    input.style.color = '#E4E6EB';
                    input.style.borderColor = '#4E4F52';
                });

                sliders.forEach(slider => {
                    slider.style.filter = 'brightness(0.7)';
                });

                toggleSwitches.forEach(switchEl => {
                    switchEl.style.backgroundColor = '#4E4F52';
                });

                bgElements.forEach(el => {
                    el.style.backgroundColor = '#1E1F22';
                });

                $('theme-toggle').innerHTML = '<i class="fa-regular fa-sun"></i>';
            } else {
                panel.style.backgroundColor = 'white';
                panel.style.color = '#111827';
                panel.style.borderColor = '#E5E7EB';

                buttons.forEach(btn => {
                    btn.style.backgroundColor = '';
                    btn.style.color = '';
                });

                inputs.forEach(input => {
                    input.style.backgroundColor = '';
                    input.style.color = '';
                    input.style.borderColor = '#d1d5db';
                });

                sliders.forEach(slider => {
                    slider.style.filter = '';
                });

                toggleSwitches.forEach(switchEl => {
                    switchEl.style.backgroundColor = '#e5e7eb';
                });

                bgElements.forEach(el => {
                    el.style.backgroundColor = '#f9fafb';
                });

                $('theme-toggle').innerHTML = '<i class="fa-regular fa-moon"></i>';
            }
        });

        // 绑定提示词输入框事件
        $('main-prompt').oninput = e => {
            params.prompt = e.target.value;
            updatePromptParams();
        };

        // 绑定滑块事件
        const bindSliderEvent = (id, property, displayId = null) => {
            $(id).oninput = e => {
                const value = e.target.type === 'range' ? +e.target.value : e.target.value;
                params[property] = value;
                if (displayId) $(displayId).textContent = value;
                updatePromptParams();
            };
        };

        bindSliderEvent('stylize', 'stylize', 'stylize-value');
        bindSliderEvent('weird', 'weird', 'weird-value');
        bindSliderEvent('chaos', 'chaos', 'chaos-value');
        bindSliderEvent('quality-slider', 'quality', 'quality-value');
        bindSliderEvent('stop-slider', 'stop', 'stop-value');

        // 绑定单选按钮组
        const bindRadioGroup = (groupClass, property) => {
            document.querySelectorAll(`.${groupClass}`).forEach(btn => {
                btn.addEventListener('click', () => {
                    // 移除同组其他按钮的active状态
                    document.querySelectorAll(`.${groupClass}`).forEach(b => {
                        b.classList.remove('active');
                        b.style.backgroundColor = 'white';
                        b.style.color = '#111827';
                    });

                    // 添加当前按钮的active状态
                    btn.classList.add('active');
                    btn.style.backgroundColor = '#4f46e5';
                    btn.style.color = 'white';

                    // 更新参数
                    params[property] = btn.dataset.value || btn.id.replace('-btn', '');
                    updatePromptParams();
                });
            });
        };

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

        // 绑定开关切换
        const bindToggleSwitch = (switchId, property) => {
            const switchEl = $(switchId);
            const dot = switchEl.querySelector('.toggle-dot');

            switchEl.addEventListener('click', () => {
                params[property] = !params[property];

                if (params[property]) {
                    dot.style.transform = 'translateX(20px)';
                    switchEl.style.backgroundColor = '#4f46e5';
                } else {
                    dot.style.transform = 'translateX(0)';
                    switchEl.style.backgroundColor = '#e5e7eb';
                }

                updatePromptParams();
            });
        };

        bindToggleSwitch('tile-toggle-switch', 'tile');

        // 绑定草稿开关
        const draftToggle = document.querySelector('.toggle-switch');
        const draftDot = draftToggle.querySelector('.toggle-dot');

        draftToggle.addEventListener('click', () => {
            params.draft = !params.draft;

            if (params.draft) {
                draftDot.style.transform = 'translateX(20px)';
                draftToggle.style.backgroundColor = '#4f46e5';
            } else {
                draftDot.style.transform = 'translateX(0)';
                draftToggle.style.backgroundColor = '#e5e7eb';
            }

            updatePromptParams();
        });

        // 绑定版本选择
        $('version-select').onchange = e => {
            params.version = e.target.value;
            updatePromptParams();
        };

        // 绑定排除词
        $('no-prompt').oninput = e => {
            params.noPrompt = e.target.value.trim();
            updatePromptParams();
        };

        // 绑定复制按钮
        $('copy-btn').onclick = () => {
            const textarea = $('prompt-params');
            textarea.select();
            document.execCommand('copy');
            showToast('参数已复制!');
        };

        // 绑定清空按钮
        $('clear-btn').onclick = () => {
            resetParams();

            // 重置所有控件为默认值
            $('main-prompt').value = '';
            $('stylize').value = 100;
            $('weird').value = 0;
            $('chaos').value = 0;
            $('version-select').value = 'v7';
            $('no-prompt').value = '';
            $('ratio-slider').value = 5;
            $('oref-url').value = '';
            $('direct-image-url').value = '';
            $('cref-weight').value = '';
            $('sref-weight').value = '';
            $('oref-weight').value = '';
            $('direct-image-weight').value = '';

            // 重置新增参数
            $('seed-input').value = '';
            $('quality-slider').value = 1;
            $('quality-value').textContent = '1';
            $('stop-slider').value = 100;
            $('stop-value').textContent = '100';
            // 重置个性化参数
            $('personal-params').value = '';

            // 重置开关状态
            draftDot.style.transform = 'translateX(0)';
            draftToggle.style.backgroundColor = '#e5e7eb';

            const tileDot = document.querySelector('#tile-toggle-switch .toggle-dot');
            tileDot.style.transform = 'translateX(0)';
            document.querySelector('#tile-toggle-switch').style.backgroundColor = '#e5e7eb';

            // 重置按钮组状态
            document.querySelectorAll('.btn-group button').forEach(btn => {
                btn.classList.remove('active');
                btn.style.backgroundColor = 'white';
                btn.style.color = '#111827';
            });

            // 设置默认选中按钮
            document.querySelector('.speed-btn[data-value="relax"]').classList.add('active');
            document.querySelector('.speed-btn[data-value="relax"]').style.backgroundColor = '#4f46e5';
            document.querySelector('.speed-btn[data-value="relax"]').style.color = 'white';

            document.querySelector('.mode-btn[data-value="standard"]').classList.add('active');
            document.querySelector('.mode-btn[data-value="standard"]').style.backgroundColor = '#4f46e5';
            document.querySelector('.mode-btn[data-value="standard"]').style.color = 'white';

            // 移除所有可见性按钮的 active 状态
            document.querySelectorAll('.visibility-btn').forEach(btn => {
                btn.classList.remove('active');
                btn.style.backgroundColor = 'white';
                btn.style.color = '#111827';
            });

            // 设置参数为空
            params.visibility = '';

            // 触发事件以更新UI
            $('main-prompt').dispatchEvent(new Event('input'));
            $('stylize').dispatchEvent(new Event('input'));
            $('weird').dispatchEvent(new Event('input'));
            $('chaos').dispatchEvent(new Event('input'));
            $('version-select').dispatchEvent(new Event('change'));
            $('no-prompt').dispatchEvent(new Event('input'));
            $('ratio-slider').dispatchEvent(new Event('input'));
            $('seed-input').dispatchEvent(new Event('input'));
            $('quality-slider').dispatchEvent(new Event('input'));
            $('stop-slider').dispatchEvent(new Event('input'));
            // 触发个性化参数事件
            $('personal-params').dispatchEvent(new Event('input'));

            // 清空输入框
            $('cref-url').value = '';
            $('sref-url').value = '';

            // 刷新预览
            refreshPreviews();

            // 显示重置成功提示
            showToast('所有参数已重置为默认值');
        };

        // 绑定角色参考事件
        $('cref-add').onclick = () => {
            const url = $('cref-url').value.trim();
            const weight = $('cref-weight').value.trim();
            if (url && /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url)) {
                if (!params.cref.some(item => item.url === url)) {
                    params.cref.push({url, weight});
                    addPreviewImage('cref-preview', url, weight, 'cref', '--cw');
                    $('cref-url').value = '';
                    $('cref-weight').value = '';
                    updatePromptParams();
                } else {
                    showToast('该URL已添加');
                }
            } else {
                showToast('请输入有效图片URL');
            }
        };

        // 绑定风格参考事件
        $('sref-add').onclick = () => {
            const url = $('sref-url').value.trim();
            const weight = $('sref-weight').value.trim();
            if (url && /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url)) {
                if (!params.sref.some(item => item.url === url)) {
                    params.sref.push({url, weight});
                    addPreviewImage('sref-preview', url, weight, 'sref', '--sw');
                    $('sref-url').value = '';
                    $('sref-weight').value = '';
                    updatePromptParams();
                } else {
                    showToast('该URL已添加');
                }
            } else {
                showToast('请输入有效图片URL');
            }
        };

        // 绑定全方位参考事件
        $('oref-add').onclick = () => {
            const url = $('oref-url').value.trim();
            const weight = $('oref-weight').value.trim();
            if (url && /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url)) {
                if (!params.oref.some(item => item.url === url)) {
                    params.oref.push({url, weight});
                    addPreviewImage('oref-preview', url, weight, 'oref', '--ow');
                    $('oref-url').value = '';
                    $('oref-weight').value = '';
                    updatePromptParams();
                } else {
                    showToast('该URL已添加');
                }
            } else {
                showToast('请输入有效图片URL');
            }
        };

        // 绑定直接图像参考事件
        $('direct-image-add').onclick = () => {
            const url = $('direct-image-url').value.trim();
            const weight = $('direct-image-weight').value.trim();
            if (url && /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url)) {
                if (!params.directImages.some(item => item.url === url)) {
                    params.directImages.push({url, weight});
                    addPreviewImage('direct-image-preview', url, weight, 'directImages', '--iw');
                    $('direct-image-url').value = '';
                    $('direct-image-weight').value = '';
                    updatePromptParams();
                } else {
                    showToast('该URL已添加');
                }
            } else {
                showToast('请输入有效图片URL');
            }
        };

        // 绑定比例滑块事件
        const sizeMap = ['1:2', '19:6', '2:3', '3:4', '5:6', '1:1', '6:5', '4:3', '3:2', '6:19', '2:1'];
        const ratioPresets = {
            '1:2': { width: 50, height: 100 },
            '19:6': { 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 },
            '6:19': { width: 100, height: 56.25 },
            '2:1': { width: 100, height: 50 }
        };

        $('ratio-slider').oninput = e => {
            const ratio = sizeMap[+e.target.value] || '1:1';
            params.ar = ratio;
            const box = document.getElementById('ratio-box');
            const preset = ratioPresets[ratio] || { width: 100, height: 100 };
            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 = '#4f46e5';
                    btn.style.color = 'white';
                } else {
                    btn.classList.remove('active');
                    btn.style.backgroundColor = 'white';
                    btn.style.color = '#111827';
                }
            });

            updatePromptParams();
        };

        // 设置比例预设按钮
        const btnGroup = document.getElementById('size-buttons');
        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 (i === 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) {
                    $('ratio-slider').value = sliderIndex;
                    $('ratio-slider').dispatchEvent(new Event('input'));
                }
            };

            btnGroup.appendChild(btn);
        });

        // 绑定种子输入
        $('seed-input').oninput = e => {
            const value = e.target.value.trim();
            if (/^\d*$/.test(value) && (value === '' || (parseInt(value) >= 0 && parseInt(value) <= 4294967295))) {
                params.seed = value;
                updatePromptParams();
            } else {
                e.target.value = params.seed; // 恢复之前的值
            }
        };

        // 绑定个性化参数
        $('personal-params').oninput = e => {
            params.personalParams = e.target.value.trim();
            updatePromptParams();
        };

        // 绑定参数输出框点击事件(支持一键复制)
        $('prompt-params').addEventListener('click', () => {
            const textarea = $('prompt-params');
            textarea.select();
            document.execCommand('copy');
            showToast('参数已复制!');
        });

        // 为输入框添加焦点样式
        document.querySelectorAll('input, textarea').forEach(el => {
            el.addEventListener('focus', () => {
                el.style.borderColor = '#4f46e5';
            });

            el.addEventListener('blur', () => {
                el.style.borderColor = '#d1d5db';
            });
        });

        // 为按钮添加悬停效果
        document.querySelectorAll('button').forEach(btn => {
            btn.addEventListener('mouseenter', () => {
                if (!btn.classList.contains('active')) {
                    btn.style.transform = 'translateY(-1px)';
                    btn.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
                }
            });

            btn.addEventListener('mouseleave', () => {
                btn.style.transform = 'translateY(0)';
                btn.style.boxShadow = 'none';
            });
        });
    }

    // 添加预览图片并绑定删除功能
    function addPreviewImage(containerId, url, weight, paramType, weightPrefix) {
        const container = document.getElementById(containerId);
        const imgContainer = document.createElement('div');
        imgContainer.style.cssText = 'position: relative; margin: 4px;';

        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.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 4px;';
        weightBadge.textContent = weight ? `${weightPrefix.replace('--', '')}:${weight}` : `${weightPrefix.replace('--', '')}:默认`;

        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: 1; cursor:pointer; transition:all 0.2s ease; opacity: 0.8;';
        deleteBtn.textContent = '×';
        deleteBtn.onclick = function(e) {
            e.stopPropagation();

            // 添加删除动画
            img.style.opacity = '0';
            img.style.transform = 'scale(0.8)';
            imgContainer.style.transform = 'translateY(10px)';
            imgContainer.style.opacity = '0';

            setTimeout(() => {
                const index = paramType === 'cref'
                    ? params.cref.findIndex(item => item.url === url)
                    : paramType === 'sref'
                        ? params.sref.findIndex(item => item.url === url)
                        : paramType === 'oref'
                            ? params.oref.findIndex(item => item.url === url)
                            : params.directImages.findIndex(item => item.url === url);

                if (index !== -1) {
                    if (paramType === 'cref') {
                        params.cref.splice(index, 1);
                    } else if (paramType === 'sref') {
                        params.sref.splice(index, 1);
                    } else if (paramType === 'oref') {
                        params.oref.splice(index, 1);
                    } else { // directImages
                        params.directImages.splice(index, 1);
                    }
                    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 refreshPreviews() {
        ['cref', 'sref', 'oref', 'directImages'].forEach(type => {
            const container = document.getElementById(`${type === 'directImages' ? 'direct-image' : type}-preview`);
            container.innerHTML = '';

            const weightPrefix = {
                'cref': '--cw',
                'sref': '--sw',
                'oref': '--ow',
                'directImages': '--iw'
            }[type];

            params[type].forEach(item => {
                addPreviewImage(`${type === 'directImages' ? 'direct-image' : type}-preview`, item.url, item.weight, type, weightPrefix);
            });
        });
    }

    // 初始化
    function init() {
        resetParams();
        createSettingButton();
        createControlPanel();
        setInitialActiveButtons();

        // 手动触发比例滑块的input事件以更新预览
        const ratioSlider = document.getElementById('ratio-slider');
        if (ratioSlider) ratioSlider.dispatchEvent(new Event('input'));
        updatePromptParams();
    }

    window.addEventListener('load', init);
})();