打开互动对话框

本页介绍了 Google Chat 应用如何打开对话框以显示界面 (UI) 并响应用户。

在 Google Chat 中,插件会以 Google Chat 应用的形式向用户显示。如需了解详情,请参阅扩展 Google Chat 概览

对话框是基于卡片的窗口式界面,可从 Chat 聊天室或消息中打开。只有打开对话框的用户才能看到该对话框及其内容。

Chat 应用可以使用对话框向 Chat 用户请求和收集信息,包括多步表单。如需详细了解如何构建表单输入,请参阅收集和处理用户信息

前提条件

Node.js

这款 Google Workspace 插件可扩展 Google Chat 的功能。如需构建一个,请完成 HTTP 快速入门

Apps 脚本

这款 Google Workspace 插件可扩展 Google Chat 的功能。如需构建一个,请完成 Apps Script 快速入门

打开对话框

一个包含各种不同 widget 的对话框。
图 1:打开对话框以收集联系信息的 Chat 应用。

本部分介绍了如何通过执行以下操作来响应和设置对话框:

  1. 通过用户互动触发对话框请求。
  2. 通过返回并打开对话框来处理请求。
  3. 用户提交信息后,通过关闭对话框或返回另一个对话框来处理提交内容。

触发对话框请求

Chat 应用只能打开对话框来响应用户互动,例如卡片中消息的斜杠命令或按钮点击。

如需通过对话框响应用户,Chat 应用必须构建触发对话框请求的互动,例如:

  • 响应斜杠命令。如需通过斜杠命令触发请求,您必须在配置命令时勾选打开对话框复选框。
  • 消息响应按钮点击,可以是作为卡片的一部分,也可以是在消息底部。如需通过消息中的按钮触发请求,您可以通过将按钮的 interaction 设置为 OPEN_DIALOG 来配置按钮的 onClick 操作。
用于触发对话框的按钮
图 2:Chat 应用发送一条消息,提示用户使用 /addContact 斜杠命令。
该消息还包含一个按钮,用户可以点击该按钮来触发相应命令。

以下 JSON 展示了如何通过卡片消息中的按钮触发对话框请求。如需打开该对话框,请将按钮的 onClick.action.interaction 字段设置为 OPEN_DIALOG

{
  "buttonList": { "buttons": [{
    "text": "BUTTON_TEXT",
    "onClick": { "action": {
      "function": "ACTION_FUNCTION",
      "interaction": "OPEN_DIALOG"
    }}
  }]}
}

其中 BUTTON_TEXT 是按钮中显示的文本,ACTION_FUNCTION 是运行以打开初始对话框的函数。

打开初始对话框

当用户触发对话框请求时,您的 Chat 应用会收到一个事件对象,其中包含一个载荷,该载荷指定 dialogEventType 对象为 REQUEST_DIALOG

如需打开对话框,Chat 应用可以通过返回包含导航 pushCard 以显示卡片的 RenderActions 对象来响应请求。卡片应包含任何界面 (UI) 元素,包括一个或多个 widget 的 sections[]。如需从用户收集信息,您可以指定表单输入微件和按钮微件。如需详细了解如何设计表单输入,请参阅从用户收集和处理信息

以下 JSON 展示了 Chat 应用如何返回用于打开对话框的响应:

{
  "action": { "navigations": [{ "pushCard": { "sections": [{ "widgets": [{
    WIDGETS,
    { "buttonList": { "buttons": [{
      "text": "BUTTON_TEXT",
      "onClick": {
        "action": { "function": "ACTION_FUNCTION" }
      }
    }]}}
  }]}]}}]}
}

其中 BUTTON_TEXT 是按钮中显示的文本(例如 NextSubmit),WIDGETS 表示一个或多个表单输入 widgetACTION_FUNCTION 是用户点击按钮时运行的操作的回调函数

处理对话框提交内容

当用户点击用于提交对话框的按钮时,您的 Chat 应用会收到包含 ButtonClickedPayload 对象的事件对象。在载荷中,dialogEventType 设置为 SUBMIT_DIALOG

您的 Chat 应用必须通过执行以下其中一项操作来处理事件对象:

可选:返回另一个对话框

