From 07a757813eb71fd32acac2672501ac7c67239d1e Mon Sep 17 00:00:00 2001 From: "lihaozhe.charlie" Date: Mon, 22 Dec 2025 23:17:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D=20&=20gemini=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=97=B6=E9=97=B4=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app.py | 10 ++++++++++ backend/comic_generator.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/backend/app.py b/backend/app.py index 8bb24e3..2c7ae72 100644 --- a/backend/app.py +++ b/backend/app.py @@ -2,9 +2,19 @@ Comic Generator Flask Application Main entry point - registers all Blueprints """ +import logging from flask import Flask from flask_cors import CORS +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + handlers=[ + logging.StreamHandler() # Output to console + ] +) + # Configure Flask with explicit static folder app = Flask(__name__, static_folder='static', static_url_path='/static') CORS(app) # Enable CORS for frontend requests diff --git a/backend/comic_generator.py b/backend/comic_generator.py index 84e4d37..8eb708d 100644 --- a/backend/comic_generator.py +++ b/backend/comic_generator.py @@ -30,7 +30,7 @@ def generate_social_media_image_core( if not api_key: raise ValueError("Google API key is required. Please provide google_api_key parameter or set GOOGLE_API_KEY environment variable.") - client = genai.Client(api_key=api_key, vertexai=False) + client = genai.Client(api_key=api_key, vertexai=False, http_options={'timeout':120000}) MODEL_ID = "gemini-3-pro-image-preview" logger.info(f"Generating social media image for: {prompt}") From 756f1d7f99acc103068bbd9e20181b11e9b195f9 Mon Sep 17 00:00:00 2001 From: "lihaozhe.charlie" Date: Mon, 22 Dec 2025 23:45:18 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D=20&=20gemini=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=97=B6=E9=97=B4=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/app.py b/backend/app.py index 2c7ae72..0b9f79a 100644 --- a/backend/app.py +++ b/backend/app.py @@ -15,6 +15,7 @@ ] ) + # Configure Flask with explicit static folder app = Flask(__name__, static_folder='static', static_url_path='/static') CORS(app) # Enable CORS for frontend requests From 62897e9f2d0edf3c2c9e0a48d5bc166eb28012fd Mon Sep 17 00:00:00 2001 From: "lihaozhe.charlie" Date: Tue, 23 Dec 2025 12:59:41 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=96=B0session=E6=97=B6?= =?UTF-8?q?=E8=AE=B0=E4=BD=8F=E4=B8=8A=E6=AC=A1=E7=9A=84=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/services/image_service.py | 1 + frontend/js/app.js | 14 +++++++++++--- frontend/js/sessionManager.js | 10 +++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/backend/services/image_service.py b/backend/services/image_service.py index 7ec3f58..04fa605 100644 --- a/backend/services/image_service.py +++ b/backend/services/image_service.py @@ -181,6 +181,7 @@ def _create_cover_prompt(comic_style: str) -> str: - Clear and sharp text for the title, do not repeat all the titles in reference images. - Vibrant colors and "Cover Art" aesthetic. - Only present one row one panel in the cover. +- 生成的图片务必使用中文 """ final_prompt = prompt_template.format(comic_style=comic_style) print(f"Cover Prompt: {final_prompt}") diff --git a/frontend/js/app.js b/frontend/js/app.js index 12c766b..786605e 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -1428,10 +1428,18 @@ class UIController { // Save current session state this.saveCurrentSessionState(); - // Create new session + // Get current options to reuse in new session + const currentOptions = { + style: this.comicStyleSelect.value, + language: this.comicLanguageSelect.value, + pageCount: parseInt(this.pageCountInput.value), + prompt: this.promptInput.value + }; + + // Create new session with current options const sessionCount = this.sessionManager.getAllSessions().length + 1; const defaultName = 'session ' + sessionCount; - const session = this.sessionManager.createSession(defaultName); + const session = this.sessionManager.createSession(defaultName, currentOptions); // Switch to new session this.sessionManager.switchSession(session.id); @@ -1458,7 +1466,7 @@ class UIController { // Update UI this.updateSessionSelector(); - // Load default state for new session (language, style) + // Load state for new session (will use the options we passed) this.loadSessionState(); } diff --git a/frontend/js/sessionManager.js b/frontend/js/sessionManager.js index 938e40b..c1c4155 100644 --- a/frontend/js/sessionManager.js +++ b/frontend/js/sessionManager.js @@ -38,7 +38,7 @@ class SessionManager { * @param {string} name - Session name * @returns {Object} Created session */ - createSession(name) { + createSession(name, options = {}) { const sessionId = this.generateSessionId(); const now = new Date().toISOString(); @@ -48,10 +48,10 @@ class SessionManager { comicData: null, generatedImages: {}, currentPageIndex: 0, - style: 'doraemon', // Default style - language: (window.i18n && typeof window.i18n.getLanguage === 'function') ? window.i18n.getLanguage() : 'en', - pageCount: 3, - prompt: '', + style: options.style || 'doraemon', // Use provided style or default + language: options.language || ((window.i18n && typeof window.i18n.getLanguage === 'function') ? window.i18n.getLanguage() : 'en'), + pageCount: options.pageCount || 3, + prompt: options.prompt || '', createdAt: now, updatedAt: now }; From 9809884562d42547e991e3f9df59a7d59495146c Mon Sep 17 00:00:00 2001 From: "lihaozhe.charlie" Date: Tue, 23 Dec 2025 13:18:14 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E7=94=9F=E6=88=90=E5=B0=81=E9=9D=A2?= =?UTF-8?q?=E6=97=B6=E4=BD=BF=E7=94=A8=E7=95=8C=E9=9D=A2=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controllers/image_controller.py | 8 +++++--- backend/services/image_service.py | 27 ++++++++++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/backend/controllers/image_controller.py b/backend/controllers/image_controller.py index dbd432e..0822b67 100644 --- a/backend/controllers/image_controller.py +++ b/backend/controllers/image_controller.py @@ -86,17 +86,19 @@ def generate_comic_cover_endpoint(): return jsonify({"error": "Google API key is required"}), 400 comic_style = data.get('comic_style', 'doraemon') + language = data.get('language', 'en') reference_imgs = data.get('reference_imgs') - + print(f"[Cover Generation] Reference images count: {len(reference_imgs) if reference_imgs else 0}") if reference_imgs: print(f"[Cover Generation] First reference: {reference_imgs[0] if len(reference_imgs) > 0 else 'None'}") - + # Generate cover using service image_url, prompt = ImageService.generate_comic_cover( comic_style=comic_style, google_api_key=google_api_key, - reference_imgs=reference_imgs + reference_imgs=reference_imgs, + language=language ) if not image_url: diff --git a/backend/services/image_service.py b/backend/services/image_service.py index 04fa605..961d7b9 100644 --- a/backend/services/image_service.py +++ b/backend/services/image_service.py @@ -67,21 +67,23 @@ def generate_comic_image( def generate_comic_cover( comic_style: str = 'doraemon', google_api_key: str = None, - reference_imgs: List[Union[str, Dict]] = None + reference_imgs: List[Union[str, Dict]] = None, + language: str = 'en' ) -> tuple[Optional[str], str]: """ Generate comic cover image - + Args: comic_style: Style of the comic google_api_key: Google API key reference_imgs: List of reference image URLs - + language: Language for cover generation (en, zh, ja) + Returns: Tuple of (image_url, prompt) """ # Create cover prompt - prompt = ImageService._create_cover_prompt(comic_style) + prompt = ImageService._create_cover_prompt(comic_style, language) # Prepare reference images list (extract URLs from objects if needed) processed_refs = [] @@ -168,8 +170,16 @@ def _convert_page_to_prompt(page_data: Dict[str, Any], comic_style: str = 'dorae return final_prompt @staticmethod - def _create_cover_prompt(comic_style: str) -> str: + def _create_cover_prompt(comic_style: str, language: str = 'en') -> str: """Create prompt for comic cover""" + # Language-specific text requirement + language_requirements = { + 'zh': '生成的图片务必使用中文', + 'en': 'Generated images must use English', + 'ja': '生成された画像は必ず日本語を使用してください' + } + language_requirement = language_requirements.get(language, language_requirements['en']) + prompt_template = """Create a high-quality comic book cover in the style of {comic_style}. # Requirements: @@ -181,8 +191,11 @@ def _create_cover_prompt(comic_style: str) -> str: - Clear and sharp text for the title, do not repeat all the titles in reference images. - Vibrant colors and "Cover Art" aesthetic. - Only present one row one panel in the cover. -- 生成的图片务必使用中文 +- {language_requirement} """ - final_prompt = prompt_template.format(comic_style=comic_style) + final_prompt = prompt_template.format( + comic_style=comic_style, + language_requirement=language_requirement + ) print(f"Cover Prompt: {final_prompt}") return final_prompt