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让符合协议的规则在流式返回后自动进入画布。
exportfunctiongetFcDesignerAiConfig():FcDesignerAiOptions{constaccessStore=useAccessStore();const{apiURL}=useAppConfig(import.meta.env,import.meta.env.PROD);consttoken=accessStore.accessToken?`Bearer${accessStore.accessToken}`:'';return{api:`${apiURL}/ai/form-create/chat/form`,autoApply:true,token,};}设计器内部使用原生fetch,不会自动经过项目的requestClient。如果只在初始化时塞一个 Token,登录态刷新后可能继续携带旧值;多租户项目还会遗漏租户、语言和当前部门。实际接入因此增加了一个窄范围请求补丁,只处理 FormCreate AI 请求。
functionbuildHeaders(init?:RequestInit):Headers{constheaders=newHeaders(init?.headers);constaccessStore=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));}returnheaders;}window.fetch=(input,init)=>{consturl=resolveUrl(input);if(!isFormCreateAiRequest(url))returnnativeFetch(input,init);returnnativeFetch(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。
privatestaticfinalStringSYSTEM_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]。
@PostMapping(value="/chat/form",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicStreamingResponseBodychatForm(@RequestBody@ValidAiFormCreateChatReqVOreq,HttpServletResponseresponse){response.setHeader("Cache-Control","no-cache, no-transform");response.setHeader("X-Accel-Buffering","no");returnoutput->{Stringid="chatcmpl-"+UUID.randomUUID();AiModelDOmodel=modelService.getRequiredDefaultModel(AiModelTypeEnum.CHAT.getType());StringmodelName=model.getModel();StreamingChatModelchatModel=modelService.getChatModel(model.getId());FcDesignerAiStreamAssemblerassembler=newFcDesignerAiStreamAssembler(shouldStreamRules(req),isFunctionMode(req),FcDesignerAiStreamAssembler.generateTitle(lastUserText(req)));Promptprompt=newPrompt(buildMessages(req));chatModel.stream(prompt).doOnNext(chunk->{Stringcontent=AiUtils.getChatResponseContent(chunk);for(Stringevent:assembler.accept(content)){writeSse(output,buildSseDelta(id,modelName,event));}}).blockLast();for(Stringevent: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(获取产品咨询)
打开演示地址直接查看系统。