| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 |
- /**
- * AI生图弹出框
- */
- class AIGenerateView {
- constructor() {
- this.overlay = null;
- this.modal = null;
- this.previewImage = null;
- this.previewPlaceholder = null;
- this.referenceBox = null;
- this.referenceInput = null;
- this.referenceUploadArea = null;
- this.referenceImage = null;
- this.referenceImageWrapper = null;
- this.referenceRemoveBtn = null;
- this.generateBtn = null;
- this.isGenerateEnabled = false;
- this.additionalPromptInput = null;
- this.cancelBtn = null;
- this.imageData = null;
- this.referenceImageData = null;
- this.originalSpritesheetData = null;
- this.spritesheetLayout = null;
- this.folderName = null;
-
- // 当前会话的任务ID列表
- this.sessionTaskIds = [];
- this.queuePollingTimer = null;
-
- this.init();
- }
- init() {
- this.overlay = document.getElementById('aiGenerateOverlay');
- this.modal = document.getElementById('aiGenerateModal');
- this.previewImage = document.getElementById('previewImage');
- this.previewPlaceholder = document.getElementById('previewPlaceholder');
- this.referenceBox = document.getElementById('referenceBox');
- this.referenceInput = document.getElementById('referenceInput');
- this.referenceUploadArea = document.getElementById('referenceUploadArea');
- this.referenceImage = document.getElementById('referenceImage');
- this.referenceImageWrapper = document.getElementById('referenceImageWrapper');
- this.referenceRemoveBtn = document.getElementById('referenceRemoveBtn');
- this.generateBtn = document.getElementById('generateBtn');
- this.aiGeneratePriceEl = document.getElementById('aiGeneratePrice');
- this.additionalPromptInput = document.getElementById('additionalPromptInput');
- this.cancelBtn = document.getElementById('aiGenerateCancelBtn');
-
- // 加载AI生图价格
- this.loadAIGeneratePrice();
-
- this.bindEvents();
- this.reset();
- }
- bindEvents() {
- // 关闭按钮
- this.cancelBtn?.addEventListener('click', () => {
- this.close();
- });
- // AI生图按钮
- this.generateBtn?.addEventListener('click', () => {
- this.generateAI();
- });
- // 删除参考图按钮
- this.referenceRemoveBtn?.addEventListener('click', (e) => {
- e.stopPropagation();
- this.removeReferenceImage();
- });
- // 点击遮罩层关闭
- this.overlay?.addEventListener('click', (e) => {
- if (e.target === this.overlay) {
- this.close();
- }
- });
- // ESC键关闭
- document.addEventListener('keydown', (e) => {
- if (e.key === 'Escape' && this.overlay) {
- this.close();
- }
- });
- // 参考图上传区域点击
- this.referenceBox?.addEventListener('click', () => {
- this.referenceInput?.click();
- });
- // 参考图选择
- this.referenceInput?.addEventListener('change', (e) => {
- const file = e.target.files[0];
- if (file) {
- this.loadReferenceImage(file);
- }
- });
- // 拖拽上传参考图
- this.referenceBox?.addEventListener('dragover', (e) => {
- e.preventDefault();
- e.stopPropagation();
- if (this.referenceBox) {
- this.referenceBox.style.borderColor = '#667eea';
- }
- });
- this.referenceBox?.addEventListener('dragleave', (e) => {
- e.preventDefault();
- e.stopPropagation();
- if (this.referenceBox) {
- this.referenceBox.style.borderColor = '#e5e7eb';
- }
- });
- this.referenceBox?.addEventListener('drop', (e) => {
- e.preventDefault();
- e.stopPropagation();
- if (this.referenceBox) {
- this.referenceBox.style.borderColor = '#e5e7eb';
- }
-
- const file = e.dataTransfer.files[0];
- if (file && file.type.startsWith('image/')) {
- this.loadReferenceImage(file);
- }
- });
- // 监听来自父窗口的消息
- window.addEventListener('message', (event) => {
- if (event.data && event.data.type === 'show-ai-generate') {
- this.reset();
- this.folderName = event.data.folderName;
- this.originalSpritesheetData = event.data.spritesheetData;
- this.spritesheetLayout = event.data.spritesheetLayout;
- this.showPreview(event.data.spritesheetData);
- }
- });
- }
- /**
- * 显示预览图
- */
- showPreview(imageUrl) {
- if (!imageUrl) return;
- this.imageData = imageUrl;
-
- const img = new Image();
- img.onload = () => {
- if (this.previewImage) {
- this.previewImage.src = imageUrl;
- this.previewImage.classList.add('show');
- }
- if (this.previewPlaceholder) {
- this.previewPlaceholder.classList.add('hide');
- }
- };
-
- img.onerror = () => {
- if (this.previewPlaceholder) {
- const spinner = this.previewPlaceholder.querySelector('.loading-spinner');
- const loadingText = this.previewPlaceholder.querySelector('.loading-text');
- if (spinner) spinner.style.display = 'none';
- if (loadingText) {
- loadingText.textContent = '图片加载失败';
- loadingText.style.color = '#ef4444';
- }
- this.previewPlaceholder.classList.remove('hide');
- }
- };
-
- img.src = imageUrl;
- }
- /**
- * 加载参考图
- */
- loadReferenceImage(file) {
- const reader = new FileReader();
- reader.onload = (e) => {
- const data = e.target.result;
- this.referenceImageData = data;
- this.showReferenceImage(data);
- this.setGenerateButtonState(true);
- };
- reader.readAsDataURL(file);
- }
- /**
- * 删除参考图
- */
- removeReferenceImage() {
- this.referenceImageData = null;
- if (this.referenceImageWrapper) {
- this.referenceImageWrapper.style.display = 'none';
- }
- if (this.referenceImage) {
- this.referenceImage.src = '';
- }
- if (this.referenceUploadArea) {
- this.referenceUploadArea.classList.remove('hide');
- }
- if (this.referenceInput) {
- this.referenceInput.value = '';
- }
- this.setGenerateButtonState(false);
- }
- /**
- * 设置生图按钮状态
- * @param {boolean} enabled
- */
- setGenerateButtonState(enabled) {
- this.isGenerateEnabled = !!enabled;
- if (this.generateBtn) {
- this.generateBtn.disabled = !enabled;
- }
- }
- /**
- * AI生图
- */
- async generateAI() {
- if (!this.originalSpritesheetData || !this.referenceImageData) {
- this.showAlert('请先上传参考图');
- return;
- }
- const username = this.getCurrentUsername();
- if (!username) {
- this.showAlert('请先登录');
- return;
- }
- // 检查 Ani币余额
- try {
- const pricingResponse = await fetch('/api/product-pricing');
- if (!pricingResponse.ok) {
- throw new Error('获取价格失败');
- }
- const pricingResult = await pricingResponse.json();
- if (!pricingResult.success || !pricingResult.products) {
- throw new Error('获取价格失败');
- }
-
- const aiGenerateProduct = pricingResult.products.find(p => p.id === 'ai-generate');
- const price = aiGenerateProduct ? (aiGenerateProduct.price || 0) : 0;
-
- if (price > 0) {
- const pointsResponse = await fetch(`/api/user/points?username=${encodeURIComponent(username)}`);
- if (!pointsResponse.ok) {
- throw new Error('获取点数失败');
- }
- const pointsResult = await pointsResponse.json();
- if (!pointsResult.success) {
- throw new Error('获取点数失败');
- }
-
- const userPoints = pointsResult.points || 0;
-
- if (userPoints < price) {
- if (window.parent && window.parent.postMessage) {
- window.parent.postMessage({
- type: 'open-recharge-view',
- needPoints: price,
- currentPoints: userPoints
- }, '*');
- }
- this.showAlert(`Ani币不足,需要 ${price} Ani币,您当前有 ${userPoints.toFixed(2)} Ani币。请先充值!`);
- return;
- }
- }
- } catch (error) {
- console.error('[AIGenerateView] 余额检查失败:', error);
- this.showAlert('检查余额失败:' + error.message);
- return;
- }
- // 禁用生图按钮
- if (this.generateBtn) {
- this.generateBtn.disabled = true;
- }
- try {
- // 准备图片数据
- // image1 直接使用参考图,image2 使用原始spritesheet
- const image1Base64 = this.referenceImageData.replace(/^data:image\/\w+;base64,/, '');
- const image2Base64 = this.originalSpritesheetData.replace(/^data:image\/\w+;base64,/, '');
- const image1Width = this.spritesheetLayout?.sheetWidth || 0;
- const image1Height = this.spritesheetLayout?.sheetHeight || 0;
- const additionalPrompt = this.additionalPromptInput?.value || '';
- // 扣除Ani币
- const pricingResponse = await fetch('/api/product-pricing');
- const pricingResult = await pricingResponse.json();
- const aiGenerateProduct = pricingResult.products?.find(p => p.id === 'ai-generate');
- const price = aiGenerateProduct ? (aiGenerateProduct.price || 0) : 0;
-
- if (price > 0) {
- const deductResponse = await fetch('/api/user/deduct-points', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ username, points: price })
- });
-
- if (!deductResponse.ok) {
- const deductResult = await deductResponse.json();
- throw new Error(deductResult.message || '扣除Ani币失败');
- }
- const deductResult = await deductResponse.json();
- if (!deductResult.success) {
- throw new Error(deductResult.message || '扣除Ani币失败');
- }
-
- // 通知父窗口刷新点数
- if (window.parent && window.parent.postMessage) {
- window.parent.postMessage({ type: 'refresh-points' }, '*');
- }
- }
- // 调用队列API
- const response = await fetch('/api/ai/generate', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- username: username,
- image1: image1Base64,
- image2: image2Base64,
- image1Width: image1Width,
- image1Height: image1Height,
- additionalPrompt: additionalPrompt
- })
- });
- if (!response.ok) {
- const errorData = await response.json().catch(() => ({}));
- throw new Error(errorData.message || '请求生图失败');
- }
- const result = await response.json();
-
- if (result.success && result.taskId) {
- this.sessionTaskIds.push(result.taskId);
- this.showFlyAwayAnimation();
- this.loadAIQueue(username);
- } else {
- throw new Error(result.message || '请求失败');
- }
- } catch (error) {
- console.error('[AIGenerateView] 请求生图失败:', error);
- this.showAlert(error.message || '请求失败,请稍后重试');
- } finally {
- if (this.generateBtn) {
- this.generateBtn.disabled = false;
- }
- }
- }
- /**
- * 加载AI生图队列
- */
- async loadAIQueue(username) {
- if (!this.sessionTaskIds || this.sessionTaskIds.length === 0) {
- const queueSection = document.getElementById('aiQueueSection');
- if (queueSection) {
- queueSection.style.display = 'none';
- }
- return;
- }
-
- if (!username) {
- username = this.getCurrentUsername();
- }
- if (!username) return;
- try {
- const response = await fetch(`/api/ai/history?username=${encodeURIComponent(username)}`);
- if (!response.ok) return;
-
- const result = await response.json();
- if (!result.success || !result.history) return;
-
- const sessionTasks = result.history.filter(t => this.sessionTaskIds.includes(t.id));
- this.renderAIQueue(sessionTasks);
-
- // 如果有进行中的任务,继续轮询
- const hasPending = sessionTasks.some(t => t.status === 'queued' || t.status === 'rendering');
- if (hasPending) {
- if (this.queuePollingTimer) {
- clearTimeout(this.queuePollingTimer);
- }
- this.queuePollingTimer = setTimeout(() => {
- this.loadAIQueue(username);
- }, 3000);
- }
- } catch (error) {
- console.error('[AIGenerateView] 加载AI队列失败:', error);
- }
- }
- /**
- * 渲染AI队列
- */
- renderAIQueue(tasks) {
- const queueSection = document.getElementById('aiQueueSection');
- const queueList = document.getElementById('aiQueueList');
-
- if (!queueSection || !queueList) return;
-
- if (tasks.length === 0) {
- queueSection.style.display = 'none';
- return;
- }
-
- queueSection.style.display = 'block';
- queueList.innerHTML = tasks.map(task => this.createQueueItemHTML(task)).join('');
-
- // 绑定点击预览事件
- queueList.querySelectorAll('.ai-queue-item').forEach(item => {
- const taskId = item.dataset.taskId;
- const task = tasks.find(t => t.id === taskId);
-
- if (task && task.status === 'completed' && task.imageUrl) {
- item.style.cursor = 'pointer';
- item.addEventListener('click', () => {
- this.showImagePreviewModal(task.imageUrl, task.id);
- });
- }
- });
- }
- /**
- * 创建队列项HTML
- */
- createQueueItemHTML(task) {
- const previewUrl = task.previewUrl || '';
-
- if (task.status === 'queued' || task.status === 'rendering') {
- const statusText = task.status === 'queued' ? '等待中' : '生成中';
- return `
- <div class="ai-queue-item ${task.status}" data-task-id="${task.id}">
- ${previewUrl ? `<img class="ai-queue-item-preview" src="${previewUrl}" alt="预览">` : ''}
- <div class="ai-queue-item-overlay">
- <div class="ai-queue-item-spinner"></div>
- <div class="ai-queue-item-status">${statusText}</div>
- </div>
- </div>
- `;
- } else if (task.status === 'completed' && task.imageUrl) {
- return `
- <div class="ai-queue-item completed" data-task-id="${task.id}" title="点击放大预览">
- <img class="ai-queue-item-preview" src="${task.imageUrl}" alt="完成">
- <div class="ai-queue-item-overlay">
- <div class="ai-queue-item-icon">🔍</div>
- </div>
- </div>
- `;
- } else if (task.status === 'failed') {
- return `
- <div class="ai-queue-item failed" data-task-id="${task.id}">
- ${previewUrl ? `<img class="ai-queue-item-preview" src="${previewUrl}" alt="预览">` : ''}
- <div class="ai-queue-item-overlay">
- <div class="ai-queue-item-icon">❌</div>
- <div class="ai-queue-item-status">失败</div>
- </div>
- </div>
- `;
- }
- return '';
- }
- /**
- * 显示图片预览弹窗
- */
- showImagePreviewModal(imageUrl, taskId) {
- // 在父窗口中创建预览弹窗,确保在最上层
- let targetDocument = document;
- try {
- if (window.parent && window.parent !== window && window.parent.document) {
- targetDocument = window.parent.document;
- }
- } catch (e) {}
-
- const modal = targetDocument.createElement('div');
- modal.className = 'image-preview-modal';
- modal.style.cssText = 'position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 9999999; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease;';
- modal.innerHTML = `
- <div class="image-preview-modal-backdrop" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.85); backdrop-filter: blur(8px);"></div>
- <div class="image-preview-modal-content" style="position: relative; max-width: 90vw; max-height: 90vh; transform: scale(0.9); transition: transform 0.3s ease;">
- <img src="${imageUrl}" alt="AI生成图预览" style="max-width: 100%; max-height: 85vh; border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);">
- <button class="image-preview-modal-close" style="position: absolute; top: -40px; right: 0; width: 36px; height: 36px; border: none; background: rgba(255, 255, 255, 0.2); color: white; font-size: 24px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 1; transition: all 0.2s;">×</button>
- </div>
- `;
-
- targetDocument.body.appendChild(modal);
-
- // 显示动画
- requestAnimationFrame(() => {
- modal.style.opacity = '1';
- modal.querySelector('.image-preview-modal-content').style.transform = 'scale(1)';
- });
-
- const closeModal = () => {
- modal.style.opacity = '0';
- modal.querySelector('.image-preview-modal-content').style.transform = 'scale(0.9)';
- setTimeout(() => {
- if (modal.parentNode) {
- modal.parentNode.removeChild(modal);
- }
- }, 300);
- };
-
- modal.querySelector('.image-preview-modal-backdrop').onclick = closeModal;
- modal.querySelector('.image-preview-modal-close').onclick = closeModal;
-
- // 鼠标悬停关闭按钮效果
- const closeBtn = modal.querySelector('.image-preview-modal-close');
- closeBtn.onmouseenter = () => {
- closeBtn.style.background = 'rgba(255, 255, 255, 0.3)';
- closeBtn.style.transform = 'scale(1.1)';
- };
- closeBtn.onmouseleave = () => {
- closeBtn.style.background = 'rgba(255, 255, 255, 0.2)';
- closeBtn.style.transform = 'scale(1)';
- };
-
- // ESC关闭(在父窗口监听)
- const targetWindow = targetDocument.defaultView || window;
- const escHandler = (e) => {
- if (e.key === 'Escape') {
- closeModal();
- targetWindow.removeEventListener('keydown', escHandler);
- }
- };
- targetWindow.addEventListener('keydown', escHandler);
- }
- /**
- * 显示飞走动画
- */
- showFlyAwayAnimation() {
- let targetDocument = document;
- let targetWindow = window;
-
- try {
- if (window.parent && window.parent !== window && window.parent.document) {
- targetDocument = window.parent.document;
- targetWindow = window.parent;
- }
- } catch (e) {}
-
- const flyElement = targetDocument.createElement('div');
- flyElement.innerHTML = `
- <div style="display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; white-space: nowrap;">
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/>
- </svg>
- <span>AI生图任务</span>
- </div>
- `;
-
- let startLeft = targetWindow.innerWidth / 2;
- let startTop = targetWindow.innerHeight / 2;
-
- if (this.generateBtn) {
- const btnRect = this.generateBtn.getBoundingClientRect();
- try {
- if (window.parent && window.parent !== window) {
- const iframe = window.parent.document.querySelector('iframe[src*="ai-generate"]');
- if (iframe) {
- const iframeRect = iframe.getBoundingClientRect();
- startLeft = iframeRect.left + btnRect.left;
- startTop = iframeRect.top + btnRect.top;
- }
- }
- } catch (e) {
- startLeft = btnRect.left;
- startTop = btnRect.top;
- }
- }
-
- flyElement.style.cssText = `
- position: fixed;
- left: ${startLeft}px;
- top: ${startTop}px;
- z-index: 999999;
- pointer-events: none;
- transition: all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
- opacity: 1;
- transform: scale(1);
- background: linear-gradient(135deg, #10b981 0%, #059669 100%);
- color: white;
- padding: 12px 20px;
- border-radius: 12px;
- box-shadow: 0 8px 32px rgba(16, 185, 129, 0.4);
- display: flex;
- align-items: center;
- gap: 8px;
- `;
-
- targetDocument.body.appendChild(flyElement);
-
- requestAnimationFrame(() => {
- flyElement.style.left = `${targetWindow.innerWidth - 100}px`;
- flyElement.style.top = '50px';
- flyElement.style.opacity = '0';
- flyElement.style.transform = 'scale(0.3)';
- });
-
- setTimeout(() => {
- if (window.parent && window.parent.HintView) {
- window.parent.HintView.success('已添加到「我的」-「AI生图历史」,请稍后查看', 3000);
- }
- }, 300);
-
- setTimeout(() => {
- if (flyElement.parentNode) {
- flyElement.parentNode.removeChild(flyElement);
- }
- }, 1000);
- }
- /**
- * 加载AI生图价格
- */
- async loadAIGeneratePrice() {
- try {
- const response = await fetch('/api/product-pricing');
- if (response.ok) {
- const result = await response.json();
- if (result.success && result.products) {
- const aiGenerateProduct = result.products.find(p => p.id === 'ai-generate');
- if (aiGenerateProduct && this.aiGeneratePriceEl) {
- const price = aiGenerateProduct.price || 0;
- if (price > 0) {
- this.aiGeneratePriceEl.textContent = `${price} Ani币`;
- } else {
- this.aiGeneratePriceEl.textContent = '免费';
- }
- }
- }
- }
- } catch (error) {
- console.error('[AIGenerateView] 加载AI生图价格失败:', error);
- if (this.aiGeneratePriceEl) {
- this.aiGeneratePriceEl.textContent = '-';
- }
- }
- }
- /**
- * 获取当前登录用户名
- */
- getCurrentUsername() {
- try {
- const loginDataStr = localStorage.getItem('loginData');
- if (!loginDataStr) return null;
-
- const loginData = JSON.parse(loginDataStr);
- const now = Date.now();
-
- if (now >= loginData.expireTime) {
- localStorage.removeItem('loginData');
- return null;
- }
-
- return loginData.user ? loginData.user.username : null;
- } catch (error) {
- console.error('[AIGenerateView] 获取用户名失败:', error);
- return null;
- }
- }
- /**
- * 显示提示
- */
- showAlert(message, duration = 2000) {
- try {
- if (window.parent && window.parent !== window && window.parent.GlobalAlert) {
- window.parent.GlobalAlert.show(message, duration);
- return;
- }
-
- if (window.GlobalAlert) {
- window.GlobalAlert.show(message, duration);
- return;
- }
-
- console.log('[Alert]', message);
- } catch (error) {
- console.error('[AIGenerateView] 显示 alert 失败:', error);
- alert(message);
- }
- }
- /**
- * 关闭弹窗
- */
- close() {
- this.reset();
-
- if (window.parent && window.parent !== window) {
- window.parent.postMessage({
- type: 'close-ai-generate-view'
- }, '*');
- }
- }
- /**
- * 重置状态
- */
- reset() {
- this.imageData = null;
- this.referenceImageData = null;
- this.sessionTaskIds = [];
-
- if (this.queuePollingTimer) {
- clearTimeout(this.queuePollingTimer);
- this.queuePollingTimer = null;
- }
-
- const queueSection = document.getElementById('aiQueueSection');
- if (queueSection) {
- queueSection.style.display = 'none';
- }
- if (this.referenceImageWrapper) {
- this.referenceImageWrapper.style.display = 'none';
- }
- if (this.referenceImage) {
- this.referenceImage.src = '';
- }
- if (this.referenceUploadArea) {
- this.referenceUploadArea.classList.remove('hide');
- }
- if (this.referenceInput) {
- this.referenceInput.value = '';
- }
- if (this.previewImage) {
- this.previewImage.src = '';
- this.previewImage.classList.remove('show');
- }
- if (this.previewPlaceholder) {
- const spinner = this.previewPlaceholder.querySelector('.loading-spinner');
- const loadingText = this.previewPlaceholder.querySelector('.loading-text');
- if (spinner) spinner.style.display = 'block';
- if (loadingText) {
- loadingText.textContent = '正在生成预览图...';
- loadingText.style.color = '#6b7280';
- }
- this.previewPlaceholder.classList.remove('hide');
- }
- const promptConfigSection = document.getElementById('promptConfigSection');
- if (promptConfigSection) {
- promptConfigSection.style.display = 'flex';
- }
- if (this.additionalPromptInput) {
- this.additionalPromptInput.value = '';
- }
- this.setGenerateButtonState(false);
- }
- /**
- * 显示参考图并隐藏上传区域
- */
- showReferenceImage(dataUrl) {
- if (this.referenceImage) {
- this.referenceImage.src = dataUrl;
- }
- if (this.referenceImageWrapper) {
- this.referenceImageWrapper.style.display = 'flex';
- }
- if (this.referenceUploadArea) {
- this.referenceUploadArea.classList.add('hide');
- }
- const promptConfigSection = document.getElementById('promptConfigSection');
- if (promptConfigSection) {
- promptConfigSection.style.display = 'flex';
- }
- }
- }
- // 初始化
- window.AIGenerateView = new AIGenerateView();
|