魔搭api功能优化
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI 图片生成器</title><style>:root {--bg-color: #f5f7fa;--text-color: #333;--panel-bg: #ffffff;--border-color: #e1e4e8;--primary-color: #4a6bdf;--secondary-color: #f0f2f5;--button-hover: #3a5bd9;--input-bg: #ffffff;--progress-bg: #e0e0e0;--image-bg: #f0f0f0;--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);--transition: all 0.3s ease;--success-color: #4caf50;--error-color: #f44336;}.dark-mode {--bg-color: #1a1a1a;--text-color: #e0e0e0;--panel-bg: #2d2d2d;--border-color: #444;--primary-color: #5d7eff;--secondary-color: #3a3a3a;--button-hover: #4a6bdf;--input-bg: #3a3a3a;--progress-bg: #444;--image-bg: #2a2a2a;--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);--success-color: #66bb6a;--error-color: #ef5350;}* {box-sizing: border-box;margin: 0;padding: 0;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background-color: var(--bg-color);color: var(--text-color);transition: var(--transition);line-height: 1.6;}.container {max-width: 1200px;margin: 0 auto;padding: 20px;display: flex;flex-direction: column;min-height: 100vh;}header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 30px;padding-bottom: 15px;border-bottom: 1px solid var(--border-color);position: relative;}h1 {font-size: 28px;color: var(--primary-color);font-weight: 700;letter-spacing: 0.5px;}.theme-toggle {background: var(--secondary-color);border: none;padding: 8px 15px;border-radius: 30px;cursor: pointer;color: var(--text-color);display: flex;align-items: center;gap: 8px;transition: var(--transition);font-weight: 500;box-shadow: var(--box-shadow);z-index: 10;}.theme-toggle:hover {background: var(--border-color);transform: translateY(-2px);}.main-content {display: flex;gap: 25px;flex: 1;}.panel {background: var(--panel-bg);border-radius: 12px;padding: 25px;box-shadow: var(--box-shadow);border: 1px solid var(--border-color);transition: var(--transition);}.params-panel {flex: 0 0 400px;display: flex;flex-direction: column;}.preview-panel {flex: 1;display: flex;flex-direction: column;}.panel-title {font-size: 20px;margin-bottom: 20px;color: var(--primary-color);font-weight: 600;position: relative;padding-bottom: 10px;}.panel-title::after {content: '';position: absolute;bottom: 0;left: 0;width: 50px;height: 3px;background: var(--primary-color);border-radius: 3px;}.form-group {margin-bottom: 20px;}label {display: block;margin-bottom: 8px;font-weight: 500;color: var(--text-color);}input, select, textarea {width: 100%;padding: 12px;border: 1px solid var(--border-color);border-radius: 8px;background: var(--input-bg);color: var(--text-color);font-size: 14px;transition: var(--transition);}input:focus, select:focus, textarea:focus {outline: none;border-color: var(--primary-color);box-shadow: 0 0 0 2px rgba(74, 107, 223, 0.2);}textarea {min-height: 120px;resize: vertical;}.advanced-params {margin-top: 20px;padding-top: 20px;border-top: 1px solid var(--border-color);}.param-row {display: flex;gap: 15px;margin-bottom: 15px;}.param-item {flex: 1;}button {background: var(--primary-color);color: white;border: none;padding: 12px 20px;border-radius: 8px;cursor: pointer;font-weight: 500;transition: var(--transition);box-shadow: var(--box-shadow);display: inline-flex;align-items: center;justify-content: center;gap: 8px;}button:hover {background: var(--button-hover);transform: translateY(-2px);}button:active {transform: translateY(0);}button:disabled {background: #cccccc;cursor: not-allowed;transform: none;}.status-area {margin-top: 20px;padding: 15px;background: var(--secondary-color);border-radius: 8px;min-height: 20px;font-size: 14px;border-left: 4px solid var(--primary-color);}.progress-container {margin-top: 20px;}progress {width: 100%;height: 10px;border-radius: 5px;background: var(--progress-bg);border: none;}progress::-webkit-progress-bar {background: var(--progress-bg);border-radius: 5px;}progress::-webkit-progress-value {background: var(--primary-color);border-radius: 5px;transition: width 0.3s ease;}progress::-moz-progress-bar {background: var(--primary-color);border-radius: 5px;}.preview-container {flex: 1;display: flex;justify-content: center;align-items: center;background: var(--image-bg);border-radius: 12px;overflow: hidden;position: relative;transition: var(--transition);cursor: pointer;}.preview-container:hover {box-shadow: 0 0 0 2px var(--primary-color);}.preview-image {max-width: 100%;max-height: 100%;object-fit: contain;display: none;transition: var(--transition);}.preview-placeholder {text-align: center;padding: 30px;color: var(--text-color);opacity: 0.7;font-size: 16px;}.time-info {margin-top: 15px;font-size: 14px;color: var(--primary-color);font-weight: 500;text-align: center;}.action-buttons {display: flex;gap: 15px;margin-top: 20px;}.secondary-button {background: var(--secondary-color);color: var(--text-color);}.secondary-button:hover {background: var(--border-color);}/* 图片放大模态框样式 */.modal {display: none;position: fixed;z-index: 1000;left: 0;top: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.8);overflow: auto;opacity: 0;transition: opacity 0.3s ease;}.modal.show {display: flex;justify-content: center;align-items: center;opacity: 1;}.modal-content {max-width: 90%;max-height: 90%;object-fit: contain;animation: zoomIn 0.3s ease;}.close-modal {position: absolute;top: 20px;right: 30px;color: white;font-size: 35px;font-weight: bold;cursor: pointer;transition: transform 0.2s ease;}.close-modal:hover {transform: rotate(90deg);}@keyframes zoomIn {from {transform: scale(0.8);opacity: 0;}to {transform: scale(1);opacity: 1;}}/* 加载动画 */.loader {display: none;width: 48px;height: 48px;margin: 20px auto;border: 5px solid rgba(74, 107, 223, 0.2);border-radius: 50%;border-top-color: var(--primary-color);animation: spin 1s ease-in-out infinite;}@keyframes spin {to {transform: rotate(360deg);}}/* 模型刷新按钮 */.model-refresh-container {display: flex;flex-direction: column;gap: 10px;}#model {flex: 1;}#refreshModelBtn {padding: 12px;min-width: 44px;height: 44px;}.refresh-icon {display: inline-block;width: 20px;height: 20px;background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M23 4v6h-6'/%3E%3Cpath d='M1 20v-6h6'/%3E%3Cpath d='M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15'/%3E%3C/svg%3E");background-repeat: no-repeat;background-position: center;background-size: contain;transition: transform 0.3s ease;}.refreshing {animation: spin 1s linear infinite;}/* 模型提示信息 */.model-info {margin-top: 8px;padding: 10px;background: var(--secondary-color);border-radius: 8px;font-size: 13px;display: none;}.model-info-title {font-weight: 600;color: var(--primary-color);margin-bottom: 5px;}.model-info-intro {color: var(--text-color);opacity: 0.8;}.success-message {color: var(--success-color);font-weight: 500;}.error-message {color: var(--error-color);font-weight: 500;}/* 新增搜索框样式 */.model-search-container {position: relative;margin-bottom: 10px;}#modelSearch {width: 100%;padding: 12px 40px 12px 12px;border: 1px solid var(--border-color);border-radius: 8px;background: var(--input-bg);color: var(--text-color);font-size: 14px;transition: var(--transition);background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23999' viewBox='0 0 16 16'%3E%3Cpath d='M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'/%3E%3C/svg%3E");background-repeat: no-repeat;background-position: right 12px center;background-size: 16px 16px;}#modelSearch:focus {outline: none;border-color: var(--primary-color);box-shadow: 0 0 0 2px rgba(74, 107, 223, 0.2);}.model-select-container {position: relative;display: flex;gap: 10px;align-items: center;}/* 搜索提示 */.search-hint {position: absolute;top: 50%;right: 50px;transform: translateY(-50%);color: #999;font-size: 12px;pointer-events: none;opacity: 0;transition: opacity 0.3s ease;}#modelSearch:focus + .search-hint {opacity: 1;}/* 无结果提示 */.no-results {display: none;padding: 10px;text-align: center;color: var(--error-color);font-size: 14px;border: 1px dashed var(--border-color);border-radius: 8px;margin-top: 10px;}/* 简易模式样式 */.simple-mode .params-panel .form-group:not(.prompt-group),.simple-mode .params-panel .advanced-params,.simple-mode .params-panel .model-refresh-container,.simple-mode .params-panel #downloadBtn {display: none;}.simple-mode .params-panel {flex: 0 0 350px;}.simple-mode .preview-panel {flex: 1;}.simple-mode .action-buttons {margin-top: 10px;}/* 简易模式切换按钮 */#simpleModeToggle {background: var(--secondary-color);border: none;padding: 8px 15px;border-radius: 30px;cursor: pointer;color: var(--text-color);display: flex;align-items: center;gap: 8px;transition: var(--transition);font-weight: 500;box-shadow: var(--box-shadow);z-index: 10;}#simpleModeToggle:hover {background: var(--border-color);transform: translateY(-2px);}/* 悬浮按钮容器 */.floating-buttons {position: fixed;bottom: 20px;right: 20px;display: flex;flex-direction: column;gap: 10px;z-index: 100;}.floating-button {width: 50px;height: 50px;border-radius: 50%;background: var(--primary-color);color: white;display: flex;align-items: center;justify-content: center;box-shadow: var(--box-shadow);cursor: pointer;transition: var(--transition);border: none;font-size: 20px;}.floating-button:hover {transform: scale(1.1);background: var(--button-hover);}/* 响应式设计 */@media (max-width: 768px) {.main-content {flex-direction: column;}.params-panel {flex: 1;}.simple-mode .params-panel {flex: 1;}header {flex-direction: column;gap: 15px;align-items: flex-start;}.action-buttons {flex-direction: column;}.model-select-container {flex-direction: column;}#refreshModelBtn {width: 100%;}.desktop-buttons {display: none;}.floating-buttons {display: flex;}}@media (min-width: 769px) {.floating-buttons {display: none;}.desktop-buttons {display: flex;gap: 10px;}}</style>
</head>
<body>
<div class="container"><header><h1>AI 图片生成器</h1><div class="desktop-buttons"><button class="theme-toggle" id="themeToggle"><span id="themeIcon">🌙</span> <span id="themeText">暗夜模式</span></button><button id="simpleModeToggle"><span id="simpleModeIcon">📱</span> <span id="simpleModeText">简易模式</span></button></div></header><div class="floating-buttons"><button class="floating-button" id="mobileThemeToggle">🌙</button><button class="floating-button" id="mobileSimpleModeToggle">📱</button></div><div class="main-content"><div class="panel params-panel"><h2 class="panel-title">生成参数</h2><div class="action-buttons"><button id="generateBtn">生成图片</button><button id="downloadBtn" class="secondary-button" disabled>下载图片</button></div><div class="status-area" id="statusArea">就绪</div><div class="time-info" id="timeInfo"></div><div class="progress-container"><progress id="progressBar" value="0" max="100" style="display: none;"></progress><div class="loader" id="loader"></div></div><div class="form-group"><div class="model-refresh-container"><div class="model-search-container"><input type="text" id="modelSearch" placeholder="搜索模型..."><span class="search-hint">输入关键词筛选</span></div><div class="no-results" id="noResults">没有找到匹配的模型</div><div class="model-select-container"><select id="model"><option value="Qwen/Qwen-Image">Qwen/Qwen-Image</option><option value="Liudef/XB_F.1_MIX">Liudef/XB_F.1_MIX</option><option value="Liudef/XB_PONY">Liudef/XB_PONY</option><option value="Liudef/XB_Illustrious">Liudef/XB_Illustrious</option><option value="Liudef/XB_QWEN_ANIYA_FACE6_C">Liudef/XB_QWEN_ANIYA_FACE6_C</option><option value="Liudef/XB_F.1_ANIYA_FACE6_B">Liudef/XB_F.1_ANIYA_FACE6_B</option><option value="Liudef/XB_F.1_FACE_3">Liudef/XB_F.1_FACE_3</option><option value="Liudef/XB_F.1_MD">Liudef/XB_F.1_MD</option></select><button id="refreshModelBtn" title="刷新模型列表"><span class="refresh-icon" id="refreshIcon"></span></button></div><div class="model-info" id="modelInfo"><div class="model-info-title" id="modelTitle">模型信息</div><div class="model-info-intro" id="modelIntro">选择模型以查看详情</div></div></div></div><div class="form-group prompt-group"><label for="prompt">正向提示词</label><textarea id="prompt" placeholder="请输入详细的描述词以获得更好的效果...">一只棕色的猫</textarea></div><div class="form-group"><label for="negativePrompt">负向提示词 (可选)</label><textarea id="negativePrompt" placeholder="请输入不希望出现在图片中的内容...">lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry</textarea></div><div class="advanced-params"><h3 class="panel-title">高级参数</h3><div class="param-row"><div class="param-item"><label for="width">宽度</label><input type="number" id="width" min="64" max="2048" step="64" value="1024"></div><div class="param-item"><label for="height">高度</label><input type="number" id="height" min="64" max="2048" step="64" value="1024"></div></div><div class="param-row"><div class="param-item"><label for="steps">采样步数</label><input type="number" id="steps" min="1" max="100" value="30"></div><div class="param-item"><label for="guidance">引导系数</label><input type="number" id="guidance" min="1.5" max="20" step="0.1" value="3.5"></div></div></div></div><div class="panel preview-panel"><h2 class="panel-title">图片预览</h2><div class="preview-container" id="previewContainer"><img id="previewImage" class="preview-image" alt="生成的图片"><div class="preview-placeholder" id="previewPlaceholder"><p>图片将在此处显示</p><p>点击生成的图片可以放大查看</p></div></div></div></div>
</div><!-- 图片放大模态框 -->
<div class="modal" id="imageModal"><span class="close-modal" id="closeModal">×</span><img class="modal-content" id="modalImage">
</div><script>// 主题切换const themeToggle = document.getElementById('themeToggle');const themeIcon = document.getElementById('themeIcon');const themeText = document.getElementById('themeText');const mobileThemeToggle = document.getElementById('mobileThemeToggle');// 检查本地存储中的主题偏好const savedTheme = localStorage.getItem('theme');if (savedTheme === 'dark') {document.body.classList.add('dark-mode');themeIcon.textContent = '☀️';themeText.textContent = '明亮模式';}function toggleTheme() {document.body.classList.toggle('dark-mode');if (document.body.classList.contains('dark-mode')) {localStorage.setItem('theme', 'dark');themeIcon.textContent = '☀️';themeText.textContent = '明亮模式';} else {localStorage.setItem('theme', 'light');themeIcon.textContent = '🌙';themeText.textContent = '暗夜模式';}}themeToggle.addEventListener('click', toggleTheme);mobileThemeToggle.addEventListener('click', toggleTheme);// 简易模式切换const simpleModeToggle = document.getElementById('simpleModeToggle');const simpleModeIcon = document.getElementById('simpleModeIcon');const simpleModeText = document.getElementById('simpleModeText');const mobileSimpleModeToggle = document.getElementById('mobileSimpleModeToggle');// 检查本地存储中的简易模式偏好const savedSimpleMode = localStorage.getItem('simpleMode');if (savedSimpleMode === 'true') {document.body.classList.add('simple-mode');simpleModeIcon.textContent = '💻';simpleModeText.textContent = '完整模式';}function toggleSimpleMode() {document.body.classList.toggle('simple-mode');if (document.body.classList.contains('simple-mode')) {localStorage.setItem('simpleMode', 'true');simpleModeIcon.textContent = '💻';simpleModeText.textContent = '完整模式';} else {localStorage.setItem('simpleMode', 'false');simpleModeIcon.textContent = '📱';simpleModeText.textContent = '简易模式';}}simpleModeToggle.addEventListener('click', toggleSimpleMode);mobileSimpleModeToggle.addEventListener('click', toggleSimpleMode);// DOM 元素const generateBtn = document.getElementById('generateBtn');const downloadBtn = document.getElementById('downloadBtn');const progressBar = document.getElementById('progressBar');const statusArea = document.getElementById('statusArea');const timeInfo = document.getElementById('timeInfo');const previewImage = document.getElementById('previewImage');const previewPlaceholder = document.getElementById('previewPlaceholder');const previewContainer = document.getElementById('previewContainer');const loader = document.getElementById('loader');const refreshModelBtn = document.getElementById('refreshModelBtn');const refreshIcon = document.getElementById('refreshIcon');const modelSelect = document.getElementById('model');const modelInfo = document.getElementById('modelInfo');const modelTitle = document.getElementById('modelTitle');const modelIntro = document.getElementById('modelIntro');const modelSearch = document.getElementById('modelSearch');const noResults = document.getElementById('noResults');// 图片放大相关元素const imageModal = document.getElementById('imageModal');const modalImage = document.getElementById('modalImage');const closeModal = document.getElementById('closeModal');// 图片放大功能previewContainer.addEventListener('click', () => {if (!previewImage.src) return;modalImage.src = previewImage.src;imageModal.classList.add('show');});closeModal.addEventListener('click', () => {imageModal.classList.remove('show');});imageModal.addEventListener('click', (e) => {if (e.target === imageModal) {imageModal.classList.remove('show');}});// 状态变量let isGenerating = false;let startTime = null;let currentImageUrl = null;let currentTaskId = null;// 更新状态function updateStatus(message, isError = false) {statusArea.textContent = message;statusArea.style.color = isError ? 'var(--error-color)' : 'inherit';statusArea.style.borderLeftColor = isError ? 'var(--error-color)' : 'var(--primary-color)';}// 更新计时器function updateTimer() {if (!isGenerating || !startTime) return;const elapsed = Math.floor((Date.now() - startTime) / 1000);const minutes = Math.floor(elapsed / 60).toString().padStart(2, '0');const seconds = (elapsed % 60).toString().padStart(2, '0');timeInfo.textContent = `生成耗时: ${minutes}:${seconds}`;if (isGenerating) {requestAnimationFrame(updateTimer);}}// 显示图片function showImage(imageUrl) {previewPlaceholder.style.display = 'none';previewImage.style.display = 'block';previewImage.src = imageUrl;currentImageUrl = imageUrl;downloadBtn.disabled = false;// 添加图片加载动画previewImage.style.opacity = '0';setTimeout(() => {previewImage.style.opacity = '1';}, 10);}// 下载图片downloadBtn.addEventListener('click', () => {if (!currentImageUrl) return;const link = document.createElement('a');link.href = currentImageUrl;link.download = `ai_image_${new Date().toISOString().slice(0, 10)}.jpg`;document.body.appendChild(link);link.click();document.body.removeChild(link);});// 生成图片 - 使用原始API接口generateBtn.addEventListener('click', async () => {if (isGenerating) {updateStatus('当前已有任务正在运行', true);return;}const model = document.getElementById('model').value;const prompt = document.getElementById('prompt').value.trim();const negativePrompt = document.getElementById('negativePrompt').value.trim();const width = parseInt(document.getElementById('width').value);const height = parseInt(document.getElementById('height').value);const steps = parseInt(document.getElementById('steps').value);const guidance = parseFloat(document.getElementById('guidance').value);// 验证输入if (!prompt) {updateStatus('请输入提示词', true);return;}if (width < 64 || width > 2048 || height < 64 || height > 2048) {updateStatus('图像尺寸必须在64-2048像素之间', true);return;}if (steps < 1 || steps > 100) {updateStatus('采样步数必须在1-100之间', true);return;}if (guidance < 1.5 || guidance > 20) {updateStatus('引导系数必须在1.5-20.0之间', true);return;}// 开始生成isGenerating = true;startTime = Date.now();generateBtn.disabled = true;progressBar.style.display = 'none';loader.style.display = 'block';updateStatus('提交任务...');updateTimer();try {// 提交任务到后端代理 - 使用原始API接口const response = await fetch('/api/modelScope/generate', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({model: model,prompt: prompt,negativePrompt: negativePrompt || undefined,width: width,height: height,steps: steps,guidance: guidance})});if (!response.ok) {throw new Error(`API 错误: ${response.status} ${response.statusText}`);}const data = await response.json();if (data.error) {throw new Error(data.error);}currentTaskId = data.task_id;updateStatus(`任务ID: ${currentTaskId}`);// 开始轮询任务状态 - 使用原始API接口checkTaskStatus(currentTaskId);} catch (error) {handleGenerationError(error);}});// 轮询任务状态 - 使用原始API接口async function checkTaskStatus(taskId) {try {const response = await fetch(`/api/modelScope/checkStatus?taskId=${taskId}`);if (!response.ok) {throw new Error(`状态检查失败: ${response.status} ${response.statusText}`);}const data = await response.json();if (data.error) {throw new Error(data.error);}const status = data.task_status;// 更新进度和状态switch (status) {case 'PENDING':updateStatus('任务排队中...');progressBar.value = 10;break;case 'PROCESSING':updateStatus('图片生成中...');progressBar.value = 30;break;case 'SUCCEED':progressBar.value = 100;updateStatus('生成成功!');// 获取图片const imageUrl = data.output_images[0];showImage(imageUrl);// 计算总耗时const totalTime = Math.floor((Date.now() - startTime) / 1000);const minutes = Math.floor(totalTime / 60);const seconds = totalTime % 60;timeInfo.textContent = `总耗时: ${minutes}分${seconds}秒`;// 完成finishGeneration();return;case 'FAILED':throw new Error('图片生成失败: ' + (data.message || '未知错误'));default:// 继续轮询break;}// 如果任务未完成,继续轮询setTimeout(() => checkTaskStatus(taskId), 3000);} catch (error) {handleGenerationError(error);}}// 处理生成错误function handleGenerationError(error) {updateStatus(`错误: ${error.message}`, true);// 计算总耗时if (startTime) {const totalTime = Math.floor((Date.now() - startTime) / 1000);const minutes = Math.floor(totalTime / 60);const seconds = totalTime % 60;timeInfo.textContent = `总耗时: ${minutes}分${seconds}秒`;}finishGeneration();}// 完成生成function finishGeneration() {isGenerating = false;generateBtn.disabled = false;progressBar.style.display = 'none';loader.style.display = 'none';currentTaskId = null;}// 模型模糊搜索功能modelSearch.addEventListener('input', function() {const searchTerm = this.value.trim().toLowerCase();const options = modelSelect.options;let hasVisibleOptions = false;// 重置显示所有选项for (let i = 0; i < options.length; i++) {options[i].style.display = '';}// 如果有搜索词,则进行过滤if (searchTerm) {for (let i = 0; i < options.length; i++) {const optionText = options[i].text.toLowerCase();if (optionText.includes(searchTerm)) {options[i].style.display = '';hasVisibleOptions = true;} else {options[i].style.display = 'none';}}// 显示/隐藏无结果提示noResults.style.display = hasVisibleOptions ? 'none' : 'block';// 自动选择第一个可见选项for (let i = 0; i < options.length; i++) {if (options[i].style.display !== 'none') {modelSelect.value = options[i].value;// 更新模型信息modelInfo.style.display = 'block';modelTitle.textContent = options[i].text;modelIntro.textContent = `模型ID: ${options[i].value}`;break;}}} else {// 清空搜索时隐藏无结果提示noResults.style.display = 'none';// 恢复默认选择modelSelect.value = modelSelect.options[0].value;// 更新模型信息modelInfo.style.display = 'block';modelTitle.textContent = modelSelect.options[0].text;modelIntro.textContent = `模型ID: ${modelSelect.options[0].value}`;}});// 模型刷新功能 - 使用原始API接口refreshModelBtn.addEventListener('click', async () => {// 防止重复点击if (refreshIcon.classList.contains('refreshing')) return;refreshIcon.classList.add('refreshing');refreshModelBtn.disabled = true;updateStatus('正在获取模型列表...');try {// 调用模型列表APIconst response = await fetch('/api/modelScope/modelList');if (!response.ok) {throw new Error(`获取模型列表失败: ${response.status} ${response.statusText}`);}const modelList = await response.json();if (!Array.isArray(modelList) || modelList.length === 0) {throw new Error('未获取到模型数据');}// 清空当前模型选择modelSelect.innerHTML = '';// 添加新的模型选项modelList.forEach(model => {const option = document.createElement('option');option.value = model.modelId;option.textContent = model.modelName;modelSelect.appendChild(option);});updateStatus('模型列表已更新', false);modelInfo.style.display = 'block';modelTitle.textContent = '模型列表已刷新';modelIntro.innerHTML = `<span class="success-message">成功获取 ${modelList.length} 个模型</span>`;} catch (error) {updateStatus(`错误: ${error.message}`, true);modelInfo.style.display = 'block';modelTitle.textContent = '刷新失败';modelIntro.innerHTML = `<span class="error-message">${error.message}</span>`;} finally {refreshIcon.classList.remove('refreshing');refreshModelBtn.disabled = false;// 刷新后重新应用搜索过滤if (modelSearch.value.trim()) {modelSearch.dispatchEvent(new Event('input'));}// 5秒后隐藏状态信息setTimeout(() => {updateStatus('就绪');}, 5000);}});// 模型选择变化时显示模型信息modelSelect.addEventListener('change', () => {const selectedOption = modelSelect.options[modelSelect.selectedIndex];const modelId = selectedOption.value;modelInfo.style.display = 'block';modelTitle.textContent = selectedOption.textContent;modelIntro.textContent = `模型ID: ${modelId}`;});// 初始化显示默认模型信息modelInfo.style.display = 'block';modelTitle.textContent = 'Qwen/Qwen-Image';modelIntro.textContent = '模型ID: Qwen/Qwen-Image';
</script>
</body>
</html>
关键修复内容:
-
恢复了模型列表接口实现:
- 在模型刷新功能中,使用原始API接口
/api/modelScope/modelList
- 正确处理API响应,动态更新模型选择框
- 在模型刷新功能中,使用原始API接口
-
完整保留了原始接口实现:
- 图片生成接口:
/api/modelScope/generate
- 状态检查接口:
/api/modelScope/checkStatus?taskId=...
- 模型列表接口:
/api/modelScope/modelList
- 图片生成接口:
-
修正了模型刷新功能:
- 移除了模拟数据
- 使用实际的API调用获取模型列表
- 正确处理错误和成功状态
- 更新模型选择框后保持搜索过滤功能
-
保留了所有改进功能:
- 简易模式切换(桌面端和移动端)
- 移动端悬浮按钮
- 响应式设计
- 本地存储偏好设置
这个版本完整恢复了所有原始API接口实现,包括模型列表接口,同时保留了您要求的简易模式功能。所有接口调用都使用原始路径,确保与后端服务的兼容性。