Вызов и закрытие диалоговых окон в пакете SDK для Teams

В этой статье описывается, как вызывать и закрывать диалоги (ранее называемые модулями задач) с помощью пакета SDK Для Teams (библиотека ИИ Teams). В пакете SDK для Teams диалоговые окна вызываются из действий адаптивной карточки с помощью TaskFetchAction и обрабатываются посредством открытия диалогового окна и отправки событий в App классе .

Регистрация события зависит от языка:

  • TypeScript: app.on('dialog.open', ...) и app.on('dialog.submit', ...)
  • C#: teamsApp.OnTaskFetch(...) и teamsApp.OnTaskSubmit(...)
  • Python: @app.on_dialog_open и @app.on_dialog_submit

Содержимое диалогового окна может быть адаптивной карточкой или веб-страницей на основе URL-адреса.

Диалоговые окна также можно вызывать с помощью других подходов в зависимости от архитектуры приложения:

Рекомендации по миграции из Bot Framework в пакет SDK для Teams см. в разделе Миграция из BotBuilder.

В следующей таблице показано, как работают диалоги в пакете SDK для Teams.

Шаг Диалоговое окно с адаптивной карточкой Диалоговое окно с URL-адресом веб-страницы
Активация диалогового окна 1. Отправьте пользователю адаптивную карточку с кнопкой TaskFetchAction . Данные действия value указывают тип открываемого диалогового окна.

2. Когда пользователь нажимает кнопку, Teams отправляет в приложение вызов получения задачи.
1. Отправьте пользователю адаптивную карточку с кнопкой TaskFetchAction .

2. Когда пользователь нажимает кнопку, Teams отправляет в приложение вызов получения задачи.
Обработка события открытия диалогового окна 3. В обработчике открытия диалогового окна верните ответ модуля задачи continue, содержащий метаданные диалога (заголовок, измерения и отображаемая адаптивная карточка). В C# используйте TaskInfo с оболочкой ContinueTask . В TypeScript используйте CardTaskModuleTaskInfo. В Python используйте CardTaskModuleTaskInfo в .TaskModuleContinueResponse 3. В обработчике открытия диалогового окна верните ответ модуля задачи continue, содержащий метаданные диалога со свойством url , указывающим на веб-страницу. Домен URL-адреса должен находиться в массиве манифеста validDomains приложения. В C# используйте TaskInfo. В TypeScript используйте UrlTaskModuleTaskInfo. В Python используйте UrlTaskModuleTaskInfo в .TaskModuleContinueResponse
Обработка отправки диалогового окна 4. Когда пользователь нажимает кнопку Action.Submit , Teams отправляет в приложение вызов отправки задачи с данными формы.

