在开发短链助手的时候,我需要实现一个查看当前用户创建的所有短链接的能力。这个依然希望通过消息卡片来完成。而作为一个 JSON,想要构建一套合适的内容,就变得十分的麻烦和复杂。
解构消息卡片 我要发送的消息卡片当中,可以区分为动态内容和静态内容,对于静态内容,我可能长期都不会变化,而静态内容,则会根据用户的数据发生变化。
如果整体都放在代码中生成,我就需要有一段又臭又长的代码来维护其中的变化的 JSON ,而我希望整个代码的简洁,不要有比较长的代码只是用来生成卡片的逻辑,所以就用上了消息卡片的新功能:循环对象数组。
而进一步看动态内容,则我们可以将其视为是变量 A 和变量 B 在不断的被重复赋予,最终形成了一行一行的结果。
而我们想要实现这样功能。首先,需要在卡片搭建工具中创建一个循环对象数组,并将其绑定在一个「多列布局」上。
绑定完成后,你的多列布局就有了被循环的可能性。
接下来你需要在多列布局中去构建你的每一行的结果,并在对应的位置绑定上变量,比如我这里就给多列布局防止了一个 Markdown 文本组件,并在这个文本组件中,填入了 ${source}
作为变量 A 进行填充。
当你根据你的需要,构建出需要的卡片结构后,点击右上角的保存并发布,就可以准备写代码来实现批量发送数据的逻辑了。
代码片段 这里的逻辑不复杂,首先需要从数据库中提取出需要用用作列表循环的数据,这里以 data.data 为例,data.data 是一个包含了 Object 的 Array,其中每一个 Object 都有 Postfix 和 Link 两个字段。这两个字段就是我们稍后要塞在卡片中的。
let links = data.data.map(item => {
return {
source : `[${item.Postfix} ](https://link.feishu.io/${item.Postfix} )` ,
target : item.Link
}
})
await client.request({
method : "POST" ,
url : "https://open.feishu.cn/open-apis/im/v1/messages" ,
data : {
receive_id : ctx.body.event.operator.operator_id.open_id,
msg_type : 'interactive' ,
content : JSON .stringify({
"type" : "template" ,
"data" : {
"template_id" : "ctp_AAmFBm5vnHfs" ,
"template_variable" : {
"CONTENT" : links
}
}
}),
},
params : {
receive_id_type : 'open_id' ,
},
})
Code language: JavaScript ( javascript ) 最终我们构建出来,发给飞书服务器的 JSON 其实是这样子的,这段 JSON 就会和我们在卡片搭建工具中构建的 JSON 租和,自动进行拼接,从而实现我们想要的循环效果。
{
"type" : "template" ,
"data" : {
"template_id" : "ctp_AAmFBm5vnHfs" ,
"template_variable" : {
"CONTENT" : [
{
"source" :"a" ,
"target" :"https://amazon.cn"
},
{
"source" :"b" ,
"target" :"https://baidu.com"
}
]
}
}
}
Code language: JSON / JSON with Comments ( json ) 文章中构建的出的卡片 构建出的卡片 JSON 是这样的,方便你参考:
{
"elements" : [
{
"tag" : "markdown" ,
"content" : "你创建的链接如下:"
},
{
"tag" : "column_set" ,
"flex_mode" : "none" ,
"background_style" : "grey" ,
"columns" : [
{
"tag" : "column" ,
"width" : "weighted" ,
"weight" : 1 ,
"vertical_align" : "top" ,
"elements" : [
{
"tag" : "div" ,
"text" : {
"content" : "${source}" ,
"tag" : "lark_md"
}
}
]
},
{
"tag" : "column" ,
"width" : "weighted" ,
"weight" : 4 ,
"vertical_align" : "top" ,
"elements" : [
{
"tag" : "div" ,
"text" : {
"content" : "${target}" ,
"tag" : "lark_md"
}
}
]
}
],
"_varloop" : "${CONTENT}"
}
],
"header" : {
"template" : "turquoise" ,
"title" : {
"content" : "链接清单" ,
"tag" : "plain_text"
}
},
"card_link" : {
"url" : "" ,
"pc_url" : "" ,
"android_url" : "" ,
"ios_url" : ""
}
}
Code language: JSON / JSON with Comments ( json ) 完整代码参考 import cloud from '@lafjs/cloud'
import axios from 'axios'
let appid = "" ;
let secret = ""
const lark = require ('@larksuiteoapi/node-sdk' );
const client = new lark.Client({
appId : appid,
appSecret : secret
});
export default async function (ctx: FunctionContext ) {
console .log("event" ,ctx.body);
if (ctx.body.challenge) {
return ctx.body
}
if (Object .hasOwn(ctx.body, "action" ) && ctx.body.action) {
if (ctx.body.action.name != "submit" ) return { code : 1 };
try {
if (status == 200 ) {
return JSON .stringify({
"type" : "template" ,
"data" : {
"template_id" : "ctp_AAmFBm5vnlt0" ,
"template_variable" : {
"source" : ctx.body.action.form_value.postfix,
"target" : ctx.body.action.form_value.link
}
}
})
}
return {};
} catch (e) {
return JSON .stringify({
"type" : "template" ,
"data" : {
"template_id" : "ctp_AAmFBm5vZYuo" ,
"template_variable" : {
"POSTFIX" : ctx.body.action.form_value.postfix
}
}
});
}
}
if (Object .hasOwn(ctx.body, "header" ) && ctx.body.header.event_type == 'application.bot.menu_v6' ) {
if (ctx.body.event.event_key == "help" ) {
try {
let content = JSON .stringify({
template_id : "ctp_AAmFBFOpYX0S"
});
await client.request({
method : "POST" ,
url : "https://open.feishu.cn/open-apis/im/v1/messages" ,
data : {
receive_id : ctx.body.event.operator.operator_id.open_id,
msg_type : 'interactive' ,
content : JSON .stringify({
"type" : "template" ,
"data" : {
"template_id" : "ctp_AAmFBFOpYX0S" ,
}
}),
},
params : {
receive_id_type : 'open_id' ,
},
})
return {};
} catch (e) {
console .log(`key: ${ctx.body.event.event_key} , user:${ctx.body.event.operator.operator_id.open_id} ,error` , e);
return {};
}
}
if (ctx.body.event.event_key == "mylink" ) {
try {
let links = data.data.map(item => {
return {
source : `[${item.Postfix} ](https://link.feishu.io/${item.Postfix} )` ,
target : item.Link
}
})
await client.request({
method : "POST" ,
url : "https://open.feishu.cn/open-apis/im/v1/messages" ,
data : {
receive_id : ctx.body.event.operator.operator_id.open_id,
msg_type : 'interactive' ,
content : JSON .stringify({
"type" : "template" ,
"data" : {
"template_id" : "ctp_AAmFBm5vnHfs" ,
"template_variable" : {
"CONTENT" : links
}
}
}),
},
params : {
receive_id_type : 'open_id' ,
},
})
return {};
} catch (e) {
console .log(`key: ${ctx.body.event.event_key} , user:${ctx.body.event.operator.operator_id.open_id} ,error` , e);
return {};
}
}
if (ctx.body.event.event_key == "create" ) {
try {
await client.request({
method : "POST" ,
url : "https://open.feishu.cn/open-apis/im/v1/messages" ,
data : {
receive_id : ctx.body.event.operator.operator_id.open_id,
msg_type : 'interactive' ,
content : "{\"header\":{\"template\":\"turquoise\",\"title\":{\"content\":\"创建短链接\",\"tag\":\"plain_text\"}},\"elements\":[{\"tag\":\"form\",\"name\":\"form_1\",\"elements\":[{\"tag\":\"input\",\"name\":\"postfix\",\"placeholder\":{\"tag\":\"plain_text\",\"content\":\"请输入后缀\"},\"max_length\":10,\"label\":{\"tag\":\"plain_text\",\"content\":\"请输入后缀:\"},\"label_position\":\"left\",\"value\":{\"k\":\"v\"}},{\"tag\":\"input\",\"name\":\"link\",\"placeholder\":{\"tag\":\"plain_text\",\"content\":\"请输入要跳转链接\"},\"label\":{\"tag\":\"plain_text\",\"content\":\"请输入要跳转链接:\"},\"label_position\":\"left\",\"value\":{\"k\":\"v\"}},{\"action_type\":\"form_submit\",\"name\":\"submit\",\"tag\":\"button\",\"text\":{\"content\":\"提交\",\"tag\":\"lark_md\"},\"type\":\"primary\",\"confirm\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"创建短链接\"},\"text\":{\"tag\":\"plain_text\",\"content\":\"确认提交吗\"}}}]}]}" ,
},
params : {
receive_id_type : 'open_id' ,
},
})
return {};
} catch (e) {
console .log(`key: ${ctx.body.event.event_key} , user:${ctx.body.event.operator.operator_id.open_id} ,error` , e);
return {};
}
}
}
return { data : 'hi, laf' }
}
Code language: JavaScript ( javascript )