🤖 《我用AI造了个"魔法师":说句话就能生成Flutter App,连代码都不用写!》

作者:红鱼AI 发布时间: 2025-11-15 阅读量:17 评论数:0

🌟 开篇暴击

想象一下,你只需要对AI说:"我想要一个电商App,有商品展示、购物车、支付功能",3分钟后,一个完整的Android APK和iOS IPA就热腾腾地出炉了!

这不是科幻电影,这是我用FastAPI + 千问大模型打造的Flutter代码生成神器

🏗️ 整体架构设计

系统流程图

🚀 第一步:搭建FastAPI后端框架

项目结构

flutter-ai-platform/
├── app/
│   ├── __init__.py
│   ├── main.py              # FastAPI主入口
│   ├── routers/
│   │   ├── __init__.py
│   │   ├── generate.py      # 代码生成路由
│   │   ├── compile.py       # 编译打包路由
│   │   └── chat.py          # AI聊天路由
│   ├── services/
│   │   ├── __init__.py
│   │   ├── qianwen_client.py    # 千问API客户端
│   │   ├── code_generator.py     # 代码生成服务
│   │   ├── flutter_builder.py    # Flutter编译服务
│   │   └── logger_service.py     # 日志服务
│   ├── models/
│   │   ├── __init__.py
│   │   ├── request.py       # 请求模型
│   │   └── response.py      # 响应模型
│   └── utils/
│       ├── __init__.py
│       └── file_manager.py  # 文件管理工具
├── static/
├── templates/
├── temp_projects/           # 临时项目目录
└── requirements.txt

核心依赖 (requirements.txt)

TXT

fastapi==0.104.1
uvicorn==0.24.0
websockets==12.0
pydantic==2.5.0
httpx==0.25.2
python-multipart==0.0.6
aiofiles==23.2.1
asyncio-mqtt==0.16.1

🧠 第二步:千问大模型集成

千问API客户端 (app/services/qianwen_client.py)

PYTHON

import httpx
import json
from typing import Dict, Any, Optional
from app.core.config import settings
 
class QianwenClient:
    def __init__(self):
        self.api_key = settings.QIANWEN_API_KEY
        self.base_url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
        self.model = "qwen-turbo"  # 可以选择 qwen-plus, qwen-max
        
    async def generate_code(self, requirement: str) -> Dict[str, Any]:
        """根据需求生成Flutter代码"""
        prompt = f"""
        你是一个专业的Flutter开发工程师。请根据以下需求生成完整的Flutter应用代码:
 
        需求:{requirement}
 
        要求:
        1. 生成完整的项目结构,包括main.dart和相关页面文件
        2. 使用Material Design风格
        3. 确保代码语法正确,无错误
        4. 包含必要的依赖包配置(pubspec.yaml)
        5. 添加适当的注释说明
        
        请以JSON格式返回,包含以下字段:
        - main_dart: 主文件代码
        - additional_files: 其他必要文件的代码映射
        - pubspec_yaml: 依赖配置
        - description: 项目描述
        """
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": self.model,
            "input": {
                "messages": [
                    {"role": "user", "content": prompt}
                ]
            },
            "parameters": {
                "temperature": 0.7,
                "max_tokens": 4000
            }
        }
        
        async with httpx.AsyncClient() as client:
            response = await client.post(self.base_url, headers=headers, json=payload)
            result = response.json()
            
            if "output" in result:
                content = result["output"]["text"]
                # 解析AI返回的代码
                return self._parse_code_response(content)
            else:
                raise Exception(f"千问API调用失败: {result}")
    
    async def debug_code(self, code: str, error_message: str) -> str:
        """调试代码错误"""
        prompt = f"""
        以下Flutter代码在编译时出现了错误,请帮我修复:
 
        代码:
        {code}
 
        错误信息:
        {error_message}
 
        请分析错误原因并提供修复后的代码,确保语法正确且功能完整。
        """
        
        # 类似generate_code的API调用逻辑
        # ... 省略重复代码
        pass
    
    def _parse_code_response(self, content: str) -> Dict[str, Any]:
        """解析AI返回的代码响应"""
        try:
            # 尝试解析JSON格式
            if "```json" in content:
                json_str = content.split("```json")[1].split("```")[0].strip()
                return json.loads(json_str)
            else:
                # 如果不是JSON格式,手动解析
                return self._manual_parse(content)
        except:
            return self._manual_parse(content)
    
    def _manual_parse(self, content: str) -> Dict[str, Any]:
        """手动解析代码内容"""
        # 实现代码解析逻辑
        return {
            "main_dart": content,
            "additional_files": {},
            "pubspec_yaml": """
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
""",
            "description": "AI生成的Flutter应用"
        }

