无法使用 流生成器。但是,在 Visualforce 页面中嵌入流程后,即可使用 Apex 代码 和 Visualforce 标记,用于在运行时配置流程,例如在 Visualforce 页面和流程,或在运行时自定义流程的外观。
流是一个应用程序,用于收集、更新、编辑、 并创建 Salesforce 信息。
以下主题演示如何在 Visualforce 中嵌入和配置流程 页。
- 在 Visualforce 页面中嵌入流程 要自定义流程的外观或增强其功能,请将其嵌入到 Visualforce 页面
 中。如果您的组织为站点和门户启用了流程,请使用 Visualforce 页面将流程传送到您的 Salesforce 站点、门户或 Experience Cloud 站点。
- 使用 <flow:interview> 的高级示例
 该组件旨在使开发复杂的 Visualforce 交互变得容易。您可以通过创建自定义控制器来访问流中的其他功能。使用自定义控制器,您可以构建一个包含多个组件的页面,这些组件可以相互交互。组织内的任何流都可以由其自己的 Apex 类型单独引用,并且流中的变量可以作为成员变量进行访问。<flow:interview>
- 从 Visualforce 页面设置流变量值 将流程嵌入 Visualforce 页面
 后,通过组件设置变量、记录变量、集合变量和记录集合变量的初始值。<apex:param>
- 将流变量值获取到 Visualforce 页面 流变量值可以显示在 Visualforce 页面
 中。将流程嵌入 Visualforce 页面后,您可以使用 Visualforce 标记来获取变量的值或记录变量。若要显示集合变量或记录集合变量的值,可以使用 Visualforce 标记来获取集合中包含的各个值。
- 控制用户是否可以暂停 Visualforce 页面中的流程 使用组件将流程嵌入到 Visualforce 页面中后,请考虑是否允许用户暂停该页面
 中的流程。将该属性设置为 false 可防止用户暂停。<flow:interview>allowShowPause
- 自定义用户如何恢复暂停的流程面试 默认情况下,用户可以从其主页上的“暂停面试”组件恢复暂停的面试
 。如果要自定义用户恢复采访的方式和位置,请使用组件上的属性。pausedInterviewId<flow:interview>
- 在流程中配置 finishLocation 属性 如果未指定,则单击“完成”的用户将开始新的面试,并看到流程的第一个屏幕。
 您可以使用函数、变量或控制器来调整用户在最后一个屏幕上单击“完成”时发生的情况。finishLocationURLFOR$Page
- 自定义流程的用户界面
 在 Visualforce 页面中嵌入流程后,您可以通过使用 CSS 应用自定义样式来自定义流程在运行时的外观。使用流属性和 CSS 类的组合,您可以自定义流的各个部分,例如按钮位置、按钮样式、背景以及屏幕标签的外观。
- 在 Visualforce 页面中渲染流的 Lightning 运行时 默认情况下,当您在 Visualforce 页面
 中嵌入流时,该流将在 Classic 运行时中呈现。顾名思义,Classic 运行时的外观和感觉类似于常规的 Visualforce 页面和 Salesforce Classic 桌面体验。如果您希望流程在 Visualforce 页面的 Lightning 运行时中呈现,请将流程 Aura 组件嵌入到 Visualforce 页面。
在 Visualforce Pages 中嵌入流程
要自定义流的外观或增强其功能,请将其嵌入到 Visualforce 页面。如果您的组织为站点和门户启用了流程,请使用 Visualforce 页面,将流程传送到您的 Salesforce 站点、门户或 Experience Cloud 网站。
注意
用户只能运行具有活动状态的流 版本。如果嵌入的流没有活动版本,用户会看到错误 消息。如果嵌入的流包含 Subflow 元素,则引用的流 并且由 Subflow 元素调用必须具有活动版本。要向 Visualforce 页面添加流程,请使用以下组件嵌入该流程:
<flow:interview>
- 查找流的 API 名称。
- 在“设置”中,输入“快速” “查找”框,然后选择“流”。Flows
- 单击要嵌入的流的名称。
 
