Salesforce Experience Cloud 技术深度解析:构建社区站点 (Community Sites)
背景与应用场景
在数字化转型的浪潮中,企业 increasingly seek to build engaging online spaces to connect with their customers, partners, and employees. Salesforce Experience Cloud, formerly known as Community Cloud, is a powerful platform designed precisely for this purpose. It enables the rapid creation of branded, secure, and intelligent digital experiences, all built on the trusted Salesforce platform.
作为一名 Salesforce 技术架构师,理解 Experience Cloud 的核心能力与架构是设计可扩展、安全且高性能解决方案的关键。这些数字体验站点(通常仍被称为 Community Sites)不仅仅是简单的网站,它们是深入集成到企业 CRM 数据和业务流程中的动态门户。
常见的应用场景包括:
- 客户自助服务门户 (Customer Self-Service Portal): 客户可以在这里查找知识库文章、提交和跟踪支持个案 (Cases)、参与社区讨论,从而降低服务成本并提升客户满意度。
- 合作伙伴关系管理门户 (Partner Relationship Management Portal): 合作伙伴可以通过门户进行交易注册 (Deal Registration)、管理销售线索 (Leads) 和业务机会 (Opportunities)、获取营销资料,与企业实现无缝的销售协同。
- 员工社区 (Employee Community): 为员工提供一个集中的平台,用于获取公司信息、进行内部协作、访问人力资源系统等,增强员工归属感和工作效率。
这些门户的核心价值在于,它们将正确的数据和流程在正确的时间,安全地呈现在正确的用户面前。而这一切的实现,都依赖于其背后精巧的技术架构。
原理说明
要精通 Experience Cloud,我们必须深入理解其三大技术支柱:用户许可模型、安全与共享模型,以及 UI 自定义框架。
1. 用户许可与身份 (User Licensing and Identity)
与标准的 Salesforce 内部用户不同,社区用户使用专门的外部许可证。许可证的选择直接决定了成本、功能和数据访问能力,是架构设计的第一步。
- Customer Community: 这是为 B2C 场景设计的高容量许可证。用户通常需要访问个案 (Case)、知识 (Knowledge) 以及有限的账户 (Account) 和联系人 (Contact) 数据。这类许可证的用户不使用 Salesforce 的标准角色层级 (Role Hierarchy)。
- Customer Community Plus: 适用于 B2B 场景,提供了比 Customer Community 更强的数据访问能力。用户可以被分配角色,访问报表和仪表盘,并能与非自己拥有的记录进行交互(通过高级共享规则)。
- Partner Community: 功能最强大的外部许可证,专为合作伙伴设计。用户可以访问销售对象,如销售线索 (Lead) 和业务机会 (Opportunity),并拥有完整的角色层级功能,以便在合作伙伴自己的客户团队内管理数据可见性。
选择正确的许可证是项目成功的基石,因为它直接影响了后续安全模型的设计。
2. 安全与共享模型 (Security and Sharing Model)
社区的安全性是重中之重,因为它直接面向外部用户。其模型在 Salesforce 标准安全模型的基础上,针对外部场景进行了扩展。
- 基础层 (Foundation): 用户的简档 (Profile) 和权限集 (Permission Set) 决定了他们对对象 (Object) 和字段 (Field) 的访问权限(创建、读取、更新、删除)。对于外部用户,务必遵循最小权限原则。
- 记录级共享 (Record-Level Sharing): 这是社区安全的核心。
- 组织范围默认设置 (Organization-Wide Defaults, OWD): 对于外部用户的 OWD 设置通常是 `Private`,确保用户默认无法看到不属于他们的数据。
- 共享集 (Sharing Set): 这是为高容量社区用户(如 Customer Community 许可证)共享记录的主要机制。它基于用户与记录之间的直接或间接查找关系(如用户的联系人记录与个案上的联系人字段相关联)来授予访问权限。例如,一个规则可以定义为:“允许用户访问所有与他们所在客户 (Account) 相关联的个案”。
- 共享组 (Share Group): 允许您与拥有特定记录访问权限的内部或外部用户共享由共享集授予访问权限的记录。这在需要跨客户共享记录的复杂场景中非常有用。
- 外部客户层级 (External Account Hierarchy): 允许合作伙伴在他们自己的客户层级结构中共享数据,而不影响其他合作伙伴。
3. UI 与自定义 (UI and Customization)
Experience Cloud 提供了强大的声明式和编程化工具来构建用户界面。
- Experience Builder: 一个所见即所得的拖放式构建器,用于组装页面、配置组件和定义品牌主题。 - 主题与品牌 (Themes and Branding): 允许您轻松更改颜色、字体和徽标,以匹配企业 VI。 - 页面和布局 (Pages and Layouts): 您可以创建不同的页面布局,并根据受众 (Audience) 或用户简档来控制其可见性。
- Lightning Web Components (LWC) 和 Aura Components: 当标准组件无法满足复杂的业务需求时,可以使用 LWC 或 Aura 开发自定义组件。LWC 是现代、高性能的推荐框架,它利用了最新的 Web 标准,为社区用户提供快速、响应灵敏的体验。
示例代码
在社区中,最常见的需求之一是显示与当前登录用户相关的数据。下面的示例演示了如何使用一个 Apex 控制器和一个 LWC 组件,安全地查询并显示当前社区用户所属客户 (Account) 的所有相关个案 (Cases)。
这个例子严格遵循 Salesforce 官方推荐的最佳实践,特别是 `with sharing` 的使用,以确保数据安全。
1. Apex 控制器: `CommunityCaseController.cls`
这个控制器负责查询数据。关键点在于使用 with sharing
关键字,它会强制执行当前用户的共享规则,确保用户只能看到他们有权访问的个案记录。
// 从 Salesforce 官方 LWC Recipes 示例改编 // 使用 'with sharing' 确保严格遵守当前用户的共享规则,这是社区开发中的安全最佳实践。 public with sharing class CommunityCaseController { // @AuraEnabled(cacheable=true) 注解使方法可以被 LWC 调用,并启用客户端缓存以提升性能。 @AuraEnabled(cacheable=true) public static List<Case> getCasesForCurrentUser() { // 获取当前登录用户的信息。在社区上下文中,这将是社区用户的 User Id。 Id currentUserId = User.getUserId(); // 查询与当前用户关联的联系人记录。 // 这是确定用户所属客户的常用方法。 User currentUser = [SELECT Id, ContactId FROM User WHERE Id = :currentUserId LIMIT 1]; if (currentUser.ContactId == null) { // 如果用户没有关联的联系人,则返回空列表,避免出错。 return new List<Case>(); } // 根据联系人ID查询其所属的客户ID。 Contact userContact = [SELECT Id, AccountId FROM Contact WHERE Id = :currentUser.ContactId LIMIT 1]; if (userContact.AccountId == null) { // 如果联系人没有关联到客户,也返回空列表。 return new List<Case>(); } // 查询该客户下的所有个案。 // 由于类是 'with sharing' 的,Salesforce 将自动应用共享规则。 // 用户只能看到他们在共享集(Sharing Set)或其它共享规则中被授予访问权限的个案。 return [ SELECT Id, CaseNumber, Subject, Status, CreatedDate FROM Case WHERE AccountId = :userContact.AccountId ORDER BY CreatedDate DESC LIMIT 50 ]; } }
2. LWC 组件: `communityCaseList`
这个组件通过 @wire
服务调用 Apex 方法,并以响应式的方式将数据显示在页面上。
communityCaseList.html
<template> <lightning-card title="My Team's Cases" icon-name="standard:case"> <div class="slds-p-around_medium"> <!-- 如果 @wire 正在加载数据,显示加载提示 --> <template if:true={cases.data}> <table class="slds-table slds-table_cell-buffer slds-table_bordered"> <thead> <tr class="slds-line-height_reset"> <th scope="col"><div class="slds-truncate" title="Case Number">Case Number</div></th> <th scope="col"><div class="slds-truncate" title="Subject">Subject</div></th> <th scope="col"><div class="slds-truncate" title="Status">Status</div></th> </tr> </thead> <tbody> <!-- 遍历从 Apex 返回的个案列表 --> <template for:each={cases.data} for:item="caseRec"> <tr key={caseRec.Id}> <td data-label="Case Number"><div class="slds-truncate">{caseRec.CaseNumber}</div></td> <td data-label="Subject"><div class="slds-truncate">{caseRec.Subject}</div></td> <td data-label="Status"><div class="slds-truncate">{caseRec.Status}</div></td> </tr> </template> </tbody> </table> </template> <!-- 如果 @wire 返回错误,显示错误信息 --> <template if:true={cases.error}> <p>An error occurred while loading cases.</p> </template> </div> </lightning-card> </template>
communityCaseList.js
import { LightningElement, wire } from 'lwc'; // 导入 Apex 方法 import getCasesForCurrentUser from '@salesforce/apex/CommunityCaseController.getCasesForCurrentUser'; export default class CommunityCaseList extends LightningElement { // 使用 @wire 服务以响应式方式调用 Apex 方法。 // 当组件加载时,它会自动调用 getCasesForCurrentUser。 // 如果 Apex 方法的依赖数据发生变化,@wire 会自动重新获取数据。 // 返回的结果(数据或错误)会赋给 cases 属性。 @wire(getCasesForCurrentUser) cases; }
注意事项
在设计和实施社区解决方案时,架构师必须密切关注以下几点:
- 权限与安全 (Permissions & Security):
- Guest User Security: 访客用户(未登录用户)的安全性至关重要。Salesforce 近年来持续收紧访客用户安全策略,务必在“共享设置”中启用“保护对访客用户记录的访问”,并仔细审查访客用户简档,移除所有不必要的对象和字段权限。
- Apex Sharing: 除非有充分的、经过安全审查的理由,否则所有暴露给社区的 Apex 控制器都应使用
with sharing
。避免使用without sharing
,因为它会绕过用户的共享规则,可能导致数据泄露。 - 字段级安全 (FLS): 确保外部用户简档只对必要的字段有读取或编辑权限。
- API 限制与性能 (API Limits & Performance):
- Governor Limits: 社区用户的每一次操作(如加载 LWC、提交表单)都会消耗组织的 SOQL 查询、DML 操作和 API 调用等限制。对于高流量的社区,必须进行容量规划,以避免达到组织限制。
- 缓存: 充分利用 Salesforce 提供的 CDN 缓存静态资源。在 LWC 中,使用
@wire
并将 Apex 方法标记为(cacheable=true)
,以利用客户端缓存,减少不必要的服务器调用。 - 页面加载时间: 优化 LWC 组件,避免在单次交互中执行过多的服务器请求。对图片等静态资源进行压缩,并考虑使用懒加载 (lazy loading) 技术。
- 部署 (Deployment):
- ExperienceBundle: 现代的社区部署使用
ExperienceBundle
和DigitalExperience
元数据类型。这使得通过 SFDX 或变更集 (Change Set) 进行部署和版本控制变得更加可靠和可读。避免依赖手动配置。
- ExperienceBundle: 现代的社区部署使用
总结与最佳实践
成功构建一个 Salesforce Experience Cloud 站点,不仅仅是拖拽组件那么简单。它需要技术架构师从全局视角进行规划,平衡功能、安全、性能和成本。
以下是关键的最佳实践:
- 从许可证开始规划 (License First): 在项目初期,根据业务需求和用户交互模型,仔细选择最合适的社区许可证。这是后续所有技术决策的基础。
- 安全优先的设计 (Security by Design): 始终采用最小权限原则。默认关闭所有访问,然后根据明确的业务需求,通过共享集、权限集等工具逐一开放。定期审计外部用户的权限。
- 声明式优先,编程为辅 (Declarative Before Code): 尽可能利用 Experience Builder 的标准组件、Flows 和配置能力。只有在声明式工具无法满足需求时,才考虑开发自定义 LWC 组件。这能降低维护成本和开发周期。
- 为可扩展性而设计 (Design for Scale): 对于预计用户量或数据量较大的社区,要提前考虑性能问题。优化 Apex 和 SOQL,合理设计数据模型以避免数据倾斜 (data skew),并充分利用缓存机制。
- 以用户为中心 (User-Centric Experience): 外部用户可能不熟悉 Salesforce 的界面。设计时应力求简洁、直观,提供清晰的导航和友好的错误提示,确保卓越的用户体验。
遵循这些原则,您将能够构建出不仅功能强大,而且安全、可靠、深受用户喜爱的 Salesforce Experience Cloud 站点,为企业创造真正的商业价值。
评论
发表评论