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);
}