- 定义新的 Visualforce 页面或打开要编辑的页面。
- 添加组件, 在标签之间的某个地方。<flow:interview><apex:page>
- 将属性设置为唯一属性 流的名称。例如:name<apex:page> <flow:interview name="flowAPIName"/> </apex:page>注意如果流程是 在托管包中,该属性必须是 采用以下格式:.namenamespace.flowuniquename
- 通过为 包含它的 Visualforce 页面。若要运行流,外部用户(例如 在 Experience Cloud 站点上)需要访问 Visualforce 页面。要运行 流程中,内部用户需要访问 Visualforce 页面,并且:
- “运行流”权限
- 在其用户上启用了 Flow User 字段 详情页面
- 如果覆盖默认行为并限制对 已启用的配置文件或权限集被选中 单个流,用户按配置文件访问该流 或权限集
 
在流程中设置变量值
在这个 例如,我们将构建一个简单的流程,以允许客户支持代理 通过创建案例对调制解调器问题进行故障排除。您可以在启动流通过组件时设置变量的值。对于我们的 示例,设置使用初始值调用的案例编号变量 01212212当流加载时,请使用以下标记:
<apex:param>vaCaseNumber
<apex:page>
    <flow:interview name="ModemTroubleShooting">
        <apex:param name="vaCaseNumber" value="01212212"/>
    </flow:interview>
</apex:page>您还可以使用标准 Visualforce 控制器设置变量。例如,如果 Visualforce页面正在使用控制器,可以增强页面传入标准中的数据 控制器。
standardCase
<apex:page standardController="Case" tabStyle="Case" >
    <flow:interview name="ModemTroubleShooting">
        <apex:param name="vaCaseNumber" value="{!Case.CaseNumber}"/>
    </flow:interview>
</apex:page>有关设置变量值的更多示例,请参见从 Visualforce 页面设置流变量值。为 有关从流程中获取变量值以在 Visualforce 中显示的信息 页面上,请参阅将流变量值获取到 Visualforce 页面。
设置 finishLocation 属性
基于调制解调器故障排除示例,我们还将设置属性以将用户重定向到 Salesforce 主页 页面,当他们单击末尾的“完成”按钮时 流。
finishLocation
<apex:page standardController="Case" tabStyle="Case" >
    <flow:interview name="ModemTroubleShooting" finishLocation="{!URLFOR('/home/home.jsp')}">
        <apex:param name="vaCaseNumber" value="{!case.CaseNumber}"/>
    </flow:interview>
</apex:page>有关设置的更多示例,请参阅在流中配置 finishLocation 属性。finishLocation
使用 <flow:interview> 的高级示例
组件设计 以便轻松开发复杂的 Visualforce 交互。您可以 通过创建自定义控制器来访问流程中的其他功能。带定制 控制器,您可以构建一个包含多个组件的页面,这些组件可以与每个组件进行交互 其他。组织内的任何流都可以由其自己的 Apex 单独引用 类型,并且流中的变量可以作为成员变量进行访问。
<flow:interview>
注意
你 只能设置允许输入访问的变量,并且只能获取 允许输出访问。对于不允许输入或输出访问的变量,尝试 get 变量被忽略,并且 Visualforce 页面、其组件或 Apex 类的编译可能会失败。<apex:page>在下一个示例中,API 名称为“ModemTroubleShooting”的流是 引用为 。标记演示了如何显示 不同部分的流变量的值 页:
Flow.Interview.ModemTroubleShooting
<apex:page Controller="ModemTroubleShootingCustomSimple" tabStyle="Case">
    <flow:interview name="ModemTroubleShooting" interview="{!myflow}"/>
    <apex:outputText value="Default Case Prioriy: {!casePriority}"/>
