将 Experience Cloud 站点从沙盒部署到生产环境

我们建议在测试中创建、自定义和测试您的 Experience Cloud 站点 环境,例如沙盒,然后再将其部署到生产组织。当测试是 完成时,您可以使用更改集或元数据 API 将站点从一个组织迁移到另一个组织。 决定是使用变更集还是 MD API 取决于几个因素。需要考虑的一些事项 是要迁移的更改的复杂性,还是您对开发人员的满意程度 工具,以及您正在使用的应用程序生命周期管理 (ALM) 模型。

提示

要了解有关可用的 ALM 模型和开发选项的更多信息,请执行以下操作: 查看确定哪个应用程序生命周期 管理模式非常适合您在 Trailhead 上。

注意

Lightning Bolt 解决方案不适合在 组织。使用 Lightning Bolt 解决方案在 AppExchange 上共享或销售解决方案,或实施 具有交钥匙解决方案或新外观的网站。

更改集

如果您更习惯使用点击式工具,那么更改集就是您的部署 朋友。更改集表示组织(或元数据组件)中的一组自定义项 您可以部署到连接的组织。

您可以使用声明性工具管理应用程序。您不必使用命令行 接口或版本控制系统,以满足您的定制需求。您可以使用“设置”菜单 在开发环境中创建更改。然后,将更改迁移到 环境,在您完成 ALM 步骤时。

发布工件是一组相对于生产组织中的内容的元数据更改。 发布的只是已添加或更改的元数据,如果它没有更改,则它是 不在版本中。

元数据 API

如果您能够快速掌握元数据 API,并且对代码世界更熟悉,请使用元数据 用于以编程方式部署更改的 API。您可以检索、部署、创建、更新和删除 组织的自定义信息,例如 Experience Cloud 站点、自定义对象 定义和页面布局。

当您的更改很复杂或需要更严格的更改时,使用元数据 API 是理想的选择 变更管理流程和审计流程(或版本控制系统)来管理多个 工作流。

与更改集过程一样,您创建的发布工件是一组元数据 相对于生产组织的变化。

提示

某些 Experience Cloud 站点设置和功能尚不受支持 元数据 API,因此您必须在环境之间手动迁移它们。请记住跟踪这些 更改,以便您不会忘记迁移它们。

  • 使用更改集
    部署 Experience Cloud 站点 使用更改集在具有部署连接的相关组织之间移动全部或部分 Experience Cloud 站点。您可以使用网络组件类型移动任何完整的 Experience Cloud 站点。或者,您可以使用“数字体验”组件类型移动增强型 LWR 站点的部分站点内容。
  • 使用元数据 API 部署 Experience Cloud 站点 使用元数据 API
    将 Experience Cloud 站点从一个 Salesforce 组织移动到另一个组织。在测试环境中设置和测试站点,然后检索站点的数据并将其部署到生产组织。
  • Experience Builder 站点的 ExperienceBundle ExperienceBundle 元数据类型提供构成 Experience Builder 站点
    的不同设置和组件(如页面、品牌集和主题)的基于文本的表示形式。无论是您自己的组织,还是咨询合作伙伴或 ISV,您都可以使用首选开发工具(包括 Salesforce Extensions for VS Code、Salesforce CLI 或您喜欢的 IDE 或文本编辑器)以编程方式快速更新和部署站点。
  • 从24年冬季开始,在迁移到增强型LWR站点时避免部署问题,您无法再禁用23年冬季首次引入的增强型站点
    和内容平台。因此,默认情况下,从 LWR 模板创建的任何站点现在都是增强的 LWR 站点。与使用 ExperienceBundle 元数据类型的非增强型 LWR 站点不同,增强型 LWR 站点使用 DigitalExperienceBundle 和 DigitalExperienceConfig 类型。但是,如果您在 24 年冬季之前在源组织(如沙盒)上创建了非增强型 LWR 站点,并且现在希望首次将该站点部署到目标组织(如生产),则元数据类型的这种差异可能会导致部署问题。
  • 部署经过身份验证的 LWR 站点
    的注意事项 从 23 年冬季开始,通过 Experience Builder 或 Connect API 创建的新 LWR 站点在其 URL 末尾不包含 /s。在 23 年冬季之前创建的经过身份验证的 LWR 站点的 URL 仍包含 /s,如果沙盒和生产 URL 不匹配,则此 URL 结构更新会影响部署。了解支持哪些部署方案,以及如何解决与 /s 相关的不受支持的部署错误。

使用更改集部署 Experience Cloud 站点

使用更改集在相关组织之间移动全部或部分 Experience Cloud 站点 具有部署连接。您可以使用 Network 组件类型来移动任何完整的 Experience Cloud 站点。或者,您可以使用“数字体验”组件类型移动部分站点 增强型 LWR 站点的内容。

  • 使用更改集
    部署完整的 Experience Cloud 站点 使用更改集在具有部署连接的相关组织(例如沙盒和生产组织)之间移动 Experience Cloud 站点。在测试环境中创建、自定义和测试站点,然后在测试完成后将站点迁移到生产环境。
  • 使用更改集
    部署部分 Experience Cloud 站点内容 使用更改集在具有部署连接的相关组织(例如沙盒和生产组织)之间移动各个 Experience Cloud 组件和内容。在测试环境中创建和测试更改,然后在准备就绪时仅将这些更改迁移到生产环境。
  • 部署具有更改集
    的 Experience Cloud 站点的注意事项 在迁移具有更改集的 Experience Builder 或 Salesforce 选项卡 + Visualforce 站点时,请记住以下注意事项和限制。

使用更改集部署完整的 Experience Cloud 站点

使用更改集在具有 部署连接,例如沙盒和生产组织。创建、自定义和测试 测试环境中的站点,然后在测试时将站点迁移到生产环境 完成。

用户权限 需要
要自定义或发布 Experience Cloud 站点,请执行以下操作:创建和设置体验
若要编辑部署连接并使用入站更改集,请执行以下操作:部署更改集并修改所有数据注意如果用户 仅需要访问部署的元数据,则可以启用修改 元数据:通过元数据 API 函数权限。此权限提供以下 用户部署所需的访问权限,而无需提供对组织数据的访问权限。 有关详细信息,请参阅《通过元数据 API 函数权限修改元数据》中的 “修改元数据” Salesforce 帮助。
要使用出站更改集,请执行以下操作:创建和上载更改集,创建 AppExchange 软件包,并上传 AppExchange 软件包

您可以使用更改集来移动完整的 Experience Builder 和 Salesforce 选项卡 + Visualforce 使用网络组件类型的站点。

  1. 在首选测试组织(如沙盒)中创建和测试站点。
  2. 在测试组织的“设置”中,在 “快速查找”框,然后选择“出站更改集”。
  3. 创建更改集,然后单击“更改集组件”中的“添加” 部分。
  4. 选择“网络”组件类型,选择您的站点,然后选择 单击添加到更改集
  5. 若要添加依赖项,请单击“查看/添加依赖项”。我们 建议选择列出的所有依赖项。提示
    • 对于链接到标准对象的导航菜单,自定义列表视图不是 作为依赖项包含在内。手动将自定义列表视图添加到更改中 列表。
    • 手动添加“管理”|”成员
    • 依赖项列表有两个 Site.com items— 和 . 保存您可以设置的各种 Visualforce 页面 在 Experience Workspaces 的管理中。 包括 Experience Builder 中的页面。MySiteNameMySiteName1MySiteNameMySiteName1
  6. 单击“上传”,然后选择您的目标组织,例如 生产。确保目标组织允许入站连接。入站和出站 组织必须具有部署连接。
  7. 从“设置”中,选择“入站更改集”并查找更改集 您从源组织上传的。
  8. 验证并部署更改集,使其在目标组织中可用。警告当您部署入站更改集时,它会覆盖 目标组织。
  9. 手动重新配置目标组织站点中任何不受支持的项目。
  10. 为您的网站添加数据,并对其进行测试以确保一切按预期工作。 然后发布您的更改以上线。

使用更改集部署部分 Experience Cloud 站点内容

使用更改集在 具有部署连接的相关组织,例如沙盒和生产组织。创造 并在测试环境中测试更改,然后在以下情况下仅将这些更改迁移到生产环境 他们已经准备好了。

所需的用户权限
要自定义或发布 Experience Cloud 站点,请执行以下操作:创建和设置体验
若要编辑部署连接并使用入站更改集,请执行以下操作:部署更改集并修改所有数据注意如果用户只需要访问元数据 对于部署,您可以启用通过元数据修改元数据 API 函数 许可。此权限为此类用户提供了部署所需的访问权限,而无需 提供对组织数据的访问。有关详细信息,请参阅“通过元数据 API 修改元数据 Salesforce 帮助中的“Functions 权限”。
要使用出站更改集,请执行以下操作:创建和上传更改集,创建 AppExchange 包,以及上传 AppExchange 包

23 年冬季创建的增强型 LWR 站点可使用更改集进行部分部署 和以后。

您可以使用更改集移动使用数字 Experience Builder 站点的部分内容 体验组件类型。

  1. 在首选测试组织(如沙盒)中创建和测试站点。
  2. 在测试组织的“设置”中,在“快速查找”框中,输入“出站更改” 集,然后选择“出站更改集”。
  3. 创建更改集,然后单击“更改集组件”中的“添加” 部分。
  4. 选择“数字体验”组件类型。
  5. 从组件列表中选择要部署的内容,然后单击“添加到更改集”。提示
    • 要确定每个列出的组件属于哪个增强型 LWR 站点,请使用类型 列。Type 列使用命名约定 site/。MySiteName
    • 若要标识每个列出的组件所代表的内容,请使用“名称”列。名称 列使用命名约定 sfdc_cms__<contentType>/<contentName>。例如 名称 sfdc_cms__brandingSet/Build_Your_Own_LWR 表示名为 Build Your 的品牌集 拥有轻水堆。
  6. 单击“上传”,然后选择您的目标组织,例如生产组织。确保目标组织允许入站连接。入站和出站组织 必须具有部署连接。
  7. 从“设置”中,选择“入站更改集”,然后找到 您从源组织上传。
  8. 验证并部署更改集,使其在目标组织中可用。警告部署入站更改集时,它将覆盖相应的站点 目标组织中的内容。
  9. 手动重新配置目标组织站点中任何不受支持的项目。
  10. 为确保一切正常,请测试您的网站。然后发布更改 上线。

部署具有更改集的 Experience Cloud 站点的注意事项

迁移 Experience Builder 或 Salesforce 选项卡 + 带有更改集的 Visualforce 站点。

常规

  • 当您部署入站更改集时,它会覆盖 目标组织。因此,尽管不能使用更改集删除组件,但可以删除 Experience Builder 站点中的页面。例如,假设您从 沙盒中的Experience Builder站点,然后创建更新的出站更改集。什么时候 在目标组织(如生产组织)中重新部署更改集时,页面也 在那里删除了。
  • 如果您更新 Experience Cloud 站点模板,请确保您还更新了 在部署更改集之前定位组织。
  • 您无法部署到使用早期发行版的目标组织。例如 如果您的源组织位于 Summer ’19(API 版本 46.0)上,则无法部署到目标组织 在 Spring ’19 上(API 版本 45.0)。

管理

管理设置位于 Experience Workspaces 中。

  • 请记住添加“管理”|”成员添加到出站更改集。它们不会自动包含在内 依赖。
  • 对于在 17 年夏季版本之前在沙盒组织中创建的 Experience Cloud 站点,您 必须在迁移之前重新保存管理设置才能成功传输这些设置。
  • 在目标组织中发布站点之前,更改密码的设置会忘记 “密码”、“主页”、“自助注册”和“登录”页面似乎将恢复为默认值 值。
  • 要更新“会员”区域和“登录和注册”区域中的设置,您必须 在单独的更改集中部署更改。首先更新和部署“成员”区域 设置,然后更新和部署“登录和注册”设置。

导航菜单

导航菜单组件在 Experience Builder 站点中可用。

  • 对于链接到对象的菜单项,列表视图将重置为默认列表视图。 此外,标准对象的自定义列表视图不作为依赖项包含在内。
  • 部署带有其他菜单项的导航菜单会删除所有翻译 应用于目标环境中的现有菜单项。

建议

  • 不支持对建议名称的更新。如果更改 建议 在之前迁移过它的源组织中,目标组织会处理它 作为一项新的建议。
  • 不支持推荐图像。
  • 当您部署入站更改集时,它会覆盖目标组织的计划更改集 来自源组织的建议的建议。

增强型 LWR 站点的部分部署

  • 部分站点内容部署可用于增强的 LWR Experience Cloud 站点 创建于 23 年冬季或之后。
  • 若要部署部分网站内容,请确保目标组织包含现有网站 与源站点同名。
  • 将数字体验组件添加到出站更改集还会添加 组件到更改集的变体。例如,添加主视图组件 自动添加“主页”视图的所有翻译。

不支持的设置和功能

不支持以下项目。在部署入站更改集后手动添加它们。

  • 导航和特色主题
  • 观众 针对
  • 仪表板和参与度
  • 推荐图片
  • Experience Builder 中的品牌面板图像
  • Experience Workspaces中的以下管理设置:
    • “登录和注册”的“注册”部分中的“帐户”字段 面积
    • 选择要显示的登录选项选项 “登录和注册”区域的“登录”部分
    • “设置”区域
    • “富发布者应用”区域

使用元数据 API 部署 Experience Cloud 站点

使用元数据 API 将您的 Experience Cloud 站点从一个 Salesforce 组织移动到 另一个。在测试环境中设置和测试站点,然后检索站点的 数据并将其部署到您的生产组织。

根据网站框架的不同,以下元数据类型组合在一起以定义 网站。若要成功迁移站点,请使用元数据 API 检索调用来检索 org 的组件。网络表示 Experience Cloud 站点。包含管理设置,例如 作为页面覆盖、电子邮件和成员资格配置。定制网站包含域和页面设置信息,包括 indexPage、siteAdmin 和 URL 定义。DigitalExperienceBundle 和 DigitalExperienceConfig 或 ExperienceBundle  SiteDotCom所需的元数据类型因网站类型而异。代表 不同的设置和组件,例如页面、品牌集和 主题,构成一个网站。

对于冬季推出的增强型轻水堆站点 ’23(API 版本 56.0)、DigitalExperienceBundle 和 DigitalExperienceConfig 组合以提供基于文本的表示形式 您的网站元素和设置,但重新构想了更多 以内容为中心的结构。您可以检索可编辑的站点元数据,以及 以编程方式快速创建、更新、发布和部署网站。你 还可以部分部署增强型轻水堆站点。

对于非增强型轻水堆 站点,ExperienceBundle 提供基于文本的表示形式 站点的设置、页面和组件。您可以检索可编辑的网站 元数据,并快速创建、更新、发布和部分部署 以编程方式访问网站。

对于 Aura 站点,您可以选择使用 ExperienceBundle 或 SiteDotCom,但我们建议使用 体验捆绑包。在 Summer ’19(API 版本 45.0 及更早版本)之前, Network、CustomSite 和 SiteDotCom 元数据类型组合在一起以定义 光环网站。但是,检索 SiteDotCom 类型会生成人类不可读的二进制 .site 文件。请参阅 Experience Builder 站点的 ExperienceBundle。

为 Visualforce 站点,网络代表站点。

有关这些元数据类型的其他信息以及有关迁移的说明 data,请参阅元数据 API 开发 人员 指南和 Salesforce CLI 命令 参考资料。

所需元数据类型一目了然

用于部署网站的元数据类型因网站类型而异。

必需的元数据类型增强型 LWR 站点轻水堆站点Aura 站点Visualforce 网站
网络必填必填必填必填
定制网站必填必填必填必填
数字体验捆绑包必填
DigitalExperienceConfig 数字体验配置必填
体验捆绑包必填必填ExperienceBundle  SiteDotCom
网站DotCom必填

提示和注意事项

  • 在将数据迁移到另一个组织之前,请在目标组织中启用数字体验 并输入您在沙盒组织中使用的相同域名,以避免 出现错误。
  • 对于每个 Experience Cloud 站点,网络组件都具有唯一的名称和 URL 路径前缀。检索网络组件时,生成的 XML 文件 name 基于网络的名称。迁移时,API 会查看 文件名,如果存在,则更新站点。如果不存在,则 API 创建站点。如果有人在沙盒中更改了站点名称,然后尝试 要进行迁移,他们会看到一个错误。该 API 正在尝试使用 现有路径前缀。
  • 检查 CustomSite 的 XML 文件,确保所有依赖项都 带过来。如果缺少任何内容,请在 XML 文件中显式说明它们。
  • 除了前面描述的必需组件外,还包括所有 您的网站所需的其他组件。组件可以包括以下项 自定义对象、自定义字段、自定义 Lightning 组件和 Apex 类。
  • 要使用未锁定的软件包部署网络和配置文件组件,请创建一个 为每个组件单独解锁包并单独部署它们。
  • 使用 ExperienceBundle 部署 Aura 站点时,请确保 SiteDotCom 类型不包含在清单文件中。
  • 如果在“管理”|”设置,请确保源站点和目标站点具有匹配的值 用于 Network 组件中的 和 属性。picassoSitesite
  • 如果来宾用户配置文件有任何更改,请将配置文件作为一部分包括在内 的站点迁移。
  • 迁移用户配置文件时,用户将添加到生产中的站点 组织。然后,电子邮件将以与任何新网站相同的方式发送给会员。
  • 在部署过程中,请确保目标组织中的 NavigationMenu 开发人员名称与源中的开发人员名称相同 组织。
  • 如果 containerType 为 CommunityTemplateDefinition,则不能 通过元数据 API 更新现有的 NavigationMenu。
  • 要使用自定义模板部署 Aura 站点,请首先检索并部署 CommunityTemplateDefinition 和相关元数据类型,例如 CommunityThemeDefinition。然后检索并部署 ExperienceBundle 或 SiteDotCom 和相关元数据类型。
  • 部署带有其他菜单项的导航菜单会删除任何 应用于目标环境中现有菜单项的翻译。
  • 若要在移动站点时包含导航菜单,请使用 NavigationMenu 元数据类型。
  • 您无法部署到使用早期发行版的目标组织。为 例如,如果您的源组织使用的是 Summer ’19(API 版本 46.0),则不能 在 Spring ’19(API 版本 45.0)上部署到目标组织。
  • NavigationLinkSet 在 Winter ’20 中已弃用(API 版本 47.0),并替换为 NavigationMenu。
  • ExperienceBundle 不支持跨不同 API 进行检索和部署 版本。如果您尝试从早期版本升级 ExperienceBundle 元数据 API 版本到更高版本,例如,从 API 版本 48.0 到 49.0 – 执行以下步骤:
    1. 将 package.xml 清单文件中的 API 版本设置为 48.0 并部署 包。
    2. 然后,将 package.xml 中的 API 版本设置为 49.0。
    3. 要获取最新的 ExperienceBundle 更新,请检索包。
  • 部署站点时,有时会收到有关无效 ID 的警告消息 值。例如:The topicId property of component 9b8a4e98-e724-4292-bd3c-0813adf9ddc2 references an object with the ID value 0TO4R000000EGPEWA4. Occasionally, when deployed to a destination org, ID values can become invalid—for example, if the referenced ID doesn’t exist in the destination org. If you encounter component issues in your destination org, verify that the ID values are correct.在这些 在这种情况下,您可以成功部署站点,尽管有警告。 但是,我们建议在目标组织中验证对象 ID 组件中引用的仍然有效。如果 ID 不正确,请手动操作 更新 ID 以解决目标组织中的任何组件问题。 或者,如果它是您创建的自定义组件,请考虑 将对象 ID 替换为对象的 API 名称,以避免 将来的问题。

示例模板

以下示例包含您 可以通过元数据进行迁移 应用程序接口。

