class DingTalkMsgExt {
        @Value("${robot.img.success}")
        public String successUrl;
        //警告时的图片url
        @Value("${robot.img.warning}")
        public String warningUrl;
        //失败时的图片url
        @Value("${robot.img.error}")
        public String errorUrl;
    }
    @Autowired
    private DingTalkMsgExt ext;

    Expression templateTestSuiteMessage = RobotMessenger.parseTemplate("""
            #{
            {
              msgtype: 'link',
              link: {
                title: '测试套件:' + suiteName + '运行完毕！',
                text: '通过数：'+pass+'
            异常数：'+warn+'
            失败数：'+fail,
                messageUrl: url,
                picUrl: (fail > 0 ? ext.errorUrl : (warn > 0 ? ext.warningUrl : ext.successUrl))
              }
            }
            }""");
    Expression templateProjectSummaryMessage = RobotMessenger.parseTemplate("""
            #{
            {
              msgtype: 'markdown',
              markdown: {
               title: 'Sonic云真机测试平台'+(isWeekly?'周':'日')+'报',
               text: '### Sonic云真机测试平台'+(isWeekly ? '周': '日')+'报
            > ###### 项目：'+projectName+'
            > ###### 时间：'+getFormat().format(startDate)+' ～ '+getFormat().format(endDate)+'
            > ###### 共测试：'+total+'次
            > ###### 通过数：<font color=#67C23A>'+pass+'</font>
            > ###### 异常数：<font color='+(warn==0?'#67C23A':'#F56C6C')+'>'+warn+'</font>
            > ###### 失败数：<font color='+(warn==0?'#67C23A':'#F56C6C')+'>'+fail+'</font>
            > ###### 测试通过率：'+rate+'%
            > ###### 详细统计：[点击查看]('+url+')'
              }
            }
            }""");
    Expression templateDeviceMessage = RobotMessenger.parseTemplate("""
            #{
            { msgtype: 'markdown',
              markdown: {
                title: '设备温度异常通知',
                text: '### Sonic设备高温'+(errorType == 1 ? '预警' : '超时，已关机！')+'
            > ###### 设备序列号：'+udId+'
            > ###### 电池温度：<font color=#F56C6C>'+tem+' ℃</font>'
              }
            }
            }""");

    /**
     * @param restTemplate RestTemplate
     * @param token        机器人token
     * @param secret       机器人密钥
     * @param jsonObject   通知内容
     * @author ZhouYiXun
     * @des 钉钉官方签名方法
     * @date 2021/8/20 18:20
     */
    private void signAndSend(RestTemplate restTemplate, String token, String secret, Map<?, ?> jsonObject) {<FILL_FUNCTION_BODY>

        try {
            String path = "";
            if (!StringUtils.isEmpty(secret)) {
                Long timestamp = System.currentTimeMillis();
                String stringToSign = timestamp + "\n" + secret;
                Mac mac = Mac.getInstance("HmacSHA256");
                mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
                byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
                String sign = URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), StandardCharsets.UTF_8);
                path = "&timestamp=" + timestamp + "&sign=" + sign;
            }

            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(token + path, jsonObject, JSONObject.class);
            log.info("robot result: " + responseEntity.getBody());
        } catch (Exception e) {
            log.warn("robot send failed, cause: " + e.getMessage());
        }
    
<no_super_class>