</apex:page>注意
如果流程是 在托管包中,该属性必须是 采用以下格式:.namenamespace.flowuniquename上述标记的控制器如下所示 这:
public class ModemTroubleShootingCustomSimple {
    // You don't need to explicitly instantiate the Flow object;
    // the class constructor is invoked automatically
    public Flow.Interview.ModemTroubleShooting myflow { get; set; }
    public String casePriority;
    public String getCasePriority() {
        // Access flow variables as simple member variables with get/set methods
        if(myflow == null) return 'High';
        else return myflow.vaCasePriority;
    }
}如果您使用的是自定义控制器,您还可以设置 流构造函数中流开头的变量。传入 使用构造函数的变量是可选的,如果是 使用标签来设置值。<apex:param>下面是一个自定义控制器的示例,该控制器在 一个 构造 函数。
public class ModemTroubleShootingCustomSetVariables {
    public Flow.Interview.ModemTroubleShooting myflow { get; set; }
 
    public ModemTroubleShootingCustomSetVariables() {
        Map<String, Object> myMap = new Map<String, Object>();
        myMap.put('vaCaseNumber','123456');
        myflow = new Flow.Interview.ModemTroubleShooting(myMap);
    }
 
    public String caseNumber { set; }
    public String getCaseNumber() {
        return myflow.vaCaseNumber;
    }
}您可以使用类中的方法访问 流变量。变量可能位于 Visualforce 页面中嵌入的流程中,也可能位于 由 Subflow 元素调用的单独流。返回的变量值来了 无论面试当前从哪个流程运行。如果指定的变量 在该流中找不到,该方法将返回 。此方法在运行时检查变量是否存在 只是,而不是在编译时。getVariableValueFlow.Interviewnull此示例使用该方法获取痕迹导航 (导航)来自流的信息。如果该流包含子流元素,并且 每个引用的流还包含一个变量,您可以为用户提供痕迹导航,而不管哪个流 面试是 运行。
getVariableValuevaBreadCrumb
public class SampleController {
   //Instance of the flow
   public Flow.Interview.Flow_Template_Gallery myFlow {get; set;}
   public String getBreadCrumb() {
      String aBreadCrumb;
      if (myFlow==null) { return 'Home';}
      else aBreadCrumb = (String) myFlow.getVariableValue('vaBreadCrumb');
      return(aBreadCrumb==null ? 'Home': aBreadCrumb);
   }
}下表显示了 流量和顶点。
| 流 | 顶点 | 
|---|---|
| 发短信 | 字符串 | 
| 数 | 十进制 | 
| 货币 | 十进制 | 
| 日期 | 日期、日期时间 | 
| 布尔 | 布尔 | 
| 使用指定对象进行记录 | 指定对象的 API 名称,例如 Account 或 箱 | 
由于针对 Apex 代码编写测试是一种很好的做法,因此以下是 编写测试类的简单示例:
ModemTroubleShootingCustomSetVariables
@isTest
private class ModemTroubleShootingCustomSetVariablesTest {
    static testmethod void ModemTroubleShootingCustomSetVariablestests() {
        PageReference pageRef = Page.ModemTroubleShootingSetVariables;
        Test.setCurrentPage(pageRef);
        ModemTroubleShootingCustomSetVariables mytestController = 
            new ModemTroubleShootingCustomSetVariables();
        System.assertEquals(mytestController.getcaseNumber(), '01212212');
    }
}设置 reRender 属性
通过使用该属性,组件将重新呈现 在不刷新整个页面的情况:reRender<flow:interview />
<apex:page Controller="ModemTroubleShootingCustomSimple" tabStyle="Case">
    <flow:interview name="ModemTroubleShooting" interview="{!myflow}" 
     reRender="casePrioritySection"/>
    <apex:outputText id="casePrioritySection" 
     value="Default Case Prioriy: {!casePriority}"/>
