Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3726f0d4d | ||
|
|
535573f95a |
10
index.html
10
index.html
@@ -38,7 +38,7 @@
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<button class="icon-btn" id="openSettings" title="设置">
|
||||
<button type="button" class="icon-btn" id="openSettings" title="设置">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||||
@@ -50,7 +50,7 @@
|
||||
<!-- API Key Alert -->
|
||||
<div class="alert-banner" id="apiKeyAlert" style="display:none">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
|
||||
<span>未配置 API Key,请先在 <button class="link-btn" id="alertSettingsBtn">设置</button> 中填写。</span>
|
||||
<span>未配置 API Key,请先在 <button type="button" class="link-btn" id="alertSettingsBtn">设置</button> 中填写。</span>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
@@ -245,7 +245,7 @@
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h2>设置</h2>
|
||||
<button class="icon-btn" id="closeSettings">
|
||||
<button type="button" class="icon-btn" id="closeSettings">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
||||
</svg>
|
||||
@@ -271,8 +271,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-secondary" id="cancelSettings">取消</button>
|
||||
<button class="btn-primary" id="saveSettingsBtn">保存</button>
|
||||
<button type="button" class="btn-secondary" id="cancelSettings">取消</button>
|
||||
<button type="button" class="btn-primary" id="saveSettingsBtn">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
153
ui.js
153
ui.js
@@ -179,12 +179,14 @@ async function copySrc(src, fmt, btn) {
|
||||
|
||||
// ── Init ────────────────────────────────────────────────────────
|
||||
|
||||
async function init() {
|
||||
const savedKey = localStorage.getItem('imgGen-apiKey') || '';
|
||||
function init() {
|
||||
const savedKey = (localStorage.getItem('imgGen-apiKey') || '').trim();
|
||||
const savedBaseUrl = localStorage.getItem('imgGen-baseUrl') || 'https://api.minimaxi.com';
|
||||
if (!savedKey) apiKeyAlert.style.display = 'flex';
|
||||
apiKeyInput.value = savedKey;
|
||||
baseUrlInput.value = savedBaseUrl;
|
||||
if (!savedKey && apiKeyAlert) {
|
||||
apiKeyAlert.style.display = 'flex';
|
||||
}
|
||||
if (apiKeyInput) apiKeyInput.value = savedKey;
|
||||
if (baseUrlInput) baseUrlInput.value = savedBaseUrl;
|
||||
}
|
||||
|
||||
// ── Generate ────────────────────────────────────────────────────
|
||||
@@ -222,80 +224,75 @@ generateForm.addEventListener('submit', async (e) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ── Quick prompt tags ──────────────────────────────────────────
|
||||
|
||||
document.querySelectorAll('.tag-pill').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const tag = btn.dataset.tag;
|
||||
const current = promptInput.value.trim();
|
||||
if (current) {
|
||||
promptInput.value = current + ',' + tag;
|
||||
} else {
|
||||
promptInput.value = tag;
|
||||
}
|
||||
promptInput.dispatchEvent(new Event('input'));
|
||||
promptInput.focus();
|
||||
});
|
||||
});
|
||||
|
||||
// ── Prompt char count ──────────────────────────────────────────
|
||||
|
||||
promptInput.addEventListener('input', () => {
|
||||
charCount.textContent = `${promptInput.value.length} / 1500`;
|
||||
});
|
||||
|
||||
// ── Settings modal ──────────────────────────────────────────────
|
||||
|
||||
function openModal() {
|
||||
settingsModal.classList.add('open');
|
||||
apiKeyInput.focus();
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
settingsModal.classList.remove('open');
|
||||
clearError();
|
||||
}
|
||||
|
||||
openSettings.addEventListener('click', openModal);
|
||||
alertSettings.addEventListener('click', openModal);
|
||||
closeSettings.addEventListener('click', closeModal);
|
||||
cancelSettings.addEventListener('click', closeModal);
|
||||
settingsModal.addEventListener('click', e => { if (e.target === settingsModal) closeModal(); });
|
||||
|
||||
toggleKey.addEventListener('click', () => {
|
||||
apiKeyInput.type = apiKeyInput.type === 'password' ? 'text' : 'password';
|
||||
});
|
||||
|
||||
saveSettingsBtn.addEventListener('click', async () => {
|
||||
clearError();
|
||||
const apiKey = apiKeyInput.value.trim();
|
||||
const baseUrl = baseUrlInput.value.trim() || 'https://api.minimaxi.com';
|
||||
|
||||
localStorage.setItem('imgGen-apiKey', apiKey);
|
||||
localStorage.setItem('imgGen-baseUrl', baseUrl);
|
||||
|
||||
if (apiKey) apiKeyAlert.style.display = 'none';
|
||||
closeModal();
|
||||
});
|
||||
|
||||
// ── Theme switcher ─────────────────────────────────────────────
|
||||
|
||||
function applyTheme(theme) {
|
||||
document.documentElement.dataset.theme = theme;
|
||||
localStorage.setItem('imgGen-theme', theme);
|
||||
document.querySelectorAll('.theme-btn').forEach(btn =>
|
||||
btn.classList.toggle('active', btn.dataset.theme === theme)
|
||||
);
|
||||
}
|
||||
|
||||
document.querySelectorAll('.theme-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => applyTheme(btn.dataset.theme));
|
||||
});
|
||||
|
||||
// Restore saved theme
|
||||
const savedTheme = localStorage.getItem('imgGen-theme');
|
||||
if (savedTheme) applyTheme(savedTheme);
|
||||
|
||||
// ── Start ──────────────────────────────────────────────────────
|
||||
|
||||
init();
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
init();
|
||||
|
||||
// Quick prompt tags
|
||||
document.querySelectorAll('.tag-pill').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const tag = btn.dataset.tag;
|
||||
const current = (promptInput.value || '').trim();
|
||||
promptInput.value = current ? current + ',' + tag : tag;
|
||||
promptInput.dispatchEvent(new Event('input'));
|
||||
promptInput.focus();
|
||||
});
|
||||
});
|
||||
|
||||
// Prompt char count
|
||||
promptInput.addEventListener('input', () => {
|
||||
charCount.textContent = `${promptInput.value.length} / 1500`;
|
||||
});
|
||||
|
||||
// Settings modal
|
||||
function openModal() {
|
||||
settingsModal.classList.add('open');
|
||||
apiKeyInput.focus();
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
settingsModal.classList.remove('open');
|
||||
clearError();
|
||||
}
|
||||
|
||||
openSettings.addEventListener('click', openModal);
|
||||
alertSettings.addEventListener('click', openModal);
|
||||
closeSettings.addEventListener('click', closeModal);
|
||||
cancelSettings.addEventListener('click', closeModal);
|
||||
settingsModal.addEventListener('click', e => { if (e.target === settingsModal) closeModal(); });
|
||||
|
||||
toggleKey.addEventListener('click', () => {
|
||||
apiKeyInput.type = apiKeyInput.type === 'password' ? 'text' : 'password';
|
||||
});
|
||||
|
||||
saveSettingsBtn.addEventListener('click', () => {
|
||||
clearError();
|
||||
const apiKey = (apiKeyInput.value || '').trim();
|
||||
const baseUrl = (baseUrlInput.value || '').trim() || 'https://api.minimaxi.com';
|
||||
|
||||
localStorage.setItem('imgGen-apiKey', apiKey);
|
||||
localStorage.setItem('imgGen-baseUrl', baseUrl);
|
||||
|
||||
if (apiKey && apiKeyAlert) apiKeyAlert.style.display = 'none';
|
||||
closeModal();
|
||||
});
|
||||
|
||||
// Theme switcher
|
||||
function applyTheme(theme) {
|
||||
document.documentElement.dataset.theme = theme;
|
||||
localStorage.setItem('imgGen-theme', theme);
|
||||
document.querySelectorAll('.theme-btn').forEach(btn =>
|
||||
btn.classList.toggle('active', btn.dataset.theme === theme)
|
||||
);
|
||||
}
|
||||
|
||||
document.querySelectorAll('.theme-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => applyTheme(btn.dataset.theme));
|
||||
});
|
||||
|
||||
const savedTheme = localStorage.getItem('imgGen-theme');
|
||||
if (savedTheme) applyTheme(savedTheme);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user