import gradio as gr import time import logging from model_handler import ModelHandler from config import CHAT_MODEL_SPECS, LING_1T, CODE_FRAMEWORK_SPECS, STATIC_PAGE from ui_components.model_selector import create_model_selector from ui_components.code_framework_selector import create_code_framework_selector from tab_code_prompts.html_system_prompt import get_html_system_prompt # Configure logging logger = logging.getLogger(__name__) # Read the content of the JavaScript file for error catching try: with open("static/catch-error.js", "r", encoding="utf-8") as f: CATCH_ERROR_JS_SCRIPT = f.read() except FileNotFoundError: logger.error("Error: static/catch-error.js not found. The error catching overlay will not work.") CATCH_ERROR_JS_SCRIPT = "" def get_spinner_html(): """Return HTML with a CSS spinner animation""" return """
""" def generate_code(code_type, model_choice, user_prompt, chatbot_history): """Generate code and provide a preview, updating a log stream chatbot.""" logger.info(f"--- [Code Generation] Start ---") logger.info(f"Code Type: {code_type}, Model: {model_choice}, Prompt: '{user_prompt}'") if not user_prompt: chatbot_history.append({"role": "assistant", "content": "🚨 **错误**: 请输入提示词。"}) yield "", gr.update(value="

预览将在此处显示。

"), chatbot_history, gr.update() return chatbot_history.append({"role": "assistant", "content": "⏳ 开始生成代码..."}) yield "", gr.HTML(get_spinner_html()), chatbot_history, gr.update() if user_prompt == "create an error": error_code = f"""

This will create an error

"""; escaped_code = error_code.replace("'", "'").replace('"', '"') final_preview_html = f"""
""" chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 已生成一个用于测试的错误页面。"}) yield error_code, gr.update(value=final_preview_html), chatbot_history, gr.Tabs(selected=0) return start_time = time.time() model_handler = ModelHandler() if code_type == "静态页面": system_prompt = get_html_system_prompt() full_code_with_think = "" full_code_for_preview = "" buffer = "" is_thinking = False for code_chunk in model_handler.generate_code(system_prompt, user_prompt, model_choice): full_code_with_think += code_chunk buffer += code_chunk while True: if is_thinking: end_index = buffer.find("") if end_index != -1: is_thinking = False buffer = buffer[end_index + len(""):] else: break else: start_index = buffer.find("") if start_index != -1: part_to_add = buffer[:start_index] full_code_for_preview += part_to_add is_thinking = True buffer = buffer[start_index:] else: full_code_for_preview += buffer buffer = "" break elapsed_time = time.time() - start_time generated_length = len(full_code_with_think) speed = generated_length / elapsed_time if elapsed_time > 0 else 0 log_message = f""" **⏳ 正在生成中...** - **时间:** {elapsed_time:.2f}s - **长度:** {generated_length} chars - **速度:** {speed:.2f} char/s """ if len(chatbot_history) > 0 and "正在生成中" in chatbot_history[-1]["content"]: chatbot_history[-1] = {"role": "assistant", "content": log_message} else: chatbot_history.append({"role": "assistant", "content": log_message}) yield full_code_with_think, gr.update(), chatbot_history, gr.update() escaped_code = full_code_for_preview.replace("'", "'").replace('"', '"') final_preview_html = f"""
""" chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 代码生成完成!"}) yield full_code_with_think, gr.HTML(final_preview_html), chatbot_history, gr.Tabs(selected=0) logger.info("Static page streaming finished.") def refresh_preview(code_type, current_code, chatbot_history): """Refresh the preview and add a log entry.""" logger.info(f"--- [Manual Refresh] Start ---") logger.info(f"Code Type: {code_type}") if code_type == "静态页面": escaped_code = current_code.replace("'", "'").replace('"', '"') final_preview_html = f"""
""" chatbot_history.append({"role": "assistant", "content": "🔄 **状态**: 预览已手动刷新。"}) logger.info("Refreshed static page preview.") return gr.HTML(final_preview_html), chatbot_history chatbot_history.append({"role": "assistant", "content": "⚠️ **警告**: 未知的代码类型,无法刷新。"}) return gr.update(), chatbot_history def toggle_fullscreen(is_fullscreen): is_fullscreen = not is_fullscreen new_button_text = "退出全屏" if is_fullscreen else "全屏预览" panel_visibility = not is_fullscreen return is_fullscreen, gr.update(value=new_button_text), gr.update(visible=panel_visibility) def log_js_error(error_text, chatbot_history): """Appends a JavaScript error received from the frontend to the log chatbot.""" if not error_text: return chatbot_history formatted_error = f"🚨 **在预览中发现运行时异常!**\n```\n{error_text}\n```" # Check if the last message is the same error to prevent flooding if chatbot_history and chatbot_history[-1]["content"] == formatted_error: return chatbot_history chatbot_history.append({"role": "assistant", "content": formatted_error}) return chatbot_history def create_code_tab(): fullscreen_state = gr.State(False) html_examples = [ "Write a hello world alert", "Create a Canvas animation of continuous colorful fireworks blooming on a black background.", "Generate a Canvas special effect with iridescent light streams.", "create an error" ] with gr.Row(elem_id="indicator-code-tab"): with gr.Column(scale=1) as left_panel: with gr.Column(scale=1): # Settings Panel code_framework_dropdown = create_code_framework_selector( framework_specs=CODE_FRAMEWORK_SPECS, default_framework_constant=STATIC_PAGE ) model_choice_dropdown, model_description_markdown = create_model_selector( model_specs=CHAT_MODEL_SPECS, default_model_constant=LING_1T ) prompt_input = gr.Textbox(lines=5, placeholder="例如:创建一个带标题和按钮的简单页面", label="提示词") with gr.Column(): gr.Examples(examples=html_examples, inputs=prompt_input, label="✨ 试试这些酷炫的例子吧") generate_button = gr.Button("生成代码", variant="primary") with gr.Column(scale=4): with gr.Tabs(elem_id="result_tabs") as result_tabs: with gr.TabItem("实时预览", id=0): with gr.Row(): gr.Markdown("### 实时预览") fullscreen_button = gr.Button("全屏预览", scale=0) preview_output = gr.HTML(value="

预览将在此处显示。

") with gr.TabItem("生成的源代码", id=1): gr.Markdown("### 生成的源代码") code_output = gr.Code(language="html", label="生成的代码", interactive=True) refresh_button = gr.Button("刷新预览") with gr.Column(scale=1): log_chatbot = gr.Chatbot(label="生成日志", height=300, type="messages") js_error_channel = gr.Textbox(visible=True, elem_classes=["js_error_channel"], label="Debug Error Channel", interactive=False) refresh_button.click( fn=refresh_preview, inputs=[code_framework_dropdown, code_output, log_chatbot], outputs=[preview_output, log_chatbot] ) generate_button.click( fn=generate_code, inputs=[code_framework_dropdown, model_choice_dropdown, prompt_input, log_chatbot], outputs=[code_output, preview_output, log_chatbot, result_tabs] ) fullscreen_button.click( fn=toggle_fullscreen, inputs=[fullscreen_state], outputs=[fullscreen_state, fullscreen_button, left_panel] ) js_error_channel.change( fn=log_js_error, inputs=[js_error_channel, log_chatbot], outputs=log_chatbot )