本指南介绍了如何创建输入变量。
若要运行,步骤需要某些信息。例如,发送电子邮件需要电子邮件地址。如需提供此必要信息,请定义输入变量。定义后,输入变量通常由用户在步骤的配置卡上设置,同时用户也会设置该步骤。
在两个位置定义输入变量:插件的清单文件,以及包含配置卡的相应代码(用户可在其中输入输入变量的值)。
在清单文件中定义输入变量
在清单文件中,使用 inputs[] 数组指定输入变量。inputs[] 数组中的每个项都具有以下属性:
id:输入变量的唯一标识符。为了让流程将配置卡输入元素与此输入变量相关联,必须与相应卡元素的名称一致。description:要向最终用户显示的输入变量的说明。cardinality:允许的值数量。可能的值包括:SINGLE:仅允许一个值。
dataType:接受的值类型。dataType具有用于定义数据类型的属性basicType。有效值包括:STRING:一个字母数字字符串。INTEGER:一个数字。TIMESTAMP:以“自 Unix 纪元以来的毫秒数”格式表示的时间戳。 例如,2025 年 11 月 27 日 16:49:02 UTC 表示为1764262142988。BOOLEAN:true 或 false。EMAIL_ADDRESS:电子邮件地址,格式为dana@example.com。
以下示例为计算器步骤定义了三个输入变量。前两个输入变量是整数,第三个是算术运算。
JSON
{
"timeZone": "America/Los_Angeles",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "Calculator",
"logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
"useLocaleFromApp": true
},
"flows": {
"workflowElements": [
{
"id": "calculatorDemo",
"state": "ACTIVE",
"name": "Calculate",
"description": "Asks the user for two values and a math operation, then performs the math operation on the values and outputs the result.",
"workflowAction": {
"inputs": [
{
"id": "value1",
"description": "value1",
"cardinality": "SINGLE",
"dataType": {
"basicType": "INTEGER"
}
},
{
"id": "value2",
"description": "value2",
"cardinality": "SINGLE",
"dataType": {
"basicType": "INTEGER"
}
},
{
"id": "operation",
"description": "operation",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"outputs": [
{
"id": "result",
"description": "Calculated result",
"cardinality": "SINGLE",
"dataType": {
"basicType": "INTEGER"
}
}
],
"onConfigFunction": "onConfigCalculate",
"onExecuteFunction": "onExecuteCalculate"
}
}
]
}
}
}
在代码中定义输入变量
此步骤的代码包含一个名为 onConfigFunction() 的函数,该函数会返回一个配置卡片,其中为清单文件的 inputs[] 数组中定义的每个输入变量定义一个输入卡片 widget。
配置卡片中定义的输入 widget 具有以下要求:
- 每个输入 widget 的
name都必须与清单文件中相应输入变量的id相匹配。 - 输入 widget 的基数必须与清单文件中输入变量的
cardinality相匹配。 - 输入 widget 的数据类型必须与清单文件中的输入变量的
dataType相匹配。如果输入变量的dataType为整数,则不能包含字符串。
如需有关构建卡片界面的帮助,请参阅以下选项之一:
- 卡片构建器:一种交互式工具,可用于构建和定义卡片。
- 卡片:位于 Google Workspace 插件 API 参考文档中。
- 卡片服务:一种 Apps 脚本服务,可让脚本配置和构建卡片。
- 基于卡片的界面概览:位于 Google Workspace 插件开发者文档中。
以下示例会针对 在清单文件中定义输入变量中定义的每个输入 widget 返回一个配置卡片。
Apps 脚本
/**
* Generates and displays a configuration card for the sample calculation step.
*
* This function creates a card with input fields for two values and a drop-down
* for selecting an arithmetic operation.
*
* The input fields are configured to let the user select outputs from previous
* workflow steps as input values using the `hostAppDataSource` property.
*/
function onConfigCalculate() {
const firstInput = CardService.newTextInput()
.setFieldName("value1") // "FieldName" must match an "id" in the manifest file's inputs[] array.
.setTitle("First Value")
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
)
);
const secondInput = CardService.newTextInput()
.setFieldName("value2") // "FieldName" must match an "id" in the manifest file's inputs[] array.
.setTitle("Second Value")
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
)
);
const selectionInput = CardService.newSelectionInput()
.setTitle("operation")
.setFieldName("operation") // "FieldName" must match an "id" in the manifest file's inputs[] array.
.setType(CardService.SelectionInputType.DROPDOWN)
.addItem("+", "+", false)
.addItem("-", "-", true)
.addItem("x", "x", false)
.addItem("/", "/", false);
const sections = CardService.newCardSection()
.setHeader("Action_sample: Calculate")
.setId("section_1")
.addWidget(firstInput)
.addWidget(selectionInput)
.addWidget(secondInput)
let card = CardService.newCardBuilder()
.addSection(sections)
.build();
return card;
}
使用上一步中的输出变量
您可以配置输入变量,以接受工作流中上一步的输出变量。
启用变量选择
如需允许用户从之前的步骤中选择变量,请在 TextInput 和 SelectionInput widget 中使用 includeVariables 属性。
TextInput 和 SelectionInput widget 具有以下 Workspace Studio 特有的功能:
includeVariables:一个布尔值属性,用于让用户选择之前步骤中的变量。为了让变量选择器在后续步骤中显示,起始事件和至少一个相应的输出变量都必须映射到该变量。type:一个枚举值,用于自动补全建议。支持的值包括:USER:为用户联系人中的人员提供自动补全建议。SPACE:为用户所属的 Google Chat 聊天室提供自动补全建议。
如果同时设置了 includeVariables 和 type,输入字段会合并两者的体验。用户可以从下拉菜单中选择匹配的 type 变量,并查看该变量的自动补全建议。
-
图 4:用户在选择空间时查看自动补全建议。 -
图 5:用户从 ➕ 变量下拉菜单中选择上一步的输出变量。
使用溢出菜单仅选择一个输出变量
您可以配置 SelectionInput widget,让用户通过溢出菜单从上一步中选择单个输出变量。
当您将 SelectionInputType 设置为 OVERFLOW_MENU 时,该 widget 可用作专用变量选择器。与将变量值转换为字符串的 includeVariables 和 TextInput 不同,OVERFLOW_MENU 会保留所选变量的原始数据类型。
Apps 脚本
const selectionInput = CardService.newSelectionInput()
.setFieldName("variable_picker_1")
.setTitle("Variable Picker")
.setType(
CardService.SelectionInputType.OVERFLOW_MENU
);
允许用户组合文本和输出变量
您可以配置 TextInput widget,以控制用户如何使用 setInputMode() 与文本和输出变量互动。
RICH_TEXT:允许用户组合文本和输出变量。结果是一个连接在一起的字符串。PLAIN_TEXT:限制输入。用户可以输入文本,也可以选择单个输出变量。选择变量会替换所有现有文本。 使用此模式可强制执行清单中定义的特定数据类型。
下图显示了两个 TextInput widget。第一个配置为 RICH_TEXT,包含文本和输出变量。第二个配置为 PLAIN_TEXT,仅允许输出变量。
-
图 3:配置为 RICH_TEXT和PLAIN_TEXT的文本输入微件。
建议您为所有 TextInput widget 明确设置输入模式。
以下是用于配置具有不同输入模式的 TextInput widget 的清单文件:
JSON
{
"timeZone": "America/Toronto",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "Text and output variable demo",
"logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
"useLocaleFromApp": true
},
"flows": {
"workflowElements": [
{
"id": "richTextDemo",
"state": "ACTIVE",
"name": "Rich Text Demo",
"description": "Show the difference between rich text and plain text TextInput widgets",
"workflowAction": {
"inputs": [
{
"id": "value1",
"description": "First user input",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
},
{
"id": "value2",
"description": "Second user input",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfiguration",
"onExecuteFunction": "onExecution"
}
}
]
}
}
}
以下代码展示了如何配置具有不同输入模式的 TextInput widget:
Apps 脚本
function onConfiguration() {
const input1 = CardService.newTextInput()
.setFieldName("value1")
.setId("value1")
.setTitle("Rich Text")
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
)
)
// Set input mode to RICH_TEXT to allow mixed text and variables.
.setInputMode(CardService.TextInputMode.RICH_TEXT);
const input2 = CardService.newTextInput()
.setFieldName("value2")
.setId("value2")
.setTitle("Plain text")
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
)
)
// Set input mode to PLAIN_TEXT to enforce single variable selection.
.setInputMode(CardService.TextInputMode.PLAIN_TEXT);
const section = CardService.newCardSection()
.addWidget(input1)
.addWidget(input2);
const card = CardService.newCardBuilder()
.addSection(section)
.build();
return card;
}
function onExecution(e) {
}
自定义变量选择器按钮
您可以通过设置按钮大小和标签来自定义变量选择器按钮。
按钮大小
如需设置按钮大小,请将 setVariableButtonSize() 与以下 VariableButtonSize 枚举之一搭配使用:
UNSPECIFIED:默认值。该按钮在侧边栏中以紧凑型显示,在其他情况下则以全尺寸显示。COMPACT:按钮仅显示加号 (+)。FULL_SIZE:按钮显示完整的文本标签。
按钮标签
如需设置按钮文字,请使用 setVariableButtonLabel()。
示例:变量选择器自定义
以下示例展示了如何配置具有不同变量选择器按钮大小和自定义标签的 TextInput widget。
-
图 1:网页上的变量选择器按钮自定义。 -
图 2:在插件侧边栏中自定义变量选择器按钮。
以下是用于自定义变量选择器按钮的清单文件:
JSON
{
"timeZone": "America/Los_Angeles",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/script.locale"
],
"addOns": {
"common": {
"name": "Variable button customization",
"logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
"useLocaleFromApp": true
},
"flows": {
"workflowElements": [
{
"id": "variable_picker_customization",
"state": "ACTIVE",
"name": "Variable Picker demo",
"description": "List all possible variable picker customization options",
"workflowAction": {
"onConfigFunction": "onUpdateCardConfigFunction",
"onExecuteFunction": "onUpdateCardExecuteFunction"
}
}
]
}
}
}
以下是用于自定义变量选择器按钮的代码:
Apps 脚本
function onUpdateCardConfigFunction(event) {
const textInput1 = CardService.newTextInput()
.setFieldName("value1")
.setTitle("Regular variable picker button")
.setHostAppDataSource(
CardService.newHostAppDataSource().setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setVariableButtonSize(CardService.VariableButtonSize.UNSPECIFIED)
)
);
const textInput2 = CardService.newTextInput()
.setFieldName("value2")
.setTitle("Size: Unspecified")
.setHostAppDataSource(
CardService.newHostAppDataSource().setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setVariableButtonSize(CardService.VariableButtonSize.UNSPECIFIED)
)
);
const textInput3 = CardService.newTextInput()
.setFieldName("value3")
.setTitle("Size: Full size")
.setHostAppDataSource(
CardService.newHostAppDataSource().setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setVariableButtonSize(CardService.VariableButtonSize.FULL_SIZE)
)
);
const textInput4 = CardService.newTextInput()
.setFieldName("value4")
.setTitle("Size: Compact")
.setHostAppDataSource(
CardService.newHostAppDataSource().setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setVariableButtonSize(CardService.VariableButtonSize.COMPACT)
)
);
const textInput5 = CardService.newTextInput()
.setFieldName("value5")
.setTitle("Custom button label")
.setHostAppDataSource(
CardService.newHostAppDataSource().setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setVariableButtonLabel("New button label!")
)
);
var cardSection = CardService.newCardSection()
.addWidget(textInput1)
.addWidget(textInput2)
.addWidget(textInput3)
.addWidget(textInput4)
.addWidget(textInput5)
.setId("section_1");
var card = CardService.newCardBuilder().addSection(cardSection).build();
return card;
}
function onUpdateCardExecuteFunction(event) {
}
配置 Google Workspace 数据自动补全
您还可以根据用户 Google Workspace 环境中的数据填充自动补全建议:
- Google Workspace 用户:填充同一 Google Workspace 组织中的用户。
- Google Chat 聊天室:填充用户所属的 Google Chat 聊天室。
如需配置此功能,请在 SelectionInput widget 中设置 PlatformDataSource,并将 WorkflowDataSourceType 指定为 USER 或 SPACE。
Apps 脚本
// User Autocomplete
var multiSelect2 =
CardService.newSelectionInput()
.setFieldName("value2")
.setTitle("User Autocomplete")
.setType(CardService.SelectionInputType.MULTI_SELECT)
.setMultiSelectMaxSelectedItems(3)
.setPlatformDataSource(
CardService.newPlatformDataSource()
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setType(CardService.WorkflowDataSourceType.USER)
))
);
// Chat Space Autocomplete
var multiSelect3 =
CardService.newSelectionInput()
.setFieldName("value3")
.setTitle("Chat Space Autocomplete")
.setType(CardService.SelectionInputType.MULTI_SELECT)
.setMultiSelectMaxSelectedItems(3)
.setPlatformDataSource(
CardService.newPlatformDataSource()
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setType(CardService.WorkflowDataSourceType.SPACE)
))
);
示例:组合自动补全类型
以下示例展示了一个 onConfig 函数,该函数创建了一个包含三个 SelectionInput widget 的卡片,演示了服务器端、用户和空间自动补全功能:
JSON
{
"timeZone": "America/Los_Angeles",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "Autocomplete Demo",
"logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
"useLocaleFromApp": true
},
"flows": {
"workflowElements": [
{
"id": "autocomplete_demo",
"state": "ACTIVE",
"name": "Autocomplete Demo",
"description": "Provide autocompletion in input fields",
"workflowAction": {
"inputs": [
{
"id": "value1",
"description": "A multi-select field with autocompletion",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfigAutocomplete",
"onExecuteFunction": "onExecuteAutocomplete"
}
}
]
}
}
}
Apps 脚本
function onConfigAutocompleteTest(event) {
// Handle autocomplete request
if (event.workflow && event.workflow.elementUiAutocomplete) {
return handleAutocompleteRequest(event);
}
// Server-side autocomplete widget
var multiSelect1 =
CardService.newSelectionInput()
.setFieldName("value1")
.setTitle("Server Autocomplete")
.setType(CardService.SelectionInputType.MULTI_SELECT)
.setMultiSelectMaxSelectedItems(3)
.addDataSourceConfig(
CardService.newDataSourceConfig()
.setRemoteDataSource(
CardService.newAction().setFunctionName('getAutocompleteResults')
)
)
.addDataSourceConfig(
CardService.newDataSourceConfig()
.setPlatformDataSource(
CardService.newPlatformDataSource()
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
))
)
);
// User autocomplete widget
var multiSelect2 =
CardService.newSelectionInput()
.setFieldName("value2")
.setTitle("User Autocomplete")
.setType(CardService.SelectionInputType.MULTI_SELECT)
.setMultiSelectMaxSelectedItems(3)
.setPlatformDataSource(
CardService.newPlatformDataSource()
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setType(CardService.WorkflowDataSourceType.USER)
))
);
// Space autocomplete widget
var multiSelect3 =
CardService.newSelectionInput()
.setFieldName("value3")
.setTitle("Chat Space Autocomplete")
.setType(CardService.SelectionInputType.MULTI_SELECT)
.setMultiSelectMaxSelectedItems(3)
.setPlatformDataSource(
CardService.newPlatformDataSource()
.setHostAppDataSource(
CardService.newHostAppDataSource()
.setWorkflowDataSource(
CardService.newWorkflowDataSource()
.setIncludeVariables(true)
.setType(CardService.WorkflowDataSourceType.SPACE)
))
);
var sectionBuilder =
CardService.newCardSection()
.addWidget(multiSelect1)
.addWidget(multiSelect2)
.addWidget(multiSelect3);
var card =
CardService.newCardBuilder()
.addSection(sectionBuilder)
.build();
return card;
}
function handleAutocompleteRequest(event) {
var invokedFunction = event.workflow.elementUiAutocomplete.invokedFunction;
var query = event.workflow.elementUiAutocomplete.query;
if (invokedFunction != "getAutocompleteResults" || query == undefined || query == "") {
return {};
}
// Query your data source to get results
let autocompleteResponse = AddOnsResponseService.newUpdateWidget()
.addSuggestion(
query + " option 1",
query + "_option1",
false,
"https://developers.google.com/workspace/add-ons/images/person-icon.png",
"option 1 bottom text"
)
.addSuggestion(
query + " option 2",
query + "_option2",
false,
"https://developers.google.com/workspace/add-ons/images/person-icon.png",
"option 2 bottom text"
).addSuggestion(
query + " option 3",
query + "_option3",
false,
"https://developers.google.com/workspace/add-ons/images/person-icon.png",
"option 3 bottom text"
);
const modifyAction = AddOnsResponseService.newAction()
.addModifyCard(
AddOnsResponseService.newModifyCard()
.setUpdateWidget(autocompleteResponse)
);
return AddOnsResponseService.newRenderActionBuilder()
.setAction(modifyAction)
.build();
}
验证输入变量
最佳实践是验证用户输入的值是否合适。请参阅验证输入变量。