</apex:page>警告
如果未设置属性,则当您单击按钮导航到其他按钮时 屏幕中,整个 Visualforce 页面都会刷新, 不仅仅是组件。reRender<flow:interview>
从 Visualforce 页面设置流变量值
将流程嵌入 Visualforce 页面后,设置变量的初始值。 通过组件记录变量、集合变量和记录集合变量。
<apex:param>
注意
您只能在面试开始时设置变量。标签仅评估一次, 当流量 推出。<apex:param>
你 只能设置允许输入访问的变量。如果引用的变量 不允许输入访问,则忽略设置变量的尝试。 Visualforce 页面、其组件或 Apex 的编译可能会失败 类。<apex:page>
下表列出了设置流变量 record 的方法 变量,并使用 Visualforce 记录集合变量值。
| 方法 | 变量 | 记录变量 | 集合变量 | 记录集合变量 | 
|---|---|---|---|---|
| 没有 控制器 |  | |||
| 与标准 控制器 |  |  | ||
| 使用标准列表 控制器 |  | |||
| 使用自定义 Apex 控制器 |  |  |  |  | 
| 接受采访 地图 |  |  |  |  | 
设置不带 控制器
此示例将 myVariable 设置为面试开始时的值。01010101
<apex:page>
    <flow:interview name="flowname">
        <apex:param name="myVariable" value="01010101"/>
    </flow:interview>
</apex:page>使用标准设置变量值 控制器
您可以使用标准 Visualforce 控制器通过从记录传入数据来设置变量。此示例集 面试时 myVariable 到 Visualforce 表达式的初始值 开始。{!account}
<apex:page standardController="Account" tabStyle="Account">
    <flow:interview name="flowname">
        <apex:param name="myVariable" value="{!account}"/>
    </flow:interview>
</apex:page>设置记录集合变量值 使用标准列表控制器
由于记录集合变量表示值数组,因此必须使用 标准列表控制器或自定义 Apex 控制器。此示例将 myCollection 设置为面试开始时的值。{!accounts}
<apex:page standardController="Account" tabStyle="Account" recordSetVar="accounts">
    <flow:interview name="flowname">
        <apex:param name="myCollection" value="{!accounts}"/>
    </flow:interview>
</apex:page>使用自定义 Apex 设置变量值 控制器
要对 Visualforce 页面进行比标准控制器允许的更精细的控制,请编写 设置变量值的自定义 Apex 控制器,然后引用该变量值 控制器。此示例使用 Apex 将 myVariable 设置为特定帐户的 ID,当 面试开始。
public class MyCustomController {
    public Account apexVar {get; set;}
    public MyCustomController() {
        apexVar = [
            SELECT Id, Name FROM Account
            WHERE Name = 'Acme' LIMIT 1];
    }
}<apex:page controller="MyCustomController">
    <flow:interview name="flowname">
        <apex:param name="myVariable" value="{!apexVar}"/>
    </flow:interview>
</apex:page>此示例使用 Apex 将记录集合变量 myAccount 设置为 Name 为 的每条记录的 Id 和 Name 字段值。Acme
public class MyCustomController {
    public Account[] myAccount { 
        get {
            return [ 
                SELECT Id, Name FROM account 
                WHERE Name = 'Acme'
                ORDER BY Id
            ] ;
        }
        set {
            myAccount = value;
        }
    }
    public MyCustomController () {
    }
}<apex:page id="p" controller="MyCustomController">
    <flow:interview id="i" name="flowname">
        <apex:param name="accountColl" value="{!myAccount}"/>
    </flow:interview>
</apex:page>在面试中设置变量值 地图
此示例使用面试映射在面试开始时将 accVar 的值设置为特定客户的 Id。
public class MyCustomController {
    public Flow.Interview.TestFlow myflow { get; set; }
     public MyCustomController() {
        Map<String, Object> myMap = new Map<String, Object>();
        myMap.put('accVar', [SELECT Id FROM Account 
                             WHERE Name = 'Acme' LIMIT 1]);
        myflow = new Flow.Interview.ModemTroubleShooting(myMap);
    }
}<apex:page controller="MyCustomController">
    <flow:interview name="flowname" interview="{!myflow}"/>
</apex:page>下面是一个类似的示例,该示例在面试开始时将 accVar 的值设置为新帐户。
public class MyCustomController {
    public Flow.Interview.TestFlow myflow { get; set; }
     public MyCustomController() {
        Map<String, List<Object>> myMap = new Map<String, List<Object>>();
        myMap.put('accVar', new Account(name = 'Acme'));
        myflow = new Flow.Interview.ModemTroubleShooting(myMap);
    }
}<apex:page controller="MyCustomController">
    <flow:interview name="flowname" interview="{!myflow}"/>