⚙️ 第三步:代码生成服务

代码生成核心 (app/services/code_generator.py)

PYTHON

import os
import shutil
import asyncio
from pathlib import Path
from typing import Dict, Any, List
from app.services.qianwen_client import QianwenClient
from app.utils.file_manager import FileManager
from app.models.response import GenerationResponse
 
class CodeGenerator:
    def __init__(self):
        self.qianwen_client = QianwenClient()
        self.file_manager = FileManager()
        
    async def generate_flutter_project(self, requirement: str, project_id: str) -> GenerationResponse:
        """生成完整的Flutter项目"""
        try:
            # 1. 调用千问生成代码
            await self._update_status(project_id, "正在调用AI分析需求...")
            ai_response = await self.qianwen_client.generate_code(requirement)
            
            # 2. 创建项目目录
            await self._update_status(project_id, "正在创建项目结构...")
            project_path = await self._create_project_structure(project_id, ai_response)
            
            # 3. 验证代码语法
            await self._update_status(project_id, "正在验证代码语法...")
            validation_result = await self._validate_code(project_path)
            
            if not validation_result["valid"]:
                # 4. 如果有错误,自动修复
                await self._update_status(project_id, "检测到语法错误,正在自动修复...")
                await self._auto_fix_code(project_path, validation_result["errors"])
            
            return GenerationResponse(
                success=True,
                project_id=project_id,
                project_path=str(project_path),
                description=ai_response["description"]
            )
            
        except Exception as e:
            await self._update_status(project_id, f"代码生成失败: {str(e)}")
            return GenerationResponse(
                success=False,
                error=str(e)
            )
    
    async def _create_project_structure(self, project_id: str, ai_response: Dict[str, Any]) -> Path:
        """创建Flutter项目结构"""
        project_path = Path(f"temp_projects/{project_id}")
        
        # 如果项目已存在,先删除
        if project_path.exists():
            shutil.rmtree(project_path)
        
        # 创建基础目录结构
        os.makedirs(project_path / "lib", exist_ok=True)
        os.makedirs(project_path / "android", exist_ok=True)
        os.makedirs(project_path / "ios", exist_ok=True)
        
        # 写入pubspec.yaml
        pubspec_content = ai_response.get("pubspec_yaml", "")
        await self.file_manager.write_file(project_path / "pubspec.yaml", pubspec_content)
        
        # 写入main.dart
        main_dart_content = ai_response.get("main_dart", "")
        await self.file_manager.write_file(project_path / "lib/main.dart", main_dart_content)
        
        # 写入其他文件
        additional_files = ai_response.get("additional_files", {})
        for file_name, file_content in additional_files.items():
            file_path = project_path / file_name
            os.makedirs(file_path.parent, exist_ok=True)
            await self.file_manager.write_file(file_path, file_content)
        
        return project_path
    
    async def _validate_code(self, project_path: Path) -> Dict[str, Any]:
        """验证Flutter代码"""
        try:
            # 运行flutter analyze检查代码
            process = await asyncio.create_subprocess_exec(
                "flutter", "analyze",
                cwd=project_path,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            
            stdout, stderr = await process.communicate()
            
            if process.returncode == 0:
                return {"valid": True, "errors": []}
            else:
                # 解析错误信息
                error_lines = stderr.decode().split('\n')
                errors = [line for line in error_lines if line.strip() and 'error' in line.lower()]
                return {"valid": False, "errors": errors}
                
        except Exception as e:
            return {"valid": False, "errors": [str(e)]}
    
    async def _auto_fix_code(self, project_path: Path, errors: List[str]) -> bool:
        """自动修复代码错误"""
        try:
            main_dart_path = project_path / "lib/main.dart"
            if not main_dart_path.exists():
                return False
                
            # 读取当前代码
            current_code = await self.file_manager.read_file(main_dart_path)
            
            # 调用AI修复代码
            fixed_code = await self.qianwen_client.debug_code(
                current_code, 
                "\n".join(errors)
            )
            
            # 写入修复后的代码
            await self.file_manager.write_file(main_dart_path, fixed_code)
            
            return True
            
        except Exception as e:
            print(f"自动修复失败: {e}")
            return False
    
    async def _update_status(self, project_id: str, message: str):
        """更新状态(用于WebSocket推送)"""
        # 这里会通过WebSocket推送状态更新
        pass

🔨 第四步:编译打包服务

Flutter编译器 (app/services/flutter_builder.py)

PYTHON

import asyncio
import os
from pathlib import Path
from typing import Dict, Any, AsyncGenerator
from app.models.response import BuildResponse
 
class FlutterBuilder:
    def __init__(self):
        self.build_logs = {}
    
    async def build_app(self, project_path: str, project_id: str) -> AsyncGenerator[str, None]:
        """编译Flutter应用并实时输出日志"""
        try:
            project_dir = Path(project_path)
            
            # 1. 获取依赖
            yield "🔧 正在获取依赖包..."
            async for line in self._run_flutter_command(["pub", "get"], project_dir):
                yield line
            
            # 2. 构建Android APK
            yield "📱 开始构建Android APK..."
            async for line in self._build_android(project_dir):
                yield line
            
            # 3. 构建iOS IPA(如果环境支持)
            if os.name == 'posix':  # macOS/Linux
                yield "🍎 开始构建iOS IPA..."
                async for line in self._build_ios(project_dir):
                    yield line
            
            # 4. 生成下载链接
            yield "✅ 编译完成!正在生成下载链接..."
            download_links = await self._generate_download_links(project_dir)
            
            yield f"🎉 构建成功!下载链接:{download_links}"
            
        except Exception as e:
            yield f"❌ 构建失败: {str(e)}"
    
    async def _build_android(self, project_dir: Path) -> AsyncGenerator[str, None]:
        """构建Android APK"""
        cmd = ["build", "apk", "--release"]
        
        process = await asyncio.create_subprocess_exec(
            "flutter", *cmd,
            cwd=project_dir,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        
        async for line in self._read_process_output(process):
            yield f"Android构建: {line}"
        
        await process.wait()
        
        if process.returncode == 0:
            # 检查APK文件
            apk_path = project_dir / "build/app/outputs/flutter-apk/app-release.apk"
            if apk_path.exists():
                yield f"✅ Android APK构建完成: {apk_path}"
            else:
                yield "⚠️  APK文件未找到,构建可能失败"
        else:
            yield "❌ Android构建失败"
    
    async def _build_ios(self, project_dir: Path) -> AsyncGenerator[str, None]:
        """构建iOS IPA"""
        cmd = ["build", "ios", "--release", "--no-codesign"]
        
        process = await asyncio.create_subprocess_exec(
            "flutter", *cmd,
            cwd=project_dir,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE
        )
        
        async for line in self._read_process_output(process):
            yield f"iOS构建: {line}"
        
        await process.wait()
        
        if process.returncode == 0:
            yield "✅ iOS构建完成"
        else:
            yield "❌ iOS构建失败"
    
    async def _read_process_output(self, process) -> AsyncGenerator[str, None]:
        """读取进程输出"""
        while True:
            line = await process.stdout.readline()
            if not line:
                break
            yield line.decode().strip()
        
        # 读取错误输出
        while True:
            line = await process.stderr.readline()
            if not line:
                break
            error_line = line.decode().strip()
            if error_line:
                yield f"ERROR: {error_line}"
    
    async def _generate_download_links(self, project_dir: Path) -> Dict[str, str]:
        """生成下载链接"""
        links = {}
        
        # Android APK链接
        apk_path = project_dir / "build/app/outputs/flutter-apk/app-release.apk"
        if apk_path.exists():
            # 复制到下载目录
            download_dir = Path("static/downloads")
            download_dir.mkdir(exist_ok=True)
            
            download_apk = download_dir / f"{project_dir.name}.apk"
            shutil.copy2(apk_path, download_apk)
            links["android"] = f"/downloads/{project_dir.name}.apk"
        
        return links

🌐 第五步:FastAPI路由实现

主路由 (app/routers/generate.py)

PYTHON

from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
from app.services.code_generator import CodeGenerator
from app.models.request import GenerateRequest
from app.models.response import GenerationResponse
import uuid
import json
 
router = APIRouter(prefix="/api", tags=["代码生成"])
code_generator = CodeGenerator()
 
# WebSocket连接管理
active_connections: list[WebSocket] = []
 
@router.post("/generate", response_model=GenerationResponse)
async def generate_app(request: GenerateRequest):
    """生成Flutter应用"""
    project_id = str(uuid.uuid4())
    
    # 异步生成代码
    response = await code_generator.generate_flutter_project(
        request.requirement, 
        project_id
    )
    
    return response
 
@router.websocket("/ws/{project_id}")
async def websocket_endpoint(websocket: WebSocket, project_id: str):
    """WebSocket实时推送构建日志"""
    await websocket.accept()
    active_connections.append(websocket)
    
    try:
        while True:
            # 等待消息或定时发送状态
            await asyncio.sleep(3)  # 3秒间隔
            
            # 获取构建状态并发送
            status_data = {
                "project_id": project_id,
                "timestamp": asyncio.get_event_loop().time(),
                "message": "正在处理中...",
            }
            
            await websocket.send_text(json.dumps(status_data))
            
    except WebSocketDisconnect:
        active_connections.remove(websocket)

编译路由 (app/routers/compile.py)

PYTHON

from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from app.services.flutter_builder import FlutterBuilder
import asyncio
import json
 
router = APIRouter(prefix="/api", tags=["编译打包"])
flutter_builder = FlutterBuilder()
 
@router.post("/build/{project_id}")
async def build_app(project_id: str):
    """编译Flutter应用"""
    project_path = f"temp_projects/{project_id}"
    
    # 启动异步构建任务
    asyncio.create_task(_build_with_websocket(project_id, project_path))
    
    return {"message": "构建任务已启动", "project_id": project_id}
 
async def _build_with_websocket(project_id: str, project_path: str):
    """通过WebSocket推送构建日志"""
    # 查找对应的WebSocket连接
    for connection in active_connections:
        try:
            async for log_line in flutter_builder.build_app(project_path, project_id):
                log_data = {
                    "type": "build_log",
                    "project_id": project_id,
                    "message": log_line,
                    "timestamp": asyncio.get_event_loop().time()
                }
                await connection.send_text(json.dumps(log_data))
                
                # 3秒间隔
                await asyncio.sleep(3)
                
        except Exception as e:
            error_data = {
                "type": "error",
                "project_id": project_id,
                "message": f"构建过程出错: {str(e)}",
                "timestamp": asyncio.get_event_loop().time()
            }
            await connection.send_text(json.dumps(error_data))

AI聊天路由 (app/routers/chat.py)

PYTHON

from fastapi import APIRouter
from app.services.qianwen_client import QianwenClient
from app.models.request import ChatRequest
from app.models.response import ChatResponse
 
router = APIRouter(prefix="/api", tags=["AI聊天"])
qianwen_client = QianwenClient()
 
@router.post("/chat", response_model=ChatResponse)
async def chat_with_ai(request: ChatRequest):
    """与AI聊天调试代码"""
    try:
        # 调用千问API
        response = await qianwen_client.chat_debug(
            request.message,
            request.code_context,
            request.error_context
        )
        
        return ChatResponse(
            success=True,
            response=response,
            suggestions=["重新编译代码", "检查依赖包", "清理构建缓存"]
        )
        
    except Exception as e:
        return ChatResponse(
            success=False,
            error=str(e)
        )

🎨 第六步:前端管理界面

管理页面 (templates/admin.html)

HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flutter AI代码生成平台</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin: 0;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        
        .header h1 {
            margin: 0;
            font-size: 2.5em;
            font-weight: 700;
        }
        
        .main-content {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 30px;
            padding: 30px;
        }
        
        .input-section, .output-section {
            background: #f8f9fa;
            border-radius: 15px;
            padding: 25px;
        }
        
        .section-title {
            font-size: 1.3em;
            font-weight: 600;
            margin-bottom: 20px;
            color: #2d3748;
        }
        
        .requirement-input {
            width: 100%;
            min-height: 200px;
            padding: 15px;
            border: 2px solid #e2e8f0;
            border-radius: 10px;
            font-size: 1em;
            resize: vertical;
            transition: border-color 0.3s;
        }
        
        .requirement-input:focus {
            outline: none;
            border-color: #4299e1;
        }
        
        .generate-btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 15px 30px;
            border-radius: 10px;
            font-size: 1.1em;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.2s;
            margin-top: 15px;
        }
        
        .generate-btn:hover {
            transform: translateY(-2px);
        }
        
        .generate-btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }
        
        .log-container {
            background: #1a202c;
            color: #e2e8f0;
            border-radius: 10px;
            padding: 20px;
            height: 300px;
            overflow-y: auto;
            font-family: 'Monaco', 'Menlo', monospace;
            font-size: 0.9em;
            margin-top: 20px;
        }
        
        .log-entry {
            margin-bottom: 8px;
            padding: 5px;
            border-radius: 5px;
        }
        
        .log-info { background: rgba(59, 130, 246, 0.2); }
        .log-success { background: rgba(34, 197, 94, 0.2); }
        .log-error { background: rgba(239, 68, 68, 0.2); }
        
        .download-section {
            margin-top: 20px;
            padding: 20px;
            background: linear-gradient(135deg, #10b981 0%, #059669 100%);
            border-radius: 10px;
            color: white;
            display: none;
        }
        
        .download-btn {
            background: white;
            color: #10b981;
            border: none;
            padding: 12px 25px;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            margin: 5px;
            transition: transform 0.2s;
        }
        
        .download-btn:hover {
            transform: scale(1.05);
        }
        
        .chat-section {
            grid-column: 1 / -1;
            background: #f0f9ff;
            border-radius: 15px;
            padding: 25px;
            margin-top: 20px;
        }
        
        .chat-messages {
            height: 200px;
            overflow-y: auto;
            background: white;
            border-radius: 10px;
            padding: 15px;
            margin-bottom: 15px;
        }
        
        .chat-input-group {
            display: flex;
            gap: 10px;
        }
        
        .chat-input {
            flex: 1;
            padding: 12px;
            border: 2px solid #e2e8f0;
            border-radius: 8px;
            font-size: 1em;
        }
        
        .chat-send-btn {
            background: #3b82f6;
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 8px;
            cursor: pointer;
            font-weight: 600;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🤖 Flutter AI代码生成平台</h1>
            <p>一句话描述需求,AI自动生成完整Flutter应用</p>
        </div>
        
        <div class="main-content">
            <div class="input-section">
                <h2 class="section-title">📝 需求描述</h2>
                <textarea 
                    id="requirementInput" 
                    class="requirement-input" 
                    placeholder="请描述你想要的Flutter应用功能,例如:&#10;我想要一个电商App,包含商品列表、购物车、用户登录、支付功能&#10;或者:&#10;做一个天气预报App,显示7天天气,支持城市切换"
                ></textarea>
                <button id="generateBtn" class="generate-btn" onclick="generateApp()">
                    🚀 AI生成代码
                </button>
                
                <div class="chat-section">
                    <h3 class="section-title">💬 AI调试助手</h3>
                    <div id="chatMessages" class="chat-messages"></div>
                    <div class="chat-input-group">
                        <input 
                            type="text" 
                            id="chatInput" 
                            class="chat-input" 
                            placeholder="描述遇到的问题,我来帮你解决..."
                            onkeypress="if(event.key==='Enter') sendChatMessage()"
                        >
                        <button class="chat-send-btn" onclick="sendChatMessage()">发送</button>
                    </div>
                </div>
            </div>
            
            <div class="output-section">
                <h2 class="section-title">📊 构建日志</h2>
                <div id="logContainer" class="log-container">
                    <div class="log-entry log-info">等待生成代码...</div>
                </div>
                
                <div id="downloadSection" class="download-section">
                    <h3>🎉 构建完成!下载你的应用:</h3>
                    <button id="androidBtn" class="download-btn" onclick="downloadApp('android')">
                        📱 下载 Android APK
                    </button>
                    <button id="iosBtn" class="download-btn" onclick="downloadApp('ios')">
                        🍎 下载 iOS IPA
                    </button>
                </div>
            </div>
        </div>
    </div>
 
    <script>
        let currentProjectId = null;
        let websocket = null;
        
        // 生成应用
        async function generateApp() {
            const requirement = document.getElementById('requirementInput').value;
            if (!requirement.trim()) {
                alert('请先描述你的需求!');
                return;
            }
            
            const generateBtn = document.getElementById('generateBtn');
            generateBtn.disabled = true;
            generateBtn.textContent = '🤖 AI思考中...';
            
            addLog('正在调用AI分析需求...', 'info');
            
            try {
                const response = await fetch('/api/generate', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        requirement: requirement
                    })
                });
                
                const result = await response.json();
                
                if (result.success) {
                    currentProjectId = result.project_id;
                    addLog(`✅ 代码生成成功!项目ID: ${currentProjectId}`, 'success');
                    
                    // 启动WebSocket连接监听构建日志
                    connectWebSocket();
                    
                    // 开始构建
                    startBuild();
                } else {
                    addLog(`❌ 代码生成失败: ${result.error}`, 'error');
                }
            } catch (error) {
                addLog(`❌ 请求失败: ${error.message}`, 'error');
            } finally {
                generateBtn.disabled = false;
                generateBtn.textContent = '🚀 AI生成代码';
            }
        }
        
        // WebSocket连接
        function connectWebSocket() {
            const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
            const wsUrl = `${protocol}//${window.location.host}/api/ws/${currentProjectId}`;
            
            websocket = new WebSocket(wsUrl);
            
            websocket.onmessage = function(event) {
                const data = JSON.parse(event.data);
                
                if (data.type === 'build_log') {
                    addLog(data.message, data.message.includes('✅') ? 'success' : 
                           data.message.includes('❌') ? 'error' : 'info');
                } else if (data.type === 'error') {
                    addLog(data.message, 'error');
                }
            };
            
            websocket.onerror = function(error) {
                addLog(`WebSocket连接错误: ${error}`, 'error');
            };
            
            websocket.onclose = function() {
                addLog('连接已关闭', 'info');
            };
        }
        
        // 开始构建
        async function startBuild() {
            addLog('🔨 开始构建应用...', 'info');
            
            try {
                const response = await fetch(`/api/build/${currentProjectId}`, {
                    method: 'POST'
                });
                
                const result = await response.json();
                addLog(result.message, 'info');
            } catch (error) {
                addLog(`构建启动失败: ${error.message}`, 'error');
            }
        }
        
        // 添加日志
        function addLog(message, type = 'info') {
            const logContainer = document.getElementById('logContainer');
            const logEntry = document.createElement('div');
            logEntry.className = `log-entry log-${type}`;
            logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
            logContainer.appendChild(logEntry);
            logContainer.scrollTop = logContainer.scrollHeight;
            
            // 如果构建完成,显示下载按钮
            if (message.includes('🎉 构建成功')) {
                document.getElementById('downloadSection').style.display = 'block';
            }
        }
        
        // 下载应用
        function downloadApp(platform) {
            const baseUrl = window.location.origin;
            const downloadUrl = `${baseUrl}/downloads/${currentProjectId}.apk`;
            window.open(downloadUrl, '_blank');
        }
        
        // 发送聊天消息
        async function sendChatMessage() {
            const chatInput = document.getElementById('chatInput');
            const message = chatInput.value.trim();
            
            if (!message) return;
            
            const chatMessages = document.getElementById('chatMessages');
            
            // 添加用户消息
            const userMsg = document.createElement('div');
            userMsg.innerHTML = `<strong>你:</strong> ${message}`;
            userMsg.style.marginBottom = '10px';
            chatMessages.appendChild(userMsg);
            
            chatInput.value = '';
            
            try {
                const response = await fetch('/api/chat', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        message: message,
                        project_id: currentProjectId
                    })
                });
                
                const result = await response.json();
                
                // 添加AI回复
                const aiMsg = document.createElement('div');
                aiMsg.innerHTML = `<strong>AI助手:</strong> ${result.response || result.error}`;
                aiMsg.style.marginBottom = '10px';
                aiMsg.style.padding = '10px';
                aiMsg.style.background = '#f0f9ff';
                aiMsg.style.borderRadius = '5px';
                chatMessages.appendChild(aiMsg);
                
                chatMessages.scrollTop = chatMessages.scrollHeight;
                
            } catch (error) {
                const errorMsg = document.createElement('div');
                errorMsg.innerHTML = `<strong>AI助手:</strong> 抱歉,我遇到了一些问题: ${error.message}`;
                errorMsg.style.marginBottom = '10px';
                errorMsg.style.color = 'red';
                chatMessages.appendChild(errorMsg);
            }
        }
    </script>
