Springboot + Vue3 + FormCreate表单引擎,直接用AI对话进行单据设计,告别拖拽画表单
🌐 文档地址 :https://ruoyioffice.com
👇 文章底部获取源码和演示地址 👇
💬 :17156169080(获取产品咨询)
业务人员说清"要一张什么单",AI 先生成可运行的 FormCreate 规则;开发人员再检查字段、明细和约束,确认后保存发布。本文用一张差旅报销单,讲清这条链路怎样在 Vue3 与 Spring Boot 中真正落地。

▲ 自然语言需求经过规则生成与校验,最终变成可预览、可保存、可发布的企业单据。
引言:为什么拖拽设计单据仍然不够快
拖拽设计器解决了"不会写 Vue 代码也能画表单",却没有解决"怎样把一段业务描述准确翻译成字段、组件和校验规则"。一张稍复杂的单据,仍要重复完成选组件、改标题、起英文标识、设置必填、配置枚举、调整宽度和搭建明细表。需求变更后,这些动作还要再来一遍。
AI 对话适合承担的不是最终决策,而是从自然语言到表单草案的第一次编译。业务人员负责表达意图,模型生成结构化规则,FormCreate 负责渲染,Spring Boot 负责模型选择、安全边界和协议整形,最后仍由人确认并发布。
| 传统拖拽动作 | 对话式设计对应动作 | 仍需人工确认的内容 |
|---|---|---|
| 逐个搜索并拖入组件 | 一次描述字段和分组 | 字段是否缺失、组件是否合适 |
| 手动设置必填与占位提示 | 从"必填、两位小数"等语义生成规则 | 校验是否符合公司制度 |
| 明细列逐项搭建 | 生成一个 tableForm 及其列规则 |
列宽、枚举、合计与联动 |
| 改需求后重复编辑 | 用第二轮对话做局部修改 | 是否误改未选中的组件 |
这也是本文的边界:AI 提速的是"画草案"和"改草案",不是绕过数据建模、权限审核与发布流程。
一、AI 对话给 FormCreate 表单引擎带来了什么
FormCreate 的核心价值是把表单描述为规则数组,再由运行时渲染;AI 的价值是把自然语言转换为这份规则。两者之间不是截图识别或自动点击,而是一份可验证、可保存、可版本化的 JSON 协议。
本文对应的前端组合是 fc-designer-pro 6.4.0 与 @form-create/ant-design-vue 3.3.3:前者提供商业版设计器、智能助理和设计交互,后者负责 Vue3 + Ant Design Vue 的表单运行时。商业组件的授权仍需按其许可使用,后端接入不会改变授权边界。

▲ 流程表单列表里已经存在 AI 生成的单据,并可按独立数据表版本继续维护。
一条可落地的生成链路至少要同时满足四个条件:
| 设计点 | 采用方案 | 原因 |
|---|---|---|
| 输出格式 | 只接受 FormCreate Rule,而不是任意 HTML | 设计器能继续编辑,运行时也能直接渲染 |
| 复杂明细 | 用 tableForm 表达主子结构 |
防止模型把明细列错误铺到主表 |
| 返回方式 | SSE 流式传输并以 [DONE] 收尾 |
长表单生成时能看到进度,避免一直等待 |
| 发布边界 | 自动应用到画布,但保存、发布由人触发 | 兼顾生成效率与生产安全 |
换句话说,AI 不是 FormCreate 的替代品,而是规则生产器;设计器依然是可视化校验与二次编辑入口。
二、Vue3 如何接入 FormCreate AI 设计器
Vue3 接入的关键不是把模型密钥放进浏览器,而是只告诉设计器"内部 AI 接口在哪里、是否自动应用"。模型、平台和密钥统一留在后端的 AI 管理中,前端只携带当前登录态。
第一段核心配置非常短:接口始终指向本系统,autoApply 让符合协议的规则在流式返回后自动进入画布。
typescript
export function getFcDesignerAiConfig(): FcDesignerAiOptions {
const accessStore = useAccessStore();
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
const token = accessStore.accessToken
? `Bearer ${accessStore.accessToken}`
: '';
return {
api: `${apiURL}/ai/form-create/chat/form`,
autoApply: true,
token,
};
}
设计器内部使用原生 fetch,不会自动经过项目的 requestClient。如果只在初始化时塞一个 Token,登录态刷新后可能继续携带旧值;多租户项目还会遗漏租户、语言和当前部门。实际接入因此增加了一个窄范围请求补丁,只处理 FormCreate AI 请求。
typescript
function buildHeaders(init?: RequestInit): Headers {
const headers = new Headers(init?.headers);
const accessStore = useAccessStore();
if (accessStore.accessToken) {
headers.set('Authorization', `Bearer ${accessStore.accessToken}`);
}
headers.set('Accept', 'text/event-stream');
headers.set('Accept-Language', preferences.app.locale);
if (isTenantEnable() && accessStore.tenantId != null) {
headers.set('tenant-id', String(accessStore.tenantId));
}
if (accessStore.visitTenantId != null) {
headers.set('visit-tenant-id', String(accessStore.visitTenantId));
}
return headers;
}
window.fetch = (input, init) => {
const url = resolveUrl(input);
if (!isFormCreateAiRequest(url)) return nativeFetch(input, init);
return nativeFetch(ourApi, { ...init, method: 'POST', headers: buildHeaders(init) });
};
这样做还有一个兜底价值:即使设计器尝试回退到官方 AI 地址,也会被改写回系统内部接口,避免客户浏览器直接依赖第三方密钥。代码示例只展示请求结构,不包含任何真实 Token、Cookie 或模型凭证。
三、一句话生成带费用明细的差旅报销单
提示词写得越像一份精简的字段契约,生成结果越稳定。不要只说"生成报销单",而要把主表、明细、类型和校验说清楚。本文首轮使用的表达是:
请生成一张差旅报销单:包含申请人、部门、出差事由、起止日期;费用明细包含费用日期、费用类别、费用说明和金额;金额必填并保留两位小数。