</apex:page>此示例使用映射将两个值添加到字符串集合变量 (stringCollVar) 和两个值到一个数字集合 变量 (numberCollVar)。
public class MyCustomController {
    public Flow.Interview.flowname MyInterview { get; set; }
    public MyCustomController() {
        String[] value1 = new String[]{'First', 'Second'};
        Double[] value2 = new Double[]{999.123456789, 666.123456789};
        Map<String, Object> myMap = new Map<String, Object>();
        myMap.put('stringCollVar', value1);
        myMap.put('numberCollVar', value2);
        MyInterview = new Flow.Interview.flowname(myMap);
    }
}<apex:page controller="MyCustomController">
    <flow:interview name="flowname" interview="{!MyInterview}" />
</apex:page>将流变量值获取到 Visualforce 页面
流变量值可以显示在 Visualforce 页面中。一旦你 将您的流程嵌入到 Visualforce 页面中,您可以使用 Visualforce 标记 获取变量的值或记录变量。显示集合的值 变量或记录集合变量,您可以使用 Visualforce 标记来获取 集合中包含的单个值。
注意
你 只能获取允许输出访问的变量。如果引用不允许输出访问的变量, 获取变量的尝试将被忽略。Visualforce 页面、其组件或 顶点类。<apex:page>下面的示例使用 Apex 类从 flow,然后在 Visualforce 中显示它 页。
public class FlowController {
    public Flow.Interview.flowname myflow { get; set; }
    public Case apexCaseVar;
    public Case getApexCaseVar() {
        return myflow.caseVar;
    }
}<apex:page controller="FlowController" tabStyle="Case">
    <flow:interview name="flowname" interview="{!myflow}"/>
    <apex:outputText value="Default Case Priority: {!apexCaseVar.Priority}"/>
</apex:page>这 示例使用 Apex 类获取存储在字符串集合中的值 变量 (emailsCollVar)。然后,它使用 Visualforce 页面运行 流程面试。Visualforce 页面将循环访问流程的集合变量,并显示 中的每一项 收集。
public class FlowController {
    public Flow.Interview.flowname myflow { get; set; }
    public List<String> getVarValue() {
        if (myflow == null) { 
            return null; 
        }
        else {
            return (List<String>)myflow.emailsCollVar;
        }
    }
}<apex:page controller="FlowController">
    <flow:interview name="flowname" interview="{!myflow}" />
        <apex:repeat value="{!varValue}" var="item">
        <apex:outputText value="{!item}"/><br/>
        </apex:repeat>
</apex:page>这 以下示例使用 Apex 类将流程设置为,然后使用 Visualforce 页面运行 流程面试。Visualforce 页面使用数据表循环访问流程的记录集合 变量,并显示 收集。{!myflow}
public class MyCustomController {
   public Flow.Interview.flowname myflow { get; set; }
}<apex:page controller="MyCustomController" tabStyle="Account">
   <flow:interview name="flowname" interview="{!myflow}" reRender="nameSection" />
    <!-- The data table iterates over the variable set in the "value" attribute and 
         sets that variable to the value for the "var" attribute, so that instead of 
         referencing {!myflow.collectionVariable} in each column, you can simply refer 
         to "account".-->
    <apex:dataTable value="{!myflow.collectionVariable}" var="account" 
        rowClasses="odd,even" border="1" cellpadding="4" id="nameSection">
        <!-- Add a column for each value that you want to display.-->
        <apex:column >
            <apex:facet name="header">Name</apex:facet>
            <apex:outputlink value="/{!account['Id']}">
                {!account['Name']}
            </apex:outputlink>
        </apex:column>
        <apex:column >
            <apex:facet name="header">Rating</apex:facet>
            <apex:outputText value="{!account['Rating']}"/>
        </apex:column>
        <apex:column >
            <apex:facet name="header">Billing City</apex:facet>
            <apex:outputText value="{!account['BillingCity']}"/>
        </apex:column>
        <apex:column >
            <apex:facet name="header">Employees</apex:facet>
            <apex:outputText value="{!account['NumberOfEmployees']}"/>
        </apex:column>
    </apex:dataTable>