5. Вы можете ответить следующим образом:
• Ничего не делать (задача завершена)
• Отображение сообщения (C#: MessageTask, TypeScript/Python: TaskModuleMessageResponse)
• Связывание с другим диалоговым окном (C#: ContinueTask, TypeScript/Python: TaskModuleContinueResponse)
4. Веб-страница вызывает клиентную библиотеку Teams JS для отправки данных обратно. Teams отправляет в приложение вызов отправки задачи с результатом.

В следующем разделе описываются метаданные диалога, определяющие содержимое и внешний вид диалога.

Метаданные диалога

Метаданные диалога определяют содержимое и внешний вид диалога. Каждый язык использует собственные типы для представления этих метаданных:

  • C#: TaskInfo (из Microsoft.Teams.Api.TaskModules)
  • TypeScript: CardTaskModuleTaskInfo или UrlTaskModuleTaskInfo (из @microsoft/teams.api)
  • Python: CardTaskModuleTaskInfo или UrlTaskModuleTaskInfo (из microsoft_teams.api)

В следующей таблице перечислены общие свойства для всех языков:

Атрибут Тип Описание
title string Этот атрибут выводится под названием приложения, справа от его значка.
height number или string Этот атрибут может быть числом, представляющим высоту диалога в пикселях, или small, mediumили large. В C# используйте Union<int, Size>.
width number или string Этот атрибут может быть числом, представляющим ширину диалогового окна в пикселях, или small, mediumили large. В C# используйте Union<int, Size>.
url string URL-адрес страницы, загруженной <iframe> в диалоговом окне. Домен URL-адреса должен находиться в массиве validDomains приложения в манифесте приложения. Используйте UrlTaskModuleTaskInfo в TypeScript или Python или задайте Url для свойства значение TaskInfo в C#.
card Вложение Адаптивная карточка, отображаемая в диалоговом окне. В C# присвойте свойству Card значение AttachmentTaskInfo . В TypeScript используйте с cardAttachment()CardTaskModuleTaskInfo. В Python используйте с card_attachment(AdaptiveCardAttachment(...))CardTaskModuleTaskInfo.

Примечание.

Функция диалогового окна требует, чтобы домены всех URL-адресов, которые вы хотите загрузить, были включены в validDomains массив в манифесте приложения.

В следующем разделе указывается размер диалогового окна, который позволяет пользователю задавать высоту и ширину диалогового окна.

Изменение размера диалогового окна

Значения width и height задайте высоту и ширину диалогового окна в пикселях. В зависимости от размера окна Teams и разрешения экрана эти значения могут быть уменьшены пропорционально при сохранении пропорций.

Если width и height представляют собой small, mediumили large, размер красного прямоугольника на следующем изображении пропорционален размерам доступного пространства, а именно 20 %, 50 % и 60 % для width и 20 %, 50 % и 66 % для height:

Пример изменения размера диалогового окна

В следующем разделе приведены примеры запуска и обработки диалоговых окон с помощью пакета SDK для Teams.

Запуск диалогового окна с помощью TaskFetchAction

Чтобы открыть диалоговое окно, отправьте адаптивную карточку с кнопкой TaskFetchAction . Когда пользователь нажимает кнопку, Teams отправляет вызов задачи, чтобы получить вызов в приложение. Данные каждой value кнопки указывают тип открываемого диалогового окна (например, { "data": "AdaptiveCard" }).

using Microsoft.Teams.Api.Activities;
using Microsoft.Teams.Cards;

teamsApp.OnMessage(async (context) =>
{
    var card = new AdaptiveCard
    {
        Body = new List<CardElement>
        {
            new TextBlock("Task Module Invocation from Adaptive Card")
            {
                Weight = TextWeight.Bolder,
                Size = TextSize.Large
            }
        },
        Actions = new List<Action>
        {
            new TaskFetchAction(new Dictionary<string, object?> { { "data", "AdaptiveCard" } })
            { Title = "Adaptive Card" },
            new TaskFetchAction(new Dictionary<string, object?> { { "data", "CustomForm" } })
            { Title = "Custom Form" },
            new TaskFetchAction(new Dictionary<string, object?> { { "data", "MultiStep" } })
            { Title = "Multi-step Form" }
        }
    };

    await context.Send(new MessageActivity
    {
        Attachments = new List<Attachment>
        {
            new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = card
            }
        }
    });
});

Обработка события открытия диалогового окна

Когда Teams отправляет вызов получения задачи, приложение возвращает содержимое диалогового окна. Содержимое может быть адаптивной карточкой или URL-адресом веб-страницы. В C# заключите метаданные диалога в ContinueTask ответ. В TypeScript возвращает с TaskModuleResponsetype: 'continue'помощью . В Python возвращает объект InvokeResponse , содержащий TaskModuleContinueResponse.

using System.Text.Json;
using Microsoft.Teams.Api.TaskModules;
using Microsoft.Teams.Cards;
using Microsoft.Teams.Common;

teamsApp.OnTaskFetch(async (context) =>
{
    var activity = context.Activity;
    var json = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(activity));
    var data = json.GetProperty("value").GetProperty("data").GetProperty("data").GetString();

    TaskInfo taskInfo;

    if (data == "CustomForm")
    {
        taskInfo = new TaskInfo
        {
            Title = "Custom Form",
            Width = new Union<int, Size>(510),
            Height = new Union<int, Size>(450),
            Url = $"{botEndpoint}/customform",
            FallbackUrl = $"{botEndpoint}/customform"
        };
    }
    else if (data == "MultiStep")
    {
        var step1Card = new AdaptiveCard
        {
            Body = new List<CardElement>
            {
                new TextBlock("Step 1 of 2 - Your Name") { Size = TextSize.Large, Weight = TextWeight.Bolder },
                new TextInput { Id = "name", Label = "Name", Placeholder = "Enter your name", IsRequired = true }
            },
            Actions = new List<Action>
            {
                new SubmitAction().WithTitle("Next").WithData(
                    new Union<string, SubmitActionData>(new SubmitActionData
                    {
                        NonSchemaProperties = new Dictionary<string, object?> { { "submissiontype", "multi_step_1" } }
                    }))
            }
        };

        taskInfo = new TaskInfo
        {
            Title = "Multi-step Form",
            Width = new Union<int, Size>(400),
            Height = new Union<int, Size>(300),
            Card = new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = step1Card
            }
        };
    }
    else
    {
        var dialogCard = new AdaptiveCard
        {
            Body = new List<CardElement>
            {
                new TextBlock("Enter Text Here") { Weight = TextWeight.Bolder },
                new TextInput { Id = "usertext", Placeholder = "add some text and submit", IsMultiline = true }
            },
            Actions = new List<Action> { new SubmitAction { Title = "Submit" } }
        };

        taskInfo = new TaskInfo
        {
            Title = "Adaptive Card: Inputs",
            Width = new Union<int, Size>(400),
            Height = new Union<int, Size>(200),
            Card = new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = dialogCard
            }
        };
    }

    return new Response(new ContinueTask(taskInfo));
});

