mirror of
https://github.com/certd/certd.git
synced 2026-04-23 11:37:23 +08:00
perf: 支持邮件模版设置
This commit is contained in:
@@ -3,8 +3,16 @@ export type BuildContentReq = {
|
||||
data: any;
|
||||
}
|
||||
|
||||
export type BuildContentReply = Record<string, string>;
|
||||
|
||||
export interface ITemplateProvider {
|
||||
buildContent: (params: BuildContentReq) => Promise<BuildContentReply>;
|
||||
}
|
||||
export interface ITemplateProvider<T=any> {
|
||||
buildContent: (params: BuildContentReq) => Promise<T>;
|
||||
|
||||
buildDefaultContent:(params: BuildContentReq) => Promise<T>;
|
||||
}
|
||||
|
||||
|
||||
export type EmailContent = {
|
||||
subject:string,
|
||||
content?:string,
|
||||
html?:string
|
||||
};
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './plugin-common.js'
|
||||
export * from './plugin-register-code.js'
|
||||
export * from './plugin-forgot-password.js'
|
||||
export * from './plugin-pipeline-result.js'
|
||||
@@ -1,52 +1,87 @@
|
||||
import { AddonInput, BaseAddon } from "@certd/lib-server";
|
||||
import { BuildContentReply, BuildContentReq, ITemplateProvider } from "../api.js";
|
||||
import { get } from "lodash-es";
|
||||
import { BuildContentReq, EmailContent, ITemplateProvider } from "../api.js";
|
||||
|
||||
|
||||
export class BaseEmailTemplateProvider extends BaseAddon implements ITemplateProvider {
|
||||
export class BaseEmailTemplateProvider extends BaseAddon implements ITemplateProvider<EmailContent> {
|
||||
@AddonInput({
|
||||
title: "配置说明",
|
||||
component:{
|
||||
name:"a-alert",
|
||||
props:{
|
||||
type:"info",
|
||||
message:"在标题和内容模版中,通过${param}引用参数,例如: 感谢注册${siteTitle},您的注册验证码为:${code}",
|
||||
component: {
|
||||
name: "a-alert",
|
||||
props: {
|
||||
type: "info",
|
||||
message: "在标题和内容模版中,通过${param}引用参数,例如: 感谢注册${siteTitle},您的注册验证码为:${code}",
|
||||
}
|
||||
},
|
||||
order: 1,
|
||||
col:{span:24},
|
||||
col: { span: 24 },
|
||||
})
|
||||
useIntro = "";
|
||||
|
||||
|
||||
@AddonInput({
|
||||
title: "邮件格式",
|
||||
component: {
|
||||
name: "a-select",
|
||||
props: {
|
||||
options: [
|
||||
{ label: "HTML", value: "html" },
|
||||
{ label: "TEXT", value: "text" },
|
||||
]
|
||||
}
|
||||
},
|
||||
order: 1,
|
||||
col: { span: 24 },
|
||||
})
|
||||
formatType = "";
|
||||
|
||||
@AddonInput({
|
||||
title: "邮件标题模版",
|
||||
required: true,
|
||||
order: 10,
|
||||
component: {
|
||||
name: "a-input",
|
||||
props: {
|
||||
placeholder: "邮件标题模版",
|
||||
}
|
||||
},
|
||||
col: { span: 24 },
|
||||
})
|
||||
titleTemplate = "";
|
||||
|
||||
@AddonInput({
|
||||
title: "邮件内容模版",
|
||||
component: {
|
||||
placeholder: "邮件内容模版",
|
||||
name: "a-textarea",
|
||||
rows: 6,
|
||||
},
|
||||
order: 20,
|
||||
col: { span: 24 },
|
||||
required: true,
|
||||
})
|
||||
contentTemplate = "";
|
||||
|
||||
|
||||
async buildContent(params: BuildContentReq) : Promise<BuildContentReply>{
|
||||
const title = this.compile(this.titleTemplate)(params.data)
|
||||
const content = this.compile(this.contentTemplate)(params.data)
|
||||
return {
|
||||
title,
|
||||
content,
|
||||
}
|
||||
async buildContent(params: BuildContentReq): Promise<EmailContent> {
|
||||
const title = this.compile(this.titleTemplate)(params.data)
|
||||
const content = this.compile(this.contentTemplate)(params.data)
|
||||
|
||||
const body: any = {
|
||||
subject: title,
|
||||
}
|
||||
if (this.formatType === "html") {
|
||||
body.html = content
|
||||
} else {
|
||||
body.content = content
|
||||
}
|
||||
return body
|
||||
};
|
||||
|
||||
async buildDefaultContent(params: BuildContentReq): Promise<EmailContent> {
|
||||
throw new Error("请实现 buildDefaultContent 方法")
|
||||
}
|
||||
|
||||
compile(templateString: string) {
|
||||
return function(data:any):string {
|
||||
return function (data: any): string {
|
||||
return templateString.replace(/\${(.*?)}/g, (match, key) => {
|
||||
const value = get(data, key, '');
|
||||
return String(value);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { AddonInput, IsAddon } from "@certd/lib-server";
|
||||
import { BuildContentReq, EmailContent, ITemplateProvider } from "../api.js";
|
||||
import { BaseEmailTemplateProvider } from "./plugin-base.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "emailTemplate",
|
||||
name: 'common',
|
||||
title: '通用邮件模版',
|
||||
desc: '通用邮件模版',
|
||||
icon: "simple-icons:email:blue",
|
||||
showTest: false,
|
||||
})
|
||||
export class CommonEmailTemplateProvider extends BaseEmailTemplateProvider implements ITemplateProvider<EmailContent> {
|
||||
@AddonInput({
|
||||
title: "可用参数",
|
||||
component: {
|
||||
name: "ParamsShow",
|
||||
params:[
|
||||
{labele:"标题",value:"title"},
|
||||
{labele:"内容",value:"content"},
|
||||
{labele:"URL",value:"url"}
|
||||
]
|
||||
},
|
||||
order: 5,
|
||||
col: { span: 24 },
|
||||
})
|
||||
paramIntro = "";
|
||||
|
||||
|
||||
async buildDefaultContent(req:BuildContentReq) {
|
||||
const defaultTemplate = new CommonEmailTemplateProvider()
|
||||
defaultTemplate.titleTemplate = "${title}"
|
||||
defaultTemplate.contentTemplate = "${content} \n\n 查看详情:${url}"
|
||||
defaultTemplate.formatType = "text"
|
||||
return await defaultTemplate.buildContent(req)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { AddonInput, IsAddon } from "@certd/lib-server";
|
||||
import { BuildContentReq, EmailContent, ITemplateProvider } from "../api.js";
|
||||
import { BaseEmailTemplateProvider } from "./plugin-base.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "emailTemplate",
|
||||
name: 'forgotPassword',
|
||||
title: '忘记密码邮件模版',
|
||||
desc: '忘记密码邮件模版',
|
||||
icon: "simple-icons:email:blue",
|
||||
showTest: false,
|
||||
})
|
||||
export class ForgotPasswordEmailTemplateProvider extends BaseEmailTemplateProvider implements ITemplateProvider<EmailContent> {
|
||||
@AddonInput({
|
||||
title: "可用参数",
|
||||
component: {
|
||||
name: "ParamsShow",
|
||||
params:[
|
||||
{labele:"验证码",value:"code"}
|
||||
]
|
||||
},
|
||||
order: 5,
|
||||
col: { span: 24 },
|
||||
})
|
||||
paramIntro = "";
|
||||
|
||||
|
||||
async buildDefaultContent(req:BuildContentReq) {
|
||||
const defaultTemplate = new ForgotPasswordEmailTemplateProvider()
|
||||
defaultTemplate.titleTemplate = "忘记密码"
|
||||
defaultTemplate.contentTemplate = "您的验证码是:${code},请勿泄露"
|
||||
defaultTemplate.formatType = "text"
|
||||
return await defaultTemplate.buildContent(req)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { AddonInput, IsAddon } from "@certd/lib-server";
|
||||
import { BuildContentReq, EmailContent, ITemplateProvider } from "../api.js";
|
||||
import { BaseEmailTemplateProvider } from "./plugin-base.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "emailTemplate",
|
||||
name: 'pipelineResult',
|
||||
title: '流水线执行结果邮件模版',
|
||||
desc: '流水线执行结果邮件模版',
|
||||
icon: "simple-icons:email:blue",
|
||||
showTest: false,
|
||||
})
|
||||
export class PipelineResultEmailTemplateProvider extends BaseEmailTemplateProvider implements ITemplateProvider<EmailContent> {
|
||||
@AddonInput({
|
||||
title: "可用参数",
|
||||
component: {
|
||||
name: "ParamsShow",
|
||||
params:[
|
||||
{labele:"运行结果",value:"pipelineResult"},
|
||||
{labele:"流水线标题",value:"pipelineTitle"},
|
||||
{labele:"流水线ID",value:"pipelineId"},
|
||||
{labele:"运行Id",value:"historyId"},
|
||||
{labele:"错误信息",value:"errors"},
|
||||
{labele:"URL",value:"url"},
|
||||
]
|
||||
},
|
||||
order: 5,
|
||||
col: { span: 24 },
|
||||
})
|
||||
paramIntro = "";
|
||||
|
||||
|
||||
async buildDefaultContent(req:BuildContentReq) {
|
||||
const defaultTemplate = new PipelineResultEmailTemplateProvider()
|
||||
|
||||
const subject = "${result},${pipelineTitle}【${pipelineId}】";
|
||||
const content = "流水线ID:${pipelineId},运行ID:${runtimeId} \n\n ${errors}";
|
||||
defaultTemplate.titleTemplate = subject
|
||||
defaultTemplate.contentTemplate = content
|
||||
defaultTemplate.formatType = "text"
|
||||
return await defaultTemplate.buildContent(req)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { AddonInput, IsAddon } from "@certd/lib-server";
|
||||
import { BuildContentReq, EmailContent, ITemplateProvider } from "../api.js";
|
||||
import { BaseEmailTemplateProvider } from "./plugin-base.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "emailTemplate",
|
||||
name: 'registerCode',
|
||||
title: '注册验证码邮件模版',
|
||||
desc: '注册验证码邮件模版',
|
||||
icon: "simple-icons:email:blue",
|
||||
showTest: false,
|
||||
})
|
||||
export class RegisterCodeEmailTemplateProvider extends BaseEmailTemplateProvider implements ITemplateProvider<EmailContent> {
|
||||
@AddonInput({
|
||||
title: "可用参数",
|
||||
component: {
|
||||
name: "ParamsShow",
|
||||
params:[
|
||||
{labele:"验证码",value:"code"}
|
||||
]
|
||||
},
|
||||
order: 5,
|
||||
col: { span: 24 },
|
||||
})
|
||||
paramIntro = "";
|
||||
|
||||
|
||||
async buildDefaultContent(req:BuildContentReq) {
|
||||
const defaultTemplate = new RegisterCodeEmailTemplateProvider()
|
||||
defaultTemplate.titleTemplate = "注册验证码"
|
||||
defaultTemplate.contentTemplate = "您的注册验证码是:${code},请勿泄露"
|
||||
defaultTemplate.formatType = "text"
|
||||
return await defaultTemplate.buildContent(req)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { AddonInput, IsAddon } from "@certd/lib-server";
|
||||
import { BaseEmailTemplateProvider } from "./plugin-base.js";
|
||||
|
||||
@IsAddon({
|
||||
addonType: "emailTemplate",
|
||||
name: 'register',
|
||||
title: '注册邮件模版',
|
||||
desc: '注册邮件模版',
|
||||
icon:"simple-icons:gitee:red",
|
||||
showTest: false,
|
||||
})
|
||||
export class RegisterEmailTemplateProvider extends BaseEmailTemplateProvider {
|
||||
|
||||
@AddonInput({
|
||||
title: "可用参数",
|
||||
component:{
|
||||
name:"a-alert",
|
||||
props:{
|
||||
type:"info",
|
||||
message:"站点名称:${siteTitle};注册验证码:${code};有效期:${duration}分钟",
|
||||
}
|
||||
},
|
||||
order: 5,
|
||||
col:{span:24},
|
||||
})
|
||||
paramIntro = "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./email/index.js"
|
||||
Reference in New Issue
Block a user