</apex:page>取决于 在流中记录集合变量的内容上,内容如下 该数据表如下所示。
控制用户是否可以暂停来自 Visualforce 的流程 页
使用组件在 Visualforce 页面中嵌入流程后,请考虑是否要让用户暂停流程 那一页。将属性设置为 false 阻止用户暂停。
<flow:interview>allowShowPause是否显示“暂停”按钮取决于三个设置。
- 组织的流程自动化设置必须启用允许用户暂停流程。
- 为此,不能是假的。默认值为 真。<flow:interview>allowShowPause
- 每个屏幕都必须配置为显示“暂停”按钮。
例
在 Visualforce 页面中,您嵌入了一个包含三个屏幕的流程。屏幕 1 是 配置为显示“暂停”按钮。屏幕 2 和 3 配置为 不显示“暂停”按钮。
| 允许用户暂停流(过程自动化设置) | allowShowPause(视觉力 组件) | 结果暂停按钮 | 
|---|---|---|
| 启用 | true或未设置 | 暂停按钮仅出现在第一个屏幕上 | 
| 启用 | false | 此 Visualforce 页面中的任何屏幕均未显示暂停按钮 | 
| 未启用 | true或未设置 | 暂停按钮不会出现在任何屏幕上 | 
此示例将 MyUniqueFlow 流嵌入到 Visualforce 页面中,并且不允许“暂停”按钮 出现。
<apex:page>   
   <flow:interview name="MyUniqueFlow" allowShowPause="false" />
</apex:page>自定义用户恢复暂停流程访谈的方式
默认情况下,用户可以从“暂停的面试”中恢复暂停的面试 组件。如果要自定义用户恢复其恢复的方式和位置 interviews,请使用组件上的属性。
pausedInterviewId<flow:interview>以下示例显示了如何恢复面试或开始新的面试 一个 – 从页面布局上的按钮。当用户单击“调查”时 客户从联系人记录中,Visualforce 页面执行以下两项操作之一: 取决于用户是否对“调查客户”流程进行了任何暂停的访谈。
- 如果用户这样做,它将恢复第一个。
- 如果用户不这样做,它会启动一个新的。
创建 Visualforce 和 Apex 控制器
因为 Visualforce 页面将是 在特定于联系人的按钮中引用,它必须使用该标准控制器。使用 控制器扩展,以使用 Apex 向页面添加更多逻辑,这是页面获取的位置 要恢复的面试的 ID。
<apex:page
   standardController="Contact" extensions="MyControllerExtension_SurveyCustomers">
   <flow:interview name="Survey_Customers" pausedInterviewId="{!pausedId}"/>
</apex:page>此 Apex 控制器扩展执行 SOQL 查询以获取暂停访谈的列表。如果 查询中不返回任何内容,返回 null 值,并且 Visualforce 页面将开始新的面试。如果至少一个 interview 从查询中返回,则 Visualforce 页面将恢复 那个列表。getPausedId()
public class MyControllerExtension_SurveyCustomers {
    
    // Empty constructor, to allow use as a controller extension
    public MyControllerExtension_SurveyCustomers(
        ApexPages.StandardController stdController) { }
    
    // Flow support methods
    public String getInterviews() { return null; }
    
    public String showList { get; set; }
    
