从设计稿到代码:VTJ.PRO 的 AI 集成系统架构解析

0 阅读5分钟

🎨 还在手动将 Figma 设计稿转换成 Vue 代码?我们的 AI 系统已经能直接吃设计稿吐代码了!


前言

在低代码平台中,如何让 AI 真正理解开发意图并生成可用的代码?VTJ.PRO 设计了一套完整的 AI 集成系统,支持多模态输入(文本/截图/设计稿)、工具调用、增量更新等能力。本文将深入剖析这一系统的架构设计与实现细节。


一、系统总览:五层架构设计

整个 AI 集成系统由五个核心层组成,各层职责分明:

flowchart TD
    subgraph UI层["UI层"]
        AIWidget
        ChatInput
        ImageInput
        JsonInput
    end
    
    subgraph 编排层["编排层"]
        useAI
        useOpenApi
        useAgent
    end
    
    subgraph 工具层["工具层"]
        ToolRegistry
        40+内置工具
    end
    
    subgraph 转换层["代码转换层"]
        CodeIncrementalUpdater
        VueToDSL转换器
    end
    
    subgraph 后端层["后端服务"]
        API端点
        LLM服务
        SSE流
    end
    
    UI层 --> 编排层
    编排层 --> 工具层
    编排层 --> 转换层
    编排层 --> 后端层

二、多模态输入:不止是聊天

2.1 三种输入模式

// 1. 文本输入 - 最直接的交互方式
interface TextInput {
  prompt: string;      // 自然语言描述
  model: string;       // 模型选择(GPT-4/Claude等)
  project: ProjectSchema; // 当前项目上下文
}

// 2. 图像输入 - 截图即代码
interface ImageInput {
  file: File;          // PNG/JPG/JPEG
  model: string;       // 自动选择视觉模型
}

// 3. JSON输入 - 设计工具集成
type TopicDataType = 'sketch' | 'figma' | 'mastergo' | 'unknown';
// 自动识别设计工具类型
if (json.includes('/sketch/')) return 'sketch';
if (json.includes('/figma/')) return 'figma';

2.2 输入处理流程

sequenceDiagram
    participant User
    participant UI
    participant API
    
    User->>UI: 拖入Figma JSON
    UI->>UI: 检测数据类型
    UI->>API: POST /api/open/topic/json
    API-->>UI: 返回Topic + Chat
    UI->>UI: 初始化对话上下文
    UI-->>User: 准备就绪

三、编排层:三个核心Hook

3.1 useAI - 中央状态管理

// 核心状态
const state = {
  isReady: Ref<boolean>,      // 初始化状态
  loading: Ref<boolean>,      // 请求进行中
  topics: Ref<AITopic[]>,     // 对话线程
  chats: Ref<AIChat[]>,       // 消息历史
  settings: Ref<Settings>     // AI配置
}

// 关键函数
const onPostTopic = async (data: AISendData) => {
  // 1. 创建新主题
  // 2. 发送初始消息
  // 3. 处理流式响应
}

const processOutput = (chat: AIChat) => {
  // 解析AI响应
  // 执行工具调用
  // 转换Vue代码
}

3.2 useOpenApi - 后端通信

实现健壮的SSE流式处理:

// 行缓冲区处理
let buffer = '';
const decoder = new TextDecoder();

const onChunk = (chunk: Uint8Array) => {
  buffer += decoder.decode(chunk, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop() || '';  // 保留不完整的行
  
  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const data = JSON.parse(line.slice(6));
      callback?.(data, false);
    }
  }
};

3.3 useAgent - 输出处理

flowchart TD
    Response["AI响应"]
    Parse["提取代码块"]
    
    Response --> Parse
    
    Parse -- "```vue" --> Vue["完整SFC"]
    Parse -- "```diff" --> Diff["增量更新"]
    Parse -- "```json" --> Json["工具调用"]
    
    Vue --> Convert["convertVueToDsl()"]
    Diff --> Apply["applyPatch()"]
    Json --> Execute["callTool()"]
    
    Convert --> DSL["BlockSchema"]
    Apply --> Convert
    Execute --> Result["执行结果"]

四、工具系统:40+个内置工具

