---
schema_version: "1"
id: 990c226657c021e527fb232de79ef97b478c5483089d856b24d839835bd361e5
title: 建筑表单
collection: architect
version: next
locale: zh-cn
portal_url: https://docs.salesforce.com/architect/next/zh-cn/decision-guides/guides/build-forms.md
canonical_url: https://staging.architect.salesforce.com/docs/architect/zh-cn/decision-guides/guide/build-forms.html
source_site: staging.architect.salesforce.com
content_type: documentation
content_hash: 2e8d70e27b6143cf7d405c7dcdc6bb803a6a9db673c19b5aa5ef2322eaa1a54a
products:
  - 决策指南
  - Architect Site Content Repo
updated_at: 2025-10-01T00:00:00Z
---
## 指南概览

想要在 Salesforce 平台上构建表单？您有多个选项，跨越整个低代码到专业代码的连续体。代表低代码的是 Lightning 应用程序生成器中的动态表单和 Flow Builder 中的屏幕流。在连续体的中间挂出的是使用 LWC 扩展屏幕流和使用 OmniStudio 构建面向客户的表单的能力。代表 pro-code 的是 LWC 框架及其不断增长的基组件库。

选项很好，但您如何确定哪个选项（或哪个组合）是正确的选项？这就是本指南的作用所在。

## 重要外卖

- **外卖 #1：在为 Lightning 页面构建创建/编辑/查看布局时，使用动态表单。**您可能会注意到本指南的对比表中缺少页面布局。下一步，配置记录详细信息页面的推荐方法是在 Lightning 应用程序生成器中使用动态表单。有关我们为何不期望进一步增强它们的更多信息，请查看[页面布局](#页面布局)部分。
- **外卖 #2：如果您需要仅为一个对象构建创建或编辑表单，请从 Lightning 页面和动态表单开始。**这是在 Salesforce 平台上构建表单的最简单方法。它还提供了一些额外的功能，例如控制字段可见性的能力。如果您的要求更高，请继续阅读。屏幕流、OmniStudio 或 Lightning Web 组件 (LWC) 可能更适合。
- **外卖 #3：如果您正在构建多页面表单或向导，并且没有严格的 UX 或品牌化要求，请从屏幕流开始。**屏幕流为编排多个表单提供了线性导航框架。您可以使用 LWC 构建您自己的框架以在表单之间导航，但我们建议让 Flow 为您完成繁重的工作，这样您就可以专注于表单本身，而不是担心[表单状态](/docs/architect/zh-cn/well-architected/guide/engaging#表格)。
- **外卖 #4：如果您需要*在表单后*添加其他逻辑或操作，请使用屏幕流、OmniStudio 或 LWC。**所有这三个工具都为您的解决方案提供了实现更多功能的方法，而不仅仅是创建或编辑单个记录。“更多”可能是更高级的逻辑，例如分支或迭代，也可能是更多操作，例如与外部系统集成、发送电子邮件或将通知推送到用户的移动应用程序。
- **外卖 #5：有复杂的 UX 要求吗？需要动态处理可见性以外的内容？使用 LWC 或 Omniscript。**如果您的要求可以通过简单的主题化和基于列的布局来实现，您可以直接在低代码生成器中构建表单。为了获得对表单样式的更精细的控制，您需要 LWC 的最终灵活性。如果您是行业客户，需要像素级完美品牌化，或者拥有复杂的层次结构数据，请使用 OmniStudio，这将允许您构建能够处理复杂业务逻辑和数据转换的消费者等级表单。
- **外卖 #6：如果您需要测试自动化，请从 Lightning Web 组件开始。**您可以为任何 LWC 编写单元测试，无论您计划将其嵌入何处。这使您能够创建更强大的测试策略，其中包括具有多个记录的批量测试和消极测试。有关创建测试的更多信息，请[参阅 Salesforce 架构良好 - 测试策略](/docs/architect/zh-cn/well-architected/guide/resilient#测试策略)，这将帮助您了解表单与功能和非功能需求的一致性。

请记住，您的选择不必是要么/要么 - 您可以组合多个选项的功能。例如，如果您同时需要 Flow 的内置导航系统和 LWC 提供的完整样式灵活性，请将它们一起使用。

## 使用 Salesforce 构建表单的工具

下表概述了可用于使用 Salesforce 构建表单的工具，以及所需的技能和许可证注意事项。稍后，我们将深入了解每个工具支持的特定功能，以及如何在基于点击的工具和基于代码的工具之间进行选择（以及何时组合）：

<table>
  <colgroup>
    <col span="1" style="width: 40%;">
    <col span="1" style="width: 30%;">
    <col span="1" style="width: 30%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">所需技能</th>
      <th scope="col">其他许可证要求</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><b>动态表单</b></td>
      <td>低代码</td>
      <td>没有</td>
    </tr>
    <tr>
      <td><b>屏幕流</b></td>
      <td>低代码</td>
      <td>没有</td>
    </tr>
    <tr>
      <td><b>OmniStudio</b></td>
      <td>低代码 + 专业代码</td>
      <td>需要行业软件包</td>
    </tr>
    <tr>
      <td><b>屏幕流 + Lightning Web 组件</b></td>
      <td>低代码 + 专业代码</td>
      <td>没有</td>
    </tr>
    <tr>
      <td><b>Lightning Web组件</b></td>
      <td>Pro 代码</td>
      <td>没有</td>
    </tr>
  </tbody>
</table>

## 决策点概览

下表概述了在选择产品时需要考虑的决策点，以及您应该问自己的每个问题。在本指南的其余部分中，我们将更深入地探讨每个主题。

<table>
  <colgroup>
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 75%;">
  </colgroup>
  <tbody>
    <tr>
      <td><b>对象影响</b></td>
      <td>确定您的表单是针对单个对象还是需要对多个对象进行操作。</td>
    </tr>
    <tr>
      <td><b>表单范围和导航</b></td>
      <td>确定表单上的所有字段是否逻辑上适合一个屏幕，或者用户是否应该能够在多个屏幕之间导航。</td>
    </tr>
    <tr>
      <td><b>位置</b></td>
      <td>确定您想要嵌入表单的位置，该位置的范围可以从 Salesforce 应用程序中的某个位置到移动应用程序，甚至是外部网站。</td>
    </tr>
    <tr>
      <td><b>控制器</b></td>
      <td>确定用户与您的表单交互时需要在后台执行的操作或逻辑，包括数据转换和与外部系统的集成。</td>
    </tr>
    <tr>
      <td><b>验证</b></td>
      <td>确定您是否有 Salesforce 提供的标准系统级验证之外的任何其他输入验证要求。</td>
    </tr>
    <tr>
      <td><b>安全性</b></td>
      <td>确定您的表单是否应该在执行某些操作之前检查用户的访问权限，您是否想要控制谁可以访问表单，以及您是否想要控制表单可以嵌入的位置。</td>
    </tr>
    <tr>
      <td><b>交互设计</b></td>
      <td>确定应在表单中触发动态响应的交互或条件类型。</td>
    </tr>
    <tr>
      <td><b>样式</b></td>
      <td>确定所需样式和 CSS 的复杂程度。</td>
    </tr>
    <tr>
      <td><b>布局</b></td>
      <td>根据所需列数、选项卡、折叠和显示重复数据块的能力，确定表格的布局要求。</td>
    </tr>
    <tr>
      <td><b>翻译</b></td>
      <td>确定表单是否需要本地化为其他语言。</td>
    </tr>
    <tr>
      <td><b>UI 测试自动化</b></td>
      <td>确定 DevOps 流程是否需要对表单进行自动化单元测试或自动化端到端测试</td>
    </tr>
    <tr>
      <td><b>度量</b></td>
      <td>确定您想要跟踪表单使用情况的方式，包括页面视图、在表单上花费的时间、完成率和成功率</td>
    </tr>
    <tr>
      <td><b>打包和部署</b></td>
      <td>确定在构建表单后您想要如何分发或部署表单。</td>
    </tr>
  </tbody>
</table>

以下是我们在对比表中使用的术语及其定义：

- **可用：**基本注意事项工作正常。
- **不理想：**可以工作，但不是最佳工具。
- **路线图：**预计未来 12 个月内的支持（2025 年 6 月）。
- **未来**:未来 12 个月之后的支助估算。
- **不可用：**未来 12 个月内没有计划支持此功能。

## 决策点逐步解说

如承诺的那样，让我们开始深入了解动态表单、屏幕流、OmniStudio、带有嵌入式 LWC 的屏幕流以及 LWC 框架本身之间的各种比较点和功能差异。

### 对象影响

如果您的表单针对单个 Salesforce 对象操作，我们正在比较的任何工具都将正常工作。对于跨对象或与对象无关的表单，事情会变得有点复杂。我们所说的对象无关是指不映射到任何 Salesforce 对象的输入。也许您的表单代表您将发送到外部服务的数据结构，例如 Stripe 或 DocuSign。或者，您可能正在使用表单中的多个输入来计算值，然后将该值提交到数据库。