用户提交初始对话框后,聊天应用可以返回一个或多个其他对话框,以帮助用户在提交前查看信息、完成多步表单或动态填充表单内容。

为了处理用户输入的数据,Chat 应用会处理事件的 commonEventObject.formInputs 对象中的数据。如需详细了解如何从输入 widget 检索值,请参阅收集和处理用户信息

如需跟踪用户从初始对话框输入的任何数据,您必须向用于打开下一个对话框的按钮添加参数。如需了解详情,请参阅将数据转移到其他卡

在此示例中,Chat 应用会打开一个初始对话框,该对话框会在提交之前打开第二个对话框以供确认:

Node.js

/**
 * Google Cloud Function that handles all Google Workspace Add On events for
 * the contact manager app.
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
exports.contactManager = function contactManager(req, res) {
  const chatEvent = req.body.chat;
  // Handle MESSAGE events
  if(chatEvent.messagePayload) {
    return res.send(handleMessage(req.body));
  // Handle button clicks
  } else if(chatEvent.buttonClickedPayload) {
    switch(req.body.commonEventObject.parameters.actionName) {
        case "openInitialDialog":
            return res.send(openInitialDialog(req.body));
        case "openConfirmationDialog":
            return res.send(openConfirmationDialog(req.body));
        case "submitDialog":
            return res.send(submitDialog(req.body));
    }
  }
};

/**
 * Responds to a message in Google Chat.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} response that handles dialogs.
 */
function handleMessage(event) {
  // Reply with a message that contains a button to open the initial dialog
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    text: "To add a contact, use the `ADD CONTACT` button below.",
    accessoryWidgets: [{ buttonList: { buttons: [{
      text: "ADD CONTACT",
      onClick: { action: {
        // Use runtime environment variable set with self URL
        function: process.env.BASE_URL,
        parameters: [{ key: "actionName", value: "openInitialDialog" }],
        interaction: "OPEN_DIALOG"
      }}
    }]}}]
  }}}}};
}

/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} open the dialog.
 */
function openInitialDialog(event) {
  return { action: { navigations: [{ pushCard: { sections: [{ widgets: [{
    textInput: {
      name: "contactName",
      label: "First and last name",
      type: "SINGLE_LINE"
    }},
    WIDGETS, {
    buttonList: { buttons: [{
      text: "NEXT",
      onClick: { action: {
        // Use runtime environment variable set with self URL
        function: process.env.BASE_URL,
        parameters: [{ key: "actionName", value: "openConfirmationDialog" }]
      }}
    }]}}
  ]}]}}]}};
}

/**
 * Opens the second step of the dialog that lets users confirm details.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} update the dialog.
 */
function openConfirmationDialog(event) {
  // Retrieve the form input values
  const name = event.commonEventObject.formInputs["contactName"].stringInputs.value[0];
  return { action: { navigations: [{ pushCard: { sections: [{ widgets: [{
    // Display the input values for confirmation
    textParagraph: { text: "<b>Name:</b> " + name }},
    WIDGETS, {
    buttonList: { buttons: [{
      text: "SUBMIT",
      onClick: { action: {
        // Use runtime environment variable set with self URL
        function: process.env.BASE_URL,
        parameters: [{
          key: "actionName", value: "submitDialog" }, {
          // Pass input values as parameters for last dialog step (submission)
          key: "contactName", value: name
        }]
      }}
    }]}}]
  }]}}]}};
}

Apps 脚本

此示例通过返回卡片 JSON 来发送卡片消息。您还可以使用 Apps 脚本卡片服务

/**
 * Responds to a message in Google Chat.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} response that handles dialogs.
 */
function onMessage(event) {
  // Reply with a message that contains a button to open the initial dialog
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    text: "To add a contact, use the `ADD CONTACT` button below.",
    accessoryWidgets: [{ buttonList: { buttons: [{
      text: "ADD CONTACT",
      onClick: { action: {
        function: "openInitialDialog",
        interaction: "OPEN_DIALOG"
      }}
    }]}}]
  }}}}};
}

/**
 * Opens the initial step of the dialog that lets users add contact details.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} open the dialog.
 */