4.1 工具注册表架构

interface ToolConfig {
  name: string;           // 工具名称
  description: string;    // 给LLM的描述
  parameters: ToolParameter[]; // 参数定义
  handler: (context) => (...args) => Promise<any>;
}

// 示例:创建页面工具
const createPage: ToolConfig = {
  name: 'createPage',
  description: 'Create a new page in the current project',
  parameters: [
    {
      name: 'page',
      type: 'object',
      required: true,
      properties: {
        name: { type: 'string', required: true },
        title: { type: 'string', required: true },
        icon: { type: 'string' }
      }
    }
  ],
  createHandler: ({ project }) => async (page, parentId?) => {
    const newPage = await project.createPage(page, parentId);
    return { id: newPage.id, name: page.name };
  }
};

4.2 工具分类

类别典型工具用途
页面管理createPage, getMenus操作项目页面
块管理createBlock, cloneBlock管理组件块
API配置setApi, getApis配置后端接口
状态管理setGlobalStorePinia配置
权限控制setGlobalAccess路由守卫

五、代码转换:从AI到可运行代码

5.1 增量更新器

使用SEARCH/REPLACE模式实现精准更新:

------- SEARCH
<template>
  <div>旧代码</div>
</template>

=======
<template>
  <div>新代码</div>
</template>

+++++++ REPLACE

5.2 模糊匹配策略

当精确匹配失败时,使用Levenshtein距离进行容错:

searchAndReplace(code: string, search: string, replace: string) {
  // 先尝试精确匹配
  if (code.includes(search)) {
    return { success: true, updatedCode: code.replace(search, replace) };
  }
  
  // 模糊匹配:距离 < 30% 长度
  const chunks = this.splitIntoChunks(code, search.length);
  for (const chunk of chunks) {
    const distance = this.levenshteinDistance(chunk, search);
    if (distance < search.length * 0.3) {
      return { success: true, updatedCode: code.replace(chunk, replace) };
    }
  }
  
  return { success: false, error: '模式未找到' };
}

5.3 Vue到DSL转换

const convertVueToDsl = (chat: AIChat) => {
  try {
    // 1. 获取当前文件上下文
    const fileId = engine.current.value?.id;
    
    // 2. 解析Vue SFC
    const result = service.parseVue(chat.vue, projectDsl);
    
    if (result.errors?.length) {
      chat.status = 'Error';
      chat.message = result.errors.join('\n');
      return;
    }
    
    // 3. 存储DSL
    chat.dsl = result.block;
    chat.status = 'Success';
  } catch (error) {
    chat.status = 'Failed';
    chat.message = error.message;
  }
};

六、后端通信:SSE流式处理

6.1 完整流程

sequenceDiagram
    participant Frontend
    participant Backend
    participant LLM
    
    Frontend->>Backend: POST /api/open/topic
    Backend-->>Frontend: {topic, chat}
    
    Frontend->>Backend: GET /api/open/completions (SSE)
    Backend->>LLM: 请求LLM
    
    loop 流式传输
        LLM-->>Backend: chunk
        Backend-->>Frontend: data: {...}
        Frontend->>Frontend: 累积content
        Frontend->>Frontend: 响应式更新UI
    end
    
    Backend-->>Frontend: [DONE]
    Frontend->>Backend: POST /api/open/chat/save

6.2 CompletionChunk结构

interface CompletionChunk {
  id: string;
  choices: Array<{
    delta: {
      content?: string;        // 主要响应
      reasoning_content?: string; // 思维链
      role?: 'assistant';
    };
    finish_reason: 'stop' | 'length' | null;
  }>;
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
  };
}

七、状态管理:数据模型设计

7.1 AITopic - 对话主题

interface AITopic {
  id: string;
  fileId: string;      // 关联的文件
  title: string;       // 自动生成
  model: string;       // 使用的模型
  prompt: string;      // 初始提示
  dsl: any;            // 项目快照
  type?: TopicType;    // text/image/json
  dataType?: TopicDataType; // sketch/figma/mastergo
}

7.2 AIChat - 聊天消息

interface AIChat {
  id: string;
  topicId: string;
  
