🎨 还在手动将 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 三种输入模式
typescript
// 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 - 中央状态管理
typescript
// 核心状态
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流式处理:
typescript
// 行缓冲区处理
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 工具注册表架构
typescript
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 | 配置后端接口 |
| 状态管理 | setGlobalStore | Pinia配置 |
| 权限控制 | setGlobalAccess | 路由守卫 |
五、代码转换:从AI到可运行代码
5.1 增量更新器
使用SEARCH/REPLACE模式实现精准更新:
xml
------- SEARCH
<template>
<div>旧代码</div>
</template>
=======
<template>
<div>新代码</div>
</template>
+++++++ REPLACE
5.2 模糊匹配策略
当精确匹配失败时,使用Levenshtein距离进行容错:
typescript
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转换
typescript
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结构
typescript
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 - 对话主题
typescript
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 - 聊天消息
typescript
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组件结构
vue
<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渲染优化
typescript
// 带节流的流式渲染
const throttledUpdate = useThrottle(
(content: string) => {
markdownContent.value = content;
},
50 // 50ms节流
);
// 标签映射(中文化)
const labelMap = {
'T:': '思考',
'A:': '执行',
'O:': '系统',
'P:': '计划',
'F:': '总结',
'R:': '结果'
};
九、与Designer的深度集成
9.1 应用AI生成的DSL
typescript
// 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 自动应用逻辑
typescript
// 当满足条件时自动应用
watch(() => currentChat.value, (chat) => {
if (
engine.state.autoApply && // 开启自动应用
chat?.status === 'Success' && // 生成成功
chat?.dsl // 有有效DSL
) {
onApply(chat);
}
});
十、自定义LLM配置
支持接入任意OpenAI兼容的API:
typescript
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集成系统通过精心设计的五层架构,实现了从多模态输入到可运行代码的完整闭环。核心亮点包括:
- 多模态支持:文本、截图、设计稿一键转换
- 工具系统:40+个内置工具,让AI真正能操作项目
- 增量更新:通过SEARCH/REPLACE实现精准修改
- 容错机制:模糊匹配确保代码更新的稳定性
- 流式体验:SSE + 响应式UI提供流畅交互
这个系统不仅大幅提升了开发效率,更重要的是让AI真正成为了开发者的得力助手,而不是简单的代码生成器。
想了解更多细节?欢迎访问 VTJ.PRO 技术文档