</body>
</html>

🚀 第七步:主程序启动

FastAPI主程序 (app/main.py)

PYTHON

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
from fastapi.middleware.cors import CORSMiddleware
from app.routers import generate, compile, chat
import os
 
app = FastAPI(
    title="Flutter AI代码生成平台",
    description="基于千问大模型的Flutter应用自动生成系统",
    version="1.0.0"
)
 
# CORS设置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
 
# 静态文件
app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount("/downloads", StaticFiles(directory="static/downloads"), name="downloads")
 
# 路由
app.include_router(generate.router)
app.include_router(compile.router)
app.include_router(chat.router)
 
@app.get("/", response_class=HTMLResponse)
async def root():
    """管理页面"""
    with open("templates/admin.html", "r", encoding="utf-8") as f:
        return HTMLResponse(content=f.read())
 
@app.get("/health")
async def health_check():
    """健康检查"""
    return {"status": "healthy", "message": "Flutter AI平台运行正常"}
 
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

🎯 运行和测试

启动命令

BASH

# 安装依赖
pip install -r requirements.txt
 
# 启动服务
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
 
# 访问管理界面
open http://localhost:8000

环境要求

  • Python 3.8+

  • Flutter SDK

  • Android Studio (用于Android编译)

  • Xcode (用于iOS编译,仅macOS)

💫 功能亮点

  1. 🤖 智能代码生成:千问大模型分析需求,生成完整Flutter代码

  2. 🔄 实时日志推送:WebSocket每3秒推送构建状态

  3. 💬 AI调试助手:与AI聊天解决编译问题

  4. 📱 一键打包:自动生成APK和IPA文件

  5. 🎨 现代化UI:渐变色彩设计,用户体验友好

🎭 公众号爆文素材

钩子段落

"我花了一个月时间,把程序员最痛恨的编译过程变成了'一句话搞定'的魔法!现在同事们以为我是AI超人..."

核心价值

"从需求描述到可下载的App,全程AI自动完成,连bug都让AI来修!这就是程序员的终极懒人神器!"

情感共鸣

"还记得那些为了编译错误熬过的夜晚吗?现在,AI成了你的24小时贴身技术顾问..."

这个平台把Flutter开发变成了"说句话"的魔法,让你的技术能力在同事面前直接封神!

想了解更多技术细节?看看分层架构概述平台集成章节,让你的AI助手更加强大!

评论