使用 Visualforce 渲染流程

无法使用 流生成器。但是,在 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>

  1. 查找流的 API 名称。
    1. 在“设置”中,输入“快速” “查找”框,然后选择“流”。Flows
    2. 单击要嵌入的流的名称。
  2. 定义新的 Visualforce 页面或打开要编辑的页面。
  3. 添加组件, 在标签之间的某个地方。<flow:interview><apex:page>
  4. 将属性设置为唯一属性 流的名称。例如:name<apex:page> <flow:interview name="flowAPIName"/> </apex:page>注意如果流程是 在托管包中,该属性必须是 采用以下格式:.namenamespace.flowuniquename
  5. 通过为 包含它的 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>

取决于 在流中记录集合变量的内容上,内容如下 该数据表如下所示。Example of a data table that displays the contents of a record collection variable

控制用户是否可以暂停来自 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 页面。

  1. 创建一个声明对组件的依赖关系的 Lightning 应用程序。lightning:flow
  2. 添加 Lightning 组件 使用组件将 Visualforce JavaScript 库添加到您的 Visualforce 页面。<apex:includeLightning/>
  3. 在 Visualforce 页面中,引用依赖项应用。
  4. 编写一个 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>