""" @file generate_layout.py @brief Vue组件代码生成模块 基于DeepSeek API生成响应式Vue 3组件布局代码 @author 王秀强 (2310460@mail.nankai.edu.cn) @date 2025.5.19 @version v1.0.0 @details 本文件主要实现: - DeepSeek API调用封装和错误处理 - Vue 3 Composition API组件代码生成 - 海报布局的动态排版和样式生成 - 代码清理和格式化处理 - 备用Vue模板生成机制 @note - 需要配置DEEPSEEK_API_KEY环境变量 - 支持流式和非流式响应模式 - 生成的Vue代码包含完整的template、script和style部分 - 具备指数退避重试机制处理API限流 @usage # 生成Vue组件代码 vue_code = generate_vue_code("生成端午节海报Vue组件") save_code(vue_code, "../outputs/poster.vue") # 调用DeepSeek API result, usage = call_deepseek(prompt="请生成代码", temperature=0.6) @copyright (c) 2025 砚生项目组 """ import os from openai import OpenAI from dotenv import load_dotenv import time from colorama import init, Fore, Back, Style # 初始化colorama init(autoreset=True) # === Config LLM call === load_dotenv() deepseek_url = 'https://api.deepseek.com/v1' # set to be compatible with the OpenAI API deepseek_api = os.getenv("DEEPSEEK_API_KEY") if not deepseek_api: raise ValueError("DEEPSEEK_API_KEY not set!") def call_deepseek( messages=None, system_prompt="你是一个擅长前端开发的AI,专注于生成Vue.js代码。", prompt=None, model='deepseek-chat', temperature=0.6, max_tokens=2000, # 增加token数量 stream=False, max_retries=3, ): """ 调用 DeepSeek API,支持多轮对话和流式/非流式响应 """ # 初始化 OpenAI 客户端 client = OpenAI( api_key=deepseek_api, base_url=deepseek_url, ) # 参数验证 if messages is None: if not prompt: raise ValueError("必须提供 message 或 prompt 参数") messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": prompt} ] elif not isinstance(messages, list) or not messages: raise ValueError("message 参数必须是非空列表") # 模型验证 models = ["deepseek-chat", "deepseek-reasoner"] if model not in models: raise ValueError(f"无效的模型名称: {model},可用模型: {models}") # 调用 API for attempt in range(max_retries): try: print(f"{Fore.BLUE}📡 正在调用DeepSeek API (尝试 {attempt + 1}/{max_retries})...{Style.RESET_ALL}") response = client.chat.completions.create( model=model, messages=messages, temperature=temperature, max_tokens=max_tokens, stream=stream ) # 流式响应 if stream: def stream_generator(): usage = None for chunk in response: if chunk.choices[0].delta.content is not None: yield chunk.choices[0].delta.content return usage return stream_generator(), None else: # 非流式响应 content = response.choices[0].message.content print(f"{Fore.GREEN}✅ API调用成功,返回内容长度: {len(content)}{Style.RESET_ALL}") return content, response.usage except Exception as e: print(f"{Fore.RED}❌ API调用失败 (尝试 {attempt + 1}/{max_retries}): {str(e)}{Style.RESET_ALL}") if hasattr(e, 'status_code') and e.status_code == 429: # 限流 print(f"{Fore.YELLOW}⏳ 请求过于频繁,等待重试...{Style.RESET_ALL}") time.sleep(2 ** attempt) # 指数退避 elif attempt == max_retries - 1: raise else: time.sleep(1) raise Exception("达到最大重试次数,API 调用失败") def generate_vue_code(prompt=None): """ 生成Vue组件代码 """ if not prompt: prompt = ( "生成一个Vue组件代码,用于端午节活动海报,包含以下部分并指定排版位置:" "1. 背景图层:div,占据整个组件区域。" "2. 主体图层:div,位于顶部1/4处,居中,包含标题和副标题。" "3. 活动亮点:div,位于底部1/4处,居中,使用网格布局展示三项活动(每项包含图标、标题和描述)。" "4. 页脚:div,位于底部,居中,包含主办单位信息和logo图片。" "组件尺寸为1080x1920px,布局使用absolute定位,生成完整可用的Vue 3代码。" ) system_prompt = ( "你是一个擅长前端开发的AI,专注于生成Vue.js代码。" "请生成完整的Vue 3组件,包含template、script setup和style部分。" "确保代码结构清晰,语法正确,可以直接使用。" "不要包含任何解释文字,只返回纯代码。" ) try: print(f"{Fore.CYAN}🎨 正在生成Vue组件代码...{Style.RESET_ALL}") result, usage = call_deepseek(prompt=prompt, system_prompt=system_prompt, temperature=0.4) # 清理代码,移除可能的markdown标记 if result: # 移除markdown代码块标记 if "```vue" in result: result = result.split("```vue")[1].split("```")[0].strip() elif "```html" in result: result = result.split("```html")[1].split("```")[0].strip() elif result.startswith("```") and result.endswith("```"): result = result[3:-3].strip() print(f"{Fore.GREEN}✅ Vue代码生成成功,长度: {len(result)} 字符{Style.RESET_ALL}") return result else: print(f"{Fore.RED}❌ Vue代码生成失败,返回空内容{Style.RESET_ALL}") return generate_fallback_vue_code() except Exception as e: print(f"{Fore.RED}❌ Vue代码生成异常: {str(e)}{Style.RESET_ALL}") return generate_fallback_vue_code() def generate_fallback_vue_code(): """ 生成备用的Vue代码 """ print(f"{Fore.YELLOW}⚠️ 使用备用Vue模板{Style.RESET_ALL}") return """ """ def save_code(code, file_path="../outputs/generated_code.vue"): """ 保存代码到文件 """ try: # 确保目录存在 os.makedirs(os.path.dirname(file_path), exist_ok=True) # 写入文件 with open(file_path, "w", encoding="utf-8") as f: f.write(code) print(f"{Fore.GREEN}✅ Vue代码已保存到: {file_path}{Style.RESET_ALL}") # 验证文件是否成功创建 if os.path.exists(file_path): file_size = os.path.getsize(file_path) print(f"{Fore.CYAN}📁 文件大小: {file_size} 字节{Style.RESET_ALL}") else: print(f"{Fore.RED}❌ 文件保存失败{Style.RESET_ALL}") except Exception as e: print(f"{Fore.RED}❌ 保存代码时出错: {str(e)}{Style.RESET_ALL}") if __name__ == "__main__": print(f"{Fore.MAGENTA}🚀 开始生成Vue组件...{Style.RESET_ALL}") vue_code = generate_vue_code() save_code(vue_code) print(f"{Fore.GREEN}✅ Vue组件代码生成完成{Style.RESET_ALL}")