▲ 对话输入与当前设计器处于同一屏幕,用户描述需求后才会发起生成。截图仅填写提示词,没有提交或改动演示数据。
这段话同时验证了系统字段、日期组件、数字精度和明细表四类能力。模型应把申请人、部门等放在主表,把费用日期、类别、说明和金额放进同一个 tableForm,而不是生成四个散落的输入框。
首轮生成后,需求往往还会补充。第二轮不需要推倒重来,可以继续说:
增加发票附件和报销总金额,将出差事由设为必填,费用类别改为交通、住宿、餐饮和其他。
| 需求表达 | 应生成的规则 | 验收点 |
|---|---|---|
| "申请人、部门" | UserSelect、DeptSelect |
是否复用系统选择器,而非普通输入框 |
| "起止日期" | 两个 datePicker 或日期区间 |
字段语义和必填是否正确 |
| "金额保留两位" | inputNumber + precision: 2 |
不能退化成文本输入 |
| "费用明细" | 单个 tableForm |
每列有宽度、规则和唯一 field |
| "发票附件" | FileUpload |
文件类型与数量仍需人工按制度调整 |

▲ 生成结果包含申请人、部门、日期、事由、附件与费用明细,仍可在设计器中继续调整。
差旅报销只是一个压力测试样例:它同时具备基础字段、系统字段、枚举、附件和一对多明细,足以判断这条 AI 规则链路能否用于企业单据,而不是只会生成简单问卷。
四、Spring Boot 如何约束模型输出 FormCreate 规则
后端不能把用户问题原样转发给模型,因为"看起来像 JSON"不等于"设计器能打开"。系统提示词需要把组件白名单、字段命名、分组方式、明细结构和修改范围写成明确约束。
下面是核心约束的摘录。重点不是提示词长度,而是把最容易出错的结构变成协议:英文小驼峰字段、唯一代码块、整表与局部修改的差异,以及明细必须使用 tableForm。
java
private static final String SYSTEM_MESSAGE = """
你是 FormCreate Pro 6.4 表单设计器助手,UI 为 ant-design-vue。
只输出一个标记为 fcRuleDiff 的代码块。
整表返回 {"rule":[...]};局部修改增加 scope,并使用给定 _fc_id。
field 使用英文小驼峰,title 使用中文;必填字段设置 $required。
可用组件包括 input、select、datePicker、inputNumber、
UserSelect、DeptSelect、FileUpload、tableForm 等。
用户要求明细、子表、表格或清单时,必须生成 tableForm。
tableForm 每列必须包含 label、style.width 和 rule;
金额使用 inputNumber,日期使用 datePicker。
不要输出 _fc_id、sql 或 sqlType。
""";
请求还会携带当前 rule、option、选中组件 ID、可用字段和函数源码。模型因此能区分"从零生成整表"和"只改当前组件"。为了避免超长上下文拖垮请求,当前规则等 JSON 会限制长度;已有组件未被要求修改时,也必须保留。
字段名还有单独的安全阀:AI 可以把"出差事由"命名为 travelReason,但结果必须满足字母开头、英文小驼峰、最长 25 个字符,并避开 id、tenantId、createTime 等系统保留名。不合格的命名不会直接进入结果,而是交给调用方兜底。

