Bot Framework:如何向 CancelAndHelpDialog 添加用户确认步骤

Bot Framework: How to add user-confirmation step to CancelAndHelpDialog

我想在实际取消所有对话框之前请用户确认。在 current sample code 中,只要用户输入取消或退出,对话框就会被取消。 有什么建议如何做到这一点?

    async interrupt(innerDc) {
        if (innerDc.context.activity.text) {
            const text = innerDc.context.activity.text.toLowerCase();

            switch (text) {
            case 'help':
            case '?': {
                const helpMessageText = 'Show help here';
                await innerDc.context.sendActivity(helpMessageText, helpMessageText, InputHints.ExpectingInput);
                return { status: DialogTurnStatus.waiting };
            }
            case 'cancel':
            case 'quit': {
                const cancelMessageText = 'Cancelling...';
                await innerDc.context.sendActivity(cancelMessageText, cancelMessageText, InputHints.IgnoringInput);
                return await innerDc.cancelAllDialogs();
            }
            }
        }
    }
}

查看 Core Bot 示例,您可以看到 CancelAndHelpDialog 是一个组件对话框,这意味着它有自己的对话框集,我们可以向其中添加对话框。在您的情况下,您需要一个确认提示和一个瀑布对话框。您可以使用 BookingDialog 作为如何实现它的指南,因为它扩展了 CancelAndHelpDialog,因此扩展了 ComponentDialog.

您可以看到 BookingDialog 在其构造函数中向其对话框集添加了内部对话框:

constructor(id) {
    super(id || 'bookingDialog');

    this.addDialog(new TextPrompt(TEXT_PROMPT))
        .addDialog(new ConfirmPrompt(CONFIRM_PROMPT))
        .addDialog(new DateResolverDialog(DATE_RESOLVER_DIALOG))
        .addDialog(new WaterfallDialog(WATERFALL_DIALOG, [
            this.destinationStep.bind(this),
            this.originStep.bind(this),
            this.travelDateStep.bind(this),
            this.confirmStep.bind(this),
            this.finalStep.bind(this)
        ]));

    this.initialDialogId = WATERFALL_DIALOG;
}

如果您想将对话框添加到基础 class CancelAndHelpDialog 中的对话框集,您应该为此定义一个构造函数:

constructor(id) {
    super(id);
    
    this.addDialog(new ConfirmPrompt(CANCELLATION_CONFIRMATION))
        .addDialog(new WaterfallDialog(CANCELLATION_WATERFALL, [
            async stepContext => await stepContext.prompt(CANCELLATION_CONFIRMATION, 'Are you sure you want to cancel?'),
            async stepContext => {
                if (stepContext.result) {
                    const cancelMessageText = 'Cancelling...';
                    await stepContext.context.sendActivity(cancelMessageText, cancelMessageText, InputHints.IgnoringInput);
                    return await stepContext.cancelAllDialogs();
                }

                return stepContext.endDialog();
            },
        ]));
}

请注意,因为 CancelAndHelpDialog 旨在用作基础 class,它将与扩展它的任何 class 共享其对话集。这意味着您需要确保没有任何对话框 ID 与扩展它的 classes 相同。例如,您可以看到 BookingDialog 已经使用了 ID 的 'confirmPrompt''waterfallDialog':

const CONFIRM_PROMPT = 'confirmPrompt';
const DATE_RESOLVER_DIALOG = 'dateResolverDialog';
const TEXT_PROMPT = 'textPrompt';
const WATERFALL_DIALOG = 'waterfallDialog';

这意味着您不能将这些字符串用作您在 CancelAndHelpDialog 中创建的确认提示和瀑布对话框的 ID。这是我正在使用的字符串:

const CANCELLATION_CONFIRMATION = 'cancellationConfirmation';
const CANCELLATION_WATERFALL = 'cancellationWaterfall';

另请注意,我使用匿名箭头函数作为瀑布步骤,但如果您想使用 BookingDialog 之类的命名函数,那么您需要想出不需要的函数名称与扩展 CancelAndHelpDialog 的 classes 中的函数冲突,就像对话框 ID 一样。因此,例如,因为 BookingDialog 包含一个名为 confirmStep 的函数,您不应将其用作调用 CancelAndHelpDialog.

中确认提示的函数的名称

您可能会注意到,我定义的瀑布对话框中的第二步包含的代码几乎与 interrupt 函数中的第二个开关案例相同:

const cancelMessageText = 'Cancelling...';
await innerDc.context.sendActivity(cancelMessageText, cancelMessageText, InputHints.IgnoringInput);
return await innerDc.cancelAllDialogs();

您需要将 interrupt 函数中的代码替换为调用瀑布对话框的代码:

return await innerDc.beginDialog(CANCELLATION_WATERFALL);