You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Teams自适应卡片提交后禁用/隐藏Submit按钮的实现方案问询

问题描述

我有如下简单的Adaptive Card模板:

{
    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.4",
    "body": [
        {
            "type": "Input.Text",
            "placeholder": "Feedback",
            "id": "feedback_text"
        },
        {
            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.Submit",
                    "title": "Submit"
                }
            ]
        }
    ]
}

希望实现用户提交反馈后完成以下任一操作:

  1. 移除Submit按钮(例如设置isVisible为false)
  2. 禁用Submit按钮
    核心需求是确保用户仅能提交一次反馈,当前使用.NET Bot Framework SDK作为机器人后端。想了解是否可通过Adaptive Card端的配置或数据方式实现该功能;若不可行,后端是否有可行的实现途径?

解决方案

一、Adaptive Card端直接实现的限制

Adaptive Card本身属于静态交互载体,仅能处理卡片内部的本地交互(比如Action.ToggleVisibility),但无法感知用户已提交反馈的全局状态——因为Action.Submit是将数据发送到后端,卡片本身没有持久化状态的能力。因此无法仅通过卡片端配置实现提交后隐藏/禁用按钮的需求。

二、.NET Bot Framework SDK后端实现方案

后端可以通过两种方式实现“仅允许提交一次”的需求,同时满足UI更新或状态拦截的要求:

方式1:提交后替换原有卡片

当用户点击Submit按钮并发送数据到后端后,生成一个更新后的卡片(隐藏/禁用按钮、锁定输入框),通过Bot Framework的UpdateActivityAsync方法替换用户聊天窗口中原有的卡片,从UI层面阻止重复提交。

示例代码:

using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using AdaptiveCards;
using Newtonsoft.Json;

public class FeedbackBot : ActivityHandler
{
    // 处理用户消息/提交动作
    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        // 判断是否为Adaptive Card的提交动作
        if (turnContext.Activity.Value != null)
        {
            // 解析用户提交的反馈数据
            var feedbackData = JsonConvert.DeserializeObject<FeedbackModel>(turnContext.Activity.Value.ToString());
            
            // 这里添加保存反馈到数据库/存储的逻辑
            
            // 生成更新后的卡片:隐藏提交按钮+锁定输入框
            var updatedCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 4))
            {
                Body = new List<AdaptiveElement>
                {
                    new AdaptiveTextInput
                    {
                        Placeholder = "Feedback",
                        Id = "feedback_text",
                        Value = feedbackData.FeedbackText,
                        IsReadOnly = true // 锁定输入框,禁止修改
                    },
                    new AdaptiveActionSet
                    {
                        Actions = new List<AdaptiveAction>
                        {
                            new AdaptiveSubmitAction
                            {
                                Title = "Submit",
                                IsVisible = false // 隐藏提交按钮
                            }
                        }
                    }
                }
            };

            // 构造更新后的卡片附件
            var updatedAttachment = new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = updatedCard
            };

            // 替换原有卡片消息
            await turnContext.UpdateActivityAsync(
                MessageFactory.Attachment(updatedAttachment), 
                cancellationToken
            );
            
            // 可选:发送提交成功提示
            await turnContext.SendActivityAsync("反馈已提交,感谢您的参与!", cancellationToken: cancellationToken);
            return;
        }

        // 首次发送原始卡片
        var originalCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 4))
        {
            Body = new List<AdaptiveElement>
            {
                new AdaptiveTextInput { Placeholder = "Feedback", Id = "feedback_text" },
                new AdaptiveActionSet
                {
                    Actions = new List<AdaptiveAction> { new AdaptiveSubmitAction { Title = "Submit" } }
                }
            }
        };

        await turnContext.SendActivityAsync(
            MessageFactory.Attachment(new Attachment { ContentType = AdaptiveCard.ContentType, Content = originalCard }), 
            cancellationToken
        );
    }
}

// 用于解析反馈数据的模型类
public class FeedbackModel
{
    [JsonProperty("feedback_text")]
    public string FeedbackText { get; set; }
}

方式2:记录用户提交状态,拦截重复提交

如果不需要更新卡片UI,可在后端维护用户的提交状态(如数据库、缓存),当用户发起重复提交时直接拦截并提示。

示例代码片段:

using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
using System.Collections.Generic;

public class FeedbackBot : ActivityHandler
{
    // 生产环境建议用数据库替代内存字典
    private static readonly Dictionary<string, bool> _submittedUserStatus = new Dictionary<string, bool>();

    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        if (turnContext.Activity.Value != null)
        {
            var userId = turnContext.Activity.From.Id;
            
            // 检查用户是否已提交过反馈
            if (_submittedUserStatus.ContainsKey(userId) && _submittedUserStatus[userId])
            {
                await turnContext.SendActivityAsync("您已提交过反馈,无需重复操作", cancellationToken: cancellationToken);
                return;
            }

            // 处理并保存反馈数据
            var feedbackData = JsonConvert.DeserializeObject<FeedbackModel>(turnContext.Activity.Value.ToString());
            
            // 标记用户为已提交
            _submittedUserStatus[userId] = true;
            
            await turnContext.SendActivityAsync("反馈已提交成功!", cancellationToken: cancellationToken);
            return;
        }

        // 首次发送卡片逻辑...
    }
}

补充说明

  • 若选择更新卡片的方式,建议同时将输入框设为IsReadOnly: true,避免用户修改已提交的内容
  • 生产环境中,用户提交状态必须存储在持久化存储(如SQL Server、Cosmos DB),不能用内存字典,避免机器人重启后状态丢失

内容的提问来源于stack exchange,提问作者Mohamad Mousheimish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:42:36