feat(X-Pack): Webhook 支持自定义 body参数 #18445

This commit is contained in:
fit2cloud-chenyw
2026-06-15 18:21:17 +08:00
committed by fit2cloud-chenyw
parent 576d5eaa9a
commit b666924fb6
11 changed files with 80 additions and 7 deletions

View File

@@ -4895,6 +4895,8 @@ export default {
add: 'Add Webhook',
search_placeholder: 'Search by name',
content_type: 'Content Type',
msg_template: 'Message Template',
msg_template_tips: 'Available placeholders: {t0}, {t1}, {t2}',
del_confirm: 'Are you sure you want to delete this Webhook?',
batch_del_confirm: 'Are you sure you want to delete {0} Webhooks?'
},

View File

@@ -4745,6 +4745,8 @@ export default {
add: '添加 Webhook',
search_placeholder: '通過名稱搜索',
content_type: '內容類型',
msg_template: '消息模板',
msg_template_tips: '可用占位符:{t0}、{t1}、{t2}',
del_confirm: '確定刪除該 Webhook嗎',
batch_del_confirm: '確定刪除 {0} 個 Webhook嗎'
}

View File

@@ -4755,6 +4755,8 @@ export default {
add: '添加 Webhook',
search_placeholder: '通过名称搜索',
content_type: '内容类型',
msg_template: '消息模板',
msg_template_tips: '可用占位符:{t0}、{t1}、{t2}',
del_confirm: '确定删除该 Webhook吗',
batch_del_confirm: '确定删除 {0} 个 Webhook吗'
},

View File

@@ -3,7 +3,7 @@ import { propTypes } from '@/utils/propTypes'
import { onBeforeMount, watch, toRefs, PropType } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import ApiVariable from './ApiVariable.vue'
import CodeEdit from './CodeEdit.vue'
import CodeEdit from '@/components/CodeEdit/CodeEdit.vue'
import Convert from './convert.js'
import { KeyValue, BODY_TYPE } from './ApiTestModel.js'
export interface ApiBodyItem {

View File

@@ -5,6 +5,7 @@ import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.api.webhook.request.WebhookSwitchRequest;
import io.dataease.api.webhook.vo.WebhookGridVO;
import io.dataease.api.webhook.vo.WebhookOption;
import io.dataease.api.webhook.vo.WebhookVO;
import io.dataease.model.KeywordRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -33,7 +34,7 @@ public interface WebhookApi {
@Operation(summary = "保存")
@PostMapping("/save")
void save(@RequestBody WebhookGridVO creator);
void save(@RequestBody WebhookVO creator);
@Operation(summary = "切换SSL")
@PostMapping("/switchSsl")
@@ -43,6 +44,10 @@ public interface WebhookApi {
@PostMapping("/delete")
void delete(@RequestBody List<Long> ids);
@Operation(summary = "查询详情")
@GetMapping("/get/{id}")
WebhookVO get(@PathVariable("id") Long id);
@Operation(summary = "查询选项")
@GetMapping("/options")
List<WebhookOption> options();

View File

@@ -24,9 +24,4 @@ public class WebhookGridVO implements Serializable {
private String contentType;
private Boolean ssl;
@JsonSerialize(using= ToStringSerializer.class)
private Long oid;
private Long createTime;
}

View File

@@ -0,0 +1,34 @@
package io.dataease.api.webhook.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class WebhookVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String name;
private String url;
private String secret;
private String contentType;
private Boolean ssl;
private String msgTemplate;
@JsonSerialize(using = ToStringSerializer.class)
private Long oid;
private Long createTime;
}

View File

@@ -717,6 +717,39 @@ public class HttpClientUtil {
}
}
public static String postRawBody(String url, String contentType, String body, boolean ssl, HttpClientConfig config) {
CloseableHttpClient httpClient = null;
try {
httpClient = buildHttpClient(ssl);
HttpPost httpPost = new HttpPost(url);
if (ObjectUtils.isEmpty(config)) {
config = new HttpClientConfig();
}
httpPost.setConfig(config.buildRequestConfig());
Map<String, String> header = config.getHeader();
for (String key : header.keySet()) {
httpPost.addHeader(key, header.get(key));
}
EntityBuilder entityBuilder = EntityBuilder.create();
entityBuilder.setText(body);
entityBuilder.setContentType(ContentType.create(contentType, java.nio.charset.StandardCharsets.UTF_8));
httpPost.setEntity(entityBuilder.build());
HttpResponse response = httpClient.execute(httpPost);
return getResponseStr(response, config);
} catch (Exception e) {
logger.error("HttpClient POST raw body failed", e);
throw new DEException(SYSTEM_INNER_ERROR.code(), "HttpClient POST raw body failed: " + e.getMessage());
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
} catch (Exception e) {
logger.error("HttpClient关闭连接失败", e);
}
}
}
public static MultipartResponse postForScreenshot(
String url, Map<String,String> body, HttpClientConfig config) throws IOException {
CloseableHttpClient httpClient = null;