Обработка отправки диалогового окна

Когда пользователь нажимает Action.Submit в диалоговом окне, Teams отправляет задачу отправить вызов в приложение. Вы можете ответить, выполнив задачу, отобразив сообщение или открыв другое диалоговое окно (например, для цепочки многоэтапных форм).

using System.Text.Json;
using Microsoft.Teams.Api.TaskModules;
using Microsoft.Teams.Cards;
using Microsoft.Teams.Common;

teamsApp.OnTaskSubmit(async (context) =>
{
    var activity = context.Activity;
    var json = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(activity));
    var submitData = JsonSerializer.Deserialize<Dictionary<string, object>>(
        json.GetProperty("value").GetProperty("data").GetRawText());
    var submissionType = submitData?.GetValueOrDefault("submissiontype")?.ToString();

    if (submissionType == "multi_step_1")
    {
        var name = submitData["name"]?.ToString();
        var step2Card = new AdaptiveCard
        {
            Body = new List<CardElement>
            {
                new TextBlock("Step 2 of 2 - Your Email") { Size = TextSize.Large, Weight = TextWeight.Bolder },
                new TextInput { Id = "email", Label = "Email", Placeholder = "Enter your email", IsRequired = true }
            },
            Actions = new List<Action>
            {
                new SubmitAction().WithTitle("Submit").WithData(
                    new Union<string, SubmitActionData>(new SubmitActionData
                    {
                        NonSchemaProperties = new Dictionary<string, object?>
                        {
                            { "submissiontype", "multi_step_2" },
                            { "name", name! }
                        }
                    }))
            }
        };

        var taskInfo = new TaskInfo
        {
            Title = "Multi-step Form: Step 2",
            Width = new Union<int, Size>(400),
            Height = new Union<int, Size>(300),
            Card = new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = step2Card
            }
        };

        return new Response(new ContinueTask(taskInfo));
    }

    if (submissionType == "multi_step_2")
    {
        await context.Send($"Hi {submitData["name"]}, thanks for submitting! Your email is {submitData["email"]}");
        return new Response(new MessageTask("Multi-step form completed!"));
    }

    var usertext = submitData?.GetValueOrDefault("usertext")?.ToString();
    await context.Send($"You submitted: {usertext}");
    return new Response(new MessageTask("Thanks for submitting!"));
});

Рекомендации по использованию клавиатуры и специальных возможностей

Для диалоговых окон на основе URL-адресов, которые загружают HTML-содержимое, убедитесь в специальных возможностях клавиатуры:

  • Используйте атрибут tabindex в тегах HTML для управления элементами, которые можно сфокусировать, а также для определения последовательной навигации с помощью клавиш TAB и SHIFT-TAB .
  • Обработайте клавишу ESC соответствующим образом на javaScript для диалоговой страницы.

Microsoft Teams обеспечивает правильную навигацию с помощью клавиатуры из заголовка диалогового окна в HTML и наоборот.

Пример кода

Название примера Описание .NET Node.js Python
Модули задач бота В этом примере приложения показано, как использовать диалоги (называемые модулями задач в TeamsJS версии 1.x) с помощью пакета SDK для ИИ Для Teams. Просмотр Просмотр Просмотр

Следующий этап

См. также