    public String getPausedId() {
        String currentUser = UserInfo.getUserId();
        List<FlowInterview> interviews = 
            [SELECT Id FROM FlowInterview WHERE CreatedById = :currentUser AND InterviewLabel LIKE '%Survey Customers%'];
        if (interviews == null || interviews.isEmpty()) {
            return null; // early out
        }
        
        // Return the ID for the first interview in the list
        return interviews.get(0).Id;
    }
}参考 Visualforce 页面 从页面布局
为了实际暴露这个 Visualforce 页面,使其可从“联系人”页面布局中使用。
提示
如果将 Visualforce 页面直接嵌入到页面中 布局中,每次用户访问联系人时,他们都会自动恢复他们的第一个联系人 暂停采访——可能是无意的。用户最好将 有意识地选择开始或恢复面试,所以让我们使用自定义按钮。首先,为链接到 Visualforce 页面的 Contact 对象创建一个自定义按钮。使用这些字段 值来创建按钮。
| 田 | 价值 | 
|---|---|
| 标签 | 调查客户 | 
| 显示类型 | “详情页面”按钮 | 
| 内容源 | Visualforce 页面 | 
| 内容 | YourVisualforcePage | 
最后,将按钮添加到“联系人”页面布局中。
在流中配置 finishLocation 属性
如果未指定,则用户 谁单击完成开始新的面试并看到 流。您可以确定当用户在最终阶段单击“完成”时会发生什么情况 使用函数、变量或控制器进行筛选。
finishLocationURLFOR$Page以下各节显示了配置组件属性的方法。
<flow:interview>finishLocation
- 使用 URLFOR 函数设置 finishLocation
- 使用 $Page 变量设置 finishLocation
- 使用 Controller 设置 finishLocation
使用 URLFOR 函数设置 finishLocation
注意
- 您无法将流用户重定向到符合以下条件的 URL Salesforce 组织外部。
- 不要在同一流中调用方法和属性。 表示 Visualforce 页面登录流程结束。如果在同一流中,则在流中执行 启动,为用户提供对会话的完全访问权限。Auth.SessionManagement.finishLoginFlowfinishLocationAuth.SessionManagement.finishLoginFlowfinishLocationfinishLocation
将用户路由到 相对 URL 或特定记录或详细信息页面,使用其 ID 使用该函数。URLFOR此示例将用户路由到 Salesforce 主页 页。
<apex:page>
    <flow:interview name="MyUniqueFlow" finishLocation="{!URLFOR('/home/home.jsp')}"/>
</apex:page>此示例将用户引导至详细信息页面 ID 为 001D000000IpE9X。
<apex:page>
    <flow:interview name="MyUniqueFlow" finishLocation="{!URLFOR('/001D000000IpE9X')}"/>
</apex:page>有关 的详细信息,请参阅函数。URLFOR
使用 $Page 变量设置 finishLocation
要在不使用 的情况下将用户路由到另一个 Visualforce 页面,请设置为目标的名称 页面的格式为 .
URLFORfinishLocation{!$Page.pageName}
<apex:page>
    <flow:interview name="MyUniqueFlow" finishLocation="{!$Page.MyUniquePage}"/>
</apex:page>有关 的详细信息,请参阅全局变量。$Page
使用 Controller 设置 finishLocation
您可以使用自定义控制器通过多种方式进行设置。finishLocation此示例控制器配置了一个 流动的完成行为在三种不同的 方式。
public class myFlowController {
    
    public PageReference getPageA() {
        return new PageReference('/300');
    }
    
    public String getPageB() {
        return '/300';
    }
    
    public String getPageC() {
        return '/apex/my_finish_page';
    }
}下面是一个 Visualforce 示例 引用控制器并将流完成行为设置为第一个的页面 选择。
<apex:page controller="myFlowController">
    <h1>Congratulations!</h1> This is your new page.
    <flow:interview name="flowname" finishLocation="{!pageA}"/>