<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://soap.sforce.com/2006/04/metadata">
    <allowInternalUserLogin>true</allowInternalUserLogin>
    <allowMembersToFlag>true</allowMembersToFlag>
    <allowedExtensions>txt,png,jpg,jpeg,pdf,doc,csv</allowedExtensions>
    <caseCommentEmailTemplate>unfiled$public/ContactFollowUpSAMPLE</caseCommentEmailTemplate>
    <changePasswordTemplate>unfiled$public/CommunityChangePasswordEmailTemplate</changePasswordTemplate>
    </communityRoles>
    <disableReputationRecordConversations>true</disableReputationRecordConversations>
    <emailSenderAddress>admin@myorg.com</emailSenderAddress>
    <emailSenderName>MyCommunity</emailSenderName>
    <enableCustomVFErrorPageOverrides>true</enableCustomVFErrorPageOverrides>
    <enableDirectMessages>true</enableDirectMessages>
    <enableGuestChatter>true</enableGuestChatter>
    <enableGuestFileAccess>false</enableGuestFileAccess>
    <enableInvitation>false</enableInvitation>
    <enableKnowledgeable>true</enableKnowledgeable>
    <enableNicknameDisplay>true</enableNicknameDisplay>
    <enablePrivateMessages>false</enablePrivateMessages>
    <enableReputation>true</enableReputation>
    <enableShowAllNetworkSettings>true</enableShowAllNetworkSettings>
    <enableSiteAsContainer>true</enableSiteAsContainer>
    <enableTalkingAboutStats>true</enableTalkingAboutStats>
    <enableTopicAssignmentRules>true</enableTopicAssignmentRules>
    <enableTopicSuggestions>true</enableTopicSuggestions>
    <enableUpDownVote>true</enableUpDownVote>
    <forgotPasswordTemplate>unfiled$public/CommunityForgotPasswordEmailTemplate</forgotPasswordTemplate>
    <gatherCustomerSentimentData>false</gatherCustomerSentimentData>
    <lockoutTemplate>unfiled$public/CommunityLockoutEmailTemplate</lockoutTemplate>
    <maxFileSizeKb>51200</maxFileSizeKb>
    <networkMemberGroups>
        <permissionSet>MyCommunity_Permissions</permissionSet>
        <profile>Admin</profile>
    </networkMemberGroups>
    <networkPageOverrides>
        <changePasswordPageOverrideSetting>VisualForce</changePasswordPageOverrideSetting>
        <forgotPasswordPageOverrideSetting>Designer</forgotPasswordPageOverrideSetting>
        <homePageOverrideSetting>Designer</homePageOverrideSetting>
        <loginPageOverrideSetting>Designer</loginPageOverrideSetting>
        <selfRegProfilePageOverrideSetting>Designer</selfRegProfilePageOverrideSetting>
    </networkPageOverrides>
    <picassoSite>MyCommunity1</picassoSite>
    <selfRegistration>true</selfRegistration>
    <sendWelcomeEmail>true</sendWelcomeEmail>
    <site>MyCommunity</site>
    <status>Live</status>
    <tabs>
        <defaultTab>home</defaultTab>
        <standardTab>Chatter</standardTab>
    </tabs>
    <urlPathPrefix>mycommunity</urlPathPrefix>
    <welcomeTemplate>unfiled$public/CommunityWelcomeEmailTemplate</welcomeTemplate>
</Network>

示例包 .xml 清单文件

清单文件定义您尝试检索的组件。以下 示例显示了 检索 Experience Builder 站点的所有组件。package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>Network</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomSite</name>
    </types>
    <types>
        <members>*</members>
        <name>ExperienceBundle</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexPage</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexComponent</name>
    </types>
    <types>
        <members>*</members>
        <name>Portal</name>
    </types>
    <types>
        <members>*</members>
        <name>Profile</name>
    </types>
    <types>
        <members>*</members>
        <name>Document</name>
    </types>
    <version>46.0</version>
</Package>

适用于 Experience Builder 站点的 ExperienceBundle

ExperienceBundle 元数据类型提供基于文本的不同 构成体验的设置和组件,例如页面、品牌集和主题 建筑商网站。无论是对于你自己的组织,还是咨询合作伙伴或 ISV,你都可以 使用首选开发工具以编程方式快速更新和部署站点, 包括适用于 VS Code 的 Salesforce 扩展、Salesforce CLI 或你喜欢的 IDE 或文本 编辑 器。

在 Summer ’19 版本(API 版本 45.0 及更早版本)之前,Network、CustomSite 和 SiteDotCom 元数据类型组合在一起以定义 Experience Builder 站点。但是,检索 SiteDotCom 类型生成一个非人类的二进制 .site 文件 读。通过检索 ExperienceBundle 类型而不是 SiteDotCom,您可以提取和 以人类可读的格式编辑粒度网站元数据,包含在三级文件夹中 结构。

局限性

  • 不支持托管包。

ExperienceBundle 结构

检索 ExperienceBundle 时,数据存储在三级文件夹结构中。

“体验”文件夹包含每个“体验生成器”的文件夹 组织中的站点。每个文件夹(在本例中customer_service)包含 子文件夹,用于定义站点并表示您在Experience Builder中访问的不同元素。每 子文件夹包含 .json 文件,其中包含可在本地编辑的属性 machine或scratch org,然后部署。site_name让我们仔细看看定义每个Experience Builder站点的文件。

文件夹内容
品牌集branding_set_name.json 定义了 网站的品牌设置属性。
配置site_name.json 定义了一些站点 设置,例如公共访问和渐进式渲染。languages.json 定义支持的语言。loginAppPage.json 和 mainAppPage.json 是单页应用程序 (SPA)。loginAppPage.json 用于需要 login,mainAppPage 用于所有其他页面。一 SPA 是加载单个 HTML 页面的 Web 应用。与传统的不同 网站,包括用户在其中导航的多个页面, SPA 由多个视图组成,这些视图以用户身份动态更新页面 与它交互。
路线每页包含一个名为 page_name.json 的文件,用于定义 URL 以及其他与路由相关的信息。
主题每个主题包含一个名为 theme_name.json 的文件,该文件定义了 主题。
变化每个变体包含一个名为 experienceVariation_name.json 的文件。你 可以使用体验变体来更改体验的默认行为 基于受众的构建器网站,例如品牌、页面变体、组件 可见性或组件属性。
视图每个视图包含一个名为 view_name.json 的文件。每个文件定义一个 SPA 视图,相当于最终用户的页面。视图由区域组成 在呈现的页面中包含其他区域或组件。

提示

在更新 Experience Builder 站点的 .json 文件之前,我们 建议复制站点的文件夹作为备份。

有关 ExperienceBundle 及其包含的文件的完整定义,请参阅元数据 API 开发人员 指南。

启用 ExperienceBundle 元数据类型

为 Aura 站点启用 ExperienceBundle 后,元数据 API 调用 ( 和 ) 和 Salesforce DX 操作 (, , 和 ) 使用 ExperienceBundle 类型,而不是 SiteDotCom。retrievedeploypullpushstatus

如果使用更改集来部署站点,则依赖项列表包括以下两项 键入 Site.com 和 1。1 现在表示 ExperienceBundle 而不是 SiteDotCom。MySiteNameMySiteNameMySiteName

注意

您无需为 LWR 站点启用 ExperienceBundle 元数据类型。轻水堆站点使用 默认为 ExperienceBundle。

  1. 在“设置”中,在“快速查找”框中输入, ,然后选择设置Digital Experiences
  2. 选择启用 ExperienceBundle 元数据 API
  3. 保存更改。

