您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
在 Discord 中添加 Midjourney 参数设置面板,支持完整卡片式 UI 和最新参数功能(需开启开发者模式)
当前为
// ==UserScript== // @name Discord Midjourney 参数面板 // @namespace https://github.com/cwser // @version 0.1.2 // @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: '' }; function createSettingButton() { const button = document.createElement('button'); button.textContent = 'MJ设置'; button.style.position = 'fixed'; button.style.right = '20px'; button.style.bottom = '20px'; button.style.padding = '10px 20px'; button.style.backgroundColor = '#5865F2'; button.style.color = 'white'; button.style.border = 'none'; button.style.borderRadius = '8px'; button.style.cursor = 'pointer'; button.style.zIndex = '9999'; button.addEventListener('click', toggleControlPanel); document.body.appendChild(button); } function toggleControlPanel() { const panel = document.getElementById('mj-control-panel'); if (panel) { panel.style.display = panel.style.display === 'none' ? 'block' : 'none'; } } 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; 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; `; 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> </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;"> </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;"> </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;"> </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;">速度 <select id="speed-select" style="width:100%; padding:6px;"> <option value="relax">标准</option> <option value="fast">快速</option> <option value="turbo">极速</option> </select> </label> <label style="flex:1;">模式 <select id="mode-select" style="width:100%; padding:6px;"> <option value="standard">标准</option> <option value="raw">原始</option> </select> </label> </div> <div style="display:flex; gap:10px; align-items:center;"> <label style="flex:1;">草稿 <input type="checkbox" id="draft-toggle"> </label> <label style="flex:2;">版本 <select id="version-select" style="width:100%; padding:6px;"> <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;"> <input type="number" id="cref-weight" placeholder="权重" style="flex:1; padding:6px;"> </div> <button id="cref-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer;">添加</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;"> <input type="number" id="sref-weight" placeholder="权重" style="flex:1; padding:6px;"> </div> <button id="sref-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer;">添加</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;"> <input type="number" id="oref-weight" placeholder="权重" style="flex:1; padding:6px;"> </div> <button id="oref-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer;">添加</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;"> <input type="number" id="direct-image-weight" placeholder="权重" style="flex:1; padding:6px;"> </div> <button id="direct-image-add" style="margin-top:6px; padding:4px 8px; background:#4f46e5; color:white; border:none; border-radius:4px; cursor:pointer;">添加</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;"> <input type="checkbox" id="tile-toggle"> <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;"> </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;"> </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" style="padding:6px 12px; border:1px solid #d1d5db; border-radius:6px; cursor:pointer;">隐身</button> <button id="public-btn" class="visibility-btn" style="padding:6px 12px; border:1px solid #d1d5db; border-radius:6px; cursor:pointer;">公开</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;"></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;"></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;" 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;">拷贝参数</button> <button id="clear-btn" style="flex:1; padding:8px; background:#e5e7eb; color:#111827; border:none; border-radius:6px; cursor:pointer;">清空参数</button> </div> `; document.body.appendChild(panel); bindControlEvents(); } function bindControlEvents() { const $ = id => document.getElementById(id); // 绑定提示词输入框事件 $('main-prompt').oninput = e => { params.prompt = e.target.value; updatePromptParams(); }; // 绑定已有控件事件 $('stylize').oninput = e => { params.stylize = +e.target.value; updatePromptParams(); }; $('weird').oninput = e => { params.weird = +e.target.value; updatePromptParams(); }; $('chaos').oninput = e => { params.chaos = +e.target.value; updatePromptParams(); }; $('mode-select').onchange = e => { params.mode = e.target.value; updatePromptParams(); }; $('version-select').onchange = e => { params.version = e.target.value; updatePromptParams(); }; $('draft-toggle').onchange = e => { params.draft = e.target.checked; updatePromptParams(); }; $('speed-select').onchange = e => { params.speed = 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'); alert('参数已复制!'); }; // 重置所有控件状态 $('clear-btn').onclick = () => { resetParams(); // 重置所有控件为默认值 $('main-prompt').value = ''; $('stylize').value = 100; $('weird').value = 0; $('chaos').value = 0; $('mode-select').value = 'standard'; $('version-select').value = 'v7'; $('draft-toggle').checked = false; $('speed-select').value = 'relax'; $('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 = ''; // 重置新增参数 $('tile-toggle').checked = false; $('seed-input').value = ''; $('quality-slider').value = 1; $('quality-value').textContent = '1'; $('stop-slider').value = 100; $('stop-value').textContent = '100'; // 重置个性化参数 $('personal-params').value = ''; // 重置可见性按钮状态 const visibilityBtns = document.querySelectorAll('.visibility-btn'); visibilityBtns.forEach(btn => { 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')); $('mode-select').dispatchEvent(new Event('change')); $('version-select').dispatchEvent(new Event('change')); $('draft-toggle').dispatchEvent(new Event('change')); $('speed-select').dispatchEvent(new Event('change')); $('no-prompt').dispatchEvent(new Event('input')); $('ratio-slider').dispatchEvent(new Event('input')); $('tile-toggle').dispatchEvent(new Event('change')); $('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(); // 显示重置成功提示 alert('所有参数已重置为默认值'); }; // 绑定角色参考事件 $('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 { alert('该URL已添加'); } } else { alert('请输入有效图片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 { alert('该URL已添加'); } } else { alert('请输入有效图片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 { alert('该URL已添加'); } } else { alert('请输入有效图片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 { alert('该URL已添加'); } } else { alert('请输入有效图片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; 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.style.cssText = 'padding:4px 12px; border-radius:6px; border:1px solid #d1d5db; background:white; cursor:pointer;'; // 修复:正确映射预设比例 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); }); // 绑定新增参数事件 $('tile-toggle').onchange = e => { params.tile = e.target.checked; updatePromptParams(); }; $('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; // 恢复之前的值 } }; $('quality-slider').oninput = e => { const value = parseFloat(e.target.value); params.quality = value; $('quality-value').textContent = value; updatePromptParams(); }; $('stop-slider').oninput = e => { const value = parseInt(e.target.value); params.stop = value; $('stop-value').textContent = value; updatePromptParams(); }; // 可见性按钮事件 const visibilityBtns = document.querySelectorAll('.visibility-btn'); visibilityBtns.forEach(btn => { btn.onclick = () => { // 重置所有按钮样式 visibilityBtns.forEach(b => { b.style.backgroundColor = 'white'; b.style.color = '#111827'; }); // 设置当前按钮样式 btn.style.backgroundColor = '#4f46e5'; btn.style.color = 'white'; // 设置可见性参数 if (btn.id === 'stealth-btn') { params.visibility = 'stealth'; } else if (btn.id === 'public-btn') { params.visibility = 'public'; } else { params.visibility = ''; } updatePromptParams(); }; }); // 绑定个性化参数事件 $('personal-params').oninput = e => { params.personalParams = e.target.value.trim(); updatePromptParams(); }; } // 添加预览图片并绑定删除功能 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'; // 添加权重显示 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(0,0,0,0.7); color: white; border: none; border-radius: 50%; width: 16px; height: 16px; font-size: 10px; line-height: 1; cursor: pointer;'; deleteBtn.textContent = '×'; deleteBtn.onclick = function(e) { e.stopPropagation(); 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(); } }; 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(); // 手动触发比例滑块的input事件以更新预览 const ratioSlider = document.getElementById('ratio-slider'); if (ratioSlider) ratioSlider.dispatchEvent(new Event('input')); updatePromptParams(); } window.addEventListener('load', init); })();