增加构建通知

This commit is contained in:
dengqichen 2025-11-12 18:14:20 +08:00
parent c00153082c
commit b1cbf52044
21 changed files with 425 additions and 112 deletions

View File

@ -48,7 +48,7 @@ public class NotificationTemplateApiController extends BaseController<Notificati
@Operation(summary = "渲染模板预览")
@PostMapping("/render")
public Response<String> renderTemplate(@Valid @RequestBody TemplateRenderRequest request) {
String result = notificationTemplateService.renderTemplate(request.getTemplateCode(), request.getParams());
String result = notificationTemplateService.renderTemplate(request.getTemplateContext(), request.getParams());
return Response.success(result);
}

View File

@ -1,9 +1,17 @@
package com.qqchen.deploy.backend.notification.converter;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import com.qqchen.deploy.backend.framework.utils.JsonUtils;
import com.qqchen.deploy.backend.notification.dto.NotificationTemplateDTO;
import com.qqchen.deploy.backend.notification.dto.template.BaseTemplateConfigDTO;
import com.qqchen.deploy.backend.notification.dto.template.EmailTemplateConfigDTO;
import com.qqchen.deploy.backend.notification.dto.template.WeworkTemplateConfigDTO;
import com.qqchen.deploy.backend.notification.entity.NotificationTemplate;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Map;
/**
* 通知模板转换器
@ -13,4 +21,49 @@ import org.mapstruct.Mapper;
*/
@Mapper(componentModel = "spring")
public interface NotificationTemplateConverter extends BaseConverter<NotificationTemplate, NotificationTemplateDTO> {
@Override
@Mapping(target = "templateConfig", expression = "java(mapToTemplateConfigDTO(entity.getTemplateConfig(), entity.getChannelType()))")
@Mapping(target = "extraData", ignore = true)
NotificationTemplateDTO toDto(NotificationTemplate entity);
@Override
@Mapping(target = "templateConfig", expression = "java(mapToTemplateConfigMap(dto.getTemplateConfig()))")
NotificationTemplate toEntity(NotificationTemplateDTO dto);
@Override
@Mapping(target = "templateConfig", expression = "java(mapToTemplateConfigMap(dto.getTemplateConfig()))")
@Mapping(target = "id", ignore = true)
@Mapping(target = "createTime", ignore = true)
@Mapping(target = "updateTime", ignore = true)
@Mapping(target = "createBy", ignore = true)
@Mapping(target = "updateBy", ignore = true)
@Mapping(target = "version", ignore = true)
@Mapping(target = "deleted", ignore = true)
void updateEntity(@org.mapstruct.MappingTarget NotificationTemplate entity, NotificationTemplateDTO dto);
/**
* 将Map转换为TemplateConfigDTO
*/
default BaseTemplateConfigDTO mapToTemplateConfigDTO(Map<String, Object> configMap, NotificationChannelTypeEnum channelType) {
if (configMap == null || channelType == null) {
return null;
}
return switch (channelType) {
case WEWORK -> JsonUtils.fromMap(configMap, WeworkTemplateConfigDTO.class);
case EMAIL -> JsonUtils.fromMap(configMap, EmailTemplateConfigDTO.class);
default -> null;
};
}
/**
* 将TemplateConfigDTO转换为Map
*/
default Map<String, Object> mapToTemplateConfigMap(BaseTemplateConfigDTO configDTO) {
if (configDTO == null) {
return null;
}
return JsonUtils.toMap(configDTO);
}
}

View File

