From b1cbf520444874df9f53f981bc561165246a5984 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Wed, 12 Nov 2025 18:14:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9E=84=E5=BB=BA=E9=80=9A?= =?UTF-8?q?=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotificationTemplateApiController.java | 2 +- .../NotificationTemplateConverter.java | 53 ++++++++++++++++ .../notification/dto/NotificationRequest.java | 60 ------------------- .../dto/NotificationTemplateDTO.java | 4 ++ .../dto/template/BaseTemplateConfigDTO.java | 34 +++++++++++ .../dto/template/EmailTemplateConfigDTO.java | 42 +++++++++++++ .../dto/template/TemplateRenderRequest.java | 10 ++-- .../dto/template/TemplateSendRequest.java | 30 ---------- .../dto/template/WeworkTemplateConfigDTO.java | 35 +++++++++++ .../entity/NotificationTemplate.java | 11 ++++ .../entity/config/BaseTemplateConfig.java | 20 +++++++ .../entity/config/EmailTemplateConfig.java | 33 ++++++++++ .../entity/config/WeworkTemplateConfig.java | 27 +++++++++ .../enums/EmailContentTypeEnum.java | 35 +++++++++++ .../notification/enums/EmailPriorityEnum.java | 40 +++++++++++++ .../service/INotificationTemplateService.java | 2 + .../service/impl/NotificationServiceImpl.java | 41 ++++++++++--- .../impl/NotificationTemplateServiceImpl.java | 38 +++++++++++- .../db/changelog/changes/v1.0.0-data.sql | 10 ++-- .../db/changelog/changes/v1.0.0-schema.sql | 2 +- .../src/main/resources/messages.properties | 8 ++- 21 files changed, 425 insertions(+), 112 deletions(-) delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationRequest.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/BaseTemplateConfigDTO.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/EmailTemplateConfigDTO.java delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateSendRequest.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/WeworkTemplateConfigDTO.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseTemplateConfig.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/EmailTemplateConfig.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/WeworkTemplateConfig.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailContentTypeEnum.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailPriorityEnum.java diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/api/NotificationTemplateApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/api/NotificationTemplateApiController.java index d68d1ace..e7eb4858 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/api/NotificationTemplateApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/api/NotificationTemplateApiController.java @@ -48,7 +48,7 @@ public class NotificationTemplateApiController extends BaseController 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); } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationTemplateConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationTemplateConverter.java index 47344b63..bcf026b5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationTemplateConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationTemplateConverter.java @@ -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 { + + @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 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 mapToTemplateConfigMap(BaseTemplateConfigDTO configDTO) { + if (configDTO == null) { + return null; + } + return JsonUtils.toMap(configDTO); + } } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationRequest.java deleted file mode 100644 index cfb417a9..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationRequest.java +++ /dev/null @@ -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 receivers; - - /** - * @人列表(可选) - * - 企业微信:@specific用户(手机号或userid) - * - 邮件:抄送列表 - */ - private List mentions; -} - diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationTemplateDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationTemplateDTO.java index 9bacbb9e..3cf0c4f2 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationTemplateDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationTemplateDTO.java @@ -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; } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/BaseTemplateConfigDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/BaseTemplateConfigDTO.java new file mode 100644 index 00000000..e187e119 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/BaseTemplateConfigDTO.java @@ -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(); +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/EmailTemplateConfigDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/EmailTemplateConfigDTO.java new file mode 100644 index 00000000..1fe441e6 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/EmailTemplateConfigDTO.java @@ -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; + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateRenderRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateRenderRequest.java index 2aeb8ded..f7389254 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateRenderRequest.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateRenderRequest.java @@ -15,11 +15,11 @@ import java.util.Map; @Data @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 params; } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateSendRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateSendRequest.java deleted file mode 100644 index c88ba4d5..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/TemplateSendRequest.java +++ /dev/null @@ -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 params; -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/WeworkTemplateConfigDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/WeworkTemplateConfigDTO.java new file mode 100644 index 00000000..0cf9fc55 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/template/WeworkTemplateConfigDTO.java @@ -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; + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/NotificationTemplate.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/NotificationTemplate.java index fc547b81..a4b75abf 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/NotificationTemplate.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/NotificationTemplate.java @@ -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 { */ @Column(nullable = false) private Boolean enabled = true; + + /** + * 模板配置(JSON格式,不同渠道存储不同配置) + */ + @Type(JsonType.class) + @Column(columnDefinition = "JSON") + private Map templateConfig; } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseTemplateConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseTemplateConfig.java new file mode 100644 index 00000000..6199f4f9 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseTemplateConfig.java @@ -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(); +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/EmailTemplateConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/EmailTemplateConfig.java new file mode 100644 index 00000000..7c23d85d --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/EmailTemplateConfig.java @@ -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; + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/WeworkTemplateConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/WeworkTemplateConfig.java new file mode 100644 index 00000000..5c13f502 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/WeworkTemplateConfig.java @@ -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; + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailContentTypeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailContentTypeEnum.java new file mode 100644 index 00000000..c520eafd --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailContentTypeEnum.java @@ -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; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailPriorityEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailPriorityEnum.java new file mode 100644 index 00000000..69fa8368 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/enums/EmailPriorityEnum.java @@ -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; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/INotificationTemplateService.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/INotificationTemplateService.java index 9ccc3c67..a535f699 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/INotificationTemplateService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/INotificationTemplateService.java @@ -24,6 +24,8 @@ public interface INotificationTemplateService extends IBaseService params); + String renderByCode(String templateCode, Map params); + /** * 根据编码获取模板 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationServiceImpl.java index 3b003bf7..53ee70ca 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationServiceImpl.java @@ -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 params) { + private void sendWeworkNotification(Long channelId, String content, NotificationTemplate template, Map 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 params) { + private void sendEmailNotification(Long channelId, String content, NotificationTemplate template, Map 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"); } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationTemplateServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationTemplateServiceImpl.java index d7ecf891..b993804f 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationTemplateServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationTemplateServiceImpl.java @@ -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 params) { + public String renderTemplate(String templateContext, Map params) { + return processTemplate(templateContext, params); + } + + @Override + public String renderByCode(String templateCode, Map params) { NotificationTemplate template = getTemplateByCode(templateCode); return processTemplate(template.getContentTemplate(), params); } @@ -115,4 +125,30 @@ public class NotificationTemplateServiceImpl extends BaseServiceImpl 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); + }; + } } diff --git a/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql b/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql index 663b6ea3..31246a62 100644 --- a/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql +++ b/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql @@ -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 --- -*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
-

Deploy Ease Platform 自动通知

', 1), +

Deploy Ease Platform 自动通知

', 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 --- -*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
-

Deploy Ease Platform 自动通知

', 1); +

Deploy Ease Platform 自动通知

', 1, '{"contentType": "HTML", "priority": "NORMAL"}'); diff --git a/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql b/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql index 3ad34cf0..fb755205 100644 --- a/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql +++ b/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql @@ -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='通知模板表'; - diff --git a/backend/src/main/resources/messages.properties b/backend/src/main/resources/messages.properties index 6fffb19f..ee4f37f3 100644 --- a/backend/src/main/resources/messages.properties +++ b/backend/src/main/resources/messages.properties @@ -251,4 +251,10 @@ deploy.already.running=该应用正在部署中,请等待当前部署完成 deploy.permission.denied=无权限在此环境部署应用 deploy.environment.locked=环境已锁定,禁止部署 deploy.approval.required=该环境需要审批才能部署 -deploy.record.not.found=部署记录不存在 \ No newline at end of file +deploy.record.not.found=部署记录不存在 + +# 通知模板相关 (3100-3119) +notification.template.not.found=通知模板不存在或已删除 +notification.template.code.exists=模板编码{0}已存在 +notification.template.disabled=通知模板已禁用 +notification.template.render.error=模板渲染失败 \ No newline at end of file