</apex:page>如果使用标准控制器显示 在与流程相同的页面上进行记录,单击“完成”的用户将开始新的流程访谈。他们看到流的第一个屏幕,但没有 记录,因为查询字符串 参数不会保留在页面 URL 中。如果需要,请配置 将用户路由回 记录。idfinishLocation
自定义流的用户界面
在 Visualforce 页面中嵌入流程后,您可以通过应用 使用 CSS 的自定义样式。结合使用流属性和 CSS 类,您可以自定义流程的各个部分,例如 作为按钮位置、按钮样式、背景以及外观和 屏幕标签的感觉。
Flow 按钮属性
使用这些属性可以更改“下一步”、“上一个”、“完成”、“暂停”和“不暂停”按钮在 你的流程。
| 属性 | 描述 | 
|---|---|
| buttonLocation | 定义导航按钮在流中的位置 用户界面。可用值为:topbottomboth例如: <apex:page> <flow:interview name="MyFlow" buttonLocation="bottom"/> </apex:page>注意如果未指定,则该值默认为 。buttonLocationboth | 
| buttonStyle | 将样式作为一组分配给流导航按钮。能 仅用于内联样式,不用于 CSS 类。例如: <apex:page> <flow:interview name="MyFlow" buttonStyle="color:#050; background-color:#fed; border:1px solid;"/> </apex:page> | 
特定于流的 CSS 类
您可以覆盖这些预定义的流样式 具有您自己的 CSS 样式的类。
| Flow Style 类 | 适用于… | 
|---|---|
| FlowContainer(流程容器) | 包含 流。<div> | 
| FlowPageBlockBtns(流页块Btns) | 元素 包含流导航按钮。<apex:pageBlockButtons>注意防止流的 CSS 样式 导航按钮不被其他位置应用的按钮样式覆盖 系统中,我们建议您在每次应用 CSS 时指定此流样式类 流导航按钮的样式。例如,输入 ,而不是 。.FlowPreviousBtn {}.FlowPageBlockBtns .FlowPreviousBtn {} | 
| FlowCancelBtn | “不暂停”按钮。 | 
| FlowPauseBtn | “暂停”按钮。 | 
| 流程上一页Btn | “上一步”按钮。 | 
| 流下一个BTN | “下一步”按钮。 | 
| FlowFinishBtn | “完成”按钮。 | 
| 流文本 | 文本字段标签。 | 
| FlowTextArea | 文本区域字段标签。 | 
| 流量编号 | 数字字段标签。 | 
| 流日期 | 日期字段标签。 | 
| 流货币 | 货币字段标签。 | 
| FlowPassword(流密码) | 密码字段标签。 | 
| FlowRadio(英语:FlowRadio | 单选按钮字段标签。 | 
| FlowDropdown | 选择列表标签。 | 
在 Visualforce 页面中渲染流程的 Lightning 运行时
默认情况下,当您在 Visualforce 页面中嵌入流程时,该流程将以 Classic 格式呈现 运行。顾名思义,Classic 运行时的外观和感觉都像常规的 Visualforce 页面 以及 Salesforce Classic 桌面体验。如果您希望流程在 Lightning 中渲染 运行时,将流 Aura 组件嵌入到 Visualforce 页面。
- 创建一个声明对组件的依赖关系的 Lightning 应用程序。lightning:flow
- 添加 Lightning 组件 使用组件将 Visualforce JavaScript 库添加到您的 Visualforce 页面。<apex:includeLightning/>
- 在 Visualforce 页面中,引用依赖项应用。
- 编写一个 JavaScript 函数,该函数使用 在页面上创建组件。$Lightning.createComponent()
例
<aura:application access="global" extends="ltng:outApp" >
    <aura:dependency resource="lightning:flow"/>
</aura:application><apex:page >
   <html>
      <head>
         <apex:includeLightning />
      </head>
      <body class="slds-scope">
         <div id="flowContainer" />
         <script>
            var statusChange = function (event) {
               if(event.getParam("status") === "FINISHED") {
                  // Control what happens when the interview finishes
 
                  var outputVariables = event.getParam("outputVariables");
                  var key;
                  for(key in outputVariables) {
                     if(outputVariables[key].name === "myOutput") {
                        // Do something with an output variable
                     }
                  }
               }
            };
            $Lightning.use("c:lightningOutApp", function() {
               // Create the flow component and set the onstatuschange attribute
               $Lightning.createComponent("lightning:flow", {"onstatuschange":statusChange},
                  "flowContainer",
                  function (component) {
                     // Set the input variables
                     var inputVariables = [
                        {
                           name : 'myInput',
                           type : 'String',
                           value : "Hello, world"
                        }
                     ];
                     
                     // Start an interview in the flowContainer div, and 
                     // initializes the input variables.
                     component.startFlow("myFlowName", inputVariables);
                  }
               );
            });
         </script>
      </body>
   </html>
</apex:page>