或者,您可以在使用临时组织创建临时组织时启用此功能 定义文件。(请参阅元数据覆盖范围 报告。

{
    "orgName": "Sample Org",
    "edition": "developer",
    "features": [
        "COMMUNITIES"
    ],
    "settings": {
        "experienceBundleSettings": {
            "enableExperienceBundleMetadata": true
        },
        "communitiesSettings": {
            "enableNetworksEnabled": true
        }
    }
}

使用元数据 API 检索和部署 ExperienceBundle

在元数据 API 中,清单文件定义您尝试检索的组件。 此示例显示 使用 ExperienceBundle 而不是 SiteDotCom 检索 Experience Builder 站点。package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomSite</name>
    </types>
    <types>
        <members>*</members>
        <name>ExperienceBundle</name>
    </types>
    <types>
        <members>*</members>
        <name>Network</name>
    </types>
    <version>46.0</version>
</Package>

检索 .zip 文件后,将其解压缩以访问和编辑文件。

请参阅部署和检索元数据 替换为 Zip 文件。

使用 Salesforce DX 检索和部署 ExperienceBundle

Salesforce 开发人员体验 (DX) 是一组工具,可简化整个 开发生命周期。它改善了团队发展和协作,促进了自动化 测试和持续集成,并使发布周期更加高效和 敏捷。如果您已设置 Salesforce DX 环境,则可以快速:

  • 使用以下命令检索组织中的所有Experience Builder站点sf project retrieve start
  • 使用以下方式部署更新sf project deploy start
  • 使用 或sf project deploy preview sf project retrieve preview
  • 检索可用模板的列表sf community list template
  • 使用以下方法创建站点sf community create
  • 使用sf community publish

如果您不熟悉 Salesforce DX,请查看这些很棒的资源。

避免迁移到增强型 LWR 站点时出现部署问题

从 24 年冬季开始,您无法再禁用增强的网站和内容平台, 它于 23 年冬季首次推出。因此,从 LWR 模板创建的任何站点都是 现在是默认增强的 LWR 站点。与使用 ExperienceBundle 的非增强型 LWR 站点不同 元数据类型,增强的 LWR 站点使用 DigitalExperienceBundle 和 DigitalExperienceConfig 类型。但是,如果您在源组织(如沙盒)上创建了非增强型 LWR 站点 24 年冬季,您现在希望首次将站点部署到目标组织,例如 生产,元数据类型的这种差异可能会导致部署问题。

在这种情况下,我们不是在部署之前在目标组织上创建站点,而是 建议使用部署过程创建站点。否则,如果首先创建 目标组织上的站点,则新站点是增强的 LWR 站点,这意味着它使用 DigitalExperienceBundle 和 DigitalExperienceConfig 类型。并且因为非增强 源组织上的 LWR 站点使用 ExperienceBundle(如果您随后尝试将其部署到目标) org,则由于元数据类型不匹配,部署失败。

但是,假设您在部署之前在目标组织中创建了站点。你能做什么 如何解决部署错误?

由于您无法删除 Experience Cloud 站点,因此我们建议您重命名站点并 更新目标组织中的站点 URL,使其不再与源中的值匹配 组织。此方法释放了部署过程,以便使用 源组织的值。

  1. 在目标组织中,在站点的“管理”工作区的“设置”页上,将 站点,使其与源组织中的站点不同。
  2. 在“设置”的“快速查找”框中,输入“自定义 URL”。
  3. 在“自定义 URL”中,找到网站的两个 URL。每个站点包括:
    • 映射到 ExperienceBundle 或 DigitalExperienceBundle 的 Site.com 社区 URL 和 DigitalExperienceConfig 元数据类型(视情况而定)映射到 CustomSite 的社区 URL
  4. 更改这两个站点 URL,以确保它们不再与 来源组织。
  5. 更新站点名称和 URL 后,使用更改集或 使用首选部署工具的元数据 API。
  6. 如果您使用的是元数据 API,请记住检索站点并包含网络和 CustomSite 类型,以允许系统在 目标组织。如果您使用的是更改集,请记住在之前重新创建更改集 部署。

部署经过身份验证的 LWR 站点的注意事项

从 23 年冬季开始,通过 Experience Builder 或 Connect API 创建新的 LWR 站点 不要在其 URL 末尾包含 /s。在 Winter 之前创建的经过身份验证的 LWR 站点的 URL ’23 仍包含 /s,如果沙盒和生产环境,此 URL 结构更新会影响部署 URL 不匹配。了解支持哪些部署方案以及如何解决不支持的方案 与 /s 相关的部署错误。

注意

所描述的方案假定沙盒和生产环境位于同一版本的 Salesforce的。不支持将站点从较新版本部署到较旧版本。

元数据 API 部署

  • 支持通过元数据 API 部署创建站点,无论源站点的 URL 包括 /s。如果源站点的 URL 包含 /s,则新目标站点的 URL 将包含 /s。如果 源站点的 URL 不包含 /s,新目标站点的 URL 不包含 /s。
  • 若要使用元数据 API 部署更新站点,请源站点的 URL 和目标站点的 URL 必须匹配。两个 URL 都必须包含 /s,否则任何一个 URL 都不能包含 /s。
  • 要解决与 /s 相关的元数据 API 部署错误,请将元数据包更新为 在源站点的 URL 中添加或删除 /s。确保源站点的 URL 与 目标站点的 URL。您不能在目标站点的 URL 中添加或删除 /s。

更改集部署

  • 支持通过更改集部署创建站点,无论源站点的 URL 包括 /s。如果源站点的 URL 包含 /s,则新目标站点的 URL 将包含 /s。如果 源站点的 URL 不包含 /s,新目标站点的 URL 不包含 /s。
  • 若要使用更改集部署更新站点,源站点的 URL 和目标站点的 URL 必须匹配。两个 URL 都必须包含 /s,否则任何一个 URL 都不能包含 /s。
  • 若要解决与 /s 相关的更改集部署错误,请重命名源站点或 通过API或Experience Builder的目标站点。重命名其中一个站点会创建一个 站点,而不是更新目标站点。不能将 /s 添加到 /s 中,也不能从 源站点的 URL 或目标站点的 URL。

开发安全站点: CSP、LWS 和 闪电 柜子

光环 和轻水堆站点 在 Experience Cloud 中 使用内容安全策略 (CSP) 和 Lightning Web 安全 (LWS) 或 Lightning Locker 来保护 这 网站免受恶意攻击和自定义代码漏洞。潜在影响的因素 当您开发自己的自定义组件时,使用第三方组件时,这些安全功能, 或在标记中添加自定义代码。

head

云解决方案提供商

CSP 是一种 W3C 标准,用于控制可在页面上加载的内容源。 CSP 规则在页面级别工作,适用于所有第三方组件和自定义代码。由 默认情况下,框架的标头仅允许从安全 (HTTPS) URL 加载内容 并禁止来自 JavaScript 的 XHR 请求。

Experience Builder 提供了不同级别的 CSP 脚本安全性。CSP 级别 特定于每个站点。

闪电储物柜 和 Lightning Web Security

这 Lightning Locker 架构层通过隔离单个 Lightning 来增强安全性 组件命名空间,并强制执行编码最佳实践。闪电 Locker 一直是 Lightning 组件和 Aura 的默认安全架构 体验中的站点 云。

LWS 旨在使您的组件更容易使用安全编码实践和 旨在取代闪电储物柜。与 Lightning Locker 一样,LWS 的目标是防止 Lightning 组件干扰或访问属于平台代码的数据 或来自其他命名空间的组件。但是,Lightning Web Security 的架构 使用不同的方法保护 Lightning Web 组件。

LWS 如何在组织和站点级别应用

管理员可以在组织级别启用 LWS 以在整个组织内使用,而不是 Lightning 通过将 Lightning Web Security 用于 Lightning Web 组件和 Aura 组件的 Locker 在“设置”的“会话设置”中设置。

此组织级别设置会影响 Aura 站点,因为在组织中启用 LWS 时,LWS 在站点级别替换 Lightning Locker。然后,如果您禁用 Lightning Locker 在 Experience Builder 中为 Aura 站点进行设置时,您实际上是在禁用 LWS。

LWR 站点有自己的 LWS 实例,因此 LWS 的组织设置对 LWR 没有影响 网站。如果在 LWR 站点中禁用 Lightning Locker,则该站点的 LWS 实例为 禁用,即使在组织中启用了 LWS 也是如此。

注意

默认情况下,会为所有新的Experience Builder站点启用严格CSP,这意味着 Lightning Locker 或 LWS 也已启用。要访问 Lightning Locker 设置 Experience Builder,选择“轻松的 CSP”。

对于 B2B 商店和 B2C 商店 LWR 模板 在 Commerce Cloud 中,默认情况下不启用 LWS。

下表总结了组织级别设置和站点级别设置在 Aura 或 LWR 站点。

Experience Cloud 站点框架网站级设置组织级别设置现场使用的 LWS 或储物柜
光环上上上
上检查上
检查上闪电储物柜
检查检查LWS系列
轻水堆上上上
上检查上
检查上LWS(站点的实例)
检查检查LWS(站点的实例)
  • 解决 Aura 站点中的 Lightning Locker 冲突 默认情况下,Experience Cloud 中的所有新 Aura
    站点都启用了 Lightning Locker。但是,有时,由于与 Lightning Locker 发生冲突,页面上的第三方组件或标记中的自定义代码无法按预期工作。在这种情况下,Salesforce 建议使用此处描述的解决方法之一。head
  • 允许第三方组件在 Lightning Locker 关闭
    时运行 如果您在 Experience Builder 站点中关闭 Lightning Locker,则必须将从托管包安装的任何第三方组件配置为在设计时可用并在运行时呈现。
  • 示例:Aura Sites
    中的 Adobe Analytics 和 Lightning Locker 由于 Adobe Analytics 会与 Aura 站点中的组件进行交互,因此 Lightning Locker 可能会产生意想不到的结果。建议的解决方法是在标记中使用 JavaScript 自定义事件来隔离 Adobe Analytics。然后,Adobe Analytics 可以与组件进行交互,而无需负责直接加载或引用该资源。head

解决 Lightning Locker 冲突 光环 网站

默认情况下,Lightning Locker 为所有新 光环 体验中的站点 云。但是,偶尔会有第三方组件在页面上或自定义 由于以下原因,标记中的代码无法按预期工作 与 Lightning Locker 冲突。在这种情况下,Salesforce 建议使用 此处介绍的解决方法。

head

使用 JavaScript 自定义事件

Lightning Locker 可防止第三方组件和自定义代码与 来自其他命名空间的资源,但不来自标记的资源。此限制意味着您的标记可以 包含绕过 Lightning Locker 并引入安全漏洞的自定义代码。headhead

要解决此限制,请隔离您的第三方 Aura 和 Lightning Web 组件,并 使用 构造函数的自定义代码 您的标记。第三方组件和自定义代码 然后,可以与资源交互,而无需负责加载或引用 该资源。CustomEventhead

必须通过事件传递到侦听器的任何数据都将在属性中传递,该属性是在初始化 事件。该属性映射到 dataLayer。自定义事件 然后,被分派给任何扩展的资源。有关使用自定义事件的示例,请参阅 Adobe Analytics 和 Lightning Locker。detaildetailheadEventTarget

警告

请注意使用 JavaScript 构造函数传递的数据,并确保使用量 安全。网页上运行的任何 JavaScript,包括任何第三方 App Exchange 您正在使用的组件可能会侦听您的事件名称并读取此内容 数据。CustomEvent

将 Aura 组件设置为 API 39.0

如果您的第三方组件或自定义代码未与 Aura 组件交互,则 预期,您可以将 Aura 组件设置为 Salesforce API 版本 39.0,这将禁用 组件的 Lightning Locker。请参阅《Lightning Aura 组件开发人员指南》中的禁用组件的 Lightning Locker。

警告

禁用 Aura 组件的 Lightning Locker 可以引入安全性 缺陷进入您的网站,并阻止组件在设计时可用,或者 在运行时呈现。

为了保持一致性和易于调试,请避免使用父 Aura 组件和子组件 组件。因此,请勿使用任何设置为 API 的 Aura 组件 组件层次结构中的版本 39.0,例如组件中的组件或组件 这扩展了另一个组件。

如果在组织中启用了 LWS,则在组件中设置 API 版本 39.0 不会禁用 LWS 对于组件。但是,LWS 可能允许 Lightning 的组件的行为 Locker 块,无需禁用它。

关闭 Lightning Locker

警告

仅将此解决方法用作最后的手段。

如果您在站点中关闭 Lightning Locker,则会为站点的所有第三方组件和自定义代码禁用它。后果可能是 范围广泛且出乎意料,例如在您的网站中引入安全漏洞。如果 第三方组件尚未启用,无法在没有 Lightning Locker 的情况下工作,它可以防止这种情况发生 组件在设计时可用,在运行时呈现。当闪电 Locker 已关闭,来自不同命名空间的组件可以与每个命名空间交互并访问每个 其他的文档对象模型 (DOM) 以及有关自定义资源交互的限制 与您的网站是放松的。

有关禁用 Lightning Locker 的更多信息,请参阅 Salesforce 帮助中的在 Experience Builder 站点中选择安全级别。

注意

如果在组织中启用了 LWS,则当您在 Aura 站点中禁用 Lightning Locker 时,您 实际上在站点中禁用 LWS。如果在 LWR 站点中禁用 Lightning Locker,则 站点的 LWS 实例被禁用,即使在组织中启用了 LWS 也是如此。

允许第三方组件在 Lightning Locker 关闭时运行

如果您在 Experience Builder 站点中关闭了 Lightning Locker,则任何第三方 从托管包安装的组件必须配置为在设计时可用 并在运行时渲染。

您可以从 Relaxed CSP 安全性中关闭 Lightning LockerYou can off Lightning Locker from the Relaxed CSP security 水平。

如果 LWS 在组织中启用,当您在 Aura 站点中禁用 Lightning Locker 时,您实际上是禁用的 LWS 在站点中。如果在 LWR 站点中禁用 Lightning Locker,则该站点的 LWS 实例 被禁用,即使在组织中启用了 LWS。 LWR 站点可以包含第三方库 而不禁用 Lightning Locker 或 LWS。有关详细信息,请参阅集成 在 LWR 站点中使用特权脚本标记的第三方库 经验 云。

警告

关闭 Lightning Locker 可能会给您的网站带来安全漏洞。 禁用 Lightning Locker 仅作为最后的手段。

配置 第三方光环 要运行的组件 不带 Lightning Locker

对于第三方 Aura 组件,托管包开发人员必须为 元件。lightningcommunity:allowInRelaxedCSP

配置 第三方闪电网络 要运行的组件 不带储物柜

对于第三方 Lightning Web 组件,托管软件包开发人员必须在组件配置文件的标记中配置该值。lightningCommunity__RelaxedCSPcapability

示例:Adobe Analytics 和 Lightning Locker 光环 网站

因为 Adobe Analytics 会与 光环 站点,Lightning Locker可能会产生意想不到的结果。建议的解决方法是隔离 Adobe Analytics,在标记中使用 JavaScript 自定义事件。然后,Adobe Analytics 可以与组件进行交互,而无需 负责直接加载或引用该资源。

head

提示

LWR 站点可以使用不同的策略来包含分析。为 有关详细信息,请参阅集成第三方库 在 LWR 站点中使用特权脚本标记以获得体验 云。

将 Adobe Analytics 包含在 光环 网站

将 Adobe Analytics 脚本和适用的事件侦听器添加到 使用标记的网站标记。

headscript

<script> 
    document.addEventListener('analyticsEvent', function(e) {
        //add logic here to tell your dataLayer about the event
        //dataLayer.action = e.detail.action;
        //dataLayer.label = e.detail.label;
        //or map payload to an AA library event
    });
    
    document.addEventListener('analyticsViewChange', function() {
    });
</script>
<script src="full-url-to-your-adobe-script" async></script>

使用自定义事件

对于要与 Adobe Analytics 交互的任何组件,请使用 该物业。此属性传递数据 通过事件发送到侦听器,并映射到 In your Markup 侦听器。这 然后,可以将自定义事件分派给扩展 的任何资源。

detaildataLayerheadEventTarget

document.dispatchEvent(new CustomEvent('analyticsEvent', {'detail': {action: 'click', label: 'Submitted Case'}}));

警告

请注意使用 JavaScript 构造函数传递的数据,并确保使用量 安全。在页面上运行的任何 JavaScript(包括 Adobe Analytics)都可能 侦听您的事件名称并读取此数据。CustomEvent

为 Aura 组件实现其他事件

如果Adobe Analytics与Aura组件交互,则还必须实施and事件。forceCommunity:routeChangeaura:locationChange

forceCommunity:routeChange跟踪视图更改 在 Lightning 组件中 框架。

<aura:component implements="forceCommunity:availableForAllPageTypes">
    <aura:handler event="forceCommunity:routeChange" action="{!c.handleRouteChange}" />
</aura:component>
handleRouteChange : function(component, event, helper) {
    document.dispatchEvent(new Event('analyticsViewChange'));
}

aura:locationChange表示哈希部分 浏览器位置栏中的 URL 已被修改。但是,更改哈希部分 的位置 URL 很少使用,例如,在 选项卡组件。

分析和改进 Experience Builder 站点性能

Salesforce Page Optimizer 会分析您的网站并识别影响的问题 性能。使用这些信息来优化您的设计并提高网站性能 成员。Page Optimizer 是 Chrome 网上应用店提供的免费插件。下载和 像安装任何 Chrome 扩展程序一样安装插件。

适用于:Salesforce Classic(并非在所有组织中都可用)和 闪电体验
适用于:EnterprisePerformanceUnlimited 和 Developer Edition
用户权限 需要
要自定义 Experience Cloud 站点,请执行以下操作:成为网站成员并创建和设置 经验或成为站点的成员,并查看设置和配置,以及 该站点中的体验管理员、发布者或构建者
要发布 Experience Cloud 站点,请执行以下操作:成为网站成员并创建和设置 经验或成为网站的成员,并且是其中的体验管理员或发布者 网站

要下载页面优化器,请在 Experience Builder 中单击设置左侧边栏,然后 ,然后点按“高级”。

安装后,页面优化器将与您的其他 Chrome 扩展程序一起定位。

见解

要分析您的网站,请导航到已发布的网站,加载页面,然后启动 页面优化器。

“见解”选项卡 (1) 根据 Web 应用程序的最佳实践评估您的页面 使用 Lightning 框架开发。此选项卡显示总体性能分数 (3) 以及各种分析规则的个人分数 (5)。查看详细信息和建议 操作中,单击每个规则。如需更多工作空间,请单击弹出窗口 (2)。

“见解”选项卡在提供建议时是保守的。如需进一步的见解, 考虑查看瀑布图、时间线、图表、成本和 “操作”选项卡。

要删除收集的指标,请单击清除 (4)。执行一些用户 操作以收集新指标,然后重新打开页面优化器。例如 要收集赞某个 Feed 项的效果指标,请清除效果指标,然后点击赞、 并重新打开页面优化器。

瀑布

“瀑布”选项卡显示所有网络请求和性能检测数据。点击 用于在边栏中查看上下文信息的行。单击每行左侧的箭头 以展开每行的信息。

时间线

“时间轴”选项卡提供每个组件渲染生命周期的配置文件。时间线 视图针对显示 Lightning 框架指标进行了优化,因此更易于解释 比 Chrome DevTools 。

图表

“图表”选项卡显示客户使用时有关内存和组件的趋势信息 您的页面。

组件

“组件”选项卡显示页面上每个组件的生命周期计数。此视图 帮助您识别潜在的组件泄漏和意外的渲染行为。使用 “组件”选项卡以及“成本”选项卡,用于全面了解组件性能。

成本

“成本”选项卡显示每个组件忙于处理其逻辑的时间量。这 时间越短,性能越好。

行动

“操作”选项卡显示页面上执行的所有操作的列表及其 计时信息。

出口

将您的分析导出到文件中,以便与您的开发和支持团队共享。

提交反馈

我们希望收到您的来信。分享您的意见、问题、请求和任何问题 找到。提交反馈。


将 Pardot 跟踪添加到您的体验构建器站点

Pardot 可以跟踪访问者在网站上的互动和活动,即使访问者 尚未转换为潜在客户。启用跟踪后,使用 Pardot 查看以下方面的报告 访客参与度,并根据现场活动自动对潜在客户进行评分。

  1. 在 Pardot 中,导航到要跟踪的广告系列。
  2. 点击查看跟踪 代码, 并复制代码。
  3. 访问要向其添加跟踪的站点的 Experience Builder。
  4. “设置”|”高级,单击“编辑头部标记”,然后粘贴到 Pardot 中 跟踪代码。

Experience Builder 站点是单页应用程序 (SPA),因此当用户导航到 网站上的不同页面,仅重新加载内容区域,而不是整个页面。这 Pardot 脚本将网站的首次加载记录为页面视图。修改脚本以允许 页面内的应用内导航,以便在 Pardot 中更准确地捕获。

  1. 在“编辑标题标记”窗口中,修改 Pardot 跟踪代码,以便在页面中进行更改 状态将添加到会话历史记录中。下面是一个包含修改的示例代码片段 著名的。
<script type='text/javascript'>
piAId = '{{%pardot-id-for-your-org%}}'; //no change from OOTB code (format: 123456)
piCId = '';
piHostname = '{{%pardot-hostname-for-your-org%}}'; //no change from OOTB code (format: www.yourpardottrackerdomain.com)
    
(function() {
  //patching the history push state function to include calling
  // the async_load function that sends data to Pardot
  var pushState = history.pushState;
  history.pushState = function() {
    pushState.apply(history, arguments);
    async_load(); 
  };
    
    function async_load(){0
        var s = document.createElement('script'); s.type = 'text/javascript';
        s.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + piHostname + '/pd.js';
        var c = document.getElementsByTagName('script')[0]; c.parentNode.insertBefore(s, c);
    }
    if(window.attachEvent) 
    { 
        window.attachEvent('onload', async_load);
         //attach event listener for browser history changes
         // for browsers that support attachEvent
         window.attachEvent('onpopstate', async_load);
    }
    else 
    { 
        window.addEventListener('load', async_load, false); 
        //add eventlistener for browser history changes
        // for all other browsers
        window.addEventListener('popstate', async_load, false);
    }
})();
    
    
</script>

更新网站的内容安全策略 (CSP) 设置,使 head 标记以 预期。

  1. 访问 Experience Builder |设置 |安全性
  2. 选择“宽松的 CSP:允许访问内联脚本”和“允许” 主机,然后在确认中单击“允许” 窗。
  3. “CSP 错误”下,可以看到被阻止的站点列表。单击要允许作为 Pardot 跟踪器的每个站点的允许 URL 域。

在 Pardot 和 Experience Cloud 之间成功集成后,您可以 根据访客的 Experience Cloud 网站准确跟踪页面浏览量并对潜在客户进行评分 导航。

将 CMS 与 你 Experience Builder 站点

内容管理系统 (CMS) 使您能够重用内容,而不是拥有 来复制它。使用 CMS,您可以将内容馈送到多个站点,还可以集中更新 它使它同时在任何地方保持最新状态。

Experience Cloud 提供两个 CMS 选项来满足您的需求。Salesforce CMS 内置于您的组织中 用于在组织中使用多个渠道创建、管理和组织内容。和CMS Connect 是一种工具,用于将第三方 CMS 中的内容嵌入到您的网站中。查看更多 有关这两个选项的信息,请参阅 CMS 开发人员 指南。

关于偏转的报告:偏转信号框架

事件是 当用户启动案例,然后查看解决其问题的偏转项时触发,并且 导致他们放弃此案。

lightningcommunity:deflectionSignal

例如,假设用户正在填写表单以创建客户案例,然后 在页面上看到一篇有用的文章。单击文章后,用户发现它很有帮助,并且 决定创建案例是不必要的。然后触发一个事件。活动内容包括 有关用户与文章交互的信息。用户的操作报告为 成功偏转,因为用户未创建案例。lightningcommunity:deflectionSignal

您可以通过目标对象 Community 的自定义报告类型来报告这些事件 案例偏转指标。信号在报告中显示为成功偏转、 挠度失败或潜在挠度。

注意

仅报告由经过身份验证的用户触发的事件。lightningcommunity:deflectionSignal

  • 案例创建偏转信号
    当用户偏离创建客户案例时,将在 Aura 站点中触发该事件。在用户查看文章或讨论后,系统会询问他们互动是否有帮助,以及他们是否想放弃他们的案例。lightningcommunity:deflectionSignal

案例创建偏转信号

活动是 在 Aura 站点中,当用户偏离创建客户案例时触发。在用户之后 查看文章或讨论时,系统会询问他们互动是否有帮助,以及他们是否 想放弃他们的案子。

lightningcommunity:deflectionSignal

注意

我们仅收集由身份验证触发的事件的数据 用户。lightningcommunity:deflectionSignal

您可以将 Case Deflection 组件配置为自动触发此事件 在Experience Builder中使用组件的“偏转度量度”属性。案例 挠度组件与联系支持表一起用于记录挠度 相互 作用。

属性

来自案例的偏转信号 挠度分量为 。sourceTypecaseCreateDeflectionModal

这是用户在主题中键入的内容 字段或案例创建表单的描述。是文章或讨论偏转项的 ID。sourcedestination

是 JavaScript 对象键值映射。 以下属性用于此类信号。payload

Payload 属性类型描述支持的值必填
deflectionAnswer字符串用户对第一个问题的回答,询问偏转项目是否 有益的。YESNOnull– 用户未投票
confirmationAnswer字符串用户对第二个问题的回答,询问他们是否希望停止 创建案例。YESNOnull– 用户未投票
state字符串弹出窗口在关闭之前最后处于的状态。MeasureDeflectionState– 用户 没有回答第一个问题ConfirmationQuestionState– 用户 没有回答第二个问题ConfirmationMessageState– 用户 回答了两个问题
caseCreated布尔指示用户是否创建了案例。true– 用户创建了案例false– 用户未创建 箱

例子

自定义 Aura 组件可以侦听此系统事件并根据需要进行处理。为 例如,如果用户发现内容没有帮助,则该组件可以启动另一个组件 过程。

下面是一个侦听系统事件的示例组件。

<aura:component implements="forceCommunity:availableForAllPageTypes">
    <aura:attribute name="message" type="String" required="false"/>
    <aura:handler event="lightningcommunity:deflectionSignal" action="{!c.handleSignal}"/>
    <lightning:formattedText value="{!v.message}"/>
</aura:component>

此客户端控制器示例处理系统事件并检查失败情况 挠度。也就是说,控制器会检查用户未找到 偏转项目很有帮助。

({
    handleSignal: function(component, event, helper) {
        var signal = event.getParams() || {},
            sourceType = signal.sourceType,
            payload = signal.payload;
        // Process case create deflection signals
        if (sourceType && sourceType === "caseCreateDeflectionModal") {
            if (payload && payload.deflectionAnswer === "NO") {
                component.set("v.message", "Sorry you didn't find that helpful.");
            }
            if (payload && payload.caseCreated === true) {
                component.set("v.message", "We Apologize For The Inconvenience. We'll get in touch with you shortly about your case.");
            }
        }
    }
})

自定义 Aura 组件充当外壳创建表单,外壳偏转组件可以 同时触发此事件。给定有效参数,将自动处理该事件,并 为报告而处理。此示例使用组件中的值触发一个事件 属性。lightningcommunity:deflectionSignal

fireCaseDeflectionSignal : function(component, shouldSubmitSourceTypeSignals) {
    var evt = $A.get("e.lightningcommunity:deflectionSignal");
    evt.setParams({
        sourceType: "caseCreateDeflectionModal",
        source: cmp.get("v.deflectionTerm"),
        destinationType: component.get("v.deflectionEntityType"),
        destination: component.get("v.deflectionEntityId"),
        payload: {
            deflectionAnswer: component.get("v.deflectionAnswer"),
            confirmationAnswer: component.get("v.confirmationAnswer"),
            state: component.get("v.deflectionState"),
            caseCreated: component.get("v.caseCreated")
        },
        shouldSubmitSourceTypeSignals: shouldSubmitSourceTypeSignals
    });
    evt.fire();
}

用户可以连续查看多个偏转项目,然后最终决定是否 创建或放弃案例。每个视图都会触发一个事件。如果要处理所有事件 作为单个批处理,设置为用户在其中的最终事件 放弃或创建案例。此示例根据 案例是否已创建。lightningcommunity:deflectionSignalshouldSubmitSourceTypeSignals=true

fireCaseCreatedSignal : function(component, caseCreated) {
    // Send all accumulated signals to the server to be processed
    var evt = $A.get("e.lightningcommunity:deflectionSignal");
    evt.setParams({
        sourceType: "caseCreateDeflectionModal",
        payload: {
            caseCreated: caseCreated
        },
        shouldSubmitSourceTypeSignals: true
    });
    evt.fire();
}

开发安全站点:经过身份验证的用户和来宾用户

实施可通过外部和未经身份验证访问的 Experience Cloud 站点时 来宾用户,请牢记这些安全注意事项。外部用户具有登录权限 您的 Experience Cloud 站点,但他们无法访问您的内部 Salesforce 组织。来宾用户是 互联网上任何可以访问您的可公开访问的页面和组件的人 Experience Cloud 站点。

  • 限制声明性访问
    授予查看对象的权限允许外部用户使用标准控制器查看该对象。启用了 Lightning 功能的 Experience Builder 站点和 Salesforce 选项卡 + Visualforce 站点中提供了标准控制器。这些控制器仅根据平台声明性权限授予访问权限。
  • 确定安全模型 对于每个用例,确定是实现自定义访问控制模型还是依赖声明性平台访问控制模型
    。建议尽可能使用平台声明性访问控制模型。但是,有时您的要求需要自定义访问控制模型。
  • 限制对 Apex 类的访问 仅允许来宾和外部用户访问他们必须调用的那些类
  • 安全性
    如果来宾或外部用户必须运行流,请覆盖流权限以仅授予对特定外部用户配置文件、权限集或站点来宾用户配置文件的访问权限,而不是允许用户运行所有流。尽可能避免在系统上下文中运行流,并限制对子流的访问。否则,请确保对这些流和子流实施过程访问控制。
  • SOQL 注入:
    清理传递到动态 SOQL 查询的用户控制数据。

限制声明性访问

授予查看对象的权限允许外部用户使用 标准控制器。Experience Builder 站点中提供了标准控制器,并且 启用了 Lightning 功能的 Salesforce 选项卡 + Visualforce 站点。这些控制器 仅基于平台声明性权限授予访问权限。

授予声明性访问权限,以仅创建、查看、修改或删除其 允许外部用户通过控制器进行访问,而无需中介。Salesforce的 平台包括可用于创建、读取、更新或删除的标准控制器 数据。标准 UI 控制器强制执行 平台的共享规则,在创建、读取、更新和删除 (CRUD) 权限中,以及 字段级安全性 (FLS)。如果向外部用户授予查看或更新 对象,他们能够执行操作。不要向任何对象授予过多的权限 如果您不希望行使这些权限。

未经身份验证的访客用户准则

请考虑以下有关记录 ID 加密和提供不同级别的准则 在选择声明性或自定义访问权限之前,对未经身份验证的来宾用户进行访问 控制模型。

  • 加密来宾用户
    的记录 ID 出于安全原因,除非您希望记录是公开的,否则不允许来宾用户按记录 ID 查找记录。当前宾用户创建记录并希望稍后访问该记录时,请创建一个加密字符串,该字符串使用记录 ID、记录创建时间戳和当前时间戳的组合。加密的字符串充当记录的唯一标识符,只有记录创建者才拥有。稍后,处理请求的 Apex 代码要求来宾用户提交加密字符串。该 Apex 代码解密字符串以获取记录 ID 和其他记录标识符,并检索或更新请求的记录。
  • 授予来宾用户读取记录的访问权限 当允许来宾用户访问读取记录
    数据时,将向公众公开数据。查看我们的指南,并设计实现,以允许来宾用户进行必要的访问,而不会影响你的数据。
  • 授予来宾用户创建记录的访问权限 因此,来宾用户可以创建对象记录
    ,请配置来宾用户配置文件以包括对所需对象的创建访问权限。
  • 授予来宾用户访问更新记录的权限 若要允许来宾用户更新记录
    ,请在系统上下文中执行操作,而不进行共享。在允许用户更新记录之前,最好验证以前提供给用户的加密令牌。若要确保记录正确无误,请验证有关记录的信息,例如其创建者。

加密来宾用户的记录 ID

出于安全原因,不允许来宾用户按记录 ID 查找记录,除非你 希望记录是公开的。当前宾用户创建记录并希望稍后访问该记录时, 创建一个加密字符串,该字符串使用记录 ID、记录创建时间戳、 和当前时间戳。加密字符串充当记录的唯一标识符 只有记录创建者有。稍后,处理请求的 Apex 代码需要 要提交加密字符串的来宾用户。该 Apex 代码解密字符串以获取 记录 ID 和其他记录标识符,并检索或更新请求的 记录。

提示

用户加密解密 AppExchange 包 提供类,该类使用 Apex 库进行加密和 解密,为您存储相关数据,并提供两个模板流。使用托管 package 来实现自定义的记录 ID 加密,或创建类似的 你自己的。UserCryptoHelperSystem.Crypto

授予来宾用户对读取记录的访问权限

当您允许来宾用户访问读取记录数据时,会将您的数据公开给 公共。查看我们的指南,并设计您的实施,以允许对 来宾用户,而不会损害您的数据。

警告

Summer ’20 版本添加了新的设置并更新了访客用户记录访问指南。截至 21 年冬季,将执行 20 年夏季更新中引入的准则。之后 Winter ’21 release,请使用本文档中描述的方法之一,因为之前的方法 方法不再起作用。

每次来宾用户请求读取记录数据时,响应都会在以下模式下运行 确定共享规则是否适用于请求。因为模式具有不同的安全性 顾及以下问题,请考虑数据的敏感性,以确定最适合您的方法 业务需求。您还可以使用单独的流或多个 Apex 类来运行某些请求 在一种模式下,其他请求在另一种模式下。

如何处理敏感信息

在将数据返回给未经身份验证的人之前,从记录中删除所有敏感信息 用户。出于安全原因,请勿使用记录 ID 等可猜测信息进行检索 包含敏感信息的记录。

与共享

与共享一起运行的记录请求无法访问记录,除非共享规则提供 来宾用户对它们的访问权限。如果出现以下情况,请考虑共享只读访问规则 是真的:

  • 您希望公开记录并可供任何人访问。
  • 可以使用共享规则选择目标记录,而不会公开其他记录 记录。

无共享

警告

在不共享的情况下实现请求时,请设计请求和 仔细响应数据,以确保不会无意中暴露组织的敏感数据 数据。

在系统模式下运行而不共享的记录请求执行操作 系统级访问并绕过共享规则。如果你不小心它的行为 执行以及如何执行它们,请求可以在运行时公开或修改记录数据 没有共享。在不共享的情况下运行的查询会将所有选定的记录公开给 公共。如果以下任一情况为真,请考虑不共享的系统模式:

  • 来宾用户需要的不仅仅是对记录的只读访问权限。
  • 您不希望记录是公开的。
  • 如果不公开其他记录,则无法选择记录。
  • 目标记录是父子关系和对子项的访问的一部分 记录受父记录的写入访问权限的限制。因为共享规则不能 向来宾用户授予写入访问权限,在此方案中运行请求而不共享。

用于记录选择的加密记录 ID

如果来宾用户创建了一条记录,并且以后必须访问该记录,请使用 记录创建时间戳,并将加密后的字符串返回给客户端。为客人提供 用户具有包含加密字符串的 URL,以便他们可以避免键入长字符串。 当他们请求对记录的读取访问权限时,请从 URL 中检索加密的字符串。自 选择记录,使用解密的记录 ID。

闪电组件

直接与对象字段链接的 Lightning 组件会自动执行 对象创建、读取、更新和删除 (CRUD) 权限和字段级安全性 (FLS) 检查以确定组件是否为用户显示。对于您不这样做的记录 与来宾用户共享时,CRUD 和 FLS 检查将失败,并且组件不会显示。自 使用 Lightning 组件显示这些记录,将其值设置为变量,以及 在 Apex 代码中将这些变量与对象的字段单独关联。由于此方法适用于自动 CRUD 和 FLS 检查,因此请实现 Lightning 组件遵循以下准则:

  • 在查询中,仅包含所需的记录字段。
  • 不要将敏感字段传递给客户端代码。
  • 仅将客户端所需的字段传递给客户端。发送到客户端的所有数据 是公开的。

代码示例

  • 共享示例代码:向来宾用户授予读取记录的访问权限
  • 不共享的示例代码:授予来宾用户在同一事务中创建和读取记录的权限
  • 不共享的示例代码:授予来宾用户创建记录并在以后读取记录的权限

流样

  • 共享示例流:为来宾用户提供读取记录的访问权限
  • 不共享的示例流:授予来宾用户在一个流中创建和读取记录的权限

另见

  • Salesforce 帮助:保护访客用户的共享设置和记录 访问
  • Salesforce 帮助:共享规则
  • Salesforce 安全指南:共享规则

授予来宾用户创建记录的权限

因此,来宾用户可以创建对象记录,配置来宾用户配置文件以包括 为所需对象创建访问权限。要授予对对象的创建访问权限,必须授予对对象的读取访问权限。如果读取 不需要对该对象进行访问权限,我们建议删除该对象的所有权限,并且 在不共享控制器中运行创建逻辑。

提示

执行数据 对来宾创建的数据进行验证,以确保它不会影响自动化 过程。

记录 ID 和来宾用户

创建记录后,不要在对客户端的响应中包含记录 ID。创建 供以后访问的唯一记录标识符,在创建记录时对记录 ID 进行加密 时间戳,并将加密的字符串返回给客户端。

检索记录时,记录 ID 会自动包含在对象中。删除 对象的记录 ID,不要将其传递给客户端。

在 Apex 方法中创建和访问记录

来宾用户共享规则在事务完成后生效。如果 Apex 代码 共享创建并请求新创建的记录,而来宾用户依赖于 共享规则 若要访问记录,则读取请求失败,因为来宾共享规则 尚未生效。允许来宾用户创建记录并读取新创建的记录 记录,用关键字定义类。without sharing

Flow 中的记录创建和访问

在流程中,“创建记录”元素不会创建记录,直到面试执行 Screen、Local Action 或 Pause 元素。要在同一流中创建和读取相同的记录, 在记录创建和检索之间插入一个屏幕,或在 Apex 操作中读取记录。

样品

  • 示例流:授予来宾用户创建记录的访问权限
  • 不共享的示例流:授予来宾用户在一个流中创建和读取记录的权限
  • 不共享的示例代码:授予来宾用户在同一事务中创建和读取记录的权限

另见

  • Salesforce 帮助:配置访客用户配置文件
  • 加密来宾用户的记录 ID

授予来宾用户访问更新记录的权限

若要允许来宾用户更新记录,请在系统上下文中执行操作,而无需 共享。在允许用户更新记录之前,请先验证加密令牌 作为最佳实践提供给用户。为确保其记录正确无误,请验证 有关记录的信息,例如其创建者。

警告

Summer ’20 版本添加了新的设置并更新了访客用户记录访问指南。截至 21 年冬季,将执行 20 年夏季更新中引入的准则。之后 21 年冬季版本,必须使用无共享模式,因为无法使用共享规则 授予来宾用户对记录的更新访问权限。

Lightning 组件和访客用户

直接与对象字段链接的 Lightning 组件会自动执行 对象权限和字段级安全性 (FLS) 检查以确定组件是否 为用户显示。如果启用了“保护来宾用户记录访问”设置,则无法授予来宾用户更新记录的访问权限。在这种情况下, 需要更新权限的对象权限检查失败,组件不会 显示。要使用 Lightning 组件处理访客用户输入,请使用变量来设置 闪电组件。然后将这些变量与记录的字段分别关联 在 Apex 代码中。因为此方法适用于自动对象权限和 FLS 检查,请按照以下准则实施您的 Lightning 组件:

  • 使用服务器端代码检索记录并验证它是否是所需的记录 在执行更新之前进行更新。
  • 不要将记录字段传递给客户端,除非您希望将其显示给用户。 您发送给客户端的任何数据都是公开的。
  • 不要将记录 ID 传递给客户端。不接受来自客户端的记录 ID。自 为记录创建唯一标识符,将记录 ID 加密为字符串。
  • 使用服务器端逻辑将更新限制为仅对所需字段进行更新。请勿使用 用于确定服务器端行为的客户端代码。
  • 使用服务器端逻辑验证来自客户端的数据,然后代码执行 更新。

声明式访问控制模型示例

这些代码和流示例使用声明性访问控制模型来提供 未经身份验证的来宾用户访问读取记录。

  • 共享示例流:授予来宾用户读取记录
    的访问权限 在此示例流中,来宾用户输入日期范围,然后查看该范围内的事件。来宾用户具有对具有共享规则的记录的读取访问权限,因此来宾用户配置文件确定流可以访问哪些字段。
  • 共享示例代码:授予来宾用户读取记录
    的访问权限 在此代码示例集合中,来宾用户输入日期范围,然后查看该范围内的事件。来宾用户通过共享规则对记录具有读取访问权限。

共享示例流:为来宾用户提供读取记录的访问权限

在此示例流中,来宾用户输入日期范围,然后查看该日期范围内的事件 范围。来宾用户具有对具有共享规则的记录的读取访问权限,因此来宾用户 配置文件确定流可以访问哪些字段。

Important

在向来宾用户授予读取访问权限之前,请参阅授予 来宾用户访问读取记录。

流配置

由于来宾用户可以通过共享规则访问记录,因此请将“如何”设置为“如何” 将“流”设置运行到“用户”或“系统上下文”(Based on Flow 是如何启动的。

输入日期范围 (1)

流程中的第一个元素是显示开始日期和结束日期输入字段的屏幕。 该元素将输入日期保存在变量和 中。Start_DateEnd_Date

获取活动 (2)

下一个元素是“获取记录”查询,该查询选择符合以下条件的事件:

  • 事件大于变量。StartDateTimeStart_Date
  • 事件小于变量。EndDateTimeEnd_Date
  • 事件的值为 。isPrivateFalse
  • 事件的值为 。isArchivedFalse

该元素将所选事件保存在变量中。GetEvents

循环唱片 (3)

Loop 元素循环遍历变量中的每个事件。GetEvents

在循环中,Assignment 元素将每个事件的 、 、 和 附加到 一个字符串。StartDateTimeEndDateTimeSubjectLocation

展会活动 (4)

最后一个元素是显示包含所有事件的字符串的屏幕。

共享示例代码:向来宾用户授予读取记录的访问权限

在此代码示例集合中,来宾用户输入日期范围,然后查看 该范围内的事件。来宾用户通过共享对记录具有读取访问权限 规则。

重要

在向来宾用户授予读取访问权限之前,请参阅向来宾用户授予读取记录的访问权限。

Aura 组件:DisplayEvents.cmp

此示例 Aura 组件显示两个组件,用户在其中输入开始日期和结束日期 以查看事件。组件 显示每个事件的 、 、 和 。lightning:inputlightning:cardStartDateTimeEndDateTimeSubjectLocation

<aura:component controller="GuestUserEventsAuraController">

    <aura:attribute name="events" type="Event[]"/>
    <aura:attribute name="StartDate" type="String" default=""/>
    <aura:attribute name="EndDate" type="String" default=""/>

    <lightning:input type="datetime" name="StartDate" value="{!v.StartDate}" aura:id="StartDate" label="Start after: " required="true"/>
    <lightning:input type="datetime" name="EndDate" value="{!v.EndDate}" aura:id="EndDate" label="End before: " required="true"/>
    <lightning:button name="Submit" variant="brand" label="Find events" title="Find events" onclick="{!c.handleSearch}"/>
    
    <lightning:card title="Events">
        <p class="slds-p-horizontal--small">
            <aura:iteration items="{!v.events}" var="event">
                {!event.Subject} ({!event.Location}) starts at {!event.StartDateTime} and ends at {!event.EndDateTime} <br/>
            </aura:iteration>
        </p>
    </lightning:card>
</aura:component>

组件控制器:DisplayEventsController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    handleSearch : function(component, event, helper) {
        helper.doSearch(component, event, helper);
    }
})