▲ AI 模型配置与流程表单版本分属两组数据关系,在生成和发布链路中协同。
上面两组关系没有直接外键:ai_api_key → ai_model 决定生成时调用哪个模型,bpm_form → bpm_form_version 保存设计结果和发布版本;它们只是处在同一条"生成---检查---发布"链路中。
五、SSE 流式生成与 fcRuleDiff 自动应用
SSE 的作用不只是让文字逐字出现,更重要的是把模型的普通文本流整理成设计器认识的事件。后端使用 StreamingResponseBody,为整表生成单独设置 180 秒异步超时,持续写出 data: 事件,并最终发送 [DONE]。
java
@PostMapping(value = "/chat/form", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public StreamingResponseBody chatForm(@RequestBody @Valid AiFormCreateChatReqVO req,
HttpServletResponse response) {
response.setHeader("Cache-Control", "no-cache, no-transform");
response.setHeader("X-Accel-Buffering", "no");
return output -> {
String id = "chatcmpl-" + UUID.randomUUID();
AiModelDO model = modelService.getRequiredDefaultModel(
AiModelTypeEnum.CHAT.getType());
String modelName = model.getModel();
StreamingChatModel chatModel = modelService.getChatModel(model.getId());
FcDesignerAiStreamAssembler assembler =
new FcDesignerAiStreamAssembler(shouldStreamRules(req),
isFunctionMode(req),
FcDesignerAiStreamAssembler.generateTitle(lastUserText(req)));
Prompt prompt = new Prompt(buildMessages(req));
chatModel.stream(prompt)
.doOnNext(chunk -> {
String content = AiUtils.getChatResponseContent(chunk);
for (String event : assembler.accept(content)) {
writeSse(output, buildSseDelta(id, modelName, event));
}
}).blockLast();
for (String event : assembler.finish()) {
writeSse(output, buildSseDelta(id, modelName, event));
}
writeSse(output, "[DONE]");
};
}
组装器会先输出检查、生成等步骤事件,再把规则节点流式追加到画布;只有完整的 fcRuleDiff 代码围栏闭合后,才把最终规则交给自动应用。选中组件的局部修改则延后到最后一次应用,避免中途用不完整规则覆盖整张表。

▲ 从自然语言到画布自动应用,再到人工检查和发布的完整时序。
这条时序里,模型只负责提案,协议组装器负责把提案变成稳定事件,设计器负责应用与预览,用户负责最后的保存发布。任何一层都不能被"AI 自动完成"四个字省略。
六、鉴权、租户、对话隔离与表单发布
企业表单接入 AI 后,最容易被忽略的是上下文边界。请求要继承登录态和租户范围;不同表单的历史对话不能混在一起;模型生成的规则也不能直接越过保存、预览和发布。
| 风险 | 实现控制 | 结果 |
|---|---|---|
| 浏览器暴露模型密钥 | 前端只访问内部接口,后端解析默认模型 | 密钥不进入页面与文章示例 |
| Token 刷新后仍用旧快照 | 每次请求动态读取登录态 | 长时间编辑仍使用当前凭证 |
| 多租户上下文丢失 | 注入租户、访问租户和当前部门头 | AI 请求沿用系统边界 |
| 表单 A 看见表单 B 对话 | 按表单 ID 或草稿范围隔离本地会话 | 上下文不串单 |
| 模型误改整表 | 传递选中组件 ID 与 scope |
局部修改有明确范围 |
| 生成即上线 | 自动应用只更新画布 | 保存、预览、发布仍需人工触发 |
对话隔离使用 form:{id}、draft:create 和 draft:copy:{id} 三类范围。设计器进入时加载当前范围的本地记录,离开时归还;新建草稿首次保存拿到表单 ID 后,再把会话重新绑定到正式表单。这样既保留连续对话,也不会让不同单据互相污染。

▲ 预览阶段可以核对必填、附件和费用明细列;预览通过后,才进入保存与发布。

▲ 费用类别、发生日期、说明和金额被组织在同一个可增行明细表中,而不是散落成主表字段。
发布后,表单主体保存当前配置和字段,并通过版本表冻结发布结果。以后继续让 AI 修改时,应产生新的设计版本,而不是悄悄改变已经运行的历史实例。这一点比"生成速度快多少"更重要:企业系统需要的不是一次漂亮演示,而是可审计、可回溯、可继续维护的单据资产。
结语:AI 生成草案,规则协议保障落地
Spring Boot + Vue3 + FormCreate 的对话式设计,本质上是一条受约束的编译链:自然语言负责表达意图,System Prompt 约束组件与结构,SSE 负责增量传输,fcRuleDiff 负责把结果交给设计器,autoApply 负责即时呈现,人工预览与版本发布负责最后把关。
它最适合字段多、修改频繁、又包含明细表的企业单据。差旅报销单只是示例,合同申请、采购申请、客户拜访、资产领用等场景都可以复用同一套链路。真正值得复用的不是某一份提示词,而是"内部接口 + 规则协议 + 流式组装 + 上下文隔离 + 人工发布"这五层边界。
你更希望 AI 帮你完成整张表单的首稿,还是只修改选中的字段和明细列?这个选择会直接影响上下文长度、自动应用策略和审核方式。
如果这篇对你有用,点个「在看」或收藏。
🌐 演示地址 :https://ruoyioffice.com/web
📦 GitHub 源码 :https://github.com/yuqing2026/ruoyi-office
📦 Gitee 源码 :https://gitee.com/yqzy1688/ruoyi-office
💬 微信:17156169080(获取产品咨询)

打开演示地址直接查看系统。