@ -1,60 +0,0 @@
package com.qqchen.deploy.backend.notification.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 通知请求DTO
*
* @author qqchen
* @since 2025-11-03
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class NotificationRequest {
/**
* 通知渠道ID必填
* 从sys_notification_channel表查询
*/
@NotNull(message = "渠道ID不能为空")
private Long channelId;
/**
* 消息标题可选
* - 企业微信会与content拼接
* - 邮件作为邮件主题
*/
private String title;
/**
* 消息内容必填
* - 企业微信文本内容
* - 邮件邮件正文
*/
@NotBlank(message = "消息内容不能为空")
private String content;
/**
* 收件人列表可选
* - 企业微信不需要发送到配置的群
* - 邮件收件人邮箱列表如果为空则使用渠道配置中的默认收件人
*/
private List<String> receivers;
/**
* @人列表可选
* - 企业微信@specific用户手机号或userid
* - 邮件抄送列表
*/
private List<String> mentions;
}

View File

@ -1,6 +1,7 @@
package com.qqchen.deploy.backend.notification.dto;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.qqchen.deploy.backend.notification.dto.template.BaseTemplateConfigDTO;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
@ -44,4 +45,7 @@ public class NotificationTemplateDTO extends BaseDTO {
@Schema(description = "是否启用", example = "true")
private Boolean enabled = true;
@Schema(description = "模板配置(根据渠道类型不同而不同)")
private BaseTemplateConfigDTO templateConfig;
}

View File

@ -0,0 +1,34 @@
package com.qqchen.deploy.backend.notification.dto.template;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import lombok.Data;
/**
* 模板配置DTO基类
* 用于数据传输层与Entity层的BaseTemplateConfig对应
*
* 使用 EXISTING_PROPERTY 方式利用外层 NotificationTemplateDTO channelType 字段
* 进行多态反序列化无需在 templateConfig 内部添加额外的 type 字段
*
* @author qqchen
* @since 2025-11-12
*/
@Data
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "channelType"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = WeworkTemplateConfigDTO.class, name = "WEWORK"),
@JsonSubTypes.Type(value = EmailTemplateConfigDTO.class, name = "EMAIL")
})
public abstract class BaseTemplateConfigDTO {
/**
* 获取渠道类型与外层 NotificationTemplateDTO.channelType 保持一致
*/
public abstract NotificationChannelTypeEnum getChannelType();
}

View File

@ -0,0 +1,42 @@
package com.qqchen.deploy.backend.notification.dto.template;
import com.qqchen.deploy.backend.notification.enums.EmailContentTypeEnum;
import com.qqchen.deploy.backend.notification.enums.EmailPriorityEnum;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 邮件模板配置DTO
*
* @author qqchen
* @since 2025-11-12
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "邮件模板配置")
public class EmailTemplateConfigDTO extends BaseTemplateConfigDTO {
/**
* 渠道类型用于Jackson反序列化与外层保持一致
*/
private final NotificationChannelTypeEnum channelType = NotificationChannelTypeEnum.EMAIL;
/**
* 内容类型
*/
@Schema(description = "内容类型", example = "TEXT", allowableValues = {"TEXT", "HTML"})
private EmailContentTypeEnum contentType = EmailContentTypeEnum.TEXT;
/**
* 邮件优先级
*/
@Schema(description = "邮件优先级", example = "NORMAL", allowableValues = {"LOW", "NORMAL", "HIGH"})
private EmailPriorityEnum priority = EmailPriorityEnum.NORMAL;
@Override
public NotificationChannelTypeEnum getChannelType() {
return NotificationChannelTypeEnum.EMAIL;
}
}

View File

