仅用于营销枢纽云系统实施过程中的预览与测试,正式运营之前,请绑定私有独立域名。 注册域名

仅用于营销枢纽云系统实施过程中的预览与测试,正式运营之前,请绑定私有独立域名。 注册域名

未找到文章

请在文章详情页地址中打开该模块,例如 /article/文章ID.html。

文章加载失败

请稍后刷新页面。

附件下载

    发布时间: 2026-06-05 15:25:44 

    为什么需要这个功能

    过去代码模块如果要接入表单,通常需要把字段、占位文案、接口参数、布局样式都写进 HTML 或 JS。这样做维护成本很高:运营想换一个表单,开发要改代码;字段顺序稍微变化,布局也容易跟着乱。

    新的表单配置功能把职责拆开:编辑器负责选择真实表单、控制字段显隐和配置字段布局;代码模块负责把这份配置渲染成最终页面效果。配置只表达“用哪个表单、显示哪些字段、字段如何排布”,不强行绑定最终视觉样式。

    所以它不是一个固定样式的表单组件,而是一套配置协议。不同代码模块可以共享同一份表单配置能力,同时保留各自的视觉风格、交互效果和提交逻辑。

    表单协议驱动渲染架构
    图 1:表单协议驱动渲染架构

    整体使用流程

    使用时只需要按编辑器里的两个步骤走。第一步完成字段设置,第二步完成布局配置。保存后,主应用会把当前表单、字段、布局和运行时配置合并进代码模块变量 $[fitForm],页面渲染时由代码模块读取。

    1. 在代码模块配置里打开表单配置弹窗。
    2. 从左侧表单列表选择一个高级表单。
    3. 在字段设置中确认表单标题、描述和字段显隐。
    4. 进入布局配置,使用预设或 24 栅格调整字段排布。
    5. 点击保存,配置回写到代码模块变量。

    字段设置:先决定表单展示哪些内容

    字段设置页关注基础信息和字段可见性。左侧是表单列表,右侧展示当前表单的标题、描述以及字段开关。这个阶段不处理最终样式,只解决字段集合和展示范围。

    表单编辑器字段设置弹窗
    图 2:字段设置弹窗。这里可以修改表单标题和描述,并控制每个字段是否显示。

    这一页会影响三个核心字段:表单标题写入 form.info.title,表单描述写入 form.info.description,字段显隐写入 field.visible

    最终模块渲染时,应先过滤 field.visible !== false 的字段。被隐藏的字段不应该出现在页面中,也不应该参与提交。

    布局配置:再决定字段如何排列

    布局配置页使用 24 栅格作为默认坐标系。用户可以先用单列、双列、三列快速预设得到基础结构,再点击画布里的字段微调占据列数、左侧空列和是否另起一行。这样既能快速生成常见布局,也能处理 8/16、6/18、12/12 这类不规则组合。

    表单编辑器布局配置弹窗
    图 3:布局配置弹窗。中间画布只负责排版设定,右侧面板提供快速预设、辅助线和总列数切换。

    布局配置保存在 form.layout.fieldLayouts 中。每个字段都有独立布局对象,包含排序、占列、左侧空列和行高等信息。

    {
      "layout": {
        "columns": 24,
        "gap": 16,
        "fieldLayouts": {
          "username": {
            "fieldId": "username",
            "colSpan": 12,
            "offset": 0,
            "rowSpan": 1,
            "order": 0
          }
        }
      }
    }

    推荐做法:模块渲染时不要只写 grid-column: span 12。如果字段配置了 offset,应该计算明确起点,例如 grid-column: 4 / span 12,这样才能和编辑器画布保持一致。

    最终效果:配置决定结构,模块决定外观

    保存后,最终页面不会直接复用编辑器里的控件样式,而是由代码模块读取配置并渲染成自己的视觉效果。字段顺序和占列来自配置,输入框、选项、开关、日期范围、提交按钮等样式则由代码模块统一实现。

    配置完成后的表单效果
    图 4:配置完成后的表单效果。字段顺序和占列来自配置,输入控件样式由代码模块统一实现。

    配置保存后的数据结构

    iframe 保存时会把当前表单、字段、布局和运行时配置返回给主应用。主应用接收后,会合并为 visual_form 配置,并写回代码模块变量。

    type FormSavePayload = {
      moduleType: "form";
      form: Form;
      fields: FormField[];
      layout: FormLayout;
      runtime?: FormRuntimeConfig;
    };

    代码模块如何接入

    新建或改造代码模块时,把变量定义为 input_type: "form"。默认值保持空骨架,等待用户在编辑器里选择真实表单。不要把某个表单 ID 或字段写死在模块里。

    [
      {
        "key": "fitForm",
        "label": "高级表单配置",
        "input_type": "form",
        "default_value": ""
      }
    ]

    在 LTD 代码组件中,建议把 $[fitForm] 放进隐藏的 textarea,再由 JS 读取。这样可以避免 JSON 被当成脚本执行。

    <div class="demoFormModule" data-ltd-form-module>
      <textarea class="demo-form-config" hidden aria-hidden="true">$[fitForm]</textarea>
      <form class="demo-form-root"></form>
    </div>
    
    <script>
    const readFitFormConfig = (container) => {
      const node = container.querySelector(".demo-form-config");
      const raw = node ? String(node.textContent || "").trim() : "";
      if (!raw || raw === "$" + "[fitForm]") return {};
    
      try {
        let parsed = JSON.parse(raw);
        if (typeof parsed === "string") parsed = JSON.parse(parsed);
        return parsed && typeof parsed === "object" ? parsed : {};
      } catch (error) {
        console.warn("[form module] fitForm parse failed:", error);
        return {};
      }
    };
    </script>

    渲染字段时,先过滤隐藏字段,再按布局排序,最后根据总列数建立 CSS Grid。下面是最小化的渲染逻辑示例:

    const visibleFields = form.fields
      .filter((field) => field.visible !== false)
      .sort((a, b) => {
        const la = form.layout.fieldLayouts[a.id];
        const lb = form.layout.fieldLayouts[b.id];
        return (la?.order || 0) - (lb?.order || 0);
      });
    
    root.style.gridTemplateColumns = `repeat(${form.layout.columns || 24}, minmax(0, 1fr))`;
    
    visibleFields.forEach((field) => {
      const layout = form.layout.fieldLayouts[field.id] || { colSpan: 24, offset: 0 };
      const start = (layout.offset || 0) + 1;
      item.style.gridColumn = `${start} / span ${layout.colSpan || 24}`;
    });
    支持 反馈 关注 数据