Node.js读取Teams含Action.ShowCard的自适应卡片输入值问题
我之前也踩过这个坑!当用Action.ShowCard嵌套input.date、input.choice这类控件时,直接在onMessage里取context.activity.value或者userText返回undefined,大概率是两个原因:要么卡片的JSON配置没做好,导致提交时数据没传过来;要么Bot代码里没正确捕获自适应卡片的提交事件。
为什么会出现这个问题?
普通用户发文本消息时,onMessage会触发,但自适应卡片的Submit动作虽然也是message类型的activity,它的value字段只有在用户点击了配置好的Action.Submit按钮时才会携带输入数据。如果你的Action.ShowCard里的控件没关联到正确的Submit按钮,或者控件的id没设置对,就会导致数据丢失,拿到undefined。
一步步解决问题
1. 先检查你的自适应卡片JSON
确保所有输入控件都有唯一的id,并且ShowCard内部(或者卡片顶级)有Action.Submit按钮,最好给Submit按钮加个data字段用来识别提交动作,方便后续Bot里判断。
示例卡片配置:
{ "type": "AdaptiveCard", "version": "1.4", "body": [ { "type": "TextBlock", "text": "请填写表单信息" } ], "actions": [ { "type": "Action.ShowCard", "title": "展开填写", "card": { "type": "AdaptiveCard", "body": [ { "type": "Input.Date", "id": "selectedDate", "placeholder": "选择日期" }, { "type": "Input.ChoiceSet", "id": "selectedOption", "choices": [ { "title": "选项A", "value": "optA" }, { "title": "选项B", "value": "optB" } ], "placeholder": "选择一个选项" } ], "actions": [ { "type": "Action.Submit", "title": "提交表单", "data": { "action": "submitForm" } } ] } } ] }
这里的关键点:每个输入控件都有唯一id,ShowCard里的Submit按钮带了data.action,方便Bot识别这是表单提交。
2. 在Node.js Bot代码里正确捕获提交
不要只处理普通文本消息,要在onMessage里先判断context.activity.value是否存在——这才是自适应卡片提交时携带数据的地方。
示例代码:
const { ActivityHandler } = require('botbuilder'); class TeamsFormBot extends ActivityHandler { constructor() { super(); this.onMessage(async (context, next) => { // 先判断是不是自适应卡片提交 if (context.activity.value) { const submitData = context.activity.value; // 根据之前设置的action判断是哪个提交动作 if (submitData.action === 'submitForm') { // 从value里取出控件对应id的值 const selectedDate = submitData.selectedDate; const selectedOption = submitData.selectedOption; // 这里写你的验证逻辑,比如检查日期是否合法,选项是否有效 await context.sendActivity(`收到你的提交啦!日期:${selectedDate},选项:${selectedOption}`); } } else { // 处理普通文本消息 await context.sendActivity('收到你的文本消息了😉'); } await next(); }); } } module.exports.TeamsFormBot = TeamsFormBot;
3. 常见排查小技巧
- 用Bot Framework Emulator查看activity的详细内容,看看
value字段到底有没有数据——如果Emulator里都没有,那肯定是卡片配置的问题;如果有数据但Bot里拿不到,再查代码逻辑。 - 确保卡片的
version是1.0以上,Teams对低版本的自适应卡片支持可能有问题。 - 检查控件的
id有没有重复,重复的话会导致数据覆盖或者无法读取。 - 确认Bot已经正确安装到Teams频道,权限没问题——有时候权限不足也会导致数据传递失败。
进阶提示:用Dialog管理提交流程
如果你的Bot需要处理复杂的会话流程,推荐把卡片提交的逻辑放到Dialog里,这样可以更好地管理会话状态,比如:
// 瀑布流Dialog的示例步骤 async function handleSubmitStep(stepContext) { const submitData = stepContext.context.activity.value; const selectedDate = submitData.selectedDate; // 这里做验证,比如检查日期是否在有效范围内 if (!selectedDate) { await stepContext.context.sendActivity('请选择一个有效的日期哦'); return await stepContext.replaceDialog('FormDialog'); } // 验证通过,结束Dialog并返回数据 return await stepContext.endDialog(submitData); }
内容的提问来源于stack exchange,提问作者yuva bharathi