@ -16,9 +16,9 @@ import java.util.Map;
@Schema(description = "模板渲染请求")
public class TemplateRenderRequest {
@Schema(description = "模板编码", example = "jenkins_build_wework")
@NotBlank(message = "模板编码不能为空")
private String templateCode;
@Schema(description = "模板内容")
@NotBlank(message = "模板内容不能为空")
private String templateContext;
@Schema(description = "模板参数", example = "{\"projectName\": \"deploy-ease-platform\", \"buildNumber\": 123}")
private Map<String, Object> params;

View File

@ -1,30 +0,0 @@
package com.qqchen.deploy.backend.notification.dto.template;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.Map;
/**
* 模板发送请求
*
* @author qqchen
* @since 2025-11-12
*/
@Data
@Schema(description = "模板发送请求")
public class TemplateSendRequest {
@Schema(description = "模板编码", example = "jenkins_build_wework")
@NotBlank(message = "模板编码不能为空")
private String templateCode;
@Schema(description = "渠道ID", example = "1")
@NotNull(message = "渠道ID不能为空")
private Long channelId;
@Schema(description = "模板参数", example = "{\"projectName\": \"deploy-ease-platform\", \"buildNumber\": 123}")
private Map<String, Object> params;
}

View File

@ -0,0 +1,35 @@
package com.qqchen.deploy.backend.notification.dto.template;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 企业微信模板配置DTO
*
* @author qqchen
* @since 2025-11-12
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "企业微信模板配置")
public class WeworkTemplateConfigDTO extends BaseTemplateConfigDTO {
/**
* 渠道类型用于Jackson反序列化与外层保持一致
*/
private final NotificationChannelTypeEnum channelType = NotificationChannelTypeEnum.WEWORK;
/**
* 消息类型
*/
@Schema(description = "消息类型", example = "TEXT", allowableValues = {"TEXT", "MARKDOWN", "FILE"})
private WeworkMessageTypeEnum messageType = WeworkMessageTypeEnum.TEXT;
@Override
public NotificationChannelTypeEnum getChannelType() {
return NotificationChannelTypeEnum.WEWORK;
}
}

View File

@ -3,9 +3,13 @@ package com.qqchen.deploy.backend.notification.entity;
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import com.vladmihalcea.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import java.util.Map;
/**
* 通知模板实体
@ -56,4 +60,11 @@ public class NotificationTemplate extends Entity<Long> {
*/
@Column(nullable = false)
private Boolean enabled = true;
/**
* 模板配置JSON格式不同渠道存储不同配置
*/
@Type(JsonType.class)
@Column(columnDefinition = "JSON")
private Map<String, Object> templateConfig;
}

View File

@ -0,0 +1,20 @@
package com.qqchen.deploy.backend.notification.entity.config;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import lombok.Data;
/**
* 模板配置基类
* 用于实体层与DTO层的BaseTemplateConfigDTO对应
*
* @author qqchen
* @since 2025-11-12
*/
@Data
public abstract class BaseTemplateConfig {
/**
* 获取渠道类型
*/
public abstract NotificationChannelTypeEnum getChannelType();
}

View File

@ -0,0 +1,33 @@
package com.qqchen.deploy.backend.notification.entity.config;
import com.qqchen.deploy.backend.notification.enums.EmailContentTypeEnum;
import com.qqchen.deploy.backend.notification.enums.EmailPriorityEnum;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 邮件模板配置
*
* @author qqchen
* @since 2025-11-12
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class EmailTemplateConfig extends BaseTemplateConfig {
/**
* 内容类型
*/
private EmailContentTypeEnum contentType = EmailContentTypeEnum.TEXT;
/**
* 邮件优先级
*/
private EmailPriorityEnum priority = EmailPriorityEnum.NORMAL;
@Override
public NotificationChannelTypeEnum getChannelType() {
return NotificationChannelTypeEnum.EMAIL;
}
}

View File

@ -0,0 +1,27 @@
package com.qqchen.deploy.backend.notification.entity.config;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 企业微信模板配置
*
* @author qqchen
* @since 2025-11-12
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WeworkTemplateConfig extends BaseTemplateConfig {
/**
* 消息类型
*/
private WeworkMessageTypeEnum messageType = WeworkMessageTypeEnum.TEXT;
@Override
public NotificationChannelTypeEnum getChannelType() {
return NotificationChannelTypeEnum.WEWORK;
}
}

View File

@ -0,0 +1,35 @@
package com.qqchen.deploy.backend.notification.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 邮件内容类型枚举
*
* @author qqchen
* @since 2025-11-12
*/
@Getter
@AllArgsConstructor
public enum EmailContentTypeEnum {
/**
* 纯文本邮件
*/
TEXT("text/plain", "纯文本"),
/**
* HTML邮件
*/
HTML("text/html", "HTML格式");
/**
* MIME类型
*/
private final String mimeType;
/**
* 类型描述
*/
private final String description;
}

View File

@ -0,0 +1,40 @@
package com.qqchen.deploy.backend.notification.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 邮件优先级枚举
*
* @author qqchen
* @since 2025-11-12
*/
@Getter
@AllArgsConstructor
public enum EmailPriorityEnum {
/**
* 低优先级
*/
LOW("5", "低优先级"),
/**
* 普通优先级
*/
NORMAL("3", "普通优先级"),
/**
* 高优先级
*/
HIGH("1", "高优先级");
/**
* X-Priority 头部值
*/
private final String priorityValue;
/**
* 优先级描述
*/
private final String description;
}

View File

@ -24,6 +24,8 @@ public interface INotificationTemplateService extends IBaseService<NotificationT
*/
String renderTemplate(String templateCode, Map<String, Object> params);
String renderByCode(String templateCode, Map<String, Object> params);
/**
* 根据编码获取模板

View File

@ -2,11 +2,16 @@ package com.qqchen.deploy.backend.notification.service.impl;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.utils.JsonUtils;
import com.qqchen.deploy.backend.notification.dto.EmailSendNotificationRequest;
import com.qqchen.deploy.backend.notification.dto.SendNotificationRequest;
import com.qqchen.deploy.backend.notification.dto.WeworkSendNotificationRequest;
import com.qqchen.deploy.backend.notification.entity.NotificationChannel;
import com.qqchen.deploy.backend.notification.entity.NotificationTemplate;
import com.qqchen.deploy.backend.notification.entity.config.BaseTemplateConfig;
import com.qqchen.deploy.backend.notification.entity.config.EmailTemplateConfig;
import com.qqchen.deploy.backend.notification.entity.config.WeworkTemplateConfig;
import com.qqchen.deploy.backend.notification.enums.EmailContentTypeEnum;
import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum;
import com.qqchen.deploy.backend.notification.repository.INotificationChannelRepository;
import com.qqchen.deploy.backend.notification.repository.INotificationTemplateRepository;
@ -70,8 +75,8 @@ public class NotificationServiceImpl implements INotificationService {
// 6. 根据渠道类型发送通知
switch (template.getChannelType()) {
case WEWORK -> sendWeworkNotification(request.getChannelId(), content, request.getParams());
case EMAIL -> sendEmailNotification(request.getChannelId(), content, request.getParams());
case WEWORK -> sendWeworkNotification(request.getChannelId(), content, template, request.getParams());
case EMAIL -> sendEmailNotification(request.getChannelId(), content, template, request.getParams());
default -> throw new BusinessException(ResponseCode.INVALID_PARAM);
}
}
@ -79,13 +84,23 @@ public class NotificationServiceImpl implements INotificationService {
/**
* 发送企业微信通知
*/
private void sendWeworkNotification(Long channelId, String content, Map<String, Object> params) {
private void sendWeworkNotification(Long channelId, String content, NotificationTemplate template, Map<String, Object> params) {
WeworkSendNotificationRequest request = new WeworkSendNotificationRequest();
request.setChannelId(channelId);
request.setContent(content);
// 根据内容判断消息类型或从参数中获取
WeworkMessageTypeEnum messageType = WeworkMessageTypeEnum.MARKDOWN; // 默认使用 MARKDOWN
// 从模板配置获取消息类型
WeworkMessageTypeEnum messageType = WeworkMessageTypeEnum.TEXT; // 默认值
try {
BaseTemplateConfig baseTemplateConfig = JsonUtils.fromMap(template.getTemplateConfig(), BaseTemplateConfig.class);
if (baseTemplateConfig instanceof WeworkTemplateConfig weworkTemplateConfig) {
messageType = weworkTemplateConfig.getMessageType();
}
} catch (Exception e) {
log.warn("获取模板配置失败,使用默认消息类型: {}", e.getMessage());
}
// params 仍可以覆盖模板配置
if (params != null && params.containsKey("messageType")) {
messageType = WeworkMessageTypeEnum.valueOf(params.get("messageType").toString());
}
@ -107,7 +122,7 @@ public class NotificationServiceImpl implements INotificationService {
/**
* 发送邮件通知
*/
private void sendEmailNotification(Long channelId, String content, Map<String, Object> params) {
private void sendEmailNotification(Long channelId, String content, NotificationTemplate template, Map<String, Object> params) {
EmailSendNotificationRequest request = new EmailSendNotificationRequest();
request.setChannelId(channelId);
request.setContent(content);
@ -119,8 +134,18 @@ public class NotificationServiceImpl implements INotificationService {
}
request.setSubject(subject);
// 是否HTML格式从参数中获取
Boolean isHtml = false;
// 从模板配置获取内容类型
Boolean isHtml = false; // 默认值
try {
BaseTemplateConfig baseTemplateConfig = JsonUtils.fromMap(template.getTemplateConfig(), BaseTemplateConfig.class);
if (baseTemplateConfig instanceof EmailTemplateConfig emailTemplateConfig) {
isHtml = emailTemplateConfig.getContentType() == EmailContentTypeEnum.HTML;
}
} catch (Exception e) {
log.warn("获取模板配置失败,使用默认内容类型: {}", e.getMessage());
}
// params 仍可以覆盖模板配置
if (params != null && params.containsKey("isHtml")) {
isHtml = (Boolean) params.get("isHtml");
}

View File

@ -3,12 +3,17 @@ package com.qqchen.deploy.backend.notification.service.impl;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.framework.utils.JsonUtils;
import com.qqchen.deploy.backend.notification.converter.NotificationTemplateConverter;
import com.qqchen.deploy.backend.notification.dto.EmailSendNotificationRequest;
import com.qqchen.deploy.backend.notification.dto.NotificationTemplateDTO;
import com.qqchen.deploy.backend.notification.dto.WeworkSendNotificationRequest;
import com.qqchen.deploy.backend.notification.dto.template.NotificationTemplateQuery;
import com.qqchen.deploy.backend.notification.entity.NotificationTemplate;
import com.qqchen.deploy.backend.notification.entity.config.BaseTemplateConfig;
import com.qqchen.deploy.backend.notification.entity.config.EmailTemplateConfig;
import com.qqchen.deploy.backend.notification.entity.config.WeworkTemplateConfig;
import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum;
import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum;
import com.qqchen.deploy.backend.notification.repository.INotificationTemplateRepository;
import com.qqchen.deploy.backend.notification.service.INotificationSendService;
@ -54,7 +59,12 @@ public class NotificationTemplateServiceImpl extends BaseServiceImpl<Notificatio
}
@Override
public String renderTemplate(String templateCode, Map<String, Object> params) {
public String renderTemplate(String templateContext, Map<String, Object> params) {
return processTemplate(templateContext, params);
}
@Override
public String renderByCode(String templateCode, Map<String, Object> params) {
NotificationTemplate template = getTemplateByCode(templateCode);
return processTemplate(template.getContentTemplate(), params);
}
@ -115,4 +125,30 @@ public class NotificationTemplateServiceImpl extends BaseServiceImpl<Notificatio
template.setEnabled(false);
notificationTemplateRepository.save(template);
}
/**
* 将Map配置转换为具体的模板配置类型
*/
public BaseTemplateConfig convertTemplateConfig(NotificationTemplate template) {
if (template.getTemplateConfig() == null) {
return getDefaultTemplateConfig(template.getChannelType());
}
return switch (template.getChannelType()) {
case WEWORK -> JsonUtils.fromMap(template.getTemplateConfig(), WeworkTemplateConfig.class);
case EMAIL -> JsonUtils.fromMap(template.getTemplateConfig(), EmailTemplateConfig.class);
default -> throw new IllegalArgumentException("不支持的渠道类型: " + template.getChannelType());
};
}
/**
* 获取默认模板配置
*/
private BaseTemplateConfig getDefaultTemplateConfig(NotificationChannelTypeEnum channelType) {
return switch (channelType) {
case WEWORK -> new WeworkTemplateConfig();
case EMAIL -> new EmailTemplateConfig();
default -> throw new IllegalArgumentException("不支持的渠道类型: " + channelType);
};
}
}

View File

@ -1326,7 +1326,7 @@ INSERT INTO deploy_server_category (id, name, code, icon, description, sort, ena
-- 插入通知模板初始数据
INSERT INTO sys_notification_template (id, create_by, create_time, update_by, update_time, version, deleted,
name, code, description, channel_type, content_template, enabled) VALUES
name, code, description, channel_type, content_template, enabled, template_config) VALUES
-- Jenkins构建通知模板
(1, 'system', '2024-01-01 00:00:00', 'system', '2024-01-01 00:00:00', 1, 0,
'Jenkins构建通知-企业微信', 'jenkins_build_wework', 'Jenkins构建结果通知模板企业微信', 'WEWORK',
@ -1343,7 +1343,7 @@ INSERT INTO sys_notification_template (id, create_by, create_time, update_by, up
</#if>
---
*Deploy Ease Platform *', 1),
*Deploy Ease Platform *', 1, '{"messageType": "MARKDOWN"}'),
(2, 'system', '2024-01-01 00:00:00', 'system', '2024-01-01 00:00:00', 1, 0,
'Jenkins构建通知-邮件', 'jenkins_build_email', 'Jenkins构建结果通知模板邮件', 'EMAIL',
@ -1388,7 +1388,7 @@ INSERT INTO sys_notification_template (id, create_by, create_time, update_by, up
</#if>
<hr>
<p style="color: #666; font-size: 12px;">Deploy Ease Platform </p>', 1),
<p style="color: #666; font-size: 12px;">Deploy Ease Platform </p>', 1, '{"contentType": "HTML", "priority": "NORMAL"}'),
-- 部署通知模板
(3, 'system', '2024-01-01 00:00:00', 'system', '2024-01-01 00:00:00', 1, 0,
@ -1412,7 +1412,7 @@ INSERT INTO sys_notification_template (id, create_by, create_time, update_by, up
</#if>
---
*Deploy Ease Platform *', 1),
*Deploy Ease Platform *', 1, '{"messageType": "MARKDOWN"}'),
(4, 'system', '2024-01-01 00:00:00', 'system', '2024-01-01 00:00:00', 1, 0,
'部署通知-邮件', 'deploy_notification_email', '应用部署结果通知模板(邮件)', 'EMAIL',
@ -1459,4 +1459,4 @@ INSERT INTO sys_notification_template (id, create_by, create_time, update_by, up
</#if>
<hr>
<p style="color: #666; font-size: 12px;">Deploy Ease Platform </p>', 1);
<p style="color: #666; font-size: 12px;">Deploy Ease Platform </p>', 1, '{"contentType": "HTML", "priority": "NORMAL"}');

View File

@ -1161,9 +1161,9 @@ CREATE TABLE sys_notification_template
channel_type VARCHAR(20) NOT NULL COMMENT '渠道类型',
content_template TEXT NOT NULL COMMENT '内容模板',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
template_config JSON NULL COMMENT '模板配置',
UNIQUE KEY uk_code (code),
KEY idx_channel_type (channel_type),
KEY idx_enabled (enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='通知模板表';

View File

@ -252,3 +252,9 @@ deploy.permission.denied=无权限在此环境部署应用
deploy.environment.locked=环境已锁定,禁止部署
deploy.approval.required=该环境需要审批才能部署
deploy.record.not.found=部署记录不存在
# 通知模板相关 (3100-3119)
notification.template.not.found=通知模板不存在或已删除
notification.template.code.exists=模板编码{0}已存在
notification.template.disabled=通知模板已禁用
notification.template.render.error=模板渲染失败