// ==UserScript== // @name Discord Midjourney 参数面板 // @namespace https://github.com/cwser // @version 0.1.6 // @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 // @downloadURL none // ==/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: '', // 新增随机样式参数 randomSref: false, srefWeight: 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}`, 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.filter(item => item.url !== 'random').map(item => `--sref ${formatImageWithWeight(item.url, item.weight, '--sw')}`), ...sref.filter(item => item.url === 'random').map(item => `--sref random --sw ${item.weight}`), ...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 = `

Midjourney 参数设置

图片尺寸

1:1

美学参数

100
0
0

模型设置

角色参考 (--cref)

风格参考 (--sref)

全方位参考 (--oref)

图像参考

更多参数

1
100

可见性

提示词

排除词

最终参数

`; 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 = ''; } 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 = ''; } }); // 绑定提示词输入框事件 $('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 = ''; // 重置随机样式开关 params.randomSref = false; srefRandomDot.style.transform = 'translateX(0)'; srefRandomSwitch.style.backgroundColor = '#e5e7eb'; // 重置随机样式权重 params.srefWeight = 1; srefWeightInput.value = '1'; // 重置新增参数 $('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(); // 检查输入是URL还是sref码(数字) if (url) { if (/^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url)) { // 处理图片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 if (/^\d+$/.test(url)) { // 处理sref码(数字) if (!params.sref.some(item => item.url === url)) { params.sref.push({url, weight}); addPreviewSrefCode('sref-preview', url, weight); $('sref-url').value = ''; $('sref-weight').value = ''; updatePromptParams(); } else { showToast('该sref码已添加'); } } else { showToast('请输入有效图片URL或sref码'); } } else { showToast('请输入sref码或图片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'); } }; // 新增:随机样式开关 const srefRandomContainer = document.createElement('div'); srefRandomContainer.id = 'sref-random-container'; srefRandomContainer.style.cssText = 'display:flex; align-items:center; margin-top:6px; margin-left:6px;'; const srefRandomLabel = document.createElement('label'); srefRandomLabel.textContent = '随机样式'; srefRandomLabel.style.cssText = 'margin-right:8px;'; const srefRandomSwitch = document.createElement('div'); srefRandomSwitch.id = 'sref-random-switch'; srefRandomSwitch.style.cssText = 'position:relative; width:40px; height:20px; border-radius:10px; background:#e5e7eb; cursor:pointer;'; const srefRandomDot = document.createElement('div'); srefRandomDot.id = 'sref-random-dot'; srefRandomDot.style.cssText = '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;'; srefRandomSwitch.appendChild(srefRandomDot); srefRandomContainer.appendChild(srefRandomLabel); srefRandomContainer.appendChild(srefRandomSwitch); document.querySelector('#sref-add').parentNode.appendChild(srefRandomContainer); // 绑定随机样式开关事件 srefRandomSwitch.onclick = () => { params.randomSref = !params.randomSref; if (params.randomSref) { srefRandomDot.style.transform = 'translateX(20px)'; srefRandomSwitch.style.backgroundColor = '#4f46e5'; // 添加随机sref码 const randomSref = 'random'; // 使用"random"作为特殊标识 if (!params.sref.some(item => item.url === randomSref)) { params.sref.push({url: randomSref, weight: params.srefWeight.toString()}); addPreviewSrefCode('sref-preview', randomSref, params.srefWeight); updatePromptParams(); } } else { srefRandomDot.style.transform = 'translateX(0)'; srefRandomSwitch.style.backgroundColor = '#e5e7eb'; // 移除随机sref码 const index = params.sref.findIndex(item => item.url === 'random'); if (index !== -1) { const container = document.getElementById('sref-preview'); const codeElement = container.querySelector(`div span:first-child`); if (codeElement && codeElement.textContent === `sref:random`) { const codeContainer = codeElement.parentElement; codeContainer.style.transform = 'translateY(10px)'; codeContainer.style.opacity = '0'; setTimeout(() => { params.sref.splice(index, 1); container.removeChild(codeContainer); updatePromptParams(); }, 200); } } } }; // 新增:随机样式权重控制 const srefWeightContainer = document.createElement('div'); srefWeightContainer.style.cssText = 'display:flex; align-items:center; margin-top:6px; margin-left:6px;'; const srefWeightLabel = document.createElement('label'); srefWeightLabel.textContent = '随机权重'; srefWeightLabel.style.cssText = 'margin-right:8px;'; const srefWeightInput = document.createElement('input'); srefWeightInput.id = 'sref-weight-input'; srefWeightInput.type = 'number'; srefWeightInput.min = '0'; srefWeightInput.max = '10'; srefWeightInput.step = '0.1'; srefWeightInput.value = '1'; srefWeightInput.style.cssText = 'width:60px; padding:4px; border-radius:4px; border:1px solid #d1d5db;'; srefWeightContainer.appendChild(srefWeightLabel); srefWeightContainer.appendChild(srefWeightInput); document.querySelector('#sref-add').parentNode.appendChild(srefWeightContainer); // 初始化随机样式权重参数 params.srefWeight = 1; // 绑定随机样式权重事件 srefWeightInput.oninput = (e) => { const value = parseFloat(e.target.value); if (!isNaN(value) && value >= 0 && value <= 10) { params.srefWeight = value; // 如果随机样式已启用,更新其权重显示 const randomItem = params.sref.find(item => item.url === 'random'); if (randomItem) { randomItem.weight = value.toString(); const container = document.getElementById('sref-preview'); const codeElement = container.querySelector(`div span:first-child`); if (codeElement && codeElement.textContent === `sref:random`) { const weightBadge = codeElement.parentElement.querySelector('div:nth-child(2)'); weightBadge.textContent = `sw:${value}`; updatePromptParams(); } } } else { e.target.value = params.srefWeight.toString(); } }; // 绑定直接图像参考事件 $('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', '9:16', '2:3', '3:4', '5:6', '1:1', '6:5', '4:3', '3:2', '16:9', '2:1']; const ratioPresets = { '1:2': { width: 50, height: 100 }, '9:16': { width: 56.25, height: 100 }, '2:3': { width: 66.67, height: 100 }, '3:4': { width: 75, height: 100 }, '5:6': { width: 83.33, height: 100 }, '1:1': { width: 100, height: 100 }, '6:5': { width: 100, height: 83.33 }, '4:3': { width: 100, height: 75 }, '3:2': { width: 100, height: 66.67 }, '16:9': { width: 100, height: 56.25 }, '2:1': { width: 100, height: 50 } }; $('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); } // 新增:添加sref码预览功能 function addPreviewSrefCode(containerId, code, weight) { const container = document.getElementById(containerId); const codeContainer = document.createElement('div'); codeContainer.style.cssText = 'position: relative; margin: 4px; background: #f3f4f6; border-radius: 4px; padding: 4px 8px; display: flex; align-items: center;'; const codeText = document.createElement('span'); codeText.style.cssText = 'font-family: monospace; font-size: 12px; color: #111827;'; codeText.textContent = `sref:${code}`; // 添加权重显示 const weightBadge = document.createElement('div'); weightBadge.style.cssText = 'margin-left: 4px; background: rgba(79, 70, 229, 0.1); color: #4f46e5; font-size: 10px; padding: 1px 3px; border-radius: 2px;'; weightBadge.textContent = weight ? `sw:${weight}` : 'sw:默认'; const deleteBtn = document.createElement('button'); deleteBtn.style.cssText = 'margin-left: 8px; background: rgba(239, 68, 68, 0.1); color: #ef4444; border: none; border-radius: 4px; padding: 0 4px; font-size: 10px; cursor:pointer; transition:all 0.2s ease;'; deleteBtn.textContent = '×'; deleteBtn.onclick = function(e) { e.stopPropagation(); // 添加删除动画 codeContainer.style.transform = 'translateY(10px)'; codeContainer.style.opacity = '0'; setTimeout(() => { const index = params.sref.findIndex(item => item.url === code); if (index !== -1) { params.sref.splice(index, 1); container.removeChild(codeContainer); updatePromptParams(); } }, 200); }; // 添加按钮悬停效果 deleteBtn.addEventListener('mouseenter', () => { deleteBtn.style.backgroundColor = 'rgba(239, 68, 68, 0.2)'; }); deleteBtn.addEventListener('mouseleave', () => { deleteBtn.style.backgroundColor = 'rgba(239, 68, 68, 0.1)'; }); codeContainer.appendChild(codeText); codeContainer.appendChild(weightBadge); codeContainer.appendChild(deleteBtn); container.appendChild(codeContainer); } // 刷新预览区域 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]; // 对sref类型特殊处理,过滤掉随机sref if (type === 'sref') { const srefItems = params.sref.filter(item => item.url !== 'random'); srefItems.forEach(item => { addPreviewImage('sref-preview', item.url, item.weight, 'sref', '--sw'); }); } else { 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); })();