mirror of https://github.com/certd/certd
perf: 邮箱支持保存和选择
parent
81282a9c88
commit
f7b0b44ef6
|
@ -3,11 +3,12 @@ import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { SysSettingsEntity } from '../entity/sys-settings.js';
|
import { SysSettingsEntity } from '../entity/sys-settings.js';
|
||||||
import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, SysSecret, SysSecretBackup } from './models.js';
|
import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, SysSecret, SysSecretBackup } from './models.js';
|
||||||
import * as _ from 'lodash-es';
|
|
||||||
import { BaseService } from '../../../basic/index.js';
|
import { BaseService } from '../../../basic/index.js';
|
||||||
import { cache, logger, setGlobalProxy } from '@certd/basic';
|
import { cache, logger, setGlobalProxy } from '@certd/basic';
|
||||||
import * as dns from 'node:dns';
|
import * as dns from 'node:dns';
|
||||||
|
import {mergeUtils} from "@certd/basic";
|
||||||
|
const {merge} = mergeUtils;
|
||||||
/**
|
/**
|
||||||
* 设置
|
* 设置
|
||||||
*/
|
*/
|
||||||
|
@ -75,7 +76,7 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
||||||
}
|
}
|
||||||
let newSetting: T = new type();
|
let newSetting: T = new type();
|
||||||
const savedSettings = await this.getSettingByKey(key);
|
const savedSettings = await this.getSettingByKey(key);
|
||||||
newSetting = _.merge(newSetting, savedSettings);
|
newSetting = merge(newSetting, savedSettings);
|
||||||
await this.saveSetting(newSetting);
|
await this.saveSetting(newSetting);
|
||||||
cache.set(cacheKey, newSetting);
|
cache.set(cacheKey, newSetting);
|
||||||
return newSetting;
|
return newSetting;
|
||||||
|
|
|
@ -8,7 +8,7 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin {
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "邮箱",
|
title: "邮箱",
|
||||||
component: {
|
component: {
|
||||||
name: "a-input",
|
name: "email-selector",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
},
|
},
|
||||||
rules: [{ type: "email", message: "请输入正确的邮箱" }],
|
rules: [{ type: "email", message: "请输入正确的邮箱" }],
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
export async function EmailList() {
|
||||||
|
return await request({
|
||||||
|
url: "/mine/email/list",
|
||||||
|
method: "post",
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function EmailDelete(email: string) {
|
||||||
|
return await request({
|
||||||
|
url: "/mine/email/delete",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function EmailAdd(email: string) {
|
||||||
|
return await request({
|
||||||
|
url: "/mine/email/add",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
<template>
|
||||||
|
<a-select :options="emails">
|
||||||
|
<template #option="{ value: val }">
|
||||||
|
<div class="flex flex-row w-full">
|
||||||
|
<span class="flex-1">{{ val }}</span>
|
||||||
|
<fs-icon class="ml-5" icon="ion:close" @click="deleteItem(val)"></fs-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #dropdownRender="{ menuNode: menu }">
|
||||||
|
<v-nodes :vnodes="menu" />
|
||||||
|
<a-divider style="margin: 4px 0" />
|
||||||
|
<div class="w-full flex flex-row p-5">
|
||||||
|
<a-input ref="inputRef" v-model:value="newEmail" class="flex-1" placeholder="添加新邮箱" @keydown.enter="addItem" />
|
||||||
|
<a-button class="ml-5" type="primary" @click="addItem">
|
||||||
|
<template #icon>
|
||||||
|
<plus-outlined />
|
||||||
|
</template>
|
||||||
|
添加邮箱
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { defineComponent, onMounted, ref } from "vue";
|
||||||
|
import * as api from "./api";
|
||||||
|
import { Modal, notification } from "ant-design-vue";
|
||||||
|
|
||||||
|
const props = defineProps<{}>();
|
||||||
|
const VNodes = defineComponent({
|
||||||
|
props: {
|
||||||
|
vnodes: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return this.vnodes;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const newEmail = ref("");
|
||||||
|
const emails = ref([]);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const list = await api.EmailList();
|
||||||
|
emails.value = list.map((item: string) => {
|
||||||
|
return {
|
||||||
|
value: item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
async function addItem() {
|
||||||
|
const email = newEmail.value;
|
||||||
|
//验证邮箱格式
|
||||||
|
if (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(newEmail.value)) {
|
||||||
|
notification.error({
|
||||||
|
message: "请填写正确的邮箱地址",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.EmailAdd(email);
|
||||||
|
emails.value.push({
|
||||||
|
value: email,
|
||||||
|
label: email,
|
||||||
|
});
|
||||||
|
newEmail.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteItem(value: string) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "删除邮箱",
|
||||||
|
content: "确定要删除此邮箱吗?",
|
||||||
|
onOk: async () => {
|
||||||
|
await api.EmailDelete(value);
|
||||||
|
emails.value = emails.value.filter(item => item.value !== value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -14,12 +14,14 @@ import FileInput from "./file-input.vue";
|
||||||
import PemInput from "./pem-input.vue";
|
import PemInput from "./pem-input.vue";
|
||||||
import { defineAsyncComponent } from "vue";
|
import { defineAsyncComponent } from "vue";
|
||||||
import NotificationSelector from "../views/certd/notification/notification-selector/index.vue";
|
import NotificationSelector from "../views/certd/notification/notification-selector/index.vue";
|
||||||
|
import EmailSelector from "./email-selector/index.vue";
|
||||||
export default {
|
export default {
|
||||||
install(app: any) {
|
install(app: any) {
|
||||||
app.component(
|
app.component(
|
||||||
"CodeEditor",
|
"CodeEditor",
|
||||||
defineAsyncComponent(() => import("./code-editor/index.vue"))
|
defineAsyncComponent(() => import("./code-editor/index.vue"))
|
||||||
);
|
);
|
||||||
|
app.component("EmailSelector", EmailSelector);
|
||||||
app.component("NotificationSelector", NotificationSelector);
|
app.component("NotificationSelector", NotificationSelector);
|
||||||
app.component("PiContainer", PiContainer);
|
app.component("PiContainer", PiContainer);
|
||||||
app.component("TextEditable", TextEditable);
|
app.component("TextEditable", TextEditable);
|
||||||
|
|
|
@ -4,7 +4,7 @@ export async function doActive(form: any) {
|
||||||
return await request({
|
return await request({
|
||||||
url: "/sys/plus/active",
|
url: "/sys/plus/active",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: form
|
data: form,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,6 @@ export async function getVipTrial() {
|
||||||
return await request({
|
return await request({
|
||||||
url: "/sys/plus/getVipTrial",
|
url: "/sys/plus/getVipTrial",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: {}
|
data: {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,25 @@ export class EmailController extends BaseController {
|
||||||
await this.emailService.test(userId, receiver);
|
await this.emailService.test(userId, receiver);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/list', { summary: Constants.per.authOnly })
|
||||||
|
public async list() {
|
||||||
|
const userId = super.getUserId();
|
||||||
|
const res = await this.emailService.list(userId);
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/add', { summary: Constants.per.authOnly })
|
||||||
|
public async add(@Body('email') email) {
|
||||||
|
const userId = super.getUserId();
|
||||||
|
await this.emailService.add(userId, email);
|
||||||
|
return this.ok({});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/delete', { summary: Constants.per.authOnly })
|
||||||
|
public async delete(@Body('email') email) {
|
||||||
|
const userId = super.getUserId();
|
||||||
|
await this.emailService.delete(userId, email);
|
||||||
|
return this.ok({});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { SendMailOptions } from 'nodemailer';
|
||||||
import { UserSettingsService } from '../../mine/service/user-settings-service.js';
|
import { UserSettingsService } from '../../mine/service/user-settings-service.js';
|
||||||
import { PlusService, SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
import { PlusService, SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
||||||
import { getEmailSettings } from '../../sys/settings/fix.js';
|
import { getEmailSettings } from '../../sys/settings/fix.js';
|
||||||
|
import { UserEmailSetting } from "../../mine/service/models.js";
|
||||||
|
|
||||||
export type EmailConfig = {
|
export type EmailConfig = {
|
||||||
host: string;
|
host: string;
|
||||||
|
@ -108,4 +109,24 @@ export class EmailService implements IEmailService {
|
||||||
content: '测试邮件,from certd',
|
content: '测试邮件,from certd',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async list(userId: any) {
|
||||||
|
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId,UserEmailSetting)
|
||||||
|
return userEmailSetting.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(userId: any, email: string) {
|
||||||
|
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId,UserEmailSetting)
|
||||||
|
userEmailSetting.list = userEmailSetting.list.filter(item=>item !== email);
|
||||||
|
await this.settingsService.saveSetting(userId,userEmailSetting)
|
||||||
|
}
|
||||||
|
async add(userId: any, email: string) {
|
||||||
|
const userEmailSetting = await this.settingsService.getSetting<UserEmailSetting>(userId,UserEmailSetting)
|
||||||
|
//如果已存在
|
||||||
|
if(userEmailSetting.list.includes(email)){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userEmailSetting.list.unshift(email)
|
||||||
|
await this.settingsService.saveSetting(userId,userEmailSetting)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,3 +26,10 @@ export class UserSiteMonitorSetting extends BaseSettings {
|
||||||
|
|
||||||
notificationId?:number= 0;
|
notificationId?:number= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UserEmailSetting extends BaseSettings {
|
||||||
|
static __title__ = "用户邮箱设置";
|
||||||
|
static __key__ = "user.email";
|
||||||
|
|
||||||
|
list:string[] = [];
|
||||||
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||||
import { Repository } from "typeorm";
|
import { Repository } from "typeorm";
|
||||||
import { BaseService, BaseSettings } from "@certd/lib-server";
|
import { BaseService, BaseSettings } from "@certd/lib-server";
|
||||||
import { UserSettingsEntity } from "../entity/user-settings.js";
|
import { UserSettingsEntity } from "../entity/user-settings.js";
|
||||||
import { merge } from "lodash-es";
|
import { mergeUtils } from "@certd/basic";
|
||||||
|
const {merge} = mergeUtils
|
||||||
/**
|
/**
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue