开源表单设计器 FcDesigner 保存表单教程:toJson parseJson 回显

好用的低代码可视化表单设计器 FcDesigner 是一款基于 Vue 的开源工具(设计器项目名 form-create-designer),通过数据驱动表单渲染。可以拖拽生成表单规则,再由配套渲染器 form-create 加载 JSON 并渲染。面向政务、OA、ERP、电商、流程管理里要做动态表单的开发者和业务配置同学。

源码地址: Github | 文档 | 演示

审批单画完要入库、刷新后还得回到同一张画布、OA 里审批详情页还要用同一份 JSON 渲染------这些都是保存和回显。FcDesigner 把设计结果收成两段数据:规则 rule 和配置 options。内置保存按钮用 config.showSaveBtn: true 打开,点击触发 save 事件,handler 收到 {rule, options},两段都是 JSON 字符串。嵌进 OA 用自己的工具栏时,调用 getRule / getOptions,再用 formCreate.toJson 转成字符串后 POST。回显写在 onMounted 里,调用 setOptionssetRule。转换 JSON 必须用 formCreate.toJson / formCreate.parseJson,不要用 JSON.stringify / JSON.parse

截图是设计器顶部工具栏:导入、导出旁边有绿色的「保存」,红箭头指着它,后面是「预览」「清空」。这是把 config.showSaveBtn 设为 true 之后才会出现的内置保存按钮。点「保存」会触发 save 事件。点「预览」只是按当前画布渲染出表单,不会自动发保存请求。

FcDesigner 保存表单为什么必须用 toJson 和 parseJson?

规则里不只是普通对象,还可能带设计器自己的结构。用浏览器自带的 JSON.stringify / JSON.parse 转出来的字符串,回显时格式会对不上。保存用 formCreate.toJson,读回来用 formCreate.parseJson。本课的 formCreate@form-create/designer 引入,和设计器、渲染器是同一套。

设计器实例上和保存、回显直接相关的方法(调用前要等组件初始化完成,写在 onMounted 里):

ts 复制代码
// 设置 / 读取规则
type SetRule = (rule: string | Rule[]) => void
type GetRule = () => Rule[]
type GetJson = () => string

// 设置 / 读取配置;setOption 别名 setOptions,getOption 别名 getOptions
type SetOption = (opt: Options) => void
type GetOption = () => Options
type GetOptionsJson = () => string

getJson() / getOptionsJson() 已经是 JSON 字符串。本课保存示例按官方写法:先 getRule() / getOptions(),再 formCreate.toJson。回显不要把接口返回的字符串直接 JSON.parse,先 formCreate.parseJson,再 setRule / setOptions