JavaScript 帮助程序:DisplayEventsHelper.js

此 JavaScript 帮助程序创建一个异步请求来查找两者中的事件 用户提交的时间戳,并定义请求时要执行的操作 完成。

({
        doSearch : function(component, event, helper) {
            var start_date = component.find("StartDate").get("v.value");
            var end_date = component.find("EndDate").get("v.value");
            var action = component.get("c.searchEvents");
            action.setParams({
                "start_date": start_date,
                "end_date": end_date
            });
            action.setCallback(this, function(response){
                component.set("v.events", response.getReturnValue());
            });
            $A.enqueueAction(action);
        }
})

Apex 控制器:GuestUserEventsAuraController.cls

此示例 Apex 控制器接收从 JavaScript 查找记录的调用 助手。它选择符合以下条件的事件:

  • 事件更大 比参数。StartDateTimeStart_Date
  • 事件小于 参数。EndDateTimeEnd_Date
  • 事件的值为 。isPrivateFalse
  • 事件的值为 。isArchivedFalse

查询为每个事件返回以下字段:

  • StartDateTime
  • EndDateTime
  • Location
  • Subject
  • Id

由于来宾用户不需要记录 ID,因此循环会将所有其他字段复制到新的 Event 对象。然后,我们 将新对象添加到新列表,并将该列表返回给客户端。for

来宾用户有权访问具有共享规则的记录,因此我们定义了类 替换为关键字。with sharing

警告

Internet 上的任何系统或个人都可以调用方法。保护 方法。确保查询选择 仅所需的记录和必填字段。@AuraEnabled

public with sharing class GuestUserEventsAuraController {
	
    @AuraEnabled
    public static List<Event> searchEvents(Datetime start_date, Datetime end_date){
        List<Event> results = [SELECT Event.Subject,
                                  Event.StartDateTime,
                                  Event.EndDateTime,
                                  Event.Location
                FROM Event 
                WHERE Event.EndDateTime<:end_date AND 
                      Event.StartDateTime>:start_date AND 
                      Event.isPrivate=False AND 
                      Event.isArchived=False];

        List<Event> filtered_events = new List<Event>();
        for (Event event : results) {
            Event new_event = new Event(Subject = event.Subject, 
                                                              StartDateTime = event.StartDateTime, 
                                                              EndDateTime = event.EndDateTime,
                                                              Location = event.Location);
            filtered_events.add(new_event);
        }
        return filtered_events;
    }
}

自定义访问控制模型示例

这些代码和流示例使用自定义访问控制模型来提供 未经身份验证的来宾用户访问以创建记录。

  • 不共享的示例代码:授予来宾用户创建记录并在以后
    读取记录的权限 这些代码示例支持两个单独的交互。在第一次交互中,来宾用户创建一个案例。为了允许将来访问,Apex 方法将记录 ID 替换为加密字符串。当前宾用户稍后想要读取案例时,他们会输入加密的字符串。Apex 方法解密字符串并使用它来检索大小写。
  • 示例流:授予来宾用户创建记录的访问权限 在此示例流中,来宾用户输入反馈,流将其存储在自定义对象记录
    中。来宾用户在创建后无权读取记录。
  • 不共享的示例代码:授予来宾用户在同一事务
    中创建和读取记录的权限 在此代码示例集合中,来宾用户输入详细信息以报告支持问题,Apex 代码创建案例。Apex 方法检索新记录,Aura 组件在创建后向来宾用户显示部分记录。Apex 代码在不共享的情况下运行,因为我们不依赖对象权限和平台共享来允许来宾用户访问记录。
  • 不共享的示例流:授予来宾用户在一个流中创建和读取记录的权限 在此示例流中,来宾用户输入详细信息以报告支持问题,然后流
    创建案例。来宾用户创建记录后,默认活动用户将成为记录的所有者,并且来宾用户无法直接访问该记录。然后,流检索新案例以获取案例和字段,并将这些字段显示给来宾用户。由于来宾用户在创建记录后不拥有该记录,并且流必须检索该记录,因此该流在不共享的情况下运行。CaseNumberStatus
  • 不共享的示例代码:授予来宾用户创建记录并在以后
    更新记录的权限 这些代码示例支持两个单独的交互。在第一次交互中,来宾用户创建一个案例。出于安全原因,Apex 方法将记录 ID 替换为加密字符串。当来宾用户想要稍后关闭案例时,他们会输入该加密字符串。Apex 方法解密字符串以获取记录 ID,使用记录 ID 选择案例,并更新案例的状态。

不共享的示例代码:授予来宾用户创建记录和读取记录的权限 后

这些代码示例支持两个单独的交互。在第一次互动中,客人 用户创建案例。为了允许将来访问,Apex 方法将记录 ID 替换为 加密的字符串。当来宾用户稍后想要阅读案例时,他们会输入 加密字符串。Apex 方法解密字符串并使用它来检索大小写。

Aura 组件:CreateCase.cmp

此示例 Aura 组件显示来宾用户可以输入的多个组件 有关新案例或现有案例中的令牌的详细信息。创建记录后,组件将显示新的 案例的加密令牌或与令牌匹配的案例的状态。lightning:card

出于演示目的,此示例使用来宾用户可以在其中输入的字段 他们案件的令牌。若要实现此方案,请为来宾用户提供链接 包含令牌,并从 URL 中检索令牌。

<aura:component controller="GuestUserCreateForLater">
    <aura:attribute name="caseID" type="String"/>
    <aura:attribute name="case_status" type="String"/>
    <aura:attribute name="subject" type="String"/>
    <aura:attribute name="description" type="String"/>
    <aura:attribute name="email" type="String"/>

     Enter details to create a new case
    <lightning:input type="email" name="email" required="true" value="{!v.email}" aura:id="email" label="Where should we send email updates?"/>
    <lightning:input name="subject" label="Subject" required="true" value="{!v.subject}" aura:id="subject"/>
    <lightning:textarea name="description" required="true" label="Description" value="{!v.description}" aura:id="description"/>
    <lightning:button name="submit" variant="brand" label="Create case" title="Create case" onclick="{!c.submitCase}"/>
        
    <aura:if isTrue="{!v.caseID}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                New case created:
                <p>{!v.caseID}</p>
            </p>
        </lightning:card>
    </aura:if>

    Or enter an existing case token to view the status of the case
    <lightning:textarea name="existing_case" required="false" label="Existing case token" aura:id="existing_case"/>
	<lightning:button name="submit" variant="brand" label="Lookup case" title="Lookup case" onclick="{!c.lookupCase}"/>
    <aura:if isTrue="{!v.case_status}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                Case status: 
                <p>{!v.case_status}</p>
            </p>
        </lightning:card>
    </aura:if>
</aura:component>

组件控制器:CreateCaseController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    submitCase : function(component, event, helper) {
        helper.makeCase(component, event, helper);
    }
    lookupCase : function(component,event,helper){
        helper.getCase(component,event,helper);
    }
})

JavaScript 帮助程序:DisplayCaseHelper.js

此 JavaScript 帮助程序有两种方法:makeCase()该方法创建一个 异步请求,以使用提交的数据创建案例。当 请求完成时,回调会将新案例的唯一令牌存储在 使用的变量中的字段 由 Aura 组件提供。makeCase()caseIDgetCase()该方法使用令牌 由来宾用户输入,以异步检索匹配的案例 令牌。该方法的回调捕获来自 Apex 的响应 方法并将值存储在变量中。getCase()case_status

