【全链路】抽象卡片组装API

204 阅读3分钟

1,背景

告警命中后,需要向关注人发送交互性卡片,一张卡片里面包含告警标题(文本),采样数据(表格),归因/处理标签选择(多选框),屏蔽下拉框,按钮等等。所以需要设计一套组装卡片的API,同时具有较强的扩展性。方便后续往卡片上面添加元素(例如某指标近10h值改变趋势等等.....)

2,飞书卡片官网

飞书卡片概述 - 开发指南 - 开发文档 - 飞书开放平台 (feishu.cn)

3,设计

卡片JSON结构

{
        "elements": [{}, {}, {}, {}, {}]
}

卡片有很多种类的元素,把这些元素抽象为一个对象。

按钮,下拉单选框,表格,标题,富文本等等都抽象为一个对象

"elements" 数组里面的每一项就是一种卡片元素,例如按钮 / 表格 / 标题 .....

构建卡片的过程中使用策略模式去构建,下面是一些核心类

卡片元素种类枚举

enum  CardElementEnum {
TABLE, //表格
BUTTON, // 按钮
MARK_DOWN, //富文本
HEADER // 标题
} 

卡片元素操作环境变量

 // 提供创建 or 修改卡片元素 需要的变量
class  CardElementOperateParam {

 // 主标题
String headerTitle;
 // 副标题
String headerSubTitle;
 // 标题颜色
String headerColor;
 // 标题图标
String headerIcon;


 // 省略其他卡片元素变量

} 

卡片元素 Operator 顶层接口

interface  CardElementOperator {

    // 创建卡片元素
    JSONObject buildCardElement (CardElementOperateParam param) ;

    // 修改卡片元素,并不是每一种卡片元素都需要修改,所以这里不用强制实现
    // param -> 提供修改卡片所需要的变量
    // card -> 整张卡片
    // action -> action里面会携带一些标识(比如卡片上有5个按钮,点击了某个具体的按钮,
    // action里面会回传具体是哪个按钮)
    default  void  updateCardElement (CardElementOperateParam param,
                                      JSONObject card,
                                      Action action
                                     ) {
    }
} 

举个例子,构建标题的operator

标题元素的json模板

变量其实就是 headerTitle headerSubTitle headerColor headerIcon

{
        "title": {
                "tag": "plain_text",
                "content": "${headerTitle}"
        },
        "subtitle": {
                "tag": "plain_text",
                "content": "${headerSubTitle}"
        },
        "template": "${headerColor}",
        "ud_icon": {
                "tag": "standard_icon",
                "token": "${headerIcon
        }
}
class HeaderCardElementOperator implements CardElementOperator {


    // buildCardElement 其实就是把 headerTitle headerSubTitle headerIcon 
    // headerColor 塞入到上述的json结构体里面
    @Override
    JSONObject buildCardElement(CardElementOperateParam param) {

        // 主标题
        String headerTitle = param.getHeaderTitle();
        // 副标题
        String headerSubTitle = param.getHeaderSubTitle();
        // 颜色
        String headerColor = param.getHeaderColor();
        // 标题图标
        String headerIcon = param.getHeaderIcon();

        // 将上述变量塞到标题JSON模板里面 ....



        return titleJSONObject;
    }

    void updateCardElement() (CardElementOperateParam param, 
                              JSONObject card, 
                              Action action
                             ) {
        // 首先过滤出标题卡片元素
        JSONObject header = getHeader(card); 

        // 主标题
        String headerTitle = param.getHeaderTitle();
        // 副标题
        String headerSubTitle = param.getHeaderSubTitle();
        // 颜色
        String headerColor = param.getHeaderColor();
        // 标题图标
        String headerIcon = param.getHeaderIcon();    

        ofNullable(headerTitle).ifPresent(title->{
            // 修改主标题
        });   

        ofNullable(headerSubTitle).ifPresent(subTitle->{
            // 修改副标题
        });        

        ofNullable(headerColor).ifPresent(color->{
            // 修改标题颜色
        });        

        ofNullable(headerIcon).ifPresent(icon->{
            // 修改标题图标
        });                     
    } 


}  

调用API

调用API构建卡片标题

{
   // 主标题 供应商未知异常率 >= 80%
   // 副标题 全链路监控
   // 标题颜色取 : 红色 red
   // 标题图标xx
   
   // 这是整张卡片
   JSONObject totalCard;
   
   String headerTitle = "供应商未知异常率 >= 80%";
   String headerSubTitle = "全链路监控";
   String headerColor = "red";
   String headerIcon = xxx;
   
   CardElementOperateParam param = CardElementOperateParam
                                                .builder()
                                                .headerTitle(headerTitle)
                                                .headerSubTitle(headerSubTitle)
                                                .headerColor(headerColor)
                                                .headerIcon(headerIcon)
                                                .build();
    
   
   // 策略模式
   // 获得 HeaderCardElementOperator
   JSONObject header = CardElementOperatorFactory.getCardElementOperator(HEADER)
                                                 .buildCardElement(param);
   
   // 标题元素添加到整张卡片
   totalCard.getJSONArray("elements).add(header);
}