IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    使用飞书消息卡片变量功能,批量数据快速录入消息卡片

    白宦成发表于 2023-08-21 22:38:48
    love 0

    在开发短链助手的时候,我需要实现一个查看当前用户创建的所有短链接的能力。这个依然希望通过消息卡片来完成。而作为一个 JSON,想要构建一套合适的内容,就变得十分的麻烦和复杂。

    解构消息卡片

    我要发送的消息卡片当中,可以区分为动态内容和静态内容,对于静态内容,我可能长期都不会变化,而静态内容,则会根据用户的数据发生变化。

    如果整体都放在代码中生成,我就需要有一段又臭又长的代码来维护其中的变化的 JSON ,而我希望整个代码的简洁,不要有比较长的代码只是用来生成卡片的逻辑,所以就用上了消息卡片的新功能:循环对象数组。

    而进一步看动态内容,则我们可以将其视为是变量 A 和变量 B 在不断的被重复赋予,最终形成了一行一行的结果。

    而我们想要实现这样功能。首先,需要在卡片搭建工具中创建一个循环对象数组,并将其绑定在一个「多列布局」上。

    绑定完成后,你的多列布局就有了被循环的可能性。

    接下来你需要在多列布局中去构建你的每一行的结果,并在对应的位置绑定上变量,比如我这里就给多列布局防止了一个 Markdown 文本组件,并在这个文本组件中,填入了 ${source} 作为变量 A 进行填充。

    当你根据你的需要,构建出需要的卡片结构后,点击右上角的保存并发布,就可以准备写代码来实现批量发送数据的逻辑了。

    代码片段

    这里的逻辑不复杂,首先需要从数据库中提取出需要用用作列表循环的数据,这里以 data.data 为例,data.data 是一个包含了 Object 的 Array,其中每一个 Object 都有 Postfix 和 Link 两个字段。这两个字段就是我们稍后要塞在卡片中的。

           // data.data = [{Postfix:"a",Link:"https://amazon.cn"}]
            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',
              },
            })

    最终我们构建出来,发给飞书服务器的 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"
            }
          ]
        }
      }
    }

    文章中构建的出的卡片

    构建出的卡片 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": ""
      }
    }

    完整代码参考

    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 {
          // function to create link
    
          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 {
            // function to get all my 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',
              },
            })
            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' }
    }


沪ICP备19023445号-2号
友情链接