接口字段名官方示例里有两套,对接时按你们的后端映射即可:

  • 保存 POST /api/saveForm:body 是 { rules, options },值是 JSON 字符串(@save 参数本身叫 rule / options,POST 时规则字段写成了 rules
  • 回显 GET /api/getForm{ ruleJson, optionsJson }
  • 渲染 GET /api/getFormRules:同样是 { ruleJson, optionsJson },还可以带一份初始 formData

怎么显示内置保存按钮 showSaveBtn?审批单怎么 POST 保存?

基本示例:打开 showSaveBtn

场景: 审批单配置页。业务同学拖完字段,希望在设计器顶部看到保存按钮,先不用自己画工具栏。

按下面做:

  1. 页面里放 fc-designer,把 config 传给 :config
  2. config 里写 showSaveBtn: true
  3. 打开这个页面,看顶部工具栏,不要只看画布中间。
  4. 点「预览」确认当前表单能渲染;点绿色「保存」才会走到下一节的 @save
vue 复制代码
<template>
    <fc-designer ref="designer" :config="config"/>
</template>
<script setup>
    const config = {
        showSaveBtn: true
    }
</script>

预览后:工具栏出现绿色「保存」。此时还没有监听 @save,点保存不会发接口,但按钮已经在了。「预览」打开的是当前画布对应的表单,和保存是两件事。

再一个示例:@save 把 rule/options POST 到 /api/saveForm

场景: 录入页的表单模板要入库。业务同学点顶部「保存」,把当前规则和配置交给后端。

按下面做:

  1. 保留上一节的 showSaveBtn: true
  2. fc-designer 上写 @save="handleSave"
  3. handleSave 解构 {rule, options},两段都是 JSON 字符串,不要再 JSON.stringify
  4. axios.post('/api/saveForm', { rules: rule, options: options })。注意 body 里规则字段是 rules
  5. 点顶部「保存」发请求;只点「预览」看不到这次 POST。
vue 复制代码
<template>
    <fc-designer ref="designer" @save="handleSave" :config="config"/>
</template>
<script setup>
    import axios from 'axios'

    const config = {
        showSaveBtn: true
    }

    function handleSave ({rule, options}) {
        axios.post('/api/saveForm', {
            rules: rule, //JSON字符串
            options: options //JSON字符串
        }).then(response => {
            console.log('表单保存成功', response.data)
        }).catch(error => {
            console.error('表单保存失败', error)
        })
    }
</script>

预览后:点绿色「保存」,发出 POST /api/saveForm,body 里 rulesoptions 是两段 JSON 字符串。成功会在控制台看到「表单保存成功」。把 /api/saveForm 换成你们的模板保存地址,字段名按上表映射。

嵌进 OA 时怎么用自己的保存按钮 toJson?

基本示例:自己的按钮 + toJson(getRule()) / toJson(getOptions())

场景: 设计器嵌进 OA。页面顶部已经有业务自己的工具栏,不能靠设计器内置保存按钮,要点 OA 里那颗「保存」。

按下面做:

  1. fc-designer 可以不传 showSaveBtn(不打开内置按钮)。
  2. 在旁边(或 OA 工具栏)放自己的按钮,例如 Element Plus 的 el-button
  3. 点击时从 designergetRule()getOptions(),用 formCreate.toJson 转成 JSON 字符串。
  4. 仍然 POST /api/saveForm,body 字段还是 rulesoptions
  5. 看表单长什么样,点设计器顶部「预览」;真正入库走你自己的按钮。
vue 复制代码
<template>
    <fc-designer ref="designer"/>
    <el-button @click="save">保存</el-button>
</template>
<script setup>
    import {ref} from 'vue'
    import axios from 'axios'
    import {formCreate} from '@form-create/designer'

    const designer = ref(null)

    function save() {
        axios.post('/api/saveForm', {
            rules: formCreate.toJson(designer.value.getRule()), //JSON字符串
            options: formCreate.toJson(designer.value.getOptions()), //JSON字符串
        }).then(response => {
            console.log('保存成功')
        })
    }
</script>

预览后:点你自己的「保存」,发出的 POST 和上一节同一条 /api/saveForm,两段也是 JSON 字符串。差别是数据从实例方法取,再 toJson,而不是等 @save 把字符串递过来。getRule() 返回的是规则数组,getOptions() 返回配置对象,不要对它们 JSON.stringify。按钮要点在组件已经渲染出来之后,初始化完成前不要调这些方法。

刷新后怎么 setRule 回显?审批详情页怎么 parseJson?

基本示例:刷新回显 setRule + setOptions + parseJson

场景: 审批单配置页刷新或下次再打开,画布要回到上次保存的样子,业务同学接着改,而不是空白设计器。

按下面做:

  1. ref="designer"script setupconst designer = ref(null)
  2. onMounted 里拉接口。必须等设计器初始化完成才能调实例方法。
  3. GET /api/getForm,从 data 里取 ruleJsonoptionsJson
  4. formCreate.parseJson,再 setOptionssetRule。顺序按保存页示例:配置先于规则。
  5. 回显后点「预览」,应看到上次保存的表单,而不是空表。
vue 复制代码
<template>
    <fc-designer ref="designer" @save="handleSave" :config="config"/>
</template>
<script setup>
    import {ref, onMounted} from 'vue'
    import axios from 'axios'
    import {formCreate} from '@form-create/designer'

    const designer = ref(null)
    const config = {
        showSaveBtn: true
    }

    function handleSave ({rule, options}) {
        axios.post('/api/saveForm', {
            rules: rule, //JSON字符串
            options: options //JSON字符串
        })
    }

    onMounted(async () => {
        try {
            const { data } = await axios.get('/api/getForm')
            const { ruleJson, optionsJson } = data
            designer.value.setOptions(formCreate.parseJson(optionsJson))
            designer.value.setRule(formCreate.parseJson(ruleJson))
        } catch (error) {
            console.error('加载表单数据失败', error)
        }
    })
</script>

预览后:组件挂载结束就会去拉 /api/getForm,画布还原成 ruleJson / optionsJson 里的表单。点「预览」看到的就是这份规则渲染出来的结果。接口如果沿用保存时的 rules / options 字段,读取时改成你们实际的键名即可,不要假定一定叫 ruleJsononMounted 的回调必须是 async,才能 await axios.get

再一个示例:运行时 form-create 加载同一份 JSON

场景: 审批详情页。填表人看不到设计器,只要把已经保存的规则渲染成可填的表单,提交的是字段值,不是再存一份设计 JSON。

运行时用 <form-create>。同一份 formCreate@form-create/designer 引入;应用启动时挂载一次即可:

js 复制代码
import {formCreate} from '@form-create/designer'
app.use(formCreate)

按下面做:

  1. 页面放 <form-create>:rule:option 绑解析后的对象,v-modelformData
  2. v-if="rule.length",规则还是空数组时先不渲染。
  3. onMounted 里 GET /api/getFormRules,用 formCreate.parseJson 赋给 ruleoption
  4. 如果接口还带了初始值,赋给 formDataformData 的 key 必须和规则里的字段 field 一致。
  5. 打开详情页就能看到表单;提交走 @submit,POST 的是填写值,不是 rules / options
vue 复制代码
<template>
    <div id="app">
        <form-create
            v-if="rule.length"
            v-model="formData"
            v-model:api="api"
            @submit="handleSubmit"
            :rule="rule"
            :option="option"
        ></form-create>
    </div>
</template>
<script setup>
    import {ref, onMounted} from 'vue'
    import axios from 'axios'
    import {formCreate} from '@form-create/designer'

    const rule = ref([])
    const option = ref({})
    const api = ref(null)
    const formData = ref({})

    function handleSubmit(formData) {
        axios.post('/api/submitFormData', formData)
            .then(response => {
                console.log('提交成功:', response.data)
            })
            .catch(error => {
                console.error('提交失败:', error)
            })
    }

    onMounted(() => {
        axios.get('/api/getFormRules')
            .then(response => {
                const {ruleJson, optionsJson, formData: initFormData} = response.data
                rule.value = formCreate.parseJson(ruleJson)
                option.value = formCreate.parseJson(optionsJson)
                formData.value = initFormData || {}
            })
            .catch(error => {
                console.error('加载表单规则失败:', error)
            })
    })
</script>

预览后:详情页渲染的是保存过的那份规则。提交发出 POST /api/submitFormData,body 是当前 formData。设计器里保存的是模板(rules / options),详情页提交的是填写结果,两套接口不要混。没有 initFormData 时,formData 先空对象,等用户填;编辑已有记录时,key 必须对上 field

保存和回显常见问题

Q: 为什么不能用 JSON.stringify / JSON.parse?

A: 必须用 formCreate.toJson 代替 JSON.stringify,用 formCreate.parseJson 代替 JSON.parse,才能保证规则格式正确。@save 拿到的 rule / options 已经是 JSON 字符串,POST 时原样放入 rules / options 即可。自己取实例数据时:formCreate.toJson(designer.value.getRule())formCreate.toJson(designer.value.getOptions())。回显和运行时渲染都先 parseJson,再 setRule / setOptions 或赋给 :rule / :option

Q: @save 的 rule 和 POST 的 rules、GET 的 ruleJson 是什么关系?

A: save 事件参数是 {rule, options},两段 JSON 字符串。官方保存接口 body 写成 { rules: rule, options: options },规则多了一个 s。回显 GET /api/getForm 示例取的是 { ruleJson, optionsJson };运行时 GET /api/getFormRules 同样是这两个键,还可以带 formData。后端可以统一命名,前端按实际字段做映射,不要三种名字混在一次请求里。

Q: setRule、getRule 什么时候能调?内置保存和自己的按钮怎么选?

A: 必须等 fc-designer 初始化完成,写在 onMounted 里,通过 designer.value 调。内置按钮:config.showSaveBtn: true,点「保存」走 @save,参数已经是字符串。嵌进 OA、工具栏是自己的:不依赖 showSaveBtn,按钮里 toJson(getRule()) / toJson(getOptions())。两种保存都可以 POST /api/saveFormgetJson() / getOptionsJson() 也能拿到 JSON 字符串;本课示例按官方用 toJson 包一层 getRule / getOptions

Q: 设计器回显和审批详情页渲染有什么不同?

A: 设计器回显是给画布:setOptions(formCreate.parseJson(optionsJson))setRule(formCreate.parseJson(ruleJson)),之后还能继续拖改,点「预览」看效果。详情页不挂设计器,用 <form-create v-if="rule.length" v-model="formData" v-model:api="api" :rule="rule" :option="option">rule / option 同样来自 parseJsonformData 的 key 必须和字段 field 一致。保存的是模板 JSON,提交的是填写值,不要把 formData 存进 rules

相关推荐
HelloGitHub1 小时前
《HelloGitHub》第 125 期
开源·github
zzzzzz3103 小时前
react-bits:把动效组件库当成前端表达的参考系
react.js·开源·动效
钛态10 小时前
Vite 中的 CSS 工程化:从 CSS Modules 到 UnoCSS 的渐进式迁移
前端·vue·react·web
不开大的凯207712 小时前
开源、资本、落地、入口:AI正在同时打赢四场战争
人工智能·开源
vipjx112 小时前
百度网盘怎么加速下载?2026最新PanDownload多线程配置提速详解
开源
晓晓_za89866813 小时前
开源 GEO 优化源码二次开发:贴牌改造与业务模块扩展实践
java·运维·服务器·开发语言·性能优化·开源
冬奇Lab13 小时前
开源项目第199期:OpenWiki — LangChain 出品的代码库自维护文档 CLI,为 Agent 而生
人工智能·开源·资讯