#### 要问的问题：

- 表单将针对哪些对象操作？
- 是只有一个对象还是有多个对象？
- 您是否正在使用特定对象（即客户、联系人、业务机会、潜在客户和个案），或者您的表单是否需要与其他对象一起使用？

<table>
  <colgroup>
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">单个对象</th>
      <th scope="col">跨对象</th>
      <th scope="col">对象不可知性</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
  </tbody>
</table>

对于跨对象和与对象无关的表单，Flow 和 OmniStudio 都是可靠的选项。流屏幕中可用的组件本质上是不可知的，因此您可以选择在后台如何处理这些数据。例如，使用在一个表单中输入的数据在后台创建多个记录，或使用这些数据执行其他操作，例如生成 Chatter 帖子、发送 Slack 消息、发送电子邮件或连接到外部服务。

对于简单个案，使用现有 LWC 组件，例如 Lightningrecord-form，可以是降低提供强大解决方案所需代码的简单方法。但是，对于涉及多个对象的场景，Flow 为所有对象提供了全面的控制，开发人员无需遍历复杂的关系和依赖性。

OmniStudio 将事情向前推进了一步，并且是完全对象不可知的 — 它将用户看到的形式与基础数据模型分开。相反，OmniStudio 会操纵基础 JSON，然后使用[数据映射器](https://help.salesforce.com/s/articleView?id=sf.os_dataraptors.htm&type=5)和[集成程序](https://help.salesforce.com/s/articleView?id=sf.os_omnistudio_integration_procedures_48334.htm&type=5)等工具映射到 Salesforce 对象（或外部数据）。数据映射器和集成程序是将 OmniStudio 表单与 Salesforce 内部和外部数据连接起来的两个关键组件。使用拖放元素，您可以在外部系统中使用复杂的层次结构数据，然后根据数据需要的位置转换数据以满足您的需求。它们还允许您使用公式对数组或数据列表执行数学和逻辑，就像 Apex。

[<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-objectimpactnoheader.png" alt="OmniStudio Integrations">_OmniStudio Integrations_](/docs/architect/zh-cn/reference-diagrams/guide/omnistudio-integrations)

### 表单范围和导航

如果您可以从单个屏幕表单获取所有用户输入，请从动态表单开始。但是，虽然记录页面中的动态表单可以使用路径功能来松散地表示业务流程中的各个阶段，但它可能不适合大多数用例。

#### 要问的问题：

- 您需要一个屏幕，还是用户需要在多个屏幕之间导航以完成任务？
- 您是否希望您的用户看到他们在填写表单过程中走多远的可视化描述？
- 您的用户是否需要按特定顺序填写每个屏幕上的信息，或者他们是否应该可以根据需要在屏幕之间来回移动？

<table>
  <colgroup>
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">单屏幕</th>
      <th scope="col">多屏幕表单</th>
      <th scope="col">进度指示器</th>
      <th scope="col">在步骤/屏幕之间跳转导航</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-no">不理想</td>
      <td class="guide-table-no">不理想</td>
      <td class="guide-table-no">不理想</td>
    </tr>
  </tbody>
</table>

如果您需要比动态表单更多的功能，那么在 Flow、OmniStudio 和 LWC 之间的选择将取决于其他一些问题：

- 团队拥有哪些技能？对于管理工作量较大的组织，我们建议从流开始。如果您有行业解决方案，您的团队已经熟悉 OmniStudio，并且您的项目有严格的 UX 要求，请从 OmniStudio 开始。
- 是否可以在表格底部显示导航栏？如果屏幕流和 Omniscript 导航体验不理想，请转向 LWC。
- 表格后面需要做什么？如果您需要管理员配置行为，请构建流或 Omniscript（用于更改字段标签等基本更改）。否则，对于复杂的多对象关系，构建 Omniscript 或 LWC。
- 如果您选择 Flow 或 OmniStudio，您可能需要构建 LWC 来实现正确的 UX。如果您已经在构建 LWC 来正确设计表单样式，请考虑将[该组件嵌入流](https://developer.salesforce.com/docs/platform/lwc/guide/use-flow-embed-component.html)是否过度。

另一方面，如果您的解决方案看起来像向导，用户可以在多个屏幕之间导航，请考虑 Flow 或 OmniStudio。Flows 和 OmniStudio 带有内置导航模型，因此您无需构建和维护相互串联的 LWC。导航是线性的，具有向前移动操作、向后移动操作和保存表单以供以后使用的机制。如果符合您的目的，您也可以使用非线性导航构建表单。有关使用屏幕流的重要示例，请查看 Salesforce Labs 中的[数字商店审计](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FMkOtUAL)软件包。

OmniStudio 提供了关键的导航优势，因为它提供了来自标准导航的进度指示器，在表单中显示了“步骤”。此步骤视图自动显示用户在给定多步骤表单中的位置。与流不同，它允许用户通过单击表单的各个步骤在屏幕之间“跳转”。

无论您是构建单屏幕还是多屏幕表单，请确保您的表单已[简化](/docs/architect/zh-cn/well-architected/guide/engaging#表格)，以便用户轻松导航。

### 位置

如果您在标准 Lightning 记录页面中嵌入表格，我们正在比较的任何工具都可以使用，但需要说明的是，动态表格目前仅在桌面上可用。但是，如果您正在寻找一种允许用户从其他位置访问表单的体验，您可能需要考虑其他选项。

#### 要问的问题：

- 用户是否需要通过桌面、移动设备或两者访问表单？
- 用户是否应该能够通过实用程序栏从应用程序的任何地方访问表单？
- 您是否希望使用快速操作，以便用户无需离开当前页面即可填写表单？
- 您的表单是否需要在外部网站上可用？

<table>
  <colgroup>
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
    <col span="1" style="width: 7.14%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">Lightning 记录页面</th>
      <th scope="col">Lightning 主页或应用程序页面</th>
      <th scope="col">Aura Experience Cloud 站点</th>
      <th scope="col">LWR Experience Cloud 站点</th>
      <th scope="col">嵌入式 Snap-In</th>
      <th scope="col">实用程序栏</th>
      <th scope="col">特定于对象的操作</th>
      <th scope="col">全局操作</th>
      <th scope="col">Salesforce 移动应用程序**</th>
      <th scope="col">Field Service Mobile</th>
      <th scope="col">Mobile SDK</th>
      <th scope="col">外部站点和应用程序</th>
      <th scope="col">自定义 LWC</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用***</td>
      <td>不可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-no">不理想</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="14">*流可以嵌入 LWR Experience Cloud 站点，但您需要记住一些注意事项。<br>**Salesforce 移动应用程序支持流和 LWC，但 Salesforce 移动应用程序不支持您可以嵌入流和 LWC 的所有方式。例如，移动设备支持特定于对象的操作，但实用程序栏项目不支持。<br>***Field Service 移动应用程序不支持许多最新的流功能，因为它是从旧的流引擎和屏幕流运行时设计的 - 它有特殊的修改，可以离线工作。</td>
    </tr>
  </tbody>
</table>

由于动态表单需要记录上下文，因此仅在 Lightning 记录页面中受支持。但是，Experience Cloud 页面不支持动态表单。存在此限制，因为 Experience Cloud 不使用动态表单依赖的基础框架：Lightning 页面。我们正在根据 Experience Cloud 中对动态表单的请求进行评估。

您可以构建需要记录上下文的流或全局工作的流。因此，您可以在各种位置嵌入流。对于记录上下文流，这可能是 Lightning 记录页面、Experience Cloud 记录页面、特定于对象的操作或操作和推荐部署。对于全局流，这可能是实用程序栏、其他 Lightning 或体验生成器页面、Snap 单元或外部应用程序。流目前不支持作为全局操作，但作为解决方法，您可以将流封装在 Aura 组件中。

OmniStudio 允许您构建可组合的 FlexCard 和 Omniscript，您可以将它们放在几乎任何可以放置流的地方。但是，虽然它们可以组合，但不能打包。

LWC 支持高度的可重用性，因为您正在通过跨 Salesforce、社区甚至开源项目的元数据创建可与目标关联的组件。LWC 组件也可以通过 [Lightning Out](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lightning_out) 嵌入您自己的网站。

外部站点上的 Lightning Out 外部站点上的 Lightning Out [<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-locationnoheader.png" alt="">\_\_](/docs/architect/zh-cn/reference-diagrams/guide/lightning-out-on-external-sites)

目前，Lightning Web 组件不支持作为快速操作（特定于对象或全局），但作为解决方法，您可以在 Aura 组件中封装 LWC（与流相似）。LWC 组件也可以通过[Lightning -flow](https://developer.salesforce.com/docs/component-library/bundle/lightning-flow/documentation)组件启动流。

OmniStudio 擅长通过 OmniOut 功能向外部站点公开内容。通过 OmniStudio 和 OmniOut，您可以将 Omniscript 表单和 FlexCard 组件编译为标准组件，并在第三方站点或应用程序中将它们运行在平台外。

今天，Mobile SDK 模板不支持本指南涵盖的任何表单技术。如果移动软件开发工具包对用例至关重要，您最好在您的移动应用程序中本地构建表单或构建 Visualforce 页面，同时牢记 Salesforce 精心设计的[外形规格](/docs/architect/zh-cn/well-architected/guide/engaging#外形规格)指南。

**路线图备注：**Mobile SDK 团队正在积极致力于支持 Visualforce 页面中的 LWC。

### 控制器

如果您需要使用表单中的值来创建或更新记录，动态表单是完美的选择。对于任何其他功能，您需要利用 Flow、OmniStudio 或 LWC。这些功能可能包括决策或迭代层，或者使用表单中的输入生成 Slack 帖子或电子邮件。

#### 要问的问题：

- 您想要在后台执行哪些操作或逻辑？
- 您的数据模型是否包含层次结构数据？
- 您的表单是否需要在单个事务中或跨多个事务完成操作？
- 是否需要与外部系统集成？
- 您对可重用性和模块化的要求是什么？

<table>
  <colgroup>
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">日志和操作</th>
      <th scope="col">层次结构数据管理</th>
      <th scope="col">在一个事务中操作</th>
      <th scope="col">跨多个事务操作</th>
      <th scope="col">集成</th>
      <th scope="col">模块化设计和重用</th>
      <th scope="col">打包</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
  </tbody>
</table>

Flow 提供了发布到 Slack、发送电子邮件和与 Quip 文档交互的标准操作，因此您无需编写这些操作的代码。通过使用与[用户界面 API](https://developer.salesforce.com/docs/atlas.en-us.uiapi.meta/uiapi/ui_api_get_started.htm) 交互的线路适配器，LWC 提供了与单个记录和相关对象的丰富交互。当使用 [getListInfoByName](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/reference_get_list_info_by_name.html) 的线时，LWC 也可以与多个记录交互。

[<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-controllernoheader.png" alt="LWC 通过有线适配器交互">_Lightning Web 组件通过有线适配器交互_](/docs/architect/zh-cn/reference-diagrams/guide/lightning-web-components-interaction-via-wire-adapters)

如上所述，OmniStudio 使用集成程序和数据映射器轻松获取和转换 Salesforce 外部和内部的数据。由于您可以使用大量无代码函数，它在平展和扩展具有各种关系的数据集方面大放异彩。

**路线图备注：**Flow 将很快支持更新插入记录集合以及管理层次结构数据的功能。

Flow、OmniStudio 和 LWC 都与 Apex 集成，因此无论选择哪种解决方案，您都可以轻松弥合任何差距。例如，如果您需要从 LWC 筛选记录，您可以始终使用 Apex 的线适配器来创建复杂的 SOQL 查询。如果您被基于点击的数据趋势所左右，请考虑将 Flow 或 OmniStudio 作为 Apex 控制器的可行替代方案，以满足服务器端需求。

此处的第二个问题是，您是想要立即提交操作，还是将它们推迟到表单的特定部分。如果您使用的是多页表单，这尤其相关。流可轻松组合来自多个表单（流屏幕）的输入，并在向导（流）中稍后使用它们来执行一些操作。事实上，我们建议以这种方式设计流 — 在结束时执行操作 — 以防用户在屏幕之间来回切换，更改答案。

#### 控制操作

事务和[管理者限制](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm)是 Salesforce 平台上的一种生活方式。如果您的用例相当简单，那么控制特定操作发生在什么事务中就不那么重要。但是,在少数用例中,您可能想要将多个操作合并为一个[事务](/docs/architect/zh-cn/fundamentals/guide/architecture-basics#交易),而不是在多个事务中执行它们。一些示例：

- **回滚或不回滚**:这就是问题所在。假设您的表单在后台创建多个记录。如果第三个记录无法创建，前两个记录是否应该回滚？如果每个操作相互独立，请随意在单独的事务中执行。但如果它们有依赖性，并且您希望其中一个的失败也回滚另一个，请在单个事务中实施它们。如果您的表单在流中，您可以使用错误路径中的回滚元素来回滚事务并确保数据完整性。
- **对调控器限制的下游影响**:特别是当您的表单创建或更新记录时，请考虑该操作的下游影响。根据此记录更改，将触发哪些进程、工作流规则、流触发器、Apex 触发器或保存订单中的其他项目？这些集体更改如何影响该事务中消耗的调控器限制？如果特定记录更改将导致大量影响限制的下游更改，请考虑将该记录更改隔离到自己的事务中。
- **批处理**:即使在 UI 上下文中，您可能需要一起批量处理多个更新。假设您的多屏幕表单迭代一大组记录。与其在每个屏幕后提交记录更新，不如等到您收集了所有记录的更新，然后提交一个请求来更新所有记录。

当您使用动态表单创建或编辑记录时，您只执行过一次操作，并且该操作始终是新交易的开始。

在构建屏幕流时，您可以显著控制给定事务中会发生什么。屏幕和本地操作充当事务之间的边界。以下是如何在屏幕流架构中管理事务的高级摘要。

1. 最终用户与屏幕交互，然后单击**下一步**。
2. 客户端向带有输入的 API 发布请求。
3. API 收到请求，并打开事务和数据库连接。然后，API 调用流引擎来调用请求。
4. 流引擎接管并遵循流定义中的相应路径，直到它到达屏幕或本地操作节点。然后，引擎向 API 返回有关该节点的信息。
5. API 创建包含要呈现的下一个屏幕的详细信息的响应对象，并将该对象返回到客户端。此时，提交数据库更改（提示[执行保存订单](/docs/architect/zh-cn/fundamentals/guide/architecture-basics#数据库操作)），并关闭数据库连接和事务。
6. 客户端使用 API 响应呈现下一个屏幕，供用户交互。
7. 从步骤 1 重复。

换句话说，屏幕会“破坏”交易。发生这种情况时，提交任何等待批准的操作或 DML，关闭之前的事务，并开始新的事务。

<br/>

<img style="border:1px solid #e5e5e5;float:left;width:50%;margin:1rem 2rem 1rem 0rem" src="https://architect.salesforce.com/ns-assets/guide-forms-flow1.png" alt="多屏幕流">

正确的设计 — 您将哪些操作分组到给定的事务中 — 是您的决定。让我们来复习一些示例。

<br/>

<img style="border:1px solid #e5e5e5;float:right;width:50%;margin:1rem 2rem 1rem 0rem" src="https://architect.salesforce.com/ns-assets/guide-forms-flow2.png" alt="具有单独事务的屏幕流">

<br/>

在左侧，您可以看到跨多个屏幕收集输入的流，然后在一个事务中执行几个操作。

<br/>

右侧的流会在单独的事务中执行每个操作。

<br/>
流团队最近引入了一个新元素：如果单个操作在一系列数据库操作中失败，回滚记录元素使您能够回滚整个事务。

<br/>

<img style="border:1px solid #e5e5e5;float:right;width:50%;margin:1rem 2rem 1rem 0rem" src="https://architect.salesforce.com/ns-assets/guide-forms-flow3.png" alt="包含多个创建记录的屏幕流">

<br/>
<br/>

假设您有一个创建记录、更新记录，然后创建更多记录的流，如右侧下一个流所示。

<br/>

在这种情况下，如果前两个元素成功，最后一个元素失败，前两个 DML 操作仍会创建和更新这些记录，而第三个不会。

<br/>

<img style="border:1px solid #e5e5e5;float:left;width:50%;margin:1rem 2rem 1rem 0rem" src="https://architect.salesforce.com/ns-assets/guide-forms-flow4.png" alt="带回滚的屏幕流">

<br/>

通过使用“回滚记录”元素，您可以确保如果所有三个操作必须同时进行，整个事务将被回滚，如左侧的最终流所示。

有关更多详细信息，请查看[事务中的流](https://help.salesforce.com/articleView?id=flow_concepts_transaction.htm)和[事务中的流](https://help.salesforce.com/articleView?id=flow_concepts_bulkification.htm)批量化。Salesforce Well-Architected 的自动化部分也会在[数据处理](/docs/architect/zh-cn/well-architected/guide/automated#数据处理)中对此进行更深入的介绍。

您从 LWC 控制事务的能力取决于 LWC 用来执行操作的底层服务。如果您正在使用 Lightning 记录表单基础组件，基础操作（创建或更新记录）将在提交表单后立即在独立事务中发生。

通常，这些规则适用：

- 每个 UI API 调用都被隔离到自己的事务中。
- 如果您需要在单个事务中执行多个操作，请将输入发送到服务器端技术，例如 Apex 控制器或流。该技术的常规事务规则适用。

#### 外部集成

Flow、OmniStudio 和 LWC 都支持平台事件（适用于[事件驱动架构](/docs/architect/zh-cn/decision-guides/guide/event-driven)）和 API 集成。除了自定义 Apex 代码之外，Flow 和 OmniStudio 都支持集成 API 的声明性机制。

如果您需要连接到 MuleSoft API 或 RPA 机器人，请使用 MuleSoft 服务。这将生成外部服务。

[<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-integrations-mulesoftnoheader.png" alt="通过 MuleSoft 进行外部集成"> 通过 MuleSoft API 和 RPA 机器人进行*外部集成*](/docs/architect/zh-cn/reference-diagrams/guide/external-integrations-via-mulesoft-apis-and-rpa-bots)

如果 API 具有 OpenAPI 模式，请创建外部服务。

[<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-integrations-openapi-noheader.png" alt="通过 OpenAPI 进行外部集成"> 通过 OpenAPI 模式与 API 进行*外部集成*](/docs/architect/zh-cn/reference-diagrams/guide/external-integrations-to-apis-with-openapi-schemas)

否则，使用流中的 HTTP 标注功能或 OmniStudio 中的 HTTP 操作。流的 HTTP 标注由外部服务提供支持。

[<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-integrations-callouts-noheader.png" alt="通过 HTTP 的外部集成"> _通过 HTTP 的外部集成_](/docs/architect/zh-cn/reference-diagrams/guide/external-integrations-via-http)

OmniStudio 具有丰富的集成功能，可以通过集成程序调用外部系统，并使用数据映射器转换数据。（有关更多信息，请查看[对象影响](#对象影响)）

无论您是通过自定义 Apex 还是外部服务实施，标注都是标注。以下是您需要了解的内容。

1. 标注可能需要很长时间。
2. 当同步执行标注时，它会在数据库事务打开时执行。
3. 如果您有等待批准的数据库操作，Salesforce 不会让您保持数据库事务打开。

请记住的主要限制是所谓的**_脏事务_**的危险,即您执行创建、更新或删除操作，然后在同一事务中执行标注。不允许此模式，因为以上注意事项 #3；当然，存在此模式是因为注意事项 #1 和 #2。

在流中，您可以通过打破事务来解决此限制。请谨记，屏幕和本地操作会重新引入浏览器上下文，从而中断事务。虽然您可以在使用外部标注时使用屏幕和本地操作，但我们建议在可调用的高级设置中启用事务控制。事务控制是可调用操作的功能，允许您在调出前自动结束事务。您可以通过在调用操作的高级部分中选择始终启动新事务来启用事务控制。

<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/guide-forms-flow5.png" alt="通过标注的外部集成"> 
使用 LWC 时，标注对事务的影响不那么复杂。一般来说，您将使用 Lightning 数据服务 (LDS) 执行数据操作，然后使用 Apex 控制器进行外部标注。这种设计保护您免受脏事务的影响，因为 LDS 调用在与 Apex 标注分开的事务中隔离。

_有关 Apex 标注、外部服务和一般数据集成能力的深入指导,请参阅数据与 Salesforce 集成[架构师指南](/docs/architect/zh-cn/decision-guides/guide/data-integration)。_

#### 可重用性和模块化

动态表单不支持重用。每个动态表单都绑定到特定对象的特定 Lightning 记录页面（尽管您可以将该 Lightning 记录页面分配给多个应用程序、简档等）。

如同您可以编写用于跨多个其他组件的库、实用程序和组件一样，在通过**_子流_**创建流时，您可以应用类似的设计模式。将流保存在更小、更模块化的存储桶中，然后使用子流元素从其他流调用它们。如果您的设计需要它，您可以构建一个流，它既是独立的，又是另一个流的子流。

OmniStudio 本质上是为模块化而构建的。数据映射器、Omniscript、FlexCard 和集成程序都是独立构建的，可以互换工作。最重要的是，FlexCard 可以构建为可嵌入其他 LWC、Omniscript、记录页面和 Experience Cloud 站点的 LWC 组件。

屏幕流、Omniscript 和 LWC 都可以构建用于重复使用，并嵌入到各种位置，包括外部站点和 Lightning Out 应用程序。当您将解决方案设计成可[组合](/docs/architect/zh-cn/well-architected/guide/composable)时，您会获得额外的好处，例如适应性和稳定性。

### 验证

用于创建或更新记录的所有技术都遵守系统级验证 — 无论是经典验证规则还是内置于 Apex 触发器的自定义验证。无论您使用什么技术执行记录更改，每个更改都会经过保存顺序。这意味着，除了验证规则之外，记录更改由任意数量的保存前或保存后流、触发器、升级规则、分配规则等处理。如果您尚未这样做，请确保添加书签并熟悉 Apex 的[执行顺序](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm)。

#### 要问的问题：

- 除了系统级验证之外，您的表单是否有其他要求？
- 您是否需要在表单中动态将字段设置为必填或只读？

<table>
  <colgroup>
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">遵守系统级验证</th>
      <th scope="col">特定于此表单的自定义字段级验证</th>
      <th scope="col">自定义字段级验证</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td class="guide-table-roadmap">路线图</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
  </tbody>
</table>

流屏幕或 Omniscript 步骤上的输入本质上是未绑定的，因此表单本身不会本地遵守与特定对象关联的系统级验证。但无论您使用什么值来创建或更新记录，它们都由保存订单处理，这意味着它们通过对象的系统级验证。但请注意，并非所有屏幕流组件都支持输入验证。从 Summer '24 开始，不支持输入验证的剩余屏幕组件是单选按钮、选项列表、多选选项列表、复选框组和选择查找。

就像页面布局一样，动态表单允许您在页面级别设置要求和只读状态。但您无法覆盖系统级设置。

流为自定义表单输入的验证提供了灵活性。虽然一些检查在客户端执行（例如标记缺少必填字段或不兼容的值），但客户端验证不会阻止用户尝试导航。真正的验证发生在服务器上。当用户单击**下一步**时，流会将输入发送到服务器进行验证。如果任何输入返回无效，导航将被阻止，并显示适当的错误。服务器通过检查来验证输入：

1. 输入的要求设置，或输入的值是否与基础数据类型兼容。
2. 对该输入的自定义验证：一些标准组件（复选框、币种、日期、日期/时间、长文本区域、数字、密码和文本）支持每个屏幕的自定义验证。提供布尔值公式表达式和错误消息，以便在不满足公式表达式时显示。
3. 对基础组件的自定义验证：如果您正在为流构建自定义 LWC，请将自己的验证码添加到 validate() 方法中。

OmniStudio 具有丰富的错误和验证处理功能，可通过[设置错误](https://help.salesforce.com/s/articleView?id=sf.os_set_errors_in_an_omniscript.htm&type=5)操作与[条件视图](https://help.salesforce.com/s/articleView?id=sf.os_conditionally_display_elements_using_the_conditional_view_property.htm&type=5)和[消息](https://help.salesforce.com/s/articleView?id=sf.os_display_messages_in_omniscripts_19551.htm&type=5)传递组件组合使用。

在 LWC 侧，大多数基本组件执行自己的客户端验证。例如，Lightningrecord-form 遵守系统级要求，但不遵守页面级要求。对于自定义组件，您可以 Build Your Own 验证机制。

需要用户输入数据的字段应尽早出现在您的表单中。在提交表单之前，尽可能验证客户端的用户输入。有关简化表单的更多最佳实践，请查看 Salesforce 精心设计 - 参与中的[表单](/docs/architect/zh-cn/well-architected/guide/engaging#表格)指导。

### 安全性

一般来说，安全性是一个复杂的主题，当涉及到构建表单时，有一些您可能甚至没有想到的注意事项。在基础级别，您需要确保表单在正确的上下文中运行，并且用户拥有使用其基础数据所需的权限。但除此之外，您可能还希望采取额外的措施，从富文本字段中删除潜在的恶意代码或 URL，阻止某些用户访问表单，或者对管理员未来可能嵌入表单的位置类型进行限制。在选择工具之前，请确保彻底记录您的安全要求。Salesforce 结构良好的[安全策略模板](/docs/architect/zh-cn/resources/guide/security-policy-template)包含此类文档的指导说明。

#### 要问的问题：

- 在执行某些操作之前，表单是否应该检查用户的访问权限？
- 您是否应对用户输入进行消毒？
- 是否要控制谁可以访问表单？
- 是否要控制表格的嵌入位置？

<table>
  <colgroup>
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">提升用户权限</th>
      <th scope="col">控制谁拥有访问权限</th>
      <th scope="col">限制允许的位置</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用**</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="4">*需要 Apex<br>**虽然 Omniscript 不能有一组指定的目标位置，但 FlexCard 可以。</td>
    </tr>
  </tbody>
</table>

#### 提升用户权限

在**_用户上下文_**中运行时，Salesforce 会强制执行一系列访问权限检查，包括根据贵组织的共享规则验证字段级安全性、CRUD 权限和记录访问权限。因此，例如，用户只有在能够更新个案、适当的字段级安全性和访问有关记录时，才能运行个案更新表单。但如果您希望用户在使用*您*的表单时能够执行特定操作，而不是通过任何其他表单或交互，该怎么办？这就是**_系统上下文_**的来源。

系统上下文是在会话期间提升运行用户权限的一种方式，这样用户就不需要更新个案对象的访问权限来成功完成您的个案更新表单。这对于未经身份验证的社区尤其有用。不要授予来宾用户潜在的危险功能，而是将您的表单设置为在系统上下文中运行。

当然，系统上下文是一把双刃剑，您应该只在必要时使用它。当表格在系统上下文中运行时，每个 CRUD 操作都会绕过对象和字段级安全性和共享，而不仅仅是您关心的具体操作。另请注意，系统上下文对 Salesforce 认为操作者是谁没有影响，即您在上次修改人字段中看到的名称。对于表单执行的每个操作，例如个案更新，操作者是运行用户，即使表单在不同的上下文中运行。

动态表单、Omniscript 和 LWC 始终在用户上下文中运行，并且无法覆盖此行为。

默认情况下，屏幕流在用户上下文中运行，但您可以将其设置为在系统上下文中运行。流是否应授予对所有数据的访问权限，或是否仍应强制执行共享等记录级访问权限，由您自行决定。

- 如果您在系统上下文中运行的流中嵌入 Lightning 组件，流不会覆盖组件的上下文。如果您需要绕过用户访问检查，我们建议使用该流执行这些操作，并将适当的数据传入或传出 Lightning 组件。一些现成的组件（例如查找）无法在系统上下文中运行。
- 如果流调用 Apex 操作，还有一些细微差别需要了解。如果 Apex 类设置为继承共享，则无论流设置为什么，它都会在具有共享的系统上下文中运行。如果类没有显式共享声明，则无论流设置为什么，它都会在系统上下文中运行，而不会共享。如果类设置为“共享”或“不共享”，则会执行此操作并覆盖流的上下文。

**使用 Experience Cloud 站点查询系统上下文中的记录：**

如果您在 Experience Cloud 站点的系统上下文中运行流，**特别是未经**身份验证的流，我们建议在获取记录元素中仅存储特定字段。当您使用流并将获取记录元素的结果传递到子流、可调用操作或 Lightning 组件时，可以通过浏览器的开发人员工具检查该对象中的所有字段。这可能会使字段对您可能不打算使用的 Experience Cloud 站点用户可用。通过在“获取记录”元素中指定特定字段，即使启用了系统上下文，您也可以确保仅公开正确的字段。

请注意,Omniscript 逻辑在客户端运行,这使得攻击者能够修改 Omniscript 的预期执行*情况,并*使用浏览器的开发人员工具查看对集成程序、数据映射程序和 Apex 方法调用的响应。当您使用 Omniscript 时，我们建议尽可能在服务器端执行业务逻辑，并在通过 [@InvocableMethod 注解](https://help.salesforce.com/s/articleView?id=sf.os_integration_procedure_invocation_55721.htm&type=5)公开的任何 Apex 方法上实施输入验证规则。

**消毒输入：**

要保护您的组织免受不良行为者的攻击，也请考虑输入消毒。假设您在可公开访问的表单上有一个输入，可以映射到贵组织的富文本字段。您可能要考虑自动化，删除可能隐藏恶意 URL 的任何 HTML。通常，在表单级别实施此消毒并不理想，因为您可以让任意数量的源写入这些字段。我们建议创建快速字段更新流（保存前）或使用对象上的现有 Apex 触发器，以删除或修改可能在表单中输入的任何潜在 HTML。

**_最佳实践：_**

- _除非您需要提升运行用户对特定操作的访问权限，否则将流保留在默认上下文中运行。_
- 出于安全原因，_避免在系统上下文中为来宾用户运行流。相反，创建分配给 Experience Cloud 站点来宾用户简档的具有有限字段访问权限的权限集。_
- _在 Experience Cloud 站点的系统上下文运行流中查询记录时，仅将您需要的字段存储在获取记录元素或可调用操作中。_
- _如果流执行各种操作，但并非所有操作都需要提升访问权限，请使用子流隔离应在系统上下文中运行的操作。_
- _如果您计划在外部网页中嵌入表格，请考虑使用快速字段更新流或 Apex 触发器对用户输入进行消毒，以删除 HTML，如果它们最终将映射到富文本字段，以防止恶意行为者的任何潜在网络钓鱼攻击。_

#### 其他备注：

- 默认情况下，Omniscript、FlexCard 和 LWC 在用户上下文中运行。
- 默认情况下，LWC 在用户上下文中运行，流在用户上下文中运行，但您可以在 Apex 控制器中覆盖它。
- 通过 UI API 执行的操作在用户上下文中运行。
- 通过 Apex 控制器执行的操作取决于该类。要在系统模式下执行这些操作，请将 Apex 类设置为共享或不共享。

#### 访问控制

如果您需要控制谁可以访问您的表单，您可以经常查看嵌入表单的容器。例如，您可以将 Lightning 页面分配到可用于特定应用程序、记录类型或简档。如果表单中的某些输入敏感，请使用可见性规则进一步控制向谁显示什么；此功能适用于动态表单和屏幕流。

您可以将[流限制](https://help.salesforce.com/articleView?id=flow_distribute_security.htm)为特定简档或权限集，如同您可以限制为 Apex 类或 Visualforce 页面。默认情况下，流不受限制，这意味着任何具有运行流用户权限的用户都可以运行它们。

如果您正在使用 OmniStudio，您可以配置 [Apex 类权限检查](https://help.salesforce.com/s/articleView?id=sf.os_add_an_apex_class_permissions_checker_1.htm&type=5)器，以确保用户需要明确访问 Apex 类，该类管理从 Omniscript、Flexcard、Classic Card 或 REST API 调用的远程操作。

- 注意 Apex 类权限检查默认为新创建的脚本启用。但必须为任何现有脚本手动启用
- 另请注意，Apex 类权限检查仅适用于 Apex 类。我们建议也为[集成程序和数据映射](https://help.salesforce.com/s/articleView?id=sf.os_security_for_dataraptors_and_integration_procedures_48147.htm&type=5)程序设置简档级权限。

有关来宾用户权限的更多详细信息和最佳实践，请参阅：

- [来宾用户记录访问最佳实践](https://www.learnexperiencecloud.com/s/article/Guest-User-Record-Access-Development-Best-Practices#Pattern6)
- [开发安全站点：经过身份验证的用户和来宾用户](https://developer.salesforce.com/docs/atlas.en-us.communities_dev.meta/communities_dev/communities_dev_security_authenticated_and_guest_users.htm)

**_最佳实践：_**

- _如果您向来宾用户公开流，请仅授予来宾用户简档对所需流的访问权限。虽然可以将运行流添加到来宾用户简档，但我们认为这是一种有风险的做法。_
- _请特别小心在系统上下文中操作的流。我们强烈建议将这些流限制为特定用户组，因为他们拥有更少的制衡措施来保护您的数据。_
- _确保在来宾用户社区中运行 Apex 的任何 Omniscript 在 Apex 类定义中都有"共享"。_
- _在您的来宾用户简档中，只分配您希望来宾用户能够调用的 Apex 类，否则您就有无意中向来宾用户公开其他业务逻辑的风险。_

对于 LWC，您可以检查运行用户的权限分配，以确认他们是否有特定的标准或自定义权限。您可以直接从 JavaScript 导入 Salesforce 权限，从 @salesforce/userPermission 和 @salesforce/customPermission 范围模块导入。或者，您可以使用 Apex 检查相同内容。

#### 嵌入控制

Lightning Web 组件仅在作为有效[目标](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reference_configuration_tags)添加时在指定位置可用。例如，您可以使组件在记录页面上可用，而不可用作实用程序栏项目。

激活屏幕流后，它可在支持屏幕流的所有位置使用，而不论您是否希望它在所有位置可用。也就是说，Flow Builder 支持多种类型的具有屏幕的流。面包和黄油类型是屏幕流，但也有一些其他专用类型仅限于特定位置。例如，Field Service 移动应用程序仅支持 Field Service 移动流（您猜对了）。联系人请求流也是如此，只有 Experience Cloud 支持。

无论流类型如何，创建流的个人无法控制流的嵌入位置。该流将在支持该流类型的每个位置可用。

如果您正在使用 Salesforce Industries，在 Omniscript 方面需要稍作说明：虽然您不能为 Omniscript 本身指定目标，但您可以为要嵌入其中的 FlexCard 指定一个目标。

### 交互设计

静态表单已成为历史。今天，重要的是要动态更新表单，使其具有适合该用户的属性和值，这一次是这个地方。让我们讨论一下 Salesforce 的表单构建工具在这方面可能实现的功能。

#### 要问的问题：

- 哪些类型的交互或条件应触发表单中的动态响应？
- 在填写表单时，是否需要在后台执行屏幕外操作？
- 您是否需要将字段设置为可见、必填、只读或禁用，或者根据表单输入更改格式？

<table>
  <colgroup>
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
    <col span="1" style="width: 12.5%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">执行屏幕外数据操作</th>
      <th scope="col">条件值和计算</th>
      <th scope="col">条件可见性</th>
      <th scope="col">条件要求</th>
      <th scope="col">条件格式化</th>
      <th scope="col">条件只读状态</th>
      <th scope="col">有条件禁用状态</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td class="guide-table-roadmap">路线图</td>
      <td>不可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用**</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用*</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用**</td>
      <td class="guide-table-ok">可用**</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="8">*仅限于使用资源选择器而不是静态复选框的组件<br>**受限 Beta</td>
    </tr>
  </tbody>
</table>

由于反应性屏幕，屏幕流交互性现已成为现实。反应性允许流屏幕上的单个组件相互通信 - 使屏幕流无限强大。

**执行屏幕外数据操作：**屏幕流提供了一种声明性方法，通过屏幕操作在同一屏幕上获取数据。屏幕操作允许您在屏幕的任何更改或用户单击操作按钮组件时触发自动启动的流。然后，您可以将这些自动启动流的结果映射到同一个屏幕，使用户无需导航到另一个屏幕。

LWC 提供了全套的有线适配器，允许您访问 Salesforce 数据以动态填充表格组件中的数据，并使开发人员能够通过 Apex 控制器更新、删除和创建记录。

[<img style="border:1px solid #e5e5e5;margin:2rem 0rem" src="https://architect.salesforce.com/ns-assets/legacy/buildingformsguidediagrams-offscreendataoperations-noheader.png" alt="Lightning Web 组件屏幕外数据操作">_Lightning Web 组件屏幕外数据操作_](/docs/architect/zh-cn/reference-diagrams/guide/lightning-web-components-off-screen-data-operations)

**可见性：**可见性可在所有表单构建工具中动态控制。动态表单、Flow Builder 和 OmniStudio 通过组件可见性功能来解决这个问题。这样，您可以根据表单上的其他值或用户是否在移动设备上来声明性地显示或隐藏字段。

- 通过动态表单，可视性可以根据记录字段值、通过查找字段相关的记录和外形规格来控制。
- 通过流，您可以将可见性规则基于屏幕上的其他输入，以及流中较早填充的其他资源，例如公式或其他记录中的值。
  - **基于设备的规则：**从一开始并不明显，但是您可以使用公式来显示或隐藏用户在移动设备上的特定字段。编写检查 \$User.UIThemeDisplayed 全局变量值的流公式。如果值为 Theme4t，则用户在 Salesforce 移动应用程序上。
  - **评估其他资源：**手动变量和公式引用仅在服务器上评估。因此，当屏幕首次呈现时，该资源拥有的值是它将拥有的值，直到您导航到另一个屏幕。在导航中，流运行时向流引擎（服务器）提交请求，并获取手动变量和公式的最新值。如果您希望可见性规则在用户通过单个屏幕时更新（例如，模糊），请确保您仅引用屏幕上其他组件的值。
- 使用 OmniStudio，您可以通过设置条件视图属性来有条件地显示或隐藏组件。但是，您不能为输入添加多个条件视图属性。

**条件输入状态：**如果您需要动态控制任何其他属性，例如字段是必填、禁用还是只读，您有几个选项。正如预期的那样，LWC 为您提供了对输入状态的完整反应性控制。通过反应性屏幕流组件，您可以动态控制组件属性，例如只读、禁用和支持它的标准组件所需的属性，而 OmniStudio 支持组件特定的全部属性。如果您的要求要求您需要流，并且组件不支持特定属性状态，您可以创建可嵌入的 LWC 来实现动态输入状态。

如果您需要动态控制任何其他属性，例如某个字段是必填字段还是只读字段，您短期内的最佳方法是拥有完全控制权的 LWC。如果您有如何处理模糊或点击的定制要求，这尤其如此。

屏幕流中的反应性 LWC：在构建能够对屏幕流上的其他组件做出反应和进行更改的 LWC 时，请参考本 [LWC 屏幕流最佳实践](https://developer.salesforce.com/blogs/2023/02/lwc-best-practices-for-screen-flows)指南，以确保您的组件很好地集成到流运行时引擎中，并按预期在未来工作。

<table>
  <colgroup>
    <col span="1" style="width: 33%;">
    <col span="1" style="width: 33%;">
    <col span="1" style="width: 33%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">标准事件处理（模糊、聚焦）</th>
      <th scope="col">自定义事件处理</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td>不可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td>不可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用*</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="3">*OmniStudio 标准运行时不支持发布/订阅，但支持 Windows postMessage</td>
    </tr>
  </tbody>
</table>

现在，对于自定义事件。如果您的一些输入或整个表单需要与页面中的其他内容通信，LWC 是您的唯一选择。

- 要在相同 DOM 树中通信，请使用 [**CustomEvent 界面**](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.events)。
- 要在 DOM 之间通信 请使用[**Lightning Messaging Service**](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_message_channel)
- 如果目标容器[不支持](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_message_channel_considerations) Lightning 消息传递服务，请使用**发布/子模块**。

#### 其他资源

- 有关更多详细信息，请查看 _Lightning Web 组件开发指南_ 中的[与事件通信](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/events)和[跨 DOM 通信](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.events_pubsub)。
- 对于 OmniStudio，请从 Lightning Web 组件咨询[与 Omniscript 通信。](https://help.salesforce.com/s/articleView?id=sf.os_communicate_with_omniscript_from_a_lightning_web_component_18222.htm&type=5)

### 样式

为了提供最佳用户体验，您需要确保您的表单样式与嵌入表单的其他应用程序或站点一致。实现这一点意味着从使用 Salesforce 提供的标准模板到创建完全利用设计中的每个像素来提供更清晰的外观的自定义 CSS 的一切。

#### 要问的问题：

- 您想要的样式和 CSS 有多复杂？
- 您是否需要自定义的像素级完美样式，或者是否适合标准主题？

<table>
  <colgroup>
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
    <col span="1" style="width: 25%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">直接样式</th>
      <th scope="col">组织和体验生成器主题</th>
      <th scope="col">像素完美样式</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-roadmap">路线图</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用*</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="4">*仅限Flex 卡</td>
    </tr>
  </tbody>
</table>

FlexCard 是本指南涵盖的唯一产品，使您能够直接在工具中声明性地控制您正在构建的 UI 的样式和布局，无论是边距和填充、排字、颜色等。

动态表单和流都遵守声明性主题特征。如果您需要控制 [Salesforce 主题](https://help.salesforce.com/articleView?id=brand_your_org_in_lightning_experience.htm&mode=1)、[体验生成器品牌](https://help.salesforce.com/articleView?id=community_designer_brandsets.htm)集或 [LWR Experience Cloud 站点](https://developer.salesforce.com/docs/atlas.en-us.exp_cloud_lwr.meta/exp_cloud_lwr/brand_overview.htm)支持的内容之外的内容，请考虑编程解决方案。

对于喜欢使用 CSS 的团队，您有几个选择：

- 流和 LWC 继承[标准设计令牌](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/tokens_standard.htm)。
- Omniscript 和 FlexCard 包括对可自定义设计系统的支持：[纽波特](https://help.salesforce.com/s/articleView?id=sf.os_customize_omniscripts_and_flexcards_with_the_newport_design_system.htm&type=5)
- 使用 LWC，您可以编写自己的组件，并完全控制它们的 HTML 和 CSS。

只要有可能，我们建议使用主题和设计系统，以便您的外观始终一致地应用于所有内容。

提醒：您可在流中嵌入 Lightning 组件。因此，如果您需要对表单的外观进行像素级完美控制，但想要使用流的其他好处，例如导航模型，您可以充分利用这两个方面。同样的原则适用于 Omniscript 和 FlexCard。

### 布局

选择良好的布局对于设计简化的表单至关重要，这些表单支持快速高效的数据输入并提高数据完整性。有关此主题的更多信息，请查看 [Salesforce 结构合理 - 表单](/docs/architect/zh-cn/well-architected/guide/engaging#表格)。

#### 要问的问题：

- 您如何利用表单布局优化用户体验？
- 您如何以让用户更容易将新数据输入到表单的方式向用户显示现有数据？

<table>
  <colgroup>
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
    <col span="1" style="width: 14.28%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">2 列</th>
      <th scope="col">4 列</th>
      <th scope="col">超过 4 列</th>
      <th scope="col">重复数据块</th>
      <th scope="col">选项卡容器</th>
      <th scope="col">折叠容器</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="7">*如果将数据嵌入 Omniscript 中的 FlexCard，可以使用选项卡</td>
    </tr>
  </tbody>
</table>

动态表单支持两列布局，并可以分为带有字段的单个部分。这些部分可以放在选项卡和折叠等组件中，以创建易于使用和组织有序的布局。

流可以选择使用“部分”组件呈现。通过部分，您可以在流屏幕上添加最多四列和任意数量的部分。该组件也会响应屏幕宽度，因此可在更小的屏幕上工作。最后，它使您能够对整个部分应用条件可见性，从而更容易对该部分中的多个字段批量应用可见性。流部分还支持列标题，并提供类似折叠的体验，用户可以单击标签折叠整个部分。

Omniscript 具有用于显示字段和数据的各种布局选项。您可以创建最多 12 列的数据部分，包括有条件折叠的折叠琴。

使用 LWC，您可以使用 Lightning-form 和支持 Lightning-字段来控制布局。唯一的布局限制是那些来自 HTML/CSS 的限制。Lightningrecord-form 遵守相关页面布局中的部分配置；例如，如果部分在页面布局中是两列，则它在该组件中是两列。

### 翻译

如果您的表单将由不同地区的用户或讲不同语言的用户访问，您需要确保您将用于构建表单的工具将满足本地化要求。有关其他指导和建议，请查看 [Salesforce 架构良好 - 本地化](/docs/architect/zh-cn/well-architected/guide/compliant#本地化)。特别是对于表单，本地化要求通常涉及将文本元素翻译成其他语言。

#### 要问的问题：

- 您的表单是否将在多个国家或地区使用？
- 表格中的文本是否需要本地化为其他语言？

<table>
  <colgroup>
    <col span="1" style="width: 33%;">
    <col span="1" style="width: 33%;">
    <col span="1" style="width: 33%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">在生成器中输入的标签</th>
      <th scope="col">代码中的标签</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用*</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="3">*仅限字段部分标题</td>
    </tr>
  </tbody>
</table>

如果您已本地化自定义字段，动态表单将遵循这些翻译的标签。动态表单还遵守您在 Lightning 应用程序生成器中分配给组件标签和属性的[自定义标签](https://help.salesforce.com/s/articleView?id=platform.lightning_page_components_use_expressions_for_labels.htm&type=5)。

借助翻译工作台的功能，Flow 支持翻译所有标准和自定义屏幕组件面向用户的标签。您可以本地化这些屏幕组件的标签、帮助文本和错误消息：文本、长文本区域、数字、货币、复选框、单选按钮、选项列表、多选选项列表、复选框组、密码、日期和日期/时间。

没有现成的操作的内置翻译支持，例如发送电子邮件或发布到 Chatter。但是，有一个解决方法！如果您使用[自定义标签](https://help.salesforce.com/articleView?id=cl_about.htm)定义翻译的标签，您可以在 Flow Builder 中配置时在操作或组件中引用该自定义标签。创建引用自定义标签的流公式，并在流的适当位置引用该公式。

Omniscript 使用自定义标签进行翻译。请参考[此帮助文档](https://help.salesforce.com/s/articleView?id=sf.os_create_multi_language_omniscripts.htm)，以使 Omniscripts 准备好使用多种语言。

接下来是 LWC。如果在翻译工作台中配置了相关对象的字段、帮助文本和验证消息，则某些基本组件会自动继承它们的翻译（例如：Lightning）。

如果需要在代码中引入新颖的可翻译标签，自定义标签仍然是无名英雄。声明您需要的自定义标签，然后从 @salesforce/label 范围模块将其导入组件。

### UI 测试自动化

有几个端到端的测试自动化工具可用（例如 Selenium），这将允许您模拟用户如何与您的表单交互。您可以为任何标准或自定义 UI 编写这些测试，包括 Lightning 页面和屏幕流。但是，重要的是要注意，这些类型的测试不能验证正在执行的每种方法的输出。请确保在考虑 UI 测试自动化的要求时考虑这一点。

#### 要问的问题：

- 是否需要对表单进行自动化测试？
- 您需要执行什么类型的测试？
- 测试自动化需要什么级别的粒度？

<table>
  <colgroup>
    <col span="1" style="width: 33%;">
    <col span="1" style="width: 33%;">
    <col span="1" style="width: 33%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">单元测试</th>
      <th scope="col">端到端自动化</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用*</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td>不可用</td>
      <td class="guide-table-ok">可用*</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用*</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用*</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="3">*需要代码</td>
    </tr>
  </tbody>
</table>

考虑您对 UI 测试自动化的要求。

**单元测试**支持与行业标准 CI/CD 系统和工具一起使用的更精细的自动化和验证，可以测试组件的业务逻辑、JavaScript 控制器和输出。仅使用低代码，您将无法自行编写测试，但 Salesforce 会严格测试我们的端到端产品。

如果组件的方法足够复杂，以至于您想要单独测试，请将这些方法放入专用 JavaScript 文件中。这样，您可以使用类似 `import { sort } from 'c/utils';` 的东西将它们导入 LWC 和 Jest 测试。

有关您在 Salesforce 上构建端到端自动化的各种选项的比较，请参见 [UI 测试自动化](https://developer.salesforce.com/blogs/2020/01/ui-test-automation-on-salesforce.html)。其中包括何时使用 ISV 的无代码解决方案、Build Your Own 自定义测试自动化解决方案或使用 Selenium WebDriver 或 WebdriverIO 等开源测试框架的注意事项。这些解决方案适用于 Salesforce 中的任何 UI 交互，无论是 Lightning 页面中的动态表单、实用程序栏中的屏幕流，还是快速操作中的流中的 LWC。

### 度量

在将表单部署到生产环境后，您需要确保表单得到有效使用。根据您的用例，这可能意味着从简单地跟踪填写的次数到用户在提交信息之前填写的时间。在选择工具之前，请确保确定您想要跟踪的 KPI。

#### 要问的问题：

- 是否需要跟踪表单的使用情况？
- 哪些 KPI 将决定您的表单是否得到有效使用？

<table>
  <colgroup>
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
    <col span="1" style="width: 20%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">页面视图</th>
      <th scope="col">在表单上花费的时间</th>
      <th scope="col">跟踪表单完成情况</th>
      <th scope="col">跟踪成功率</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用**</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用**</td>
      <td class="guide-table-ok">可用*</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="5">*在启用基于软件包的 OmniStudio 运行时可用<br>** 可通过跟踪父 Lightning 页面使用情况获得</td>
    </tr>
  </tbody>
</table>

如果您需要跟踪表单的整体使用情况和采用情况，请从低代码工具开始。动态表单和屏幕流都可以使用现成的自定义报表类型进行跟踪，尽管您将从屏幕流跟踪报表中获得更大的粒度。如果您需要跟踪 LWC 的使用情况，现成可用性取决于您使用该 LWC 的位置。如果在 Lightning 页面上，任何可用于跟踪 Lightning 页面使用情况的内容都会适用于 LWC。嵌入流的 LWC 也是如此。

动态表单本身不是现成的,尽管您可以通过 [Lightning 使用对象](https://help.salesforce.com/articleView?id=lex_usage_reports.htm)跟踪父 Lightning 页面的使用情况。要跟踪标准 Lightning 页面，请使用按页面度量划分的 _Users with Lightning Usage_ 自定义报表类型。在自定义 Lightning 页面上也是如此，请使用按 FlexiPage 度量划分的 _Users with Lightning Usage_ 自定义报表类型。

对于跟踪特定表单的采用情况（而不仅仅是它所在的页面），Flow 会为您提供帮助。使用“示例流报表：屏幕流”，回答以下问题：

- 此表单的完成率如何？它是否被很好地采用？
- 用户完成此表单需要多长时间？
- 用户在哪个屏幕上花费的时间最多？
- 用户多久向后导航一次？
- 错误多久发生一次？

如果标准报表不符合您的需求，请使用*屏幕流*报表类型进行复制以自行更改或从头开始构建 Your Own。

如果您正在使用基于软件包的 Omniscript 运行时，您可以使用 [OmniStudio for Vlocity 跟踪服务](https://help.salesforce.com/s/articleView?id=sf.os_vlocity_tracking_service.htm&type=5)。此服务跟踪任何类型的事件。例如，您可以跟踪完成 Omniscript 中的步骤所需的时间，以确定流程改进。OmniStudio 团队在标准 OmniStudio 中支持此服务的路线图上。

要跟踪未嵌入屏幕流、Omniscript 或 Lightning 页面的 LWC，没有现成的选项。您可以使用 Apex 构建自定义解决方案。

### 打包和部署

当您需要将您的解决方案部署到更高的环境中进行测试或部署到生产中时，您可能习惯于使用更改集或 DevOps Center 来这样做。这些部署选项完全支持动态表单、流和 LWC。OmniStudio 需要一个单独的工具：[IDX 工作台](https://help.salesforce.com/s/articleView?language=en_US&id=sf.os_idx_workbench_desktop_application.htm&type=5)。

#### 要问的问题：

- 您计划如何部署表单？
- 您的表单会分发到多个 Salesforce 组织吗？

<table>
  <colgroup>
    <col span="1" style="width: 16.66%;">
    <col span="1" style="width: 16.66%;">
    <col span="1" style="width: 16.66%;">
    <col span="1" style="width: 16.66%;">
    <col span="1" style="width: 16.66%;">
    <col span="1" style="width: 16.66%;">
  </colgroup>
  <thead>
    <tr>
      <th scope="col"></th>
      <th scope="col">第一代受管软件包 (1GP)</th>
      <th scope="col">第二代受管软件包 (2GP)</th>
      <th scope="col">解锁的软件包</th>
      <th scope="col">更改集</th>
      <th scope="col">DevOps Center</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">动态表单</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">屏幕流</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">OmniStudio</th>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用</td>
      <td>不可用*</td>
      <td>不可用*</td>
    </tr>
    <tr>
      <th scope="row">屏幕流 + LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <th scope="row">LWC</th>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
      <td class="guide-table-ok">可用</td>
    </tr>
    <tr>
      <td colspan="6">*使用 IDX 工作台将 OmniStudio 解决方案部署到其他组织。</td>
    </tr>
  </tbody>
</table>

如果您是 ISV 或合作伙伴，并计划打包解决方案以在 AppExchange 上分发，我们建议首先查看动态表单、流和 LWC。OmniStudio 不支持打包。

## 其他主题

### 将低代码导航到专业代码连续体

本指南的重点是帮助您了解动态表单、屏幕流、OmniStudio 和 LWC 可实现哪些功能和自定义级别。在高级别：

<img align="left" style="border:1px solid #e5e5e5;float:left;width:50%;margin-right:2rem" src="https://architect.salesforce.com/ns-assets/guide-forms-lowcode-continuum.png" alt="低代码到专业代码连续">

<br>

- LWC 是构建表单最可自定义和最强大的选项，但它的防护设施最少。您可以确保[安全](/docs/architect/zh-cn/well-architected/guide/secure)性和可[扩展性](/docs/architect/zh-cn/well-architected/guide/reliable#可扩展性)的方式构建组件。
- 动态表单最不灵活，但出错的机会要少得多。
- Flow 和 OmniStudio 位于中间位置 - 比动态表单强大，但在 LWC 级别上不太强大。同样，它们的防护栏比动态表单少，但比自定义代码更难打破。

如果多个工具适合账单，决定哪个工具适合您的团队。其他[架构师决策指南](/decision-guides)介绍了做出决策时需要考虑的其他方面。

我们在这里不赘述每个方面的详细信息，但我们将针对本文档正在评估的特定工具解释它们。

**专业技能**:您的团队对您正在比较的工具拥有多少专业知识？有多少制造商精通并熟悉 LWC 或 JavaScript？谁是 Flow Builder 的专家或表示有兴趣浸泡脚趾的制造商呢？一般来说，动态表单和流技能更容易为构建表单的更多人获得。动态表单是最具声明性的表单构建工具，并且始终比流更容易学习。也就是说，流团队致力于尽可能降低标准。在复杂性方面，OmniStudio 位于 Flow 和 LWC 之间，并提供强大的表单构建功能。

**交付委派**:仅仅因为您的一些要求要求需要 LWC，并不意味着您的整个解决方案需要使用 LWC 构建。请考虑如何模块化构建解决方案，例如，需要 LWC 的部分已编码，不需要在低代码解决方案中构建的部分已编码。这样做可以最大限度地提高多元化团队的效率，并确保每个人正在解决适合其专业的问题。

现在，让我们谈谈流和 LWC。借助反应性屏幕组件，屏幕流组件现在可以在同一屏幕上相互交谈，为架构师、管理员和开发人员解锁全新的工具箱。开发人员现在可以创建有针对性的模块化组件，可以在整个组织中重复使用，提高团队每个人的工作效率。开发人员可以专注于解决新的挑战，并通过使用标准和自定义流组件的组合来实现表单动态来节省时间。在 Flow 中使用反应性组件时，在构建表单时，将 Flow 和 LWC 混合在一起再合适不过了。

**可维护性和长期所有权**:如果您有多步骤表单，最好从 Flow 或 Flow 和 LWC 的组合开始。如果您有一个低代码团队在维护解决方案，请考虑如何使解决方案尽可能适合该受众的配置和扩展。无论您选择哪种工具，都可以将您的解决方案组织成可[组合](/docs/architect/zh-cn/well-architected/guide/composable)单元，以提高可维护性和稳定性。

### 页面布局

下一步，配置记录详细信息页面的推荐方法是在 Lightning 应用程序生成器中使用 Lightning 页面的动态表单。我们已经很长时间没有改进页面布局了，这一趋势将继续。以下是原因：

- 动态表单更灵活 – 您可以将字段和部分直接放在 Lightning 应用程序生成器中的任何位置，您可以在其中利用部分、选项卡和折叠。如同您在 Lightning 页面上使用组件一样，您可以控制字段和部分的可见性，而无需定义多个页面布局或记录类型。
- 使用折叠和选项卡组件，您可以限制初始显示的字段数量。猜猜这意味着什么?更快的页面加载时间。
- Lightning 页面的布局管理更简单，因为您可以从 Lightning 应用程序生成器管理有关页面的一切内容，无论是页面内容还是哪些用户有权访问页面。无需在页面布局中进行更新，即可在 Lightning 页面中进行更改。更何况，借助可见性规则的强大功能，您无需创建多个页面（或页面布局）来控制谁可以在何时看到哪些字段。这也意味着您只需要为用户分配 Lightning 页面，而不是同时分配 Lightning 页面和页面布局。

我们建议尽可能使用动态表单，并仅在必要时返回页面布局。一如既往,我们欢迎在[意见交流中](https://ideas.salesforce.com/s/)就对您的组织最具影响力的改进提供反馈。

### 性能

与动态表单、屏幕流、OmniStudio 和 LWC 相关的任何性能注意事项都集中在这些技术本身所基于的框架上。那些基于 LWC（当然，除了 LWC）的公司将优于那些基于 Aura 的公司。LWC 框架提供了更好的性能，因为核心功能是在 Web 引擎中本地实施的，而不是通过框架抽象在 JavaScript 中实施的。如果您不熟悉，请阅读[此博客文章](https://developer.salesforce.com/blogs/2018/12/introducing-lightning-web-components.html)。

早在 2019 年,我们就做了一[个案例研究](https://developer.salesforce.com/blogs/2019/06/case-study-dreamhouse-gains-speed-by-switching-to-lwc.html),比较了 Aura 和 LWC 中相同功能的性能。由于将 Dreamhouse 从 Aura 转换为 LWC，不仅开发体验与当前的 Web 前端开发标准和模式更加一致，而且性能也显著提高。实验室测量显示，在相同两个页面上，冷缓存的增益范围为 **2.4% 至 24.7%**，热缓存的增益范围为 **31.83% 至** **63.32%**。

现在，我们的表单技术正在使用哪个框架？换句话说，哪些形式的技术受益于这种卓越的性能？

- 动态表单集成在 Lightning 页面元数据中，它建立在使用 LWC 堆栈的基础上，这将使我们能够实施一些请求已久的功能。作为性能奖励，动态表单使用渐进式渲染，这可以改善具有大量字段的页面的页面加载时间。
- 屏幕流构建在 LWC 上，除了两个现成的组件之外，大多数单独的现成的组件现在都转换为 LWC：文件上传和图像。虽然流团队将流运行时客户端转换为 LWC 及其大部分组件，但客户仍然需要将 Aura 屏幕组件转换为 LWC。不仅如此，Salesforce 仅支持屏幕流中新反应性组件框架中的 LWC 组件。有一个优秀的 Trailhead 模块解释了如何做到这一点：适用于 Aura 开发人员的 [Lightning Web 组件](https://trailhead.salesforce.com/en/content/learn/modules/lightning-web-components-for-aura-developers)。不用说:如果您正在考虑为屏幕流或任何其他容器构建自定义组件，请始终使用 LWC。
- OmniStudio 有几个版本可用。如果您是长期客户，您可能正在使用 Angular。我们鼓励所有新客户从基于 LWC 的 Omniscript 和 FlexCard 开始，并鼓励现有客户迁移到 Angular。
- LWC 基于...LWC of course.这是免费赠品。

## 结束语

作为架构师，深入了解所有可用的选项以及如何将它们应用于特定的用例非常重要。对于在 Salesforce 上构建表单，选项范围从低代码（在 Lightning 应用程序生成器中使用动态表单、在 Flow Builder 中使用屏幕流，在 OmniStudio 中使用 Omniscript）到专业代码（使用 LWC 框架），中间是屏幕流或 Omniscript 和 LWC 的组合。请记住本指南，并在您计划在 Salesforce 上构建或重新设计表单时将其作为参考。如果您正在寻找有关如何设计简化和帮助表单的指导，请咨询 [Salesforce Well-Architected：参与](/docs/architect/zh-cn/well-architected/guide/engaging)。

### 告诉我们您的想法

帮助我们确保发布与您最相关的内容：[参加我们的调查](https://forms.gle/FCFCES6vsRbKv4E29)，提供对这些内容的反馈，并告诉我们您接下来想要看到的内容。
