306 lines
11 KiB
JavaScript
306 lines
11 KiB
JavaScript
// DOM元素
|
|
const elements = {
|
|
// 主题切换
|
|
themeToggle: document.getElementById('themeToggle'),
|
|
// 移动端菜单
|
|
mobileMenuBtn: document.getElementById('mobileMenuBtn'),
|
|
mobileMenu: document.getElementById('mobileMenu'),
|
|
// 高级选项切换
|
|
advancedOptionsToggle: document.getElementById('advancedOptionsToggle'),
|
|
advancedOptions: document.getElementById('advancedOptions'),
|
|
// 生成器元素
|
|
prompt: document.getElementById('prompt'),
|
|
size: document.getElementById('size'),
|
|
style: document.getElementById('style'),
|
|
negativePrompt: document.getElementById('negativePrompt'),
|
|
guidanceScale: document.getElementById('guidanceScale'),
|
|
guidanceScaleValue: document.getElementById('guidanceScaleValue'),
|
|
generateBtn: document.getElementById('generateBtn'),
|
|
randomPromptBtn: document.getElementById('randomPromptBtn'),
|
|
clearPromptBtn: document.getElementById('clearPromptBtn'),
|
|
// 状态元素
|
|
loadingState: document.getElementById('loadingState'),
|
|
progressBar: document.getElementById('progressBar'),
|
|
progressText: document.getElementById('progressText'),
|
|
errorState: document.getElementById('errorState'),
|
|
errorMessage: document.getElementById('errorMessage'),
|
|
resultState: document.getElementById('resultState'),
|
|
resultImage: document.getElementById('resultImage'),
|
|
// 结果操作按钮
|
|
retryBtn: document.getElementById('retryBtn'),
|
|
downloadBtn: document.getElementById('downloadBtn'),
|
|
regenerateBtn: document.getElementById('regenerateBtn'),
|
|
saveToHistoryBtn: document.getElementById('saveToHistoryBtn'),
|
|
// 历史记录
|
|
historyContainer: document.getElementById('historyContainer')
|
|
};
|
|
|
|
// 示例提示词库
|
|
const examplePrompts = [
|
|
"一副典雅庄重的对联悬挂于厅堂之中,房间是个安静古典的中式布置,桌子上放着一些青花瓷,对联上左书“云端书声琅琅跨山海”,右书“智脉笔影翩翩启星辰”, 横批“东师理想”,字体飘逸,中间挂在一着一副中国风的画作,内容是岳阳楼。",
|
|
"未来城市的夜景,赛博朋克风格,霓虹灯,雨天,反射效果",
|
|
"一片宁静美丽的松林,阳光透过树叶,雾气弥漫,油画风格",
|
|
"一个穿着中世纪盔甲的骑士,站在山顶上,背景是龙和城堡",
|
|
"海底世界,五彩斑斓的珊瑚和鱼群,梦幻光影效果",
|
|
"一只戴着宇航员头盔的柴犬,站在火星表面,日落时分"
|
|
];
|
|
|
|
// 初始化函数
|
|
function init() {
|
|
// 初始化主题
|
|
initTheme();
|
|
// 加载历史记录
|
|
// loadHistory(); // 移除未定义函数调用
|
|
// 绑定事件监听器
|
|
bindEventListeners();
|
|
}
|
|
|
|
// 获取随机提示词
|
|
function getRandomPrompt() {
|
|
return examplePrompts[Math.floor(Math.random() * examplePrompts.length)];
|
|
}
|
|
|
|
// 初始化主题
|
|
function initTheme() {
|
|
// 检查本地存储
|
|
const savedTheme = localStorage.getItem('theme');
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
|
|
// 设置初始主题
|
|
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
}
|
|
|
|
// 切换主题
|
|
function toggleTheme() {
|
|
document.documentElement.classList.toggle('dark');
|
|
const isDark = document.documentElement.classList.contains('dark');
|
|
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
|
}
|
|
|
|
// 切换移动端菜单
|
|
function toggleMobileMenu() {
|
|
elements.mobileMenu.classList.toggle('hidden');
|
|
}
|
|
|
|
// 切换高级选项
|
|
function toggleAdvancedOptions() {
|
|
elements.advancedOptions.classList.toggle('hidden');
|
|
const icon = elements.advancedOptionsToggle.querySelector('i');
|
|
icon.classList.toggle('rotate-180');
|
|
}
|
|
|
|
// 更新引导力度显示
|
|
function updateGuidanceScale() {
|
|
elements.guidanceScaleValue.textContent = elements.guidanceScale.value;
|
|
}
|
|
|
|
// 显示加载状态
|
|
function showLoadingState() {
|
|
elements.generateBtn.disabled = true;
|
|
elements.loadingState.classList.remove('hidden');
|
|
elements.errorState.classList.add('hidden');
|
|
elements.resultState.classList.add('hidden');
|
|
}
|
|
|
|
// 更新进度
|
|
function updateProgress(percent) {
|
|
elements.progressBar.style.width = `${percent}%`;
|
|
elements.progressText.textContent = `进度: ${percent}%`;
|
|
}
|
|
|
|
// 显示错误状态
|
|
function showErrorState(message) {
|
|
elements.loadingState.classList.add('hidden');
|
|
elements.errorState.classList.remove('hidden');
|
|
elements.errorMessage.textContent = message;
|
|
elements.generateBtn.disabled = false;
|
|
}
|
|
|
|
// 显示结果状态
|
|
function showResultState(imageUrl) {
|
|
elements.loadingState.classList.add('hidden');
|
|
elements.resultState.classList.remove('hidden');
|
|
elements.resultImage.src = imageUrl;
|
|
elements.generateBtn.disabled = false;
|
|
}
|
|
|
|
// 生成图像
|
|
async function generateImage() {
|
|
const prompt = elements.prompt.value.trim();
|
|
|
|
// 验证输入
|
|
if (!prompt) {
|
|
showErrorState('请输入图像描述词');
|
|
return;
|
|
}
|
|
|
|
// 显示加载状态
|
|
showLoadingState();
|
|
updateProgress(10);
|
|
|
|
try {
|
|
// 构建请求数据
|
|
const requestData = {
|
|
prompt: prompt,
|
|
size: elements.size.value,
|
|
};
|
|
|
|
// 模拟进度更新
|
|
const progressInterval = setInterval(() => {
|
|
const currentWidth = parseInt(elements.progressBar.style.width);
|
|
if (currentWidth < 90) {
|
|
updateProgress(currentWidth + Math.random() * 10);
|
|
}
|
|
}, 500);
|
|
|
|
// 调用API生成图像 (参考TestQWen3Image.py中的接口)
|
|
console.log('请求URL:', '/api/qwenImage/generate');
|
|
console.log('请求参数:', JSON.stringify(requestData, null, 2));
|
|
const response = await fetch('/api/qwenImage/generate', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(requestData)
|
|
});
|
|
|
|
clearInterval(progressInterval);
|
|
updateProgress(100);
|
|
|
|
if (!response.ok) {
|
|
// 尝试解析错误响应
|
|
const errorDetails = await response.json().catch(() => ({}));
|
|
const errorMsg = errorDetails.message || `API请求失败: ${response.status} ${response.statusText}`;
|
|
throw new Error(errorMsg);
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
// 检查API返回状态 (参考TestQWen3Image.py中的响应处理)
|
|
if (result.code !== 200 || !result.data || !result.data.images || result.data.images.length === 0) {
|
|
throw new Error(result.message || '未获取到生成的图像');
|
|
}
|
|
|
|
// 显示结果
|
|
showResultState(result.data.images[0]);
|
|
|
|
} catch (error) {
|
|
console.error('生成图像失败:', error);
|
|
showErrorState(error.message || '生成图像时发生错误,请重试');
|
|
}
|
|
}
|
|
|
|
// 下载图像
|
|
function downloadImage() {
|
|
if (!elements.resultImage.src) return;
|
|
|
|
const link = document.createElement('a');
|
|
link.href = elements.resultImage.src;
|
|
link.download = `qwen-image-${new Date().getTime()}.png`;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
}
|
|
|
|
// 保存到历史记录
|
|
function saveToHistory() {
|
|
if (!elements.resultImage.src || !elements.prompt.value.trim()) return;
|
|
|
|
const historyItem = {
|
|
id: Date.now(),
|
|
prompt: elements.prompt.value.trim(),
|
|
size: elements.size.value,
|
|
style: elements.style.value,
|
|
imageUrl: elements.resultImage.src,
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
|
|
// 获取现有历史记录
|
|
const history = JSON.parse(localStorage.getItem('qwenImageHistory') || '[]');
|
|
// 添加新记录
|
|
history.unshift(historyItem);
|
|
// 限制历史记录数量
|
|
if (history.length > 20) history.pop();
|
|
// 保存到本地存储
|
|
localStorage.setItem('qwenImageHistory', JSON.stringify(history));
|
|
// 更新历史记录显示
|
|
renderHistory();
|
|
|
|
// 显示提示
|
|
alert('已保存到历史记录');
|
|
}
|
|
|
|
// 渲染历史记录
|
|
function renderHistory() {
|
|
const history = JSON.parse(localStorage.getItem('qwenImageHistory') || '[]');
|
|
|
|
if (history.length === 0) {
|
|
elements.historyContainer.innerHTML = `
|
|
<div class="text-center py-12 text-gray-500 dark:text-gray-400 col-span-full">
|
|
<i class="fa fa-history text-4xl mb-4"></i>
|
|
<p>暂无生成历史</p>
|
|
<p class="text-sm mt-2">生成图像后,历史记录将显示在这里</p>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
// 生成历史记录项
|
|
elements.historyContainer.innerHTML = history.map(item => `
|
|
<div class="bg-white dark:bg-gray-800 rounded-xl overflow-hidden shadow-md transition-all duration-300 hover:shadow-lg">
|
|
<img src="${item.imageUrl}" alt="${item.prompt.substring(0, 30)}..." class="w-full h-48 object-cover">
|
|
<div class="p-3">
|
|
<p class="text-sm font-medium truncate" title="${item.prompt}">${item.prompt}</p>
|
|
<div class="flex justify-between items-center mt-2 text-xs text-gray-500 dark:text-gray-400">
|
|
<span>${item.size}</span>
|
|
<span>${new Date(item.timestamp).toLocaleString()}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// 绑定事件监听器
|
|
function bindEventListeners() {
|
|
// 主题切换
|
|
elements.themeToggle.addEventListener('click', toggleTheme);
|
|
|
|
// 移动端菜单
|
|
elements.mobileMenuBtn.addEventListener('click', toggleMobileMenu);
|
|
|
|
// 高级选项切换
|
|
elements.advancedOptionsToggle.addEventListener('click', toggleAdvancedOptions);
|
|
|
|
// 引导力度滑块
|
|
elements.guidanceScale.addEventListener('input', updateGuidanceScale);
|
|
|
|
// 随机提示词
|
|
elements.randomPromptBtn.addEventListener('click', () => {
|
|
elements.prompt.value = getRandomPrompt();
|
|
});
|
|
|
|
// 清空提示词
|
|
elements.clearPromptBtn.addEventListener('click', () => {
|
|
elements.prompt.value = '';
|
|
});
|
|
|
|
// 生成按钮
|
|
elements.generateBtn.addEventListener('click', generateImage);
|
|
|
|
// 重试按钮
|
|
elements.retryBtn.addEventListener('click', generateImage);
|
|
|
|
// 重新生成按钮
|
|
elements.regenerateBtn.addEventListener('click', generateImage);
|
|
|
|
// 下载按钮
|
|
elements.downloadBtn.addEventListener('click', downloadImage);
|
|
|
|
// 保存到历史
|
|
elements.saveToHistoryBtn.addEventListener('click', saveToHistory);
|
|
}
|
|
|
|
// 页面加载完成后初始化
|
|
document.addEventListener('DOMContentLoaded', init); |