【问题标题】:How to handle tap action on adaptive card bot framework v4?如何处理自适应卡片机器人框架 v4 上的点击操作?
【发布时间】:2019-08-26 06:32:29
【问题描述】:

我有一张自适应卡片,它将显示在瀑布对话框中。我想知道是否可以在我不想添加按钮来处理点击的自适应卡上捕获点击动作。我正在使用 bot 框架的 v4 版本。

点击对话框被触发两次

我的自适应卡:

var Card1 = {
                    "type": "AdaptiveCard",
                    "selectAction": {
                        "type": "Action.Submit",
                        "id": "tap",
                        "title": "tap",
                        "data": "data": { tap: 'tap' }
                    },
                    "backgroundImage": "https://download-ssl.msgamestudios.com/content/mgs/ce/production/SolitaireWin10/dev/adapative_card_assets/v1/card_background.png",
                    "body": [
                        {
                            "type": "ColumnSet",
                            "columns": [
                                {
                                    "type": "Column",
                                    "items": [
                                        {
                                            "type": "Image",
                                            "url": "https://download-ssl.msgamestudios.com/content/mgs/ce/production/SolitaireWin10/dev/adapative_card_assets/v1/tile_spider.png",
                                            "size": "Stretch"
                                        }
                                    ],
                                    "width": 1
                                },
                                {
                                    "type": "Column",
                                    "items": [
                                        {
                                            "type": "TextBlock",
                                            "horizontalAlignment": "Center",
                                            "weight": "Bolder",
                                            "color": "Light",
                                            "text": "Click here to play another game of Spider in Microsoft Solitaire Collection!",
                                            "wrap": true
                                        }
                                    ],
                                    "width": 1
                                }
                            ]
                        }
                    ],
                    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                    "version": "0.5"
                };

这就是我更新代码的方式

代码

       // Add prompts that will be used by the main dialogs.
        this.dialogs.add(new TextPrompt(TAP_PROMPT, () => true));

        // Create a dialog that asks the user for their name.
        this.dialogs.add(new WaterfallDialog(PUBLICTRANS, [
            this.promptForTap.bind(this),
            this.captureTap.bind(this)
        ]));
  async promptForTap(step) {
        var Card1 = {
            "type": "AdaptiveCard",
            "selectAction": {
                "type": "Action.Submit",
                "id": "tap",
                "title": "tap",
                "data": "data": { tap: 'tap' }
            },
            "backgroundImage": "https://download-ssl.msgamestudios.com/content/mgs/ce/production/SolitaireWin10/dev/adapative_card_assets/v1/card_background.png",
            "body": [
                {
                    "type": "ColumnSet",
                    "columns": [
                        {
                            "type": "Column",
                            "items": [
                                {
                                    "type": "Image",
                                    "url": "https://download-ssl.msgamestudios.com/content/mgs/ce/production/SolitaireWin10/dev/adapative_card_assets/v1/tile_spider.png",
                                    "size": "Stretch"
                                }
                            ],
                            "width": 1
                        },
                        {
                            "type": "Column",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "horizontalAlignment": "Center",
                                    "weight": "Bolder",
                                    "color": "Light",
                                    "text": "Click here to play another game of Spider in Microsoft Solitaire Collection!",
                                    "wrap": true
                                }
                            ],
                            "width": 1
                        }
                    ]
                }
            ],
            "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
            "version": "1.0"
        };
        const reply = {
            attachments: [CardFactory.adaptiveCard(Card1)]
        };
        return await step.prompt(TAP_PROMPT, { prompt: reply });
    }

    async captureTap(step) {
        // Edited from original answer
        await step.context.sendActivity(`You selected `);
        // Send Back Channel Event
        await step.context.sendActivity({ type: 'event', name: 'tapEvent' });
        return await step.endDialog();
    }

输出卡被触发两次

【问题讨论】:

  • 您是在尝试通过WebChat 在bot 端还是在网页上捕获点击事件?您使用的是 NodeJs 还是 C# SDK?
  • 我正在使用 webchat - nodejs 开发。我想在自适应卡片上捕获来自网页的点击
  • 您为什么使用 0.5 版的 AdaptiveCards?如果没有,我建议至少使用 1.0 版,1.1 版。
  • 谢谢我修改了
  • 我希望你能成功!如果您觉得我的回答足够,请“接受”它,以便我可以从我的支持跟踪器中清除这张票。如果没有,请告诉我我还能提供哪些帮助!

标签: botframework adaptive-cards web-chat


【解决方案1】:

当用户单击 AdaptiveCard 以触发网页上的事件时,您可以从 Bot 向 WebChat 发送反向通道事件。

