基于Node.js的Teams Bot:能否删除自适应卡片轮播中的单张卡片?
如何在Teams Bot的自适应卡片轮播中删除单个点击过的卡片?
当然可行!你遇到的问题是因为自适应卡片轮播本质是单个Activity里的多个附件集合,deleteActive会删除整个Activity(也就是整个轮播),而不是其中某一张卡片。要实现删除点击的单张卡片,我们需要通过更新原轮播Activity,移除目标卡片后重新渲染轮播。
解决方案思路
- 保存轮播的Activity ID和对应卡片的关联数据(比如LeadId),方便后续定位要删除的卡片
- 用户点击操作按钮时,根据传入的LeadId过滤掉对应卡片
- 使用
context.updateActivity方法替换原轮播的附件列表,实现单张卡片的“删除”效果
修改后的代码示例
const { TurnContext, TeamsActivityHandler, CardFactory, AttachmentLayoutTypes, ActionTypes } = require('botbuilder'); class TeamsConversationBot extends TeamsActivityHandler { constructor() { super(); // 存储每个会话的轮播活动信息:会话ID -> { activityId, 卡片列表(带LeadId) } this.carouselSessionData = {}; this.onMessage(async (context:any, next:any) => { TurnContext.removeRecipientMention(context.activity); console.log("context activity at the begin is:" + JSON.stringify(context.activity)) let msg = context.activity.text let action = context.activity.value if(msg.startsWith('lead')){ msg = 'lead' } if(action !== undefined){ console.log("user did some action on a card") msg = action.action } switch (msg) { case 'lead': await this.lead(context) break; case 'qualify_lead': await this.qualifyLead(context) break; } await next(); }); } async qualifyLead(context:any){ console.log("in qualifyLead:" + JSON.stringify(context.activity)) const leadId = context.activity.value.objectId const conversationId = context.activity.conversation.id; const carouselInfo = this.carouselSessionData[conversationId]; if (carouselInfo) { // 过滤掉当前要删除的卡片 const updatedCardList = carouselInfo.cards.filter(cardItem => cardItem.LeadId !== leadId) .map(cardItem => cardItem.card); // 更新原轮播活动,替换附件列表 await context.updateActivity({ id: carouselInfo.activityId, attachments: updatedCardList, attachmentLayout: AttachmentLayoutTypes.Carousel }); // 可以清除已无卡片的会话数据(可选) if (updatedCardList.length === 0) { delete this.carouselSessionData[conversationId]; } } console.log("Lead to qualify is:" + leadId) await context.sendActivity('Lead is qualified') } async lead(context:any){ console.log("Start of lead with context:" + JSON.stringify(context)) const items = [ {"Name": 'x', "LeadId": "1"}, {"Name": 'a', "LeadId": "2"}, {"Name": 'b', "LeadId": "3"}, {"Name": 'c', "LeadId": "4"}, {"Name": 'd', "LeadId": "5"} ] // 生成卡片并保存每张卡片对应的LeadId const cardDataList = items.map(item => { const header = { "type": "TextBlock", "size": "Medium", "weight": "Bolder", "text": item.Name } const actions = [ { "type": "Action.Submit", "title": "Qualify", "data": { "action" : "qualify_lead", "objectId" : item.LeadId } } ] const acard = CardFactory.adaptiveCard( { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.0", "body": [ header ], "actions": actions } ) return { LeadId: item.LeadId, card: acard }; }); const cardArr = cardDataList.map(item => item.card); const reply = { "attachments" : cardArr, "attachmentLayout" : AttachmentLayoutTypes.Carousel } // 发送轮播并保存活动ID和卡片数据 const sentActivity = await context.sendActivity(reply); this.carouselSessionData[context.activity.conversation.id] = { activityId: sentActivity.id, cards: cardDataList }; } } module.exports.TeamsConversationBot = TeamsConversationBot;
关键说明
carouselSessionData用来存储每个会话的轮播信息,确保不同用户/会话的操作互不干扰updateActivity会替换原轮播的附件,用户看到的效果就是目标卡片被移除,其他卡片保持轮播状态- 如果所有卡片都被删除,可以选择删除会话数据或者发送一个“无卡片”提示
内容的提问来源于stack exchange,提问作者Moblize IT
相关产品推荐
相关产品推荐