({
    makeCase : function(component, event, helper) {
        var subject = component.find("subject").get("v.value");
        var description = component.find("description").get("v.value");
        var email = component.find("email").get("v.value");

        var action = component.get("c.CreateCase");
        action.setParams({
            "subject": subject,
            "description": description,
            "email": email
        });
        action.setCallback(this, function(response){
            component.set("v.caseID", response.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    getCase : function(component,event,helper){
        var case_token = component.find("existing_case").get("v.value");
        var action = component.get("c.GetCase");
        action.setParams({
            "token":case_token
        });
        action.setCallback(this, function(response){
            component.set("v.case_status", response.getReturnValue());
        });
        $A.enqueueAction(action);
    }
})

Apex 控制器:GuestUserCreateForLater.cls

此示例 Apex 控制器接收用于创建和检索案例的调用。它使用用户加密解密 AppExchange 包来加密和解密数据。CreateCase()Apex 方法创建一个 大小写与来宾用户的输入。创建记录后,它会生成一个 来自记录 ID、记录字段和当前记录的加密字符串 时间戳。Apex 方法返回加密的字符串。CreateCase()CreatedDateGetCase()该方法解密 提供的字符串,验证结果,并传递解密的记录 ID 并为帮助程序方法创建时间戳以检索原始记录。 响应是记录的状态。GetCase()

使用关键字定义类,因为我们不依赖于对象权限和平台共享 创建和访问记录。without sharing

警告

Internet 上的任何系统或个人都可以调用方法。确保查询可以 仅检索新创建的记录,并仅选择必填字段。@AuraEnabled

public class without sharing GuestUserCreateForLater {
    
    @AuraEnabled
    public static String CreateCase(String subject, 
                                         String description, 
                                         String email){
		Case new_case = new Case(Subject=subject, 
                                 Description=description,
                                 SuppliedEmail=email);
        insert new_case;
        
        List<Case> results = getCase(new_case.Id);


        String encryptedID = ued.UserCryptoHelper.doEncrypt(results[0].Id+'|'+ results[0].CreatedDate.getTime() +'|'+System.DateTime.now().getTime());
        return encryptedID;
    }
    
    public static final Long validTimestampMinutes = 10;

    @AuraEnabled
    public static String GetCase(String token){
        String status = 'Case not found';
        String decrypted_token = '';
        try {
            decrypted_token = ued.UserCryptoHelper.doDecrypt(token);
        } catch(Exception e) {
            return status;
        }
        
        String[] decrypted_parts = decrypted_token.split('\\|');
        String decryptedRecordId = decrypted_parts[0];
        String created_timestamp = decrypted_parts[1];
        String original_request_timestamp = decrypted_parts[2];

        
        
        if( isTimestampValid(System.Long.valueOf(original_request_timestamp)) ){
        	List<Case> caseList = getCase(decryptedRecordId, created_timestamp);
        	if(caseList.size() == 1){
    	        status = caseList[0].Status;
	    	}else{
                status = 'Case not found';
        	}
    	}
        return status;

    }

    private static List<Case> getCase(String caseID, Datetime created_date)
    {
        List<Case> results = [SELECT Case.CaseNumber, Case.CreatedDate, Case.Status  
        FROM Case 
        WHERE Case.Id=:caseID AND Case.CreatedDate=:created_date];
        return results;
    }

    private static Boolean isTimestampValid(Long timestamp)
    {
        return ((System.now().getTime() - timestamp) / 60000) < validTimestampMinutes;
    }
}

注意

如果要加载高度敏感的信息,请考虑以下附加信息之一 提高安全性的措施。

  • 要求用户输入与以下数据相关的其他信息 他们试图阅读或修改,只有他们自己知道。
  • 要求用户登录才能读取或修改数据。

示例流:授予来宾用户创建记录的访问权限

在此示例流中,来宾用户输入反馈,流将其存储在自定义流中 对象记录。来宾用户在创建后无权读取记录。

重要

在向来宾用户授予记录创建访问权限之前,请阅读向来宾用户授予创建记录的访问权限。

自定义Feedback__c对象

此方案使用 Feedback__c 自定义对象来存储来自来宾用户的反馈。一个 Feedback__c自定义对象都包含以下字段,按字母顺序列出:Email__c必填。来宾用户的电子邮件地址。数据类型: 电子邮件Score__c必填。来宾用户输入的反馈分数。可能的值为 、 、 、 、 、 。012345Additional_comments__c来宾用户输入的任何其他反馈。数据类型:长文本区域

流配置

因为流不需要对任何记录的读取访问权限,并且我们不依赖于对象 权限,将“如何运行流”设置设置为“系统” 无共享上下文 – 访问所有数据

意见反馈表 (1)

流中的第一个元素是显示以下组件的屏幕:

  • 用户电子邮件地址的电子邮件组件。
  • 用户反馈分数的 Slider 组件,设置为允许从 0 到 5.
  • 用于任何其他注释的长文本区域组件。

创建记录 (2)

下一个元素是创建Feedback__c记录的 Create Records 元素。

片尾画面 (3)

最后一个屏幕元素显示文本,以感谢用户的反馈。

不共享的示例代码:授予来宾用户在其中创建和读取记录的权限 交易

在此代码示例集合中,来宾用户输入详细信息以报告支持 问题和 Apex 代码创建一个案例。Apex 方法检索新记录和 Aura 组件在创建后向来宾用户显示部分记录。Apex 代码运行 没有共享,因为我们不依赖对象权限和平台共享来 允许来宾用户访问记录。

Aura 组件:CreateCase.cmp

此示例 Aura 组件显示用户在其中输入详细信息的多个组件 关于案件。创建后,该组件将显示新案例的案例编号和 地位。lightning:card

<aura:component controller="GuestUserCreateCase">

    <aura:attribute name="caseNumber" type="String"/>
    <aura:attribute name="status" type="String"/>
    <aura:attribute name="subject" type="String" default=""/>
    <aura:attribute name="description" type="String" default=""/>
    <aura:attribute name="email" type="String" default=""/>
    <aura:attribute name="name" type="String" default=""/>
    <aura:attribute name="reason" type="String"/>    
    <aura:attribute name="type" type="String" default=""/>

    <lightning:select name="select" label="Reason" required="true" value="{!v.reason}"  aura:id="reason">
        <option value="installation">Installation</option>
        <option value="equipmentcomplexity">Equipment Complexity</option>
        <option value="performance">Performance</option>
        <option value="breakdown">Breakdown</option>
        <option value="equipmentdesign">Equipment Design</option>
        <option value="feedback">Feedback</option>
        <option value="other">Other</option>
    </lightning:select>
    
    <lightning:select name="type" label="Type" required="true" value="{!v.type}"  aura:id="type">
        <option value="mechanical">Mechanical</option>
        <option value="electrical">Electrical</option>
        <option value="electronic">Electronic</option>
        <option value="structural">Structural</option>
        <option value="other">Other</option>
    </lightning:select>
    
    <lightning:input type="email" name="email" required="true" value="{!v.email}" aura:id="email" label="Where should we send email updates?"/>
    <lightning:input name="name" label="Name" required="true" value="{!v.name}" aura:id="name"/>
    
    
    <lightning:input name="subject" label="Subject" required="true" value="{!v.subject}" aura:id="subject"/>
    <lightning:textarea name="description" required="true" label="Description" value="{!v.description}" aura:id="description"/>
    
    <lightning:button name="submit" variant="brand" label="Submit case" title="Submit case" onclick="{!c.submitCase}"/>
    
    <aura:if isTrue="{!v.caseNumber}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                {!v.caseNumber} has status {!v.status}.
            </p>
        </lightning:card>
    </aura:if>
</aura:component>

组件控制器:CreateCaseController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    submitCase : function(component, event, helper) {
        helper.makeCase(component, event, helper);
    }
})

JavaScript 帮助程序:DisplayCaseHelper.js

此 JavaScript 帮助程序创建一个异步请求,以使用 提交的数据。请求完成后,回调会存储案例编号和 Aura 组件使用的变量中的案例状态。

({
        makeCase : function(component, event, helper) {
            var subject = component.get("v.subject");
            var description = component.get("v.description");
            var email = component.get("v.email");
            var name = component.get("v.name");
            var reason = component.get("v.reason");
            var type = component.get("v.type");

            
            var action = component.get("c.CreateCase");
            action.setParams({
                "subject": subject,
                "description": description,
                "email": email,
                "name": name,
                "reason": reason,
                "caseType": type
            });
            action.setCallback(this, function(response){
                component.set("v.caseNumber", response.getReturnValue()[0]);
                component.set("v.status", response.getReturnValue()[1]);
            });
            $A.enqueueAction(action);
        }
})

Apex 控制器:GuestUserCreateCase.apxc

此示例 Apex 控制器创建记录,检索新记录,然后返回 从新记录到客户端的必填字段。因为对象权限 并且不使用平台共享,此控制器在不共享的情况下运行。

为了避免意外暴露记录数据,该方法仅返回 和 字段。CreateCaseCaseNumberStatus

警告

Internet 上的任何系统或个人都可以调用类。确保方法 仅返回新记录中的必填字段。@AuraEnabled

public without sharing class GuestUserCreateCase {
    
    @AuraEnabled
    public static List<String> CreateCase(String subject, 
                                         String description, 
                                         String email,
                                         String name,
                                         String reason,
                                         String caseType,
                                         String phone){
		Case new_case = new Case(Subject=subject, 
                                 Description=description,
                                 SuppliedEmail=email,
                                 SuppliedName=name,
                                 Reason=reason,
                                 Type=caseType,
                                 SuppliedPhone=phone);
        insert new_case;
                                             
        List<Case> results = getCase(new_case.Id);

        List<String> response = new List<String>();
        response.add(results[0].CaseNumber);
        response.add(results[0].Status);
        return response;

    }

    private static List<Case> getCase(String caseID)
    {
        List<Case> results = [SELECT Case.CaseNumber, Case.CreatedDate 
        FROM Case 
        WHERE Case.Id=:caseID];
        return results;
    }

}

不共享的示例流:为来宾用户提供在一个中创建和读取记录的权限 流

在此示例流中,来宾用户输入详细信息以报告支持问题和流 创建案例。来宾用户创建记录后,默认活动用户将成为所有者 的记录,来宾用户无法直接访问它。然后,该流检索 New case 获取案例的 AND 字段,并将这些字段显示给来宾用户。 由于来宾用户在创建后不拥有该记录,并且流必须检索 记录时,流在不共享的情况下运行。

CaseNumberStatus

重要

在向来宾用户授予创建和读取访问权限之前,请先阅读授予来宾用户读取记录的访问权限和授予来宾用户创建记录的访问权限。

流配置

由于流会创建记录,然后在不共享的情况下检索该记录,因此请将“如何运行流”设置设置为“不使用系统上下文” 共享 – 访问所有数据

案例表格 (1)

流中的第一个元素是显示以下输入组件的屏幕:

  • 公司名称的文本组件
  • 提交者姓名的 Name 组件
  • 提交者电子邮件地址的电子邮件组件
  • 提交者电话号码的电话组件
  • 一个 Picklist 组件,其中包含记录类型字段中的选项值Type_Options
  • 一个 Picklist 组件,其中包含记录类型字段中的选项值Reason_Options
  • 案例主题的文本组件
  • 用于描述案例的长文本区域组件

作业 (2)

第二个元素将输入组件中的数据分配给新的记录变量。Case

创建记录 (3)

下一个元素是“创建记录”元素,该元素使用记录变量创建案例记录。除了信息 由访客用户输入,设置元素配置以定义案例的来源字段 如。CaseWeb

获取记录 (4)

“获取记录”元素通过其字段检索新记录,该字段由“创建记录”元素自动定义。这 检索到的记录存储在新记录中 变量。IdCase

片尾画面 (5)

最后一个屏幕元素显示 Get 中的 Case 和字段 Record 元素的记录变量。CaseNumberStatusCase

不共享的示例代码:授予来宾用户创建记录和更新记录的权限 后

这些代码示例支持两个单独的交互。在第一次互动中,客人 用户创建案例。出于安全原因,Apex 方法将记录 ID 替换为 加密字符串。当来宾用户想要稍后关闭案例时,他们会输入该案例 加密字符串。Apex 方法解密字符串以获取记录 ID,使用记录 ID 以选择案例,并更新案例的状态。

Aura 组件:CreateCase.cmp

此示例 Aura 组件显示用于创建和关闭记录的组件。

若要创建案例,来宾用户使用组件输入案例详细信息。记录后 创建时,组件显示 新案例的加密令牌或与令牌匹配的案例的状态。lightning:card

出于演示目的,此示例显示一个组件,其中来宾用户 直接输入案例的令牌。若要实现此方案,请提供来宾用户 替换为包含令牌的链接,然后从 URL 中检索令牌。

<aura:component controller="GuestUserCreateForLater">
    <aura:attribute name="caseID" type="String"/>
    <aura:attribute name="case_status" type="String"/>
    <aura:attribute name="subject" type="String"/>
    <aura:attribute name="description" type="String"/>
    <aura:attribute name="email" type="String"/>

     Enter details to create a new case
    <lightning:input type="email" name="email" required="true" value="{!v.email}" aura:id="email" label="Where should we send email updates?"/>
    <lightning:input name="subject" label="Subject" required="true" value="{!v.subject}" aura:id="subject"/>
    <lightning:textarea name="description" required="true" label="Description" value="{!v.description}" aura:id="description"/>
    <lightning:button name="submit" variant="brand" label="Create case" title="Create case" onclick="{!c.submitCase}"/>
        
    <aura:if isTrue="{!v.caseID}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                New case created:
                <p>{!v.caseID}</p>
            </p>
        </lightning:card>
    </aura:if>

    Or enter an existing case token to close the case
    <lightning:textarea name="existing_case" required="false" label="Existing case token" aura:id="existing_case"/>
	<lightning:button name="submit" variant="brand" label="Close case" title="Close case" onclick="{!c.updateCase}"/>
    <aura:if isTrue="{!v.case_status}">
        <lightning:card title="Case">
            <p class="slds-p-horizontal--small">
                Case status: 
                <p>{!v.case_status}</p>
            </p>
        </lightning:card>
    </aura:if>
</aura:component>

组件控制器:CreateCaseController.js

此示例 JavaScript 控制器处理 Aura 组件的事件并调用 帮助程序文件中的方法。

({
    submitCase : function(component, event, helper) {
        helper.makeCase(component, event, helper);
    },
    updateCase : function(component,event,helper){
        helper.updateCase(component,event,helper);
    }
})

JavaScript 帮助程序:CaseHelper.js

此 JavaScript 帮助程序有两种方法:makeCase()该方法创建一个 异步请求,以使用提交的数据创建案例。当 请求完成时,回调会将新案例的唯一令牌存储在 使用的变量中的字段 由 Aura 组件提供。makeCase()caseIDupdateCase()该方法使用 来宾用户输入的令牌,以异步更新大小写 匹配令牌。该方法的回调捕获来自 Apex 方法并将值存储在变量中。updateCase()case_status

({
    makeCase : function(component, event, helper) {
        var subject = component.find("subject").get("v.value");
        var description = component.find("description").get("v.value");
        var email = component.find("email").get("v.value");

        var action = component.get("c.CreateCase");
        action.setParams({
            "subject": subject,
            "description": description,
            "email": email
        });
        action.setCallback(this, function(response){
            component.set("v.caseID", response.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    updateCase : function(component,event,helper){
        var case_token = component.find("existing_case").get("v.value");
        var action = component.get("c.UpdateCase");
        action.setParams({
            "token":case_token
        });
        action.setCallback(this, function(response){
            component.set("v.case_status", response.getReturnValue());
        });
        $A.enqueueAction(action);
    }
})

Apex 控制器:GuestUserCreateForLater.cls

此示例 Apex 控制器接收用于创建和更新案例的调用。它使用用户加密解密 AppExchange 包来加密和解密数据。CreateCase()Apex 方法 使用来宾用户的输入创建案例。记录创建后,它 从记录 ID、记录字段和当前 时间戳。Apex 将新案例的 ID 替换为加密的 字符串。CreateCase()CreatedDateUpdateCase()该方法解密 提供的字符串,验证结果,并使用信息来 更新原始记录的状态。响应是 记录或错误消息(如果发生)。UpdateCase()

使用关键字定义类 因为它不直接访问记录。with sharing

警告

Internet 上的任何系统或个人都可以调用类。确保查询可以 仅更新正确的记录。@AuraEnabled

public with sharing class GuestUserCreateForLater {
    
    @AuraEnabled
    public static String CreateCase(String subject, 
                                         String description, 
                                         String email){
		Case new_case = new Case(Subject=subject, 
                                 Description=description,
                                 SuppliedEmail=email);
        insert new_case;
        
       List<Case> results = GuestUserCaseHelperWS.getCase(new_case.Id);


        String encryptedID = ued.UserCryptoHelper.doEncrypt(results[0].Id+'|'+ results[0].CreatedDate.getTime() +'|'+System.DateTime.now().getTime());
        return encryptedID;
    }
    
    public static final Long validTimestampMinutes = 10;

    @AuraEnabled
    public static String UpdateCase(String token){
        String status = 'Case not found';
        String decrypted_token = '';
        try {
            decrypted_token = ued.UserCryptoHelper.doDecrypt(token);
        } catch(Exception e) {
            return status;
        }
        String[] decrypted_parts = decrypted_token.split('\\|');
        String decryptedRecordId = decrypted_parts[0];
        String created_timestamp = decrypted_parts[1];
        String original_request_timestamp = decrypted_parts[2];


        if( isTimestampValid(System.Long.valueOf(original_request_timestamp))) {

        	List<Case> caseList = GuestUserCaseHelperWS.getCase(decryptedRecordId, created_timestamp);
            if(caseList.size() == 1){
    	       Case case_to_update = caseList[0];
                        case_to_update.Status = 'Closed';
                try {
                         GuestUserCaseHelperWS.updateCase(case_to_update);
                         status = 'Closed';
                } catch(DmlException e){
                         System.debug('An unexpected error has occurred: ' + e.getMessage());
                }
            }else{
                status = 'Case not found';
            }
        }
        return status;
    }

    private static Boolean isTimestampValid(Long timestamp)
    {
        return ((System.now().getTime() - timestamp) / 60000) < validTimestampMinutes;
    }
}

Apex 帮助程序类:GuestUserCaseHelperWS.apxc

此示例 Apex 帮助程序类定义按记录的 ID 和 更新记录。Apex 控制器调用此方法。

使用关键字定义类,以便它可以检索和更新记录,而无需共享。without sharing

public without sharing class GuestUserCaseHelperWS {

    public static List<Case> getCase(String caseID, Datetime created_date)
    {
        List<Case> results = [SELECT Case.CaseNumber, Case.CreatedDate, Case.Status  
        FROM Case 
        WHERE Case.Id=:caseIDAND Case.CreatedDate=:created_date];
        return results;
    }

    public static Case updateCase(Case case_to_update)
    {
        update case_to_update;
        return case_to_update;
    }
}

限制对 Apex 类的访问

仅允许来宾和外部用户访问他们必须访问的类 叫。

如果 Apex 类包含公开的方法,例如使用 、、 或 的方法,则来宾和外部用户可以调用这些方法 具有任意参数的方法。但是他们必须具有执行 Apex 类的权限。我们 建议将 Apex 类访问权限限制为具有特定权限集或配置文件的用户。 允许来宾和外部用户对 Apex 类的完全访问权限是不安全的。㥢 关于哪些用户必须调用哪些 Apex 类,为这些角色创建权限集,以及 为所需的权限集启用 Apex 类。@InvocableMethod@AuraEnabled@RestResourcewebservice

流量安全

如果来宾用户或外部用户必须运行流,请覆盖流权限以授予访问权限 仅适用于特定的外部用户配置文件、权限集或站点来宾用户配置文件,而不是 而不是允许用户运行所有流。尽可能避免在系统上下文中运行流,以及 限制对子流的访问。否则,请确保对 这些流和子流。

流是一项强大的功能,可以覆盖平台安全设置以访问 对象和 Apex 类。流可用于激活和停用权限集。还 屏幕流由浏览器使用用户控制的输入参数驱动。因此,我们 建议重写“运行流”权限以将访问权限分配给 基于来宾或外部用户配置文件或权限集的特定流。对于来宾用户, 在相应站点的来宾用户配置文件上配置流访问策略。

删除运行子流的权限也是一种很好的安全做法,即使用户运行 子流独立。从安全角度来看,最好创建两个单独的 流,并仅授予对用户直接运行的流的访问权限,而不授予对以 子流。仅向最高级别的父流授予流访问权限,而不向子流授予流访问权限。 同样的建议也适用于流调用的可调用的 Apex 方法。避免授予 用户对这些类的访问权限,因此调用这些方法仅限于 他们注定要被召唤。请注意,如果用户有权运行屏幕流,他们可以:

  • 随时使用他们选择的参数调用流。
  • 随时取消流。

这些注意事项也适用于子流或从其他流调用的流。具体而言,流用户可以:

  • 查看和修改屏幕流的输入(开始)变量。
  • 查看从屏幕子流返回到父流的输出变量。
  • 如果他们有权运行子流,请将输入变量修改为子流。

如果其中任何一项功能违反了您的安全策略,请不要使用子流。例如,如果 处理必须保密的账单信息或其他敏感信息 通过子流。将业务逻辑保留在主流中。

SOQL注射液

清理传递到动态 SOQL 查询的用户控制数据。当 Apex 代码将用户控制的数据插入到动态 SOQL 中时,会发生 SOQL 或 SOSL 注入 或 SOSL 查询,但未正确审查输入。有两种情况需要考虑:

  • 更改查询的整体结构
  • 更改查询参数的值

通过调用阻止调用方访问数据的 Apex 代码来控制这些方案 他们无权获得。考虑一下 法典:

@AuraEnabled
public static List<Account> getAccountName(string userId) {
  if (FeatureManagement.checkPermission('readAccount')) {
      string query='SELECT Name FROM Account WHERE Id=\''+ userId + '\'';
      return database.query(query);
  }
}

用户可能会获得对查询的控制权,并访问比他们更多的信息 有权。查询的返回值不会限制用户可以访问的信息。用户可以 提交字符串,例如 :

userId = '0035Y00003pPJiNQAW\' OR AnnualRevenue>100000.00 OR Name=\'a'
// 0035Y00003pPJiNQAW is any id to any object that is not an account

这 查询的返回值将列出年收入超过 100,000 美元的所有帐户, 这不是开发人员打算返回给调用方的内容。修复 SOQL 或 SOSL 注入需要适当的上下文编码。不适用于每个用户输入。而 根据字段在 SOQL 或 SOSL 查询中的显示位置清理字段。

String.escapeSingleQuotes

  • 对于 WHERE (SOQL)、ORDER BY (SOQL)、WITH (SOSL) 或 FIND (SOSL) 子句中的变量,请使用 绑定 变量:string query='SELECT Name FROM Account WHERE Id=:userId';
  • 对于字段和表名称,请调用字段的 。或强制执行 声明性策略,使用您自己的过程逻辑将字段或表名限制为 您的安全策略允许的内容。isAccessibledescribeResult
  • 对于带引号的字符串中的参数,请使用绑定变量。不要使用绑定变量或清理表名 和字段名称,或未出现在引号上下文中的任何参数。String.escapeSingleQuote
  • 对于其他基元类型,将用户输入转换为布尔值、整数、Id 或其他 基元(非字符串)类型。

请注意,WITH SECURITY_ENFORCED关键字不会清理 WHERE 子句,只会清理 WHERE 子句 SELECT 和 FROM 子句,因此它不是 SOQL 或 SOSL 注入攻击的清理程序。

自定义模板的主题布局

若要将自己的图章放在模板主题上并转换其外观,请构建自定义 主题布局组件。您可以自定义模板的结构布局,例如标题 和页脚,并覆盖其默认样式。

主题布局组件是模板的顶级布局 (1) 网站中的页面。主题布局组件通过以下方式组织并应用于您的页面 主题布局。主题布局组件包括通用页眉和页脚 (2),并且通常 包括导航、搜索和用户配置文件菜单。相比之下,内容布局 (3) 定义页面的内容区域。下图显示了两列内容 布局。

自定义主题布局如何工作?

要了解主题布局的工作原理,让我们看看体验中的内容 构建器透视图。在Experience Builder中,主题布局与主题布局组件相结合 让您精细控制网站中每个页面的外观和结构。您可以 自定义布局的页眉和页脚以匹配您公司的品牌和风格,配置 主题属性,或使用自定义搜索栏和用户配置文件菜单。然后,使用主题布局 将主题布局组件应用于单个页面并快速更改一个页面的布局 中心位置。主题布局对网站中共享相同主题布局的页面进行分类 元件。您可以将主题布局组件分配给任何现有主题布局。然后你 在页面的 性能。

例如,Customer Service 模板包括以下主题 布局和组件,但您可以创建自定义组件或将布局切换为 需要。

  • 默认将 Customer Service 主题布局应用于除登录名之外的所有页面 页面。
  • 登录管理器将登录正文布局主题布局组件应用于登录页面。

假设您为即将到来的春季广告系列创建了三个页面。使用该界面,您可以创建一个 开发者控制台中的自定义大标题主题布局。在“设置”|”主题区域中,您可以添加一个名为 Spring 的自定义主题布局来对广告系列进行分类 页面,然后将“大页眉布局”组件分配给它。forceCommunity:themeLayout

接下来,在每个页面的属性中应用 Spring 主题布局,这会立即 将“大页眉”布局应用于每个页面。选择覆盖默认主题 此页面的布局。(1) 显示主题布局。选择新布局 (2) 从可用的选项中。

一切看起来 玫瑰色直到副总裁 营销部门认为标题占用了太多空间。这很容易解决,因为你 无需更新每个页面的属性即可更改主题布局。取而代之的是,使用 在主题区域一键切换,即可将 Spring 切换到 Small Header 布局,并立即 更新所有三个页面。

现在,假设“小标题”布局包括两个自定义属性:蓝色 背景和小标志。您已启用这些属性并将其应用于所有广告系列 页面。但是,对于一个页面,您只想应用 Small Logo 属性。

在这种情况下,您可以创建一个名为 Spring B 的主题布局,分配 Small Header layout 组件,并启用 Small Logo。然后,将 Spring B 主题应用于 页。

不确定哪些页面与您的任何主题布局相关联?

只需单击并一目了然,您就可以看到有多少个页面以及与其中任何一个页面相关联 您的主题布局。从“设置”|”主题,单击任何主题布局行 (1) 的“分配的页面总数”。单击此按钮 value 打开与该主题布局关联的页面列表 (2)。

主题布局可以很容易地以不同的方式重用相同的主题布局组件,而 根据需要保持尽可能多的精细控制。

配置自定义主题布局组件

让我们看看如何在开发者控制台中创建自定义主题布局组件,以 转换 Customer Service 中页面的外观和整体结构 模板。

1. 将界面添加到您的主题布局 元件

主题布局组件必须实现界面才能显示在Experience Builder的“设置”|”主题面积。forceCommunity:themeLayout

在代码中显式声明,以确保主题布局包含内容布局。添加您希望页面内容显示的任何位置 在主题布局中。{!v.body}{!v.body}

在主题布局中添加声明为包含区域的属性,这些属性包含 页面的组件。您可以将组件添加到标记中的区域,也可以保留区域 打开供用户拖放组件。声明为标记并包含在标记中的属性呈现为 在主题布局中打开用户可以向其添加组件的区域。为 例:Aura.Component[]Aura.Component[]

<aura:component implements="forceCommunity:themeLayout">
<aura:attribute name="myRegion" type="Aura.Component[]"/>

{!v.body}

</aura:component>

在 Customer Service 中,模板标题包括 这些锁定区域。

  • search,其中包含搜索发布服务器 元件
  • profileMenu,其中包含配置文件标头 元件
  • navBar,其中包含导航菜单 元件

创建重用模板中现有组件的自定义主题布局 标头区域,根据需要声明 、 或作为属性名称值。为 例:

searchprofileMenunavBar

<aura:attribute name="navBar" type="Aura.Component[]" required="false" />

提示

如果创建可交换的自定义配置文件菜单或搜索 组件,声明 or 属性名称值还允许用户选择 在Experience Builder中使用主题布局时的自定义组件。searchprofileMenu

将区域添加到标记 以定义在主题布局正文中显示它们的位置。下面是 一个简单的主题 布局。

<aura:component implements="forceCommunity:themeLayout" access="global" description="Sample Custom Theme Layout">
    <aura:attribute name="search" type="Aura.Component[]" required="false"/>
    <aura:attribute name="profileMenu" type="Aura.Component[]" required="false"/>
    <aura:attribute name="navBar" type="Aura.Component[]" required="false"/>
    <aura:attribute name="newHeader" type="Aura.Component[]" required="false"/>
    <div>
        <div class="searchRegion">
            {!v.search}
        </div>
        <div class="profileMenuRegion">
            {!v.profileMenu}
        </div>
        <div class="navigation">
            {!v.navBar}
        </div>
        <div class="newHeader">
            {!v.newHeader}
        </div>
        <div class="mainContentArea">
            {!v.body}
        </div>
    </div>
</aura:component>

2. 添加设计资源以包含主题属性

您可以在Experience Builder中公开主题布局属性,方法是添加 将资源设计到您的捆绑包中。

首先,在组件中实现属性。

<aura:component implements="forceCommunity:themeLayout" access="global" description="Small Header">
    <aura:attribute name="blueBackground" type="Boolean" default="false"/> 
    <aura:attribute name="smallLogo" type="Boolean" default="false" />
    ...

在设计资源中定义主题属性,以在 UI 中公开这些属性。本示例为 Small 添加标签 标题主题布局以及两个复选框。

<design:component label="Small Header">
    <design:attribute name="blueBackground" label="Blue Background"/>
    <design:attribute name="smallLogo" label="Small Logo"/>
</design:component>

3. 添加 CSS 资源以避免重叠问题

将 CSS 资源添加到捆绑包中,以根据需要设置主题布局的样式,最好使用标准设计标记。

要避免与定位元素(如对话框或悬停器)出现重叠问题,请执行以下操作:

  • 应用 CSS 样式。.THIS { position: relative; z-index: 1; }
  • 将自定义主题布局中的元素包装在标签中。div<div class="mainContentArea"> {!v.body} </div>

注意

主题布局控制其中任何内容的样式,因此它可以添加样式,例如 作为区域或组件的投影。对于自定义主题布局,SLDS 由 违约。

使用表达式向 Aura 站点添加动态数据

使用表达式,您可以访问属性值和其他信息以传递到 组件的属性。

表达式是任何一组文本值、变量、子表达式或运算符,它们 可以解析为单个值。表达式中不允许进行方法调用。

表达式语法为: 其中 是表达式的占位符。{!expression}expression

使用这些表达式可显示经过身份验证的用户的信息、关联的图像 具有数据类别,或在网站页面上记录信息。

表达显示
{!CurrentUser.name}组合用户的名字和姓氏,如用户详细信息上所示 页。
{!CurrentUser.firstName}用户的名字,如用户编辑页面上所示。
{!CurrentUser.lastName}用户的姓氏,如用户编辑页面上所示。
{!CurrentUser.userName}定义用户登录名的管理字段。
{!CurrentUser.id}用户的 Salesforce ID。
{!CurrentUser.email}用户的电子邮件地址。
{!CurrentUser.communityNickname}用于标识网站中用户的名称。
{!CurrentUser.accountId}与用户关联的帐户 ID。此表达式显示有效帐户 合作伙伴和客户用户的 ID。对于所有其他内容,它显示 ‘000000000000000’.
{!CurrentUser.effectiveAccountId}与有效账户关联的账户 ID。此表达式显示 合作伙伴和客户用户的有效帐户 ID。对于所有其他内容,它显示 ‘000000000000000’.
{!Global.PathPrefix}/{!DataCategory.Name}.jpg与搜索组件中的数据类别关联的图像。
{!Global.PathPrefix}/<Name of the Subfolder>/{!DataCategory.Name}.jpg与搜索中的子文件夹中的数据类别关联的图像 元件。
{!recordId}对象页面上的 15 位记录 ID。
{!term}在基于 Aura 的标准中返回 HTML 编码的搜索词的表达式 搜索页面。

为 Experience Builder 创建自定义内容布局组件

Experience Builder 包含多个定义内容的即用型布局 页面的区域,例如比例为 2:1 的两列布局。但是,如果您需要 为您的网站自定义的布局,请创建自定义内容布局组件以在以下情况下使用 在Experience Builder中构建新页面。您还可以更新默认的内容布局 网站模板附带的页面。

当您在开发者控制台中创建自定义内容布局组件时,它会 显示在 Experience Builder 的 “新建页面”和“更改布局”对话框。

1. 向内容布局组件添加新界面

要显示在Experience Builder的“新建页面”和“更改布局”对话框中,请 内容布局组件必须实现接口。forceCommunity:layout下面是一个简单的两列内容的示例代码 布局。

<aura:component implements="forceCommunity:layout" description=”Custom Content Layout” access="global">
    <aura:attribute name="column1" type="Aura.Component[]" required="false"></aura:attribute>
    <aura:attribute name="column2" type="Aura.Component[]" required="false"></aura:attribute>

    <div class="container">
        <div class="contentPanel">
            <div class="left">
                {!v.column1}
            </div>
            <div class="right">
                {!v.column2}
            </div>
        </div>
    </div>
</aura:component>

注意

标记您的资源,例如 一个组件,用 可在您自己的组织外部使用的资源。access=”global”例如,如果您想要一个组件 可在已安装的软件包中使用,或由 Lightning 应用程序构建器用户或 其他组织中的 Experience Builder 用户。

您还可以为 标记为 的组件、事件或接口。本文档会自动显示在 使用或安装包的组织的组件库。access=”global”

2. 将 CSS 资源添加到组件包中

接下来,添加一个 CSS 资源来设置 根据需要进行内容布局。

下面是我们简单的两列内容布局的示例 CSS。

.THIS .contentPanel:before,
.THIS .contentPanel:after {
    content: " ";
    display: table;
}
.THIS .contentPanel:after {
    clear: both;
}
.THIS .left {
    float: left;
    width: 50%;
}
.THIS .right {
    float: right;
    width: 50%;
}

CSS 资源必须命名为 componentName.css

3. 可选:将 SVG 资源添加到组件包

您可以在 组件包,用于定义内容布局组件出现在 体验生成器。

Experience Builder 中内容布局组件的建议图像大小为 170px 按 170px。但是,如果图像具有不同的尺寸,则 Experience Builder 会进行缩放 要适合的图像。

SVG 资源必须命名为 componentName.svg

配置可交换搜索和配置文件菜单组件

创建自定义组件以替换模板的标准配置文件标题和搜索 & Experience Builder 中的 Post Publisher 组件。

例如,在 Customer Service 中,模板标题由这些锁定的 地区:

  • search,其中包含搜索发布服务器 元件
  • profileMenu,其中包含配置文件标头 元件
  • navBar,其中包含导航菜单 元件

通过这些指定的区域名称,您可以轻松地:

  • 在默认主题布局组件或自定义组件中交换搜索和配置文件组件 主题布局组件。
  • 交换主题布局组件,同时保留现有自定义项,例如 选定的搜索组件。

当组件实现正确的接口(在本例中为 )时,它将被标识为候选接口 对于这些地区。因此,它们在主题布局中显示为可交换组件 组件,例如默认的 Customer Service 主题布局组件,该组件声明 或 作为属性名称 价值。

forceCommunity:searchInterfaceforceCommunity:profileMenuInterfacesearchprofileMenu

<aura:attribute name="search" type="Aura.Component[]" required="false" />

forceCommunity:profileMenuInterface

添加接口 添加到 Aura 组件中,以允许将其用作 模板。创建自定义配置文件菜单组件后,管理员可以在Experience Builder的“设置”|”主题以替换模板的标准配置文件标头组件。forceCommunity:profileMenuInterface

此代码适用于简单的配置文件菜单组件。

<aura:component implements="forceCommunity:profileMenuInterface" access="global">
    <aura:attribute name="options" type="String[]" default="Option 1, Option 2"/>
    <ui:menu >
        <ui:menuTriggerLink aura:id="trigger" label="Profile Menu"/>
        <ui:menuList class="actionMenu" aura:id="actionMenu">
            <aura:iteration items="{!v.options}" var="itemLabel">
                <ui:actionMenuItem label="{!itemLabel}" click="{!c.handleClick}"/>
            </aura:iteration>
        </ui:menuList>
    </ui:menu>
</aura:component>

forceCommunity:搜索接口

将接口添加到 Aura 组件,允许将其用作模板的自定义搜索组件。后 您创建自定义搜索组件,管理员可以在Experience Builder的“设置”|”主题替换模板的标准 Search & Post Publisher 组件。forceCommunity:searchInterface

此代码适用于简单的搜索组件。

<aura:component implements="forceCommunity:searchInterface" access="global">
    <div class="search">
        <div class="search-wrapper">
            <form class="search-form">
                <div class="search-input-wrapper">
                    <input class="search-input" type="text" placeholder="My Search"/>
                </div>
                <input type="hidden" name="language" value="en" />
            </form>
        </div>
    </div>
</aura:component>

Experience Builder 站点的标准设计令牌

Salesforce 公开了一组基本令牌,您可以在组件样式中访问这些令牌 资源。您可以使用这些标准令牌来模仿 Salesforce 的外观 Lightning Design System (SLDS) 在您自己的自定义组件中。随着 SLDS 的发展,组件 使用标准设计令牌进行样式设置的令牌也随之发展。使用 标准设计令牌,使您的组件与体验中的“主题”面板兼容 建筑工人。

通过“主题”面板,管理员可以使用品牌快速设置整个网站的样式 性能。“主题”面板中的每个属性都映射到一个或多个标准设计标记。 当管理员更新“主题”面板中的属性时,系统会更新 使用与该属性关联的令牌的 Lightning 组件。

Experience Builder 站点的可用令牌

对于Experience Builder站点,扩展时可以使用以下标准令牌 来自 force:base

重要

标准令牌值随着 SLDS 的发展而变化。可用的令牌和 它们的值可能会更改,恕不另行通知。

这些“主题”面板属性……映射到这些标准设计令牌
文本颜色colorTextDefault
详细文本颜色colorTextActionLabel
动作颜色colorBackgroundButtonBrandcolorBorderBrandcolorBorderButtonBrandcolorBrandcolorTextBrandcolorTextActionLabelActivecolorTextTabLabelSelected注意从 Summer ’18 开始,不再映射到 Action Color。colorBackgroundHighlight
链接颜色colorTextLink
公司 LogobrandLogoImage
叠加文本颜色colorTextButtonBrandcolorTextButtonBrandHovercolorTextInverse
边框颜色colorBordercolorBorderButtonDefaultcolorBorderInputcolorBorderSeparatorAlt
主字体fontFamily
文本大小写textTransform

此外,以下标准令牌可用于 模板。在更新 “主题”面板中的属性。例如,如果更改 主题面板中,系统会根据新的 价值。

这些派生的品牌属性……映射到这些标准设计令牌
动作颜色更暗(源自 Action Color)colorBackgroundButtonBrandActivecolorBackgroundButtonBrandHover
悬停颜色(源自 Action Color)colorBackgroundButtonDefaultHovercolorBackgroundRowHovercolorBackgroundRowSelectedcolorBackgroundShade
链接颜色较深(源自 Link Color)colorTextLinkActivecolorTextLinkHover

有关 SLDS 中可用的设计令牌的完整列表,请参阅 Lightning Design 上的设计令牌 系统站点。

注意

一些开箱即用的组件不使用标准设计令牌。因此,如果你 使用标记 在设置主题布局样式时,某些组件可能不会继承 定义。

确保具有 Experience Cloud 站点的组织中的自定义组件是安全的

开发人员可以通过以下方式自定义 Experience Cloud 站点中的功能和业务逻辑 使用自定义组件。与任何自定义解决方案一样,开发人员必须意识到潜力 与安全相关的陷阱。绕过内置防御措施可以使站点和组织暴露在安全之下 风险。

例如,如果开发人员在自定义组件的定义中将敏感数据存储为文本, 数据可能会暴露。当数字体验 在组织中启用,组织具有自定义组件,并且自定义组件的开发人员名称为 已知。无论网站是公共的还是私有的,都可能发生暴露。

公开的数据可以包括:

  • 在组件定义中存储为文本的敏感信息
  • 组件的完整组件定义,包括 HTML、JavaScript 和 CSS 文件
  • 组件定义中包含的任何其他组件的名称
  • 组件定义中使用的任何 Apex 控制器和方法名称

此类数据可以针对组织中的任何自定义组件公开,无论它们是否用于 Salesforce 组织、Experience Cloud 站点上或未使用时。请执行以下步骤来降低自定义组件中数据泄露的风险。

  • 查看组织中所有自定义组件中的组件定义
  • 避免在组件定义中存储任何敏感数据。敏感数据可以包括 个人身份信息、公司机密信息或任何信息 被视为对您的业务和客户敏感
  • 查看所有自定义控制器,并确保只有必需的用户配置文件具有访问权限 对他们来说
  • 确保使用@AuraEnabled
  • 对组织复杂且唯一的自定义组件使用命名约定

自定义体验生成器模板的外观

您可以通过多种方式控制 Experience Builder 模板的外观,每种方式 具有不同的复杂性和粒度。

在Experience Builder中,您可以修改特定于模板的样式,以及 因此,不能在站点之间共享。Experience Builder 中的选项是最简单的 使用并且不需要编码。

  • “主题”面板使用简单的 点击属性。此方法非常适合管理员使用。注意个人 组件属性面板(例如标题或搜索)提供了其他更多功能 外观和感觉的具体调整。
  • CSS 编辑器允许您创建自定义 CSS,以覆盖 模板元素的基本样式。如果您熟悉 CSS 和 只想对一些开箱即用的组件或模板进行微小的修改 元素。注意随着主题交换的引入,您输入的任何自定义 CSS 现在直接绑定到您的活动主题。对于现有站点,请确保任何所需的 您当前可能使用的自定义 CSS 将复制到新选择的主题中。哪里 自定义 CSS 是必需的,请在主题中使用 Experience Builder 站点的设计令牌 有意义的布局(、等)以减轻未来的痛苦 更新了模板和主题。brandLogoImageaction color

但是,要完全自定义模板的外观,您需要构建自己的模板 组件。

  • 习惯 Aura 组件将 CSS 资源封装为 组件包,使组件可跨站点重用。
  • 内容布局组件定义 页面并包含组件。
  • 主题布局组件可让您自定义结构 模板的布局,例如页眉和页脚,并覆盖其默认值 风格。
  • 使用“主题”面板
    更新模板 在Experience Builder中,更改模板外观的最简单方法是使用“主题”面板。管理员可以使用主题面板快速设置整个网站的样式,以应用颜色、指定字体、添加徽标或调整常规页面结构和默认值。
  • 使用自定义 CSS 覆盖模板元素 使用 Experience Builder 中的 CSS 编辑器添加自定义 CSS
    ,以覆盖默认模板和主题面板样式。您还可以使用它对开箱即用组件的外观进行细微更改,例如填充调整。
  • 在Experience Builder站点中使用自定义字体 将自定义字体作为静态资源上传,并将其用于整个站点
    的主要字体和标题字体。如果要上传多个字体文件,请使用 .zip 文件。
  • 自定义模板的主题布局 若要在模板
    主题上放置自己的图章并转换其外观,请构建自定义主题布局组件。您可以自定义模板的结构布局(如页眉和页脚),并覆盖其默认样式。
  • 使用表达式向 Aura 站点
    添加动态数据 使用表达式,您可以访问属性值和其他信息以传递到组件的属性中。
  • 为 Experience Builder
    创建自定义内容布局组件 Experience Builder 包含多个现成的布局,用于定义页面的内容区域,例如比例为 2:1 的两列布局。但是,如果您需要为站点自定义的布局,请创建自定义内容布局组件,以便在Experience Builder中构建新页面时使用。您还可以更新网站模板附带的默认页面的内容布局。
  • 配置可交换的搜索和用户档案菜单组件
    在Experience Builder中创建自定义组件以替换模板的标准用户档案标题和搜索和发布发布者组件。
  • Experience Builder Sites
    Salesforce 的标准设计令牌公开了一组基本令牌,您可以在组件样式资源中访问这些令牌。您可以使用这些标准令牌在您自己的自定义组件中模拟 Salesforce Lightning Design System (SLDS) 的外观。随着 SLDS 的发展,使用标准设计标记设置样式的组件也随之发展。使用标准设计令牌的子集,使您的组件与Experience Builder中的主题面板兼容。
  • 确保具有 Experience Cloud 站点的组织中的自定义组件是安全的
    开发人员可以使用自定义组件自定义 Experience Cloud 站点中的功能和业务逻辑。与任何自定义解决方案一样,开发人员必须意识到与安全相关的潜在陷阱。绕过内置防御可能会使站点和组织面临安全风险。

使用“主题”面板更新模板

在Experience Builder中,更改模板外观的最简单方法是使用 “主题”面板。管理员可以使用主题面板快速设置整个网站的样式,以 应用颜色、指定字体、添加徽标或调整常规页面结构和 违约。

在“主题”面板中设置的属性适用于模板中的页面,并且大多数 现成的组件。使用品牌集快速应用颜色、图像和 字体。

“主题”面板的属性也适用于使用标准设计标记来控制其外观的自定义 Lightning 组件。

注意

如果您仍在使用 Spring ’17 的模板,要统一 使用网站其余页面登录页面,在“设置”|”更新。否则,您必须单独设置登录页面的主题。

使用自定义 CSS 覆盖模板元素

使用 Experience Builder 中的 CSS 编辑器添加自定义 CSS,以覆盖默认 模板和主题面板样式。您还可以使用它对外观进行细微更改 开箱即用的组件,例如填充调整。

重要

谨慎使用自定义 CSS。模板组件的未来版本可能会 不支持您的 CSS 自定义。此外,Salesforce 客户支持也无能为力 解决自定义 CSS 的任何问题。

提示

对于实质性的模板自定义,请使用 自定义 Lightning Web 组件或 Aura 组件和自定义主题中的 CSS 资源 布局组件。如果您使用全局覆盖,请始终在沙盒中测试您的网站,当它处于 更新了每个版本。

要对模板项进行细微的 CSS 修改,请使用 Chrome DevTools 检查页面 并发现项目的完全限定名称和 CSS 类。然后使用该信息 使用自定义 CSS 覆盖项目的标准 CSS。要了解有关检查和 编辑页面和样式,请参阅 Google Chrome 的 DevTools 网站。检查组件的最简单方法是在预览模式下查看页面。这个例子 检查 Headline 组件以找到组件的完全限定名称 – 。

forceCommunityHeadline

注意

如果顶级 CSS 类不是 为组件定义时,此选项不会显示,这意味着您不能可靠地 以组件为目标。

然后找到要设置样式的元素,例如 .如果元素没有类名,则必须编写 针对元素的特定选择器。headlineTitleText

使用该信息,您可以创建自定义样式以覆盖默认标题 颜色。

.forceCommunityHeadline .headlineTitleText
{
    color: red;
}

然后将其添加到CSS编辑器中。同样,您可以使用自定义 CSS 来隐藏组件 完全。

.forceCommunityHeadline
{
    display: none;
}

提示

您可以将 CSS 样式表作为静态或外部资源链接到 “设置”|”高级。但是,由于 head 标记中不支持全局值提供程序 或者在 CSS 覆盖中,你不能使用 引用静态资源。请改用语法 /sfsites/c/resource/resource_name 的相对 URL。$resource为 例如,如果您将图像作为名为 Headline 的静态资源上传,请在 CSS 编辑器作为 遵循:

.forceCommunityHeadline
{
    background-image: url('/sfsites/c/resource/headline')
}

头 标记对于添加图标、SEO 元标记和其他项目也很有用。然而 请注意,使用默认的严格 CSP 安全级别可能会影响代码。

  • 迁移 CSS 覆盖
    在 17 年春季和 19 年冬季之间,更新了多个 Experience Builder 组件的 CSS 选择器。如果您此后没有更新模板,并且您的网站使用自定义 CSS 来覆盖默认模板和主题面板样式,则必须迁移到新的选择器。

迁移 CSS 覆盖

在 17 年春季和 19 年冬季之间,多个 Experience Builder 的 CSS 选择器 组件已更新。如果您此后没有更新模板,并且您的网站使用 自定义 CSS 要覆盖默认模板和主题面板样式,您必须迁移到新的 选择。

请参阅更新体验生成器 Salesforce 帮助中的模板。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。
  • 导航菜单
    的 CSS 覆盖迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖面板容器
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录横幅组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录详细信息组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录布局组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录列表组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖记录相关列表组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖相关文章组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • 信誉排行榜组件
    的 CSS 覆盖迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖嵌入式服务侧边栏标头组件
    的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。
  • CSS 覆盖按主题组件
    分类的热门文章的迁移 如果您计划继续使用自定义 CSS 覆盖,请在更新模板后将其向前迁移。

CSS 覆盖导航菜单的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题介绍导航菜单的选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整导航菜单

上一个选择器新选择器
.forceCommunityNavigationMenu.forceCommunityNavigationMenu #navigationMenu.forceCommunityNavigationMenu .navigationMenu.forceCommunityNavigationMenu .navigationMenuWrapper.comm-navigation

移动菜单窗帘

上一个选择器新选择器
.forceCommunityNavigationMenu .navigationMenuWrapperCurtain.comm-navigation nav.slds-is-fixed

主菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .homeLink.forceCommunityNavigationMenu .homeButton.comm-navigation .slds-list__item a[data-type=”home”]

主菜单项链接

上一页 选择器新选择器
.forceCommunityNavigationMenu.homeLink.forceCommunityNavigationMenu.homeButton.comm-navigation .slds-list__item a[data-type=”home”].comm-navigation .comm-navigation__item a[data-type=”home”]

移动菜单切换按钮

上一个选择器新选择器
.forceCommunityNavigationMenu .toggleNav.siteforceServiceBody .cHeaderPanel .cAltToggleNav

顶级菜单项

包括子菜单触发器。

上一个选择器新选择器
.forceCommunityNavigationMenu .menuItem.forceCommunityGlobalNavigation .navigationMenuNode.comm-navigation .comm-navigation__list > .slds-list__item
.forceCommunityNavigationMenu .menuItem.forceCommunityGlobalNavigation .navigationMenuNode.comm-navigation .comm-navigation__list > .slds-list__item.comm-navigation .comm-navigation__list > .slds-list__item > .comm-navigation__item

当前顶级菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .current.forceCommunityGlobalNavigation .menuItem.current.comm-navigation .comm-navigation__list > .slds-list__item > .slds-is-active
.forceCommunityNavigationMenu .current.forceCommunityGlobalNavigation .menuItem.current.comm-navigation .comm-navigation__list > .slds-list__item > .slds-is-active.comm-navigation .comm-navigation__list > .slds-list__item> .comm-navigation__item > .slds-is-active

顶级菜单项链接

上一个选择器新选择器
.forceCommunityNavigationMenu .menuItemLink.forceCommunityNavigationMenu a.menuItemLink.forceCommunityNavigationMenu .menuItem .menuItemLink.forceCommunityNavigationMenu .menuItem a.forceCommunityNavigationMenu .menuItem a.menuItemLink.comm-navigation .comm-navigation__list > .slds-list__item > a.comm-navigation .comm-navigation__list > .slds-list__item > button
.forceCommunityNavigationMenu .menuItemLink.forceCommunityNavigationMenu a.menuItemLink.forceCommunityNavigationMenu .menuItem .menuItemLink.forceCommunityNavigationMenu .menuItem a.forceCommunityNavigationMenu .menuItem a.menuItemLink.comm-navigation .comm-navigation__list > .slds-list__item > a.comm-navigation .comm-navigation__list > .slds-list__item > button.comm-navigation .comm-navigation__list > .slds-list__item> .comm-navigation__item > a.comm-navigation .comm-navigation__list > .slds-list__item> .comm-navigation__item > button

子菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item

当前/活动子菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem.current.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item .slds-is-active
.forceCommunityNavigationMenu .subMenuItem.current.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item .slds-is-active.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item .slds-is-active

子菜单触发链接

上一个选择器新选择器
.forceCommunityNavigationMenu .triggerLink.forceCommunityNavigationMenu .triggerLabel.comm-navigation .slds-list__item button:enabled
.forceCommunityNavigationMenu .triggerLink..forceCommunityNavigationMenu .triggerLabel.comm-navigation .slds-list__item button:enabled.comm-navigation .comm-navigation__item button:enabled

子菜单触发链接图标

上一个选择器新选择器
.forceCommunityNavigationMenu .triggerLink .forceIcon.comm-navigation .slds-list__item button:enabled .slds-icon_container
.forceCommunityNavigationMenu .triggerLink .forceIcon.comm-navigation .slds-list__item button:enabled .slds-icon_container.comm-navigation .comm-navigation__item button:enabled .slds-icon_container

菜单项

包括顶级菜单项和子菜单项。

上一个选择器新选择器
.forceCommunityNavigationMenu .navigationMenu li.comm-navigation .slds-list__item
.forceCommunityNavigationMenu .navigationMenu li.comm-navigation .slds-list__item.comm-navigation .comm-navigation__item

菜单项链接

包括顶级菜单项和子菜单项。

上一个选择器新选择器
.forceCommunityNavigationMenu a.forceCommunityNavigationMenu a.menuItemLink.comm-navigation .slds-list__item a.comm-navigation .slds-list__item button
.forceCommunityNavigationMenu a.forceCommunityNavigationMenu a.menuItemLink.comm-navigation .slds-list__item a.comm-navigation .slds-list__item button.comm-navigation .comm-navigation__item a.comm-navigation .comm-navigation__item button

子菜单

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenu.comm-navigation .slds-list_vertical.slds-is-nested

子菜单项

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item
.forceCommunityNavigationMenu .subMenuItem.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item

子菜单项链接

上一个选择器新选择器
.forceCommunityNavigationMenu .subMenuItem a.forceCommunityNavigationMenu .subMenu a.comm-navigation .slds-list_vertical.slds-is-nested .slds-list__item a
.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item.comm-navigation .slds-list_vertical.slds-is-nested .comm-navigation__item a

CSS 覆盖 Panels 容器的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

面板容器

上一个选择器新选择器
.uiPanelManager2.onePanelManager.siteforcePanelManager.comm-panels-container

CSS 覆盖记录横幅组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

详细字段标签

上一个选择器新选择器
.forceCommunityRecordHeadline .slds-text-heading-label-normal.forceCommunityRecordHeadline .slds-form-element__label

详细信息字段值

上一个选择器新选择器
.forceCommunityRecordHeadline .slds-text-body–regular.forceCommunityRecordHeadline .slds-form-element__static

CSS 覆盖记录详细信息组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

表单元素分隔符

上一个选择器新选择器
.forceCommunityRecordDetail .slds-form-element__control .slds-form-element_separator.forceCommunityRecordDetail .slds-form-element_separator

CSS 覆盖记录布局组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

全记录布局

上一个选择器新选择器
.forceRecordLayout.forceRecordLayout.forcePageBlockforce-record-layout2force-record-layout-block

部分

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockSectionView.forceRecordLayout .full.forcePageBlockSection.forceRecordLayout .full.forcePageBlockSectionView.forcePageBlockSection.forceRecordLayout .forcePageBlockSectionView.forceRecordLayout .forcePageBlockSection.forceRecordLayout .forcePageBlockSectionView.forcePageBlockSectionforce-record-layout2 force-record-layout-section

章节标题

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockSection h3force-record-layout2 force-record-layout-section h3

节行

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockSectionRow.forceRecordLayout .forcePageBlockSectionRowforce-record-layout2 force-record-layout-row

部分项目

上一个选择器新选择器
.forceRecordLayout .full.forcePageBlockItem.forcePageBlockItemView.forceRecordLayout .full.forcePageBlockItem.forceRecordLayout .full.forcePageBlockItemView.forceRecordLayout .forcePageBlockItem.forceRecordLayout .forcePageBlockItemView.forceRecordLayout .forcePageBlockItem.forcePageBlockItemViewforce-record-layout2 force-record-layout-item

部分项目标签

上一个选择器新选择器
.forceRecordLayout .slds-form-element__labelforce-record-layout2 .slds-form-element__label

节项目值

上一个选择器新选择器
.forceRecordLayout .itemBodyforce-record-layout2 .slds-form-element__static

部分项目值链接

上一个选择器新选择器
.forceRecordLayout aforce-record-layout2 a

CSS 覆盖记录列表组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

列表视图按钮栏

上一个选择器新选择器
.forceListViewManagerHeader .forceListViewManagerButtonBar.forceListViewManagerHeader force-list-view-manager-button-bar

列表视图按钮 栏按钮

上一个选择器新选择器
.forceListViewManagerHeader .forceListViewManagerButtonBar button.forceListViewManagerHeader force-list-view-manager-button-bar button

列表视图状态信息

上一个选择器新选择器
.forceListViewManagerHeader .test-listViewStatusInfo.forceListViewManagerHeader force-list-view-manager-status-info

选取器触发器链接

上一个选择器新选择器
.forceListViewManagerHeader .triggerLink.forceListViewManagerHeader .triggerLink .slds-button

CSS 覆盖与记录相关的列表组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

详细字段标签

上一个选择器新选择器
.forceCommunityRelatedRecords .slds-card__header-link .slds-text-heading–small.forceCommunityRelatedRecords .slds-card__header-title

CSS 覆盖相关文章组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整相关文章

上一个选择器新选择器
.selfServiceSimilarArticles.base-items.uiAbstractList.selfServiceBaseSimpleItems.comm-related-articles

组件标题

上一个选择器新选择器
.selfServiceSimilarArticles h2.selfServiceSimilarArticles .base-items-header.comm-related-articles h2

文章列表

上一个选择器新选择器
.selfServiceSimilarArticles ul.selfServiceSimilarArticles .base-items.comm-related-articles ul

文章列表项

上一个选择器新选择器
.selfServiceSimilarArticles .base-simple-item.comm-related-articles li
.selfServiceSimilarArticles .base-simple-item.comm-related-articles li.comm-related-articles .comm-related-articles__item

文章链接

上一个选择器新选择器
.selfServiceSimilarArticles .item-title.selfServiceSimilarArticles .item-title-link.comm-related-articles li a
.selfServiceSimilarArticles .item-title.selfServiceSimilarArticles .item-title-link.comm-related-articles li a.comm-related-articles .comm-related-articles__item a

CSS 覆盖信誉排行榜组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整声誉排行榜

上一个选择器新选择器
.forceCommunityReputationLeaderboard.leaderboard.comm-leaderboard

声誉排行榜行

上一个选择器新选择器
.forceCommunityReputationLeaderboardRow.comm-leaderboard li
.forceCommunityReputationLeaderboardRow.comm-leaderboard li.comm-leaderboard .comm-leaderboard__item

用户信息列

上一个选择器新选择器
.forceCommunityReputationLeaderboard .pointsAndLevels.forceCommunityReputationLeaderboard .userInfoCol.comm-leaderboard .slds-media__body

声望点数列

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationCol.comm-leaderboard__points-column

标题

上一个选择器新选择器
.forceCommunityReputationLeaderboard .title.comm-leaderboard h2

用户级别名称

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationLevelName.comm-leaderboard__level-name

用户信誉级别图像

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationLevelImage.comm-leaderboard .slds-media__body .slds-icon_small

用户中的用户名

上一个选择器新选择器
.forceCommunityReputationLeaderboard .userName.comm-leaderboard__user-name

用户中的用户照片

上一个选择器新选择器
.forceCommunityReputationLeaderboard .userPhoto.comm-leaderboard .slds-media__figure

信誉级别的用户点数

上一个选择器新选择器
.forceCommunityReputationLeaderboard reputationPointsNumber..comm-leaderboard__points

用户在声誉级别中点词

上一个选择器新选择器
.forceCommunityReputationLeaderboard .reputationPointsWord..comm-leaderboard__points-word

CSS 覆盖嵌入式服务侧边栏标头组件的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

标题背景颜色

上一个选择器新选择器
.sidebarHeader { background-color: #aaa; }.embeddedServiceSidebar.sidebarHeader { background-color:#aaa; }

CSS 按主题组件覆盖热门文章的迁移

如果您计划继续使用自定义 CSS 覆盖,请将其向前迁移 更新模板后。

本主题标识选择器更改。

注意

  • 谨慎使用自定义 CSS,因为模板更新并不总是支持 定制。
  • 自定义 CSS 现在在您的所有网站页面之间共享。如果您使用自定义 CSS 进行登录 页面,复制它并关闭 CSS 编辑器。然后导航到非登录页面,重新打开 编辑器,然后添加自定义 CSS。

完整的热门文章

上一个选择器新选择器
.selfServiceTopicTrendingArticles.base-items.uiAbstractList.selfServiceBaseSimpleItems.comm-topic-trending-articles

组件标题

上一个选择器新选择器
.selfServiceTopicTrendingArticles h2.selfServiceTopicTrendingArticles .base-items-header.comm-topic-trending-articles h2

文章列表

上一个选择器新选择器
.selfServiceTopicTrendingArticles ul.selfServiceTopicTrendingArticles .base-items.comm-topic-trending-articles ul

文章列表项

上一个选择器新选择器
.selfServiceTopicTrendingArticles .base-simple-item.comm-topic-trending-articles li
.selfServiceTopicTrendingArticles .base-simple-item.comm-topic-trending-articles li.comm-topic-trending-articles .comm-topic-trending-articles__item

文章链接

上一个选择器新选择器
.selfServiceTopicTrendingArticles .item-title-link.selfServiceTopicTrendingArticles a.comm-topic-trending-articles li a
.selfServiceTopicTrendingArticles .item-title-link.selfServiceTopicTrendingArticles a.comm-topic-trending-articles li a.comm-topic-trending-articles .comm-topic-trending-articles__item a

在 Experience Builder 站点中使用自定义字体

将自定义字体作为静态资源上传,并将其用于主字体和标题字体 整个站点。如果要上传多个字体文件,请使用 .zip 文件。

  1. 在“设置”中,在“快速查找”框中输入“静态资源”,然后 选择静态资源
  2. 单击“新建”,上传文件,并为静态资源命名。 记下资源名称。如果您的网站有公共页面,请在“缓存”中选择“公共” 控制设置。如果您不公开字体资源,则页面将使用 浏览器的默认字体。
  3. 在 Experience Builder 中, 通过单击“主题”|” |编辑 CSS
  4. 使用 @font面 CSS 规则引用 上传的字体。为 例:@font-face { font-family: 'myFirstFont'; src: url('/myPartnerSite/s/sfsites/c/resource/MyFonts/bold/myFirstFont.woff') format('woff'); }注意format() 是一个可选提示,用于描述 URL 中引用的字体。
    • 要引用单个字体文件,请使用语法 /path_prefix/s/sfsites/c/resource/resource_name, 其中 是 URL 值,当您 创建了网站,例如 myPartnerSite。path_prefix例如,如果您上传一个名为 myFirstFont.woff 的文件,并且 将资源命名为 MyFonts,URL 为 /myPartnerSite/s/sfsites/c/resource/MyFonts。
    • 若要引用 .zip 文件中的文件,请包含文件夹结构,但省略 .zip 文件名。使用语法 /path_prefix/s/sfsites/c/resource/resource_name/font_folder/font_file。因此,如果您上传包含 bold/myFirstFont.woff 的 fonts.zip,并将资源命名为 MyFonts,则 URL 为 /myPartnerSite/s/sfsites/c/resource/MyFonts/bold/myFirstFont.woff。
  5. 在“主题”面板中,选择“字体”,选择“主要字体”或 “标题字体”下拉列表,然后单击“使用自定义字体”。
  6. 添加您在 CSS 编辑器中输入的字体系列名称(例如,)并保存更改。myFirstFont

Experience Cloud 开发人员指南

快速了解 Experience Builder 站点

Experience Builder 模板允许您创建品牌网站,让您的员工、 客户和合作伙伴可以建立联系。基于 Lightning 组件框架构建,Experience 构建器模板包括许多现成的功能和 Lightning 组件。但真正的 Lightning 组件框架的强大之处在于您可以开发自定义的 Lightning 组件 和功能,以满足您独特的业务需求,并彻底改变外观和感觉 您的网站。

从 Spring ’19(API 版本 45.0)开始,您可以使用两个 编程模型:Lightning Web 组件模型和原始 Aura 组件 型。Lightning Web 组件是使用 HTML 和现代构建的自定义 HTML 元素 JavaScript的。

提示

重命名为 Experience Cloud Spring ’21(API 版本 50.0)引入了一些新术语,了解起来可能很棘手 什么是什么。这是纲要。

Experience Builder 站点(以前称为 Lightning 社区)是您在 Experience Builder 中自定义的基于模板的站点。 随着 Lightning Web 运行时 (LWR) 的推出,我们为 even 添加了两个新术语 更清晰。

  • LWR 站点使用最新的基于 LWR 的模板构建,例如 构建您自己的 (LWR) 模板。LWR 站点只能与 Lightning Web 组件一起使用, 不是 Aura 组件。查看 LWR 网站获取体验 云。
  • Aura 网站是使用我们的原始模板构建的,例如客户 服务、合作伙伴中心和客户帐户门户,在 Aura 上运行。对于光环 站点、Lightning Web 组件和 Aura 组件可以在 页。

您可以将 Lightning Web 组件和 Aura 组件配置为拖放式 Experience Builder 的组件。管理员和最终用户不知道哪种编程模型 用于开发组件 – 对他们来说,它们只是 Lightning 组件。

无论你是开发人员、合作伙伴还是 ISV,本指南都介绍了如何创建自定义 Aura 网站和组件、主题布局组件和 Lightning Bolt 解决方案。

  • 开始之前 在开始
    开发自定义 Experience Builder 站点之前,请确保您熟悉如何在 Lightning 中进行开发。
  • 什么是 Salesforce Lightning?
    借助 Salesforce Lightning,您可以更轻松地为任何设备构建响应式应用程序,并包含 Lightning 组件框架和面向开发人员的有用工具。
  • 我应该使用哪个 Experience Builder 模板?
    根据您使用的 Experience Builder 模板,您可以使用两种编程模型构建 Experience Builder 站点:Lightning Web 组件模型和原始 Aura 组件模型。Build Your Own (LWR) 模板基于新的 Lightning Web 运行时 (LWR),只能与 Lightning Web 组件一起使用,而不能与 Aura 组件一起使用。其他模板基于 Aura 组件模型,可以同时使用 Lightning Web 组件和 Aura 组件。
  • Experience Cloud 开发人员发行说明 使用 Salesforce 发行说明
    了解 Experience Cloud 开发人员体验的最新更新和更改。

准备工作

在开始开发自定义 Experience Builder 站点之前,请确保您 熟悉在 Lightning 中开发。

您可以在 EnterprisePerformanceUnlimited 和 Developer Edition 或沙盒中创建 Experience Builder 站点和 Lightning 组件。

要成功使用本指南,需要:

  • 启用了数字体验的组织
  • 基于 Experience Builder 模板或 Lightning 的新站点或现有站点 螺栓解决方案
  • 熟悉使用 Experience Builder
  • 具有开发 Lightning 组件和使用 CSS 的经验

Lightning 开发资源

不熟悉 Lightning 开发?然后查看这些资源。

Lightning Aura 组件 开发者指南

所有 Aura 的首选指南。基本概念和方法 指南文档构成了本指南的基石。想想 Experience Cloud 开发人员指南作为开发系列的第 2 部分;它对你没有用,直到 您熟悉了第 1 部分。

Lightning Web 组件 开发者指南

了解如何开发 Lightning Web 组件,即使用 HTML 构建的自定义 HTML 元素 和现代 JavaScript。

LWR 体验站点 云开发人员指南

使用“构建自己的网站”(LWR) 开发加载速度快且可扩展的站点 Experience Cloud 的模板。此模板基于最新的 Lightning Web 运行时 (LWR) 和 Lightning Web 组件 (LWC) 编程模型。

Aura 组件基础知识 (Trailhead Module)

使用 Aura 组件构建具有可重用 UI 组件的新式 Web 应用程序。学习核心 Lightning 组件概念并构建可运行的简单费用跟踪器应用程序 在独立应用程序、Salesforce 移动应用程序或 Lightning Experience 中。

构建 Lightning Web 组件 (Trailhead Trail)

使用 JavaScript 和 HTML 开发可重用的 Lightning Web 组件。

快速入门:Aura 组件 (Trailhead Project)

创建第一个组件,用于呈现组织中的联系人列表。

构建自定义主题布局 Experience Builder Sites 的组件(Trailhead 项目)

使用主题布局组件自定义 Experience Builder 站点。

闪电组件 性能最佳实践(博客文章)

了解影响组件性能的 Lightning 特性,并获得 优化组件的最佳实践。

Experience Cloud 资源

不熟悉 Experience Cloud?然后查看这些资源。

设置和管理体验 Cloud Sites(帮助)

使用模板创建品牌网站,直接与您的客户互动,以及 合作伙伴在线。

通过经验扩大您的影响力 云 (Trailhead Trail)

了解开始使用 Salesforce Experience Cloud 所需的工具。

体验云 概述(帮助)

及时了解其他 Experience Cloud 资源。

什么是 Salesforce Lightning?

借助 Salesforce Lightning,您可以更轻松地为任何设备构建响应式应用程序, 并包含 Lightning 组件框架和为开发人员提供的有用工具。闪电网络包括这些技术。

  • Lightning 组件可加速开发和应用性能。开发定制 其他开发人员和管理员可用作可重用构建基块的组件 自定义 Experience Builder 站点、Salesforce 移动应用程序和 Lightning 经验。
  • Lightning 应用程序生成器使管理员能够直观地构建 Lightning 页面,无需代码, 使用现成的和定制的 Lightning 组件。制作您的 Lightning 组件 在 Lightning 应用程序生成器中可用,因此管理员可以构建自定义用户界面 没有代码。
  • Experience Builder 使管理员能够使用模板直观地构建站点,并且 组件。使您的 Lightning 组件在 Experience Builder 中可用,以便 管理员无需代码即可构建网站页面。

一些使用 Lightning 框架构建的 Salesforce 产品包括:

  • Experience Builder 模板
  • 闪电 解决 方案
  • 闪电体验
  • Salesforce 移动应用程序

注意

您无需启用 Lightning Experience 即可使用 Experience Builder 模板 或开发 Lightning 组件。Experience Builder 站点使用相同的底层技术 作为 Lightning Experience,但它们彼此独立。

我应该使用哪个 Experience Builder 模板?

根据您使用的 Experience Builder 模板,您可以构建 Experience 使用两种编程模型构建站点:Lightning Web 组件模型和原始模型 Aura 组件模型。Build Your Own (LWR) 模板基于新的 Lightning Web 运行时 (LWR),只能与 Lightning Web 组件一起使用,而不能与 Aura 组件一起使用。其他 模板基于 Aura 组件模型,可以使用 Lightning Web 组件和 光环组件。

建立你自己的

提供每个Experience Builder站点所需的基本页面:主页、创建记录、 错误、记录明细、记录列表、相关记录列表、搜索、检查密码、忘记 密码、登录名、登录错误和注册。根据需要添加更多页面和组件 您正在构建的体验。要优化网站的外观,请自定义您的品牌 和主题。

构建自己的 (LWR)

由新的 Lightning Web 运行时 (LWR) 平台提供支持,这个可自定义的模板 提供无与伦比的页面性能,提高开发人员的工作效率。快速构建 像素完美的页面,并开发 Lightning Web 组件和主题,以匹配您独特的 品牌。

适合熟悉开发的开发人员、咨询合作伙伴和 ISV 自定义 Lightning Web 组件,并使用 Salesforce DX、用户界面 API 和 顶点。

查看 LWR 站点获取体验 云指南。

客户账户门户

一个私密且安全的地方,供客户访问和更新其帐户信息。 通过让客户在 门户。客户可以查看和支付发票、更新其帐户信息以及搜索 您的知识库,用于回答他们最常见问题。

顾客服务

功能强大、响应迅速的自助服务模板,具有多个预构建的主题选项。这 Customer Service 模板允许用户将问题发布到社区、搜索和查看 文章、协作,并通过创建案例联系支持代理。支持知识, Chatter 问题和案例。

合作伙伴中心

专为渠道销售工作流程设计的灵活、响应迅速的模板。招募、建设、 并发展您的合作伙伴网络,以品牌化的方式共同推动渠道销售和营销 在线空间。轻松配置销售线索分销、交易注册和营销 活动。在中央空间中共享培训材料和销售材料,并使用 用于跟踪管道的报表。

帮助中心

一个公开您创建的文章的公共访问自助服务社区 可从知识库获取。您可以减轻客户支持团队的负担,并且 您的用户会因为找到自己的解决方案而感到满意。

Experience Cloud 开发人员发行说明

使用 Salesforce 发行说明了解 Experience Cloud 开发人员体验。

有关新功能和更改的功能,请参阅 Salesforce 发行说明的 Experience Cloud 部分。您还可以查找 Experience Cloud 在“新建和更改的项目”中 Salesforce 发行说明中的开发人员。

开发 Experience Builder 站点:基础知识

了解开发者控制台开发工具,以及如何创建基本的拖放操作 光环组件,以及在此过程中要考虑的提示。

  • 使用开发者控制台 开发者控制台
    提供了用于开发 Aura 组件和应用程序的工具。
  • 为 Experience Builder 配置拖放式 Aura 组件 在Experience Builder
    中使用自定义Aura组件之前,需要执行一些配置步骤。
  • 在Experience Builder
    中公开组件属性 您可以使用设计资源来控制在Experience Builder中公开哪些属性。设计资源与组件位于同一文件夹中。它描述了 Aura 组件的设计时行为,即可视化工具在页面或应用中显示组件所需的信息。
  • 为 Experience Builder
    配置 Aura 组件的提示和注意事项 在为 Aura 站点创建 Aura 组件和组件捆绑包时,请牢记这些准则。
  • 支持的 Aura 组件、接口和事件 基于 Aura 的 Experience Builder 站点并非支持所有 Aura 组件、接口和事件
    。有些仅适用于 Salesforce 移动应用程序或 Lightning Experience。在自定义您的网站之前,请查看可用的内容。
  • 个性化目标开发人员和组名称
    在使用 Connect REST API 或元数据 API 个性化 Experience Builder 站点时,确定体验变体目标的开发人员名称和组名称。
  • 遵守用户的个人信息可见性设置 具有门户和站点的组织提供特定设置
    ,以向其他用户隐藏用户的个人身份信息和联系信息。这些设置不会在 Apex 中强制执行,即使使用 Apex 安全功能(如子句或方法)也是如此。要对来宾或外部经过身份验证的用户隐藏特定字段,请遵循下面概述的示例代码。WITH SECURITY_ENFORCEDstripInaccessible

使用开发者控制台

开发者控制台提供了用于开发 Aura 组件和 应用。

开发人员控制台使您能够执行这些功能。

  • 使用菜单栏 (1) 创建或打开这些 Lightning 资源。
    • 应用
    • 元件
    • 接口
    • 事件
    • 令 牌
  • 使用工作区 (2) 处理 Lightning 资源。
  • 使用侧边栏 (3) 创建或打开客户端资源,这些资源是 特定组件捆绑包。
    • 控制器
    • 助手
    • 风格
    • 文档
    • 渲染
    • 设计
    • SVG

为 Experience Builder 配置拖放式 Aura 组件

在Experience Builder中使用自定义Aura组件之前,有几个 要执行的配置步骤。

1. 将界面添加到你的 元件

显示为 拖放组件 在Experience Builder中,组件必须实现接口。forceCommunity:availableForAllPageTypes

创建 Aura 组件后,该组件将显示在 Components 中 组织中所有 Aura 站点的面板。

下面是一个简单的“Hello World”组件的示例代码。组件必须 命名为 componentName.cmp

注意

要使 资源,例如组件,可在您自己的组织外部使用,请用 标记它。例如,如果您希望组件在已安装的软件包中可用,请使用 由 Experience Builder 用户提供 在另一个 组织。access=”global”access=”global”

<aura:component implements="forceCommunity:availableForAllPageTypes" access="global">
    <aura:attribute name="greeting" type="String" default="Hello" access="global" />
    <aura:attribute name="subject" type="String" default="World" access="global" />

    <div>{!v.greeting}, {!v.subject}!</div>
</aura:component>

警告

当您将自定义组件添加到 site,它们可以绕过您为来宾用户设置的对象级和字段级安全性 (FLS) 轮廓。Lightning 组件在引用对象或检索对象时不会自动强制执行 CRUD 和 FLS 从 Apex 控制器。这意味着框架继续显示记录和 用户没有 CRUD 权限和 FLS 可见性的字段。您必须手动操作 在 Apex 控制器中强制执行 CRUD 和 FLS。

2. 将设计资源添加到组件包中

设计资源控制公开的组件属性 在 Experience Builder 中。这 设计资源与 .cmp 资源位于同一文件夹中,并且 描述 Aura 组件的设计时行为 – 可视化工具所需的信息 以在页面或应用程序中显示组件。

例如,设置属性的默认值,或创建 Aura 组件属性 可供管理员在 Experience Builder 中编辑,您的 组件包需要设计资源。下面是与“Hello World”组件捆绑在一起的设计资源。一个 设计资源必须命名为 componentName.design

<design:component label="Hello World">
    <design:attribute name="greeting" label="Greeting" />
    <design:attribute name="subject" label="Subject" description="Name of the person you want to greet" />
</design:component>

自选。将 SVG 资源添加到组件包

要为组件定义自定义图标,请将 SVG 资源添加到组件包中。 该图标显示在 Experience Builder 组件中的组件旁边 面板。

如果不包含 SVG 资源,系统将使用默认图标 (默认组件图标)。

下面是一个简单的红色圆圈 SVG 资源,用于“Hello World”组件。An SVG 资源必须命名为 componentName.svg

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 
<svg xmlns="http://www.w3.org/2000/svg"
     width="400" height="400">
  <circle cx="100" cy="100" r="50" stroke="black"
    stroke-width="5" fill="red" />
</svg>

自选。将 CSS 资源添加到组件包

要设计你的 自定义组件,将 CSS 资源添加到组件包中。

这是 CSS 的 简单的类,以配合“Hello World”组件。CSS 资源必须命名为 componentName.css

.THIS .greeting {
    color: #ffe4e1;
    font-size: 20px;
}

创建类后,将其应用于组件。

<aura:component implements="forceCommunity:availableForAllPageTypes" access="global">
    <aura:attribute name="greeting" type="String" default="Hello" access="global" />
    <aura:attribute name="subject" type="String" default="World" access="global" />

    <div class="greeting">{!v.greeting}, {!v.subject}!</div>
</aura:component>

在Experience Builder中公开组件属性

您可以使用设计资源来控制在体验中显示哪些属性 建筑工人。设计资源与组件位于同一文件夹中。它描述了 Aura 组件的设计时行为 – 可视化工具显示 组件。

要使 Aura 组件属性可供管理员在 Experience Builder 中编辑,请在设计中为该属性添加一个节点 资源。当您将属性标记为必需时,该属性会自动显示在Experience Builder中,除非它 为其分配了默认值。design:attribute

您必须使用 default 指定必需的属性 在设计的组件定义中未标记为必需的值和属性 资源,使它们对用户显示。设计资源仅支持 、 或 类型的属性。intstringboolean

对于拖放组件,公开 属性将显示在组件的属性面板中。

对于主题布局组件,当主题布局 在“设置”|”主题面积。

为 Experience Builder 配置 Aura 组件的提示和注意事项

在为 光环网站。

组件

  • 使用设计文件元素中的属性为组件指定一个友好名称,例如 .label<design:component label=”foo”>
  • 将组件设计为填充 100% 的区域宽度(包括边距) 它们显示在。
  • 确保组件在声明性中提供适当的占位符行为 工具(如果需要交互)。
  • 切勿让组件显示空白框。想想其他网站是如何工作的。例如 Facebook 在源项从服务器返回之前显示源的轮廓, 这提高了用户对 UI 响应能力的感知。
  • 如果组件依赖于触发的事件,请为其指定之前显示的默认状态 事件触发。
  • 使用标准设计标记设置组件样式,使其与 Salesforce设计系统。
  • 请记住,Lightning Locker 是针对创建的所有 Aura 组件强制执行的 在 Summer ’17(API 版本 40.0)及更高版本中,当组织中启用了 Lightning Locker 时,并且 网站。在组织级别,如果 Lightning Web Security 尚未使用 Lightning Locker,则 Lightning Locker 正在使用 已启用。请参阅开发安全站点:CSP、LWS 和 Lightning Locker。
  • 对于自定义组件,当您在体验中使新属性可供编辑时 构建器,在进行网站翻译时,请牢记以下注意事项: 如果组件正在使用中 在Experience Builder的页面上,从页面中删除组件并将其替换为 更新后的版本。否则,当您导出网站内容进行翻译时, 对于导出文件中的该组件实例,将省略您添加的属性。如果 该组件包含已翻译的内容,请先将网站内容导出到 保留现有翻译。然后将组件替换为更新的 版本。

属性

  • 使用设计文件来控制向Experience Builder公开哪些属性。
  • 使您的属性易于使用,便于管理员理解。不要暴露 SOQL 查询、JSON 对象或 Apex 类名。
  • 为必需属性提供默认值,以避免用户体验不佳。当 具有必需属性且没有默认值的组件将添加到体验中 生成器,它看起来无效。
  • 使用基本支持的类型 (, , ) 公开的属性。stringintegerboolean
  • 为元素中的整数属性指定最小值和最大值,以控制接受值的范围。<design:attribute>
  • 请注意,字符串属性可以为数据源提供一组预定义的 值,允许属性将其配置公开为选择列表。
  • 为属性提供具有友好显示名称的标签。
  • 包括描述以解释预期数据并提供指南,例如 数据格式或预期的值范围。描述文本在 属性面板。
  • 若要删除实现接口的组件的设计属性,请首先 在删除 design 属性之前,从组件中删除接口。然后 重新实现接口。如果在网站页面中引用了该组件,则必须删除 该组件,然后才能更改它。forceCommunity:availableForAllPageTypes

支持的 Aura 组件、接口和事件

并非所有 Aura 组件、接口和事件都支持基于 Aura 的体验 建设者网站。有些仅适用于 Salesforce 移动应用程序或 Lightning Experience。 在自定义您的网站之前,请查看可用的内容。

Aura 组件、接口和事件记录在组件库中。每 组件、接口和事件指示它支持哪种体验。

个性化目标开发人员和组名称

在以下情况下确定体验变体目标的开发人员名称和组名称 使用 Connect REST API 或元数据 API 对 Experience Builder 站点进行个性化设置。

对于 Connect Rest API 的 Target Input 请求正文或 Audience 元数据类型的 PersonalizationTargetInfo 子类型,您必须指定:

  • 属性中的目标组名称groupName
  • 属性中的目标开发人员名称targetValue

若要确定这些名称,必须从 站点的 ExperienceBundle 文件夹。

确定这些值的方式会有所不同,具体取决于您是否定位到网页 变体、品牌集、组件 可见性或组件属性。

页面变体

要确定页面变体的组名称和开发人员名称,请打开相关的 路由文件和相应的视图文件。例如,打开 routes 文件夹中的 Home.json 文件和 views 文件夹中的 Home.json 文件。组名称Format: ,其中 是路由 JSON 文件的属性。route.idroute.idid

例: 63d9b8fe-99fc-4f54-b784-5034e09a6670开发商名称格式: ,其中:route.label_view.label_Page

  • route.label是路由 JSON 文件的属性。label
  • view.label是视图 JSON 文件的属性。label

例: Home_Gold_Home_Page

品牌集

若要确定品牌集的组名称和开发人员名称,请打开相关的 品牌设置文件和相应的主题文件。例如,在客户服务网站中, 打开 themes 文件夹中的 customerService.json 文件和 brandingSets 文件夹中的 customerService.json 文件。组名称格式: ,其中 是 主题 JSON 文件。theme.id$#$Brandingtheme.idid

例: 70ebee67-0fca-421e-ac32-12879ee55936$#$Branding开发商名称格式: ,其中:theme.developerName_brandingSet.label_Branding

  • theme.developerName是主题 JSON 文件的属性。developerName
  • brandingSet.label是品牌集 JSON 文件的属性。label

例: service_Customer_Service_Branding

组件可见性

确定组名和 开发人员名称 对于组件可见性,请打开包含该组件的视图文件。为 例如,打开 views 文件夹中的 Home.json 文件。组名称格式: ,其中:view.id$#$component.id

  • view.id是属性 的视图 JSON 文件。id
  • component.id是视图 JSON 文件中组件的属性。id

例: f8c9b721-0a1d-45bb-954f-3277a0501892$#$823cb1c0-697f-4b33-8fa4-a925aef98cf7开发商名称格式: ,其中:view.label_componentName_Component

  • view.label是视图 JSON 文件的属性。label
  • componentName是体验中组件的名称 生成器(不在 JSON 文件中)。

例: Home_Headline_Component

注意

如果 必要时,您可以向开发人员名称添加一个数值以使其唯一。为 例。Home_Page_Rich_Content_Editor_Component1

组件属性

对于组件属性,组和开发人员名称会有所不同,具体取决于 组件位于视图正文中,或者位于主题布局的页眉或页脚中。

视图主体中的组件

若要确定视图正文中组件的组和开发人员名称,请打开视图 包含组件的文件。例如,打开 Home.json 文件 在“视图”文件夹中。组名称格式: ,其中:view.id$#$component.id

  • view.id是属性 的视图 JSON 文件。id
  • component.id是视图 JSON 文件中组件的属性。id

例: f8c9b721-0a1d-45bb-954f-3277a0501892$#$823cb1c0-697f-4b33-8fa4-a925aef98cf7开发商名称格式: ,其中:view.label_componentName_Component_Properties

  • view.label是视图 JSON 文件的属性。label
  • componentName是体验中组件的名称 生成器(不在 JSON 文件中)。

例: Home_Headline_Component_Properties

注意

如有必要,您可以向开发人员名称添加一个数值,使其唯一。为 例。Home_Page_Rich_Content_Editor_Component1

页眉或页脚中的组件

确定 主题布局,打开包含组件的主题文件。例如,在 Customer 中 服务站点,在主题中打开 customerService.json 文件 文件夹。组名称格式: ,其中:themeLayout.id$#$component.id

  • themeLayout.id是包含组件的布局的属性。id
  • component.id是布局中组件的属性。id

例: 06ce2db9-2c79-4ccc-9ca8-94c7b50efb6b$#$c55d1908-fe6b-47e8-b41e-70ad05aeb490组件属性组名称开发商名称格式: ,其中:themeLayout.label_componentName_Component_Properties

  • themeLayout.label是包含组件的布局的属性。label
  • componentName是体验中组件的名称 生成器(不在 JSON 文件中)。

例: Default_Navigation_Menu_Component_Properties组件属性开发人员名称

遵守用户的个人信息可见性设置

具有门户和站点的组织提供特定设置来隐藏用户的个人信息 来自其他用户的身份信息和联系信息。这些设置不会在 Apex 中强制执行, 即使具有 Apex 安全功能,例如子句或方法。对来宾或外部隐藏特定字段 经过身份验证的用户,请遵循下面概述的示例代码。

WITH SECURITY_ENFORCEDstripInaccessible

若要在 User 对象中隐藏用户的个人信息,请执行以下操作:

public User[] fetchUserDetail(Set userIds) { 
    // Query all the fields of user which we are expected in user record to show that on UI or to 
    // perform some business logic. 
    User[] userRecords = [SELECT id, username, communitynickname, firstname, lastname, title 
    FROM User WHERE id IN :userIds]; 
 
    for (User userRecord : userRecords) { 
        // User is not fetching his own record and is not standard user. 
        if(userRecord.id != UserInfo.getUserId() && !Auth.CommunitiesUtil.isInternalUser()) { 
            // clear-out all PII fields form user record which we have queried above. 
            userRecord.username = ''; 
            userRecord.title = ''; 
        } 
    } 
    return userRecords;
}

遵守用户在社区中的联系信息可见性设置,或者 门户,我们检查与特定字段关联的首选项并显示或隐藏数据 因此。对于用户在 Experience Cloud 中的联系人可见性设置 网站:

public User[] fetchUserRecordRespectingFLVPreferences(Set<Id> userIds) {

    //Fetch users records along with fields specific user preferences.
    User[] userRecords = [SELECT email, UserPreferencesShowEmailToExternalUsers, UserPreferencesShowEmailToGuestUsers FROM User WHERE id IN :userIds];

    // If context user is internal user then return result without any restriction.
    if (Auth.CommunitiesUtil.isInternalUser()) {
        return userRecords;
    }

    // If user is guest user then return result as per the user's UserPreference for the fields related to the Guest user visibility.
    if (Auth.CommunitiesUtil.isGuestUser()){
        return fetchUserRecordForGuestUser(userRecords);
    }

    // Return result as per the user's UserPreference for the fields related to the External user visibility 
    return fetchUserRecordForExternalUser(userRecords);

}

// Apply Field level visibilty logic by checking user's UserPreferences for the fields related to the External user visibility.
public User[] fetchUserRecordForExternalUser(User[] userRecords) {

    for(User userRecord : userRecords) {

        //Clear field of user record when context user fetching other user's record and Field Level Visibility for that field is set to Restricted.
        if(userRecord.id != UserInfo.getUserId() && !userRecord.UserPreferencesShowEmailToExternalUsers)
        {
            userRecord.email = '';
        }

    }   

    return userRecords;         
}

// Apply Field level visibilty logic by checking user's UserPreferences for the fields related to the Guest user visibility.
public User[] fetchUserRecordForGuestUser(User[] userRecords) {

    for(User userRecord : userRecords) {

        //Clear field of user record when context user fetching other user's record and user preference for that field is NOT set to public.
        if(!userRecord.UserPreferencesShowEmailToGuestUsers)
        {
            userRecord.email = '';
        }

    }   

    return userRecords;       

}