带有选择操作的简单 AdaptiveCard

首先,创建一个具有selectAction 的 AdaptiveCard。请注意,您可以将selectAction 添加到整个卡片或卡片中的不同组件,例如图像或列。当用户点击卡片上带有selectAction 的部分时,它会向机器人发送一个活动,其中包含来自操作的数据属性,我们可以使用该操作来确定在机器人端触发了哪个操作。

一定要设置title属性、data字段和type应该是Action.Submit

{
  "type": "AdaptiveCard",
  "selectAction": {
      "type": "Action.Submit",
      "id": "tap",
      "title": "tap",
      "data": { "tap": "Play again"}
  },
    "body": [
      {
        "type": "TextBlock",
        "horizontalAlignment": "Center",
        "size": "Medium",
        "weight": "Bolder",
        "text": "Click Me!"
    },
    {
        "type": "Image",
        "url": "https://usercontent2.hubstatic.com/13896379.jpg"
    }],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.0"
}

机器人代码 - 节点 Js

构造函数

const TAP_PROMPT = 'tap_prompt';
constructor(conversationState, userState) {

    ...

    // Add prompts that will be used by the main dialogs.
    this.dialogs.add(new TextPrompt(TAP_PROMPT, () => true));

    // Create a dialog that asks the user for their name.
    this.dialogs.add(new WaterfallDialog(WHO_ARE_YOU, [
        this.promptForTap.bind(this),
        this.captureTap.bind(this)
    ]));
}

AdaptiveCard 提示

在 Waterfall 的其中一个步骤中,您可以创建一个回复对象,其中包含 AdaptiveCard 作为附件。然后,您可以将该回复传递给提示。我建议在此步骤中使用 TextPrompt。

// This step in the dialog sends the user an adaptive card with a selectAction
async promptForTap(step) {
    const reply = {
        attachments: [CardFactory.adaptiveCard(Card)]
    }
    return await step.prompt(TAP_PROMPT, { prompt: reply });
}

捕获 AdaptiveCard selecteAction

在瀑布的下一步中,您可以通过访问step.value获取从AdaptiveCard发送来的数据属性。在这里,向机器人发送一个带有 type 和 name 属性的活动。这两个属性将用于过滤 WebChat 中的传入活动并触发正确的事件。

// This step captures the tap and sends a back channel event to WebChat
async captureTap(step) {

    // Edited from original answer
    await step.context.sendActivity(`You selected ${step.context.activity.value.tap}`);

    // Send Back Channel Event
    await step.context.sendActivity({type: 'event', name: 'tapEvent'});

    return await step.endDialog();
}

网络聊天中间件

在 WebChat 中,我们将创建一个自定义中间件来检查传入的活动。当我们遇到具有我们识别的名称和类型的活动时,在网页上触发您的事件。在下面的示例中,我只是提醒用户他们点击了 AdaptiveCard。

const store = window.WebChat.createStore(
    {},
    ({ dispatch }) => next => action => {
        if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
          const { name, type } = action.payload.activity;

          if (type === 'event' && name === 'tapEvent') {
            alert("You tapped on the AdaptiveCard.");
          }
        }
        return next(action);
    }
);

window.WebChat.renderWebChat({
    directLine: window.WebChat.createDirectLine({ token }),
    store,
}, document.getElementById('webchat'));

有关反向通道事件和在 WebChat 中创建自定义中间件的更多详细信息,请在 WebChat 存储库中查看 this sample

希望这会有所帮助!

【讨论】:

  • 谢谢,我能知道 TAP_PROMPT 是在哪里声明的吗
  • TAP_PROMPT 只是一个引用字符串的常量变量。提示本身是在构造函数中创建的,我将其添加到上面的答案中。如果您没有经常使用对话框,我还建议您看看这个sample
  • 谢谢,但是点击对话框被触发了两次。我用截图更新了我的问题。
  • 向返回 true 的 TextPrompt 添加一个验证器函数 - 如果您愿意,可以检查其他条件。如果 AdaptiveCard 上的 selectAction 没有 title 属性,则默认验证器函数将返回 false,因为传入的活动没有 text 属性。 this.dialogs.add(new TextPrompt(TAP_PROMPT, ()=> true));
  • 谢谢,我正在使用验证器,我的卡也有文本属性。但是我仍然触发了两次自适应卡。我已经用我正在使用的自适应卡更新了问题。
猜你喜欢
  • 2021-05-01
  • 2019-12-03
  • 2017-10-18
  • 2019-06-25
  • 2020-03-21
  • 2019-12-02
  • 2020-03-01
  • 2019-03-31
  • 1970-01-01
相关资源
最近更新 更多