  // 内容
  prompt: string;      // 用户输入
  content: string;     // AI响应(累积)
  reasoning: string;   // 思维链
  vue: string;         // 生成的Vue代码
  dsl: any;            // 转换后的DSL
  
  // 状态
  status: 'Pending' | 'Success' | 'Failed' | 'Error' | 'Canceled';
  message?: string;    // 错误信息
  
  // 元数据
  tokens: number;      // token使用量
  thinking: number;    // 思考时间(秒)
  
  // 工具调用
  toolCallId?: string; // vue/diff/json
  toolContent?: string; // 执行结果
}

八、UI组件实现

8.1 AIWidget组件结构

<template>
  <div class="ai-widget">
    <!-- 标题栏 -->
    <Panel :title="'AI助手'" @open-record="openRecordDrawer" />
    
    <!-- 新对话视图 -->
    <NewTopic v-if="isNewChat">
      <ChatInput @send="onPostTopic" />
      <ImageInput @upload="onImageUpload" />
      <JsonInput @parse="onJsonParse" />
      <HotTopics @select="onHotTopicSelect" />
    </NewTopic>
    
    <!-- 聊天视图 -->
    <template v-else>
      <BubbleList :chats="chats">
        <template #bubble="{ chat }">
          <UserBubble v-if="chat.role === 'user'" :chat="chat" />
          <AIBubble v-else :chat="chat" @apply="onApply" @refresh="onRefresh" />
        </template>
      </BubbleList>
      <ChatInput @send="onPostChat" />
    </template>
    
    <!-- 对话框 -->
    <DetailDialog :visible="showDetail" :chat="selectedChat" />
    <RecordDrawer :visible="showRecord" :topics="topics" />
  </div>
</template>

8.2 Markdown渲染优化

// 带节流的流式渲染
const throttledUpdate = useThrottle(
  (content: string) => {
    markdownContent.value = content;
  },
  50 // 50ms节流
);

// 标签映射(中文化)
const labelMap = {
  'T:': '思考',
  'A:': '执行',
  'O:': '系统',
  'P:': '计划',
  'F:': '总结',
  'R:': '结果'
};

九、与Designer的深度集成

9.1 应用AI生成的DSL

// Engine类中的applyAI方法
async applyAI(dsl: BlockSchema) {
  if (!this.current.value) return;
  
  const block = this.current.value;
  const newDsl = { ...dsl, id: block.id };
  
  // 更新块模型
  block.fromDsl(newDsl);
  
  // 刷新预览
  this.simulator.refresh();
  
  // 保存历史
  if (this.state.autoHistory) {
    await this.history.save();
  }
}

9.2 自动应用逻辑

// 当满足条件时自动应用
watch(() => currentChat.value, (chat) => {
  if (
    engine.state.autoApply &&    // 开启自动应用
    chat?.status === 'Success' && // 生成成功
    chat?.dsl                    // 有有效DSL
  ) {
    onApply(chat);
  }
});

十、自定义LLM配置

支持接入任意OpenAI兼容的API:

interface LLM {
  id?: string;
  label: string;      // 显示名称
  baseURL: string;    // API地址
  model: string;      // 模型名称
  apiKey: string;     // API密钥
}

// 状态管理
state.LLMs: LLM[];    // 自定义模型列表
state.llm: string;    // 当前选中模型

// 在请求中使用
const dto: TopicDto = {
  model: selectedModel,
  prompt: userInput,
  llm: customLLM ? JSON.stringify(customLLM) : ''
};

总结

VTJ.PRO的AI集成系统通过精心设计的五层架构,实现了从多模态输入到可运行代码的完整闭环。核心亮点包括:

  1. 多模态支持:文本、截图、设计稿一键转换
  2. 工具系统:40+个内置工具,让AI真正能操作项目
  3. 增量更新:通过SEARCH/REPLACE实现精准修改
  4. 容错机制:模糊匹配确保代码更新的稳定性
  5. 流式体验:SSE + 响应式UI提供流畅交互

这个系统不仅大幅提升了开发效率,更重要的是让AI真正成为了开发者的得力助手,而不是简单的代码生成器。


想了解更多细节?欢迎访问 VTJ.PRO 技术文档