function openInitialDialog(event) {
  return { action: { navigations: [{ pushCard: { sections: [{ widgets: [{
    textInput: {
      name: "contactName",
      label: "First and last name",
      type: "SINGLE_LINE"
    }},
    WIDGETS, {
    buttonList: { buttons: [{
      text: "NEXT",
      onClick: { action: { function : "openConfirmationDialog" }}
    }]}}
  ]}]}}]}};
}

/**
 * Opens the second step of the dialog that lets users confirm details.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} update the dialog.
 */
function openConfirmationDialog(event) {
  // Retrieve the form input values
  const name = event.commonEventObject.formInputs["contactName"].stringInputs.value[0];
  return { action: { navigations: [{ pushCard: { sections: [{ widgets: [{
    // Display the input values for confirmation
    textParagraph: { text: "<b>Name:</b> " + name }},
    WIDGETS, {
    buttonList: { buttons: [{
      text: "SUBMIT",
      onClick: { action: {
        function: "submitDialog",
        // Pass input values as parameters for last dialog step (submission)
        parameters: [{ key: "contactName", value: name }]
      }}
    }]}}]
  }]}}]}};
}

其中 WIDGETS 代表任何其他表单输入 widget

关闭对话框

当用户点击对话框上的提交按钮时,您的 Chat 应用会执行其关联的操作,并提供事件对象,其中 buttonClickedPayload 设置为以下内容:

  • isDialogEventtrue
  • dialogEventTypeSUBMIT_DIALOG

Chat 应用应返回一个 RenderActions 对象,并将 EndNavigation 设置为 CLOSE_DIALOG

可选:显示通知

关闭对话框时,您还可以显示文本通知。

如需显示通知,请返回设置了字段 notificationRenderActions 对象。

以下示例会检查参数是否有效,并根据结果通过文本通知关闭对话框:

Node.js

/**
 * Handles submission and closes the dialog.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} close the dialog with a status in text notification.
 */
function submitDialog(event) {
  // Validate the parameters.
  if (!event.commonEventObject.parameters["contactName"]) {
    return { action: {
      navigations: [{ endNavigation: "CLOSE_DIALOG"}],
      notification: { text: "Failure, the contact name was missing!" }
    }};
  }

  return { action: {
    navigations: [{ endNavigation: "CLOSE_DIALOG"}],
    notification: { text: "Success, the contact was added!" }
  }};
}

Apps 脚本

/**
 * Handles submission and closes the dialog.
 *
 * @param {Object} event The event object from the Google Workspace Add-on.
 * @return {Object} close the dialog with a status in text notification.
 */
function submitDialog(event) {
  // Validate the parameters.
  if (!event.commonEventObject.parameters["contactName"]) {
    return { action: {
      navigations: [{ endNavigation: "CLOSE_DIALOG"}],
      notification: { text: "Failure, the contact name was missing!" }
    }};
  }

  return { action: {
    navigations: [{ endNavigation: "CLOSE_DIALOG"}],
    notification: { text: "Success, the contact was added!" }
  }};
}

如需详细了解如何在对话框之间传递参数,请参阅将数据传输到另一张卡片

可选:发送确认消息

关闭对话框后,您还可以发送新消息或更新现有消息。

如需发送新消息,请返回一个 DataActions 对象,并使用新消息设置 CreateMessageAction 字段。例如,如需关闭对话框并发送短信,请返回以下内容:

{ "hostAppDataAction": { "chatDataAction": { "createMessageAction": { "message": {
  "text": "Your information has been submitted."
}}}}}

如需在用户提交对话框后更新消息,请返回包含以下操作之一的 DataActions 对象:

问题排查

当 Google Chat 应用或卡片返回错误时,Chat 界面会显示“出了点问题”消息。或“无法处理您的请求”。有时,Chat 界面不会显示任何错误消息,但 Chat 应用或卡片会产生意外结果;例如,卡片消息可能不会显示。

虽然 Chat 界面中可能不会显示错误消息,但当 Chat 应用的错误日志记录功能处于开启状态时,描述性错误消息和日志数据可帮助您修正错误。如需有关查看、调试和修复错误的帮助,请参阅排查和修复 Google Chat 错误