perf: 站点证书监控通知发送,每天定时检查

This commit is contained in:
xiaojunnuo
2024-12-23 18:11:06 +08:00
parent 89c7f07034
commit bb4910f4e5
16 changed files with 536 additions and 143 deletions
@@ -41,7 +41,7 @@ export const certdResources = [
}
},
{
title: "证书监控",
title: "站点证书监控",
name: "SiteCertMonitor",
path: "/certd/monitor/site",
component: "/certd/monitor/site/index.vue",
@@ -170,33 +170,63 @@ export const sysResources = [
permission: "sys:auth:user:view"
}
},
{
title: "套餐设置",
name: "SuiteSetting",
path: "/sys/suite/setting",
component: "/sys/suite/setting/index.vue",
title: "套餐管理",
name: "SuiteManager",
path: "/sys/suite",
meta: {
icon: "ion:cart-outline",
permission: "sys:settings:edit",
show: () => {
const settingStore = useSettingStore();
return settingStore.isComm;
}
},
children: [
{
title: "套餐设置",
name: "SuiteSetting",
path: "/sys/suite/setting",
component: "/sys/suite/setting/index.vue",
meta: {
show: () => {
const settingStore = useSettingStore();
return settingStore.isComm;
},
icon: "ion:cart",
permission: "sys:settings:edit"
}
},
icon: "ion:cart",
permission: "sys:settings:edit"
}
},
{
title: "订单管理",
name: "OrderManager",
path: "/sys/suite/trade",
component: "/sys/suite/trade/index.vue",
meta: {
show: () => {
const settingStore = useSettingStore();
return settingStore.isComm;
{
title: "订单管理",
name: "OrderManager",
path: "/sys/suite/trade",
component: "/sys/suite/trade/index.vue",
meta: {
show: () => {
const settingStore = useSettingStore();
return settingStore.isComm;
},
icon: "ion:bag-check",
permission: "sys:settings:edit"
}
},
icon: "ion:bag-check",
permission: "sys:settings:edit"
}
{
title: "用户套餐",
name: "UserSuites",
path: "/sys/suite/user-suite",
component: "/certd/suite/user-suite/index.vue",
meta: {
show: () => {
const settingStore = useSettingStore();
return settingStore.isComm;
},
icon: "ion:gift-outline",
auth: true
}
}
]
}
]
}
@@ -1,54 +1,58 @@
import { request } from "/src/api/service";
export function createApi() {
const apiPrefix = "/monitor/site";
return {
async GetList(query: any) {
return await request({
url: apiPrefix + "/page",
method: "post",
data: query
});
},
const apiPrefix = "/monitor/site";
async AddObj(obj: any) {
return await request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
},
export const siteInfoApi = {
async GetList(query: any) {
return await request({
url: apiPrefix + "/page",
method: "post",
data: query
});
},
async UpdateObj(obj: any) {
return await request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
},
async AddObj(obj: any) {
return await request({
url: apiPrefix + "/add",
method: "post",
data: obj
});
},
async DelObj(id: number) {
return await request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
},
async UpdateObj(obj: any) {
return await request({
url: apiPrefix + "/update",
method: "post",
data: obj
});
},
async GetObj(id: number) {
return await request({
url: apiPrefix + "/info",
method: "post",
params: { id }
});
},
async ListAll() {
return await request({
url: apiPrefix + "/all",
method: "post"
});
}
};
}
async DelObj(id: number) {
return await request({
url: apiPrefix + "/delete",
method: "post",
params: { id }
});
},
export const pipelineGroupApi = createApi();
async GetObj(id: number) {
return await request({
url: apiPrefix + "/info",
method: "post",
params: { id }
});
},
async DoCheck(id: number) {
return await request({
url: apiPrefix + "/check",
method: "post",
data: { id }
});
},
async CheckAll() {
return await request({
url: apiPrefix + "/checkAll",
method: "post"
});
}
};
@@ -1,12 +1,13 @@
// @ts-ignore
import { useI18n } from "vue-i18n";
import { ref } from "vue";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { pipelineGroupApi } from "./api";
import { siteInfoApi } from "./api";
import dayjs from "dayjs";
import { notification } from "ant-design-vue";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { t } = useI18n();
const api = pipelineGroupApi;
const api = siteInfoApi;
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
@@ -51,7 +52,24 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}
},
rowHandle: {
width: 200
fixed: "right",
width: 240,
buttons: {
check: {
order: 0,
type: "link",
text: null,
title: "立即检查",
icon: "ion:play-sharp",
click: async ({ row }) => {
await api.DoCheck(row.id);
await crudExpose.doRefresh();
notification.success({
message: "检查完成"
});
}
}
}
},
columns: {
id: {
@@ -62,44 +80,13 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false
},
column: {
width: 100,
editable: {
disabled: true
}
width: 80,
align: "center"
},
form: {
show: false
}
},
domain: {
title: "网站域名",
search: {
show: true
},
type: "text",
form: {
rules: [{ required: true, message: "请输入域名" }]
},
column: {
width: 200,
sorter: true
}
},
port: {
title: "HTTPS端口",
search: {
show: false
},
type: "number",
form: {
value: 443,
rules: [{ required: true, message: "请输入端口" }]
},
column: {
width: 100
}
},
name: {
title: "站点名称",
search: {
@@ -110,11 +97,40 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
rules: [{ required: true, message: "请输入站点名称" }]
},
column: {
width: 200
width: 160
}
},
domains: {
title: "其他域名",
domain: {
title: "网站域名",
search: {
show: true
},
type: "text",
form: {
rules: [{ required: true, message: "请输入域名" }]
},
column: {
width: 160,
sorter: true
}
},
httpsPort: {
title: "HTTPS端口",
search: {
show: false
},
type: "number",
form: {
value: 443,
rules: [{ required: true, message: "请输入端口" }]
},
column: {
align: "center",
width: 100
}
},
certDomains: {
title: "证书域名",
search: {
show: false
},
@@ -123,13 +139,13 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false
},
column: {
width: 300,
width: 200,
sorter: true,
show: false
show: true
}
},
certInfo: {
title: "证书详情",
certProvider: {
title: "证书颁发者",
search: {
show: false
},
@@ -138,8 +154,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false
},
column: {
width: 100,
show: false
width: 200,
sorter: true
}
},
certStatus: {
@@ -147,13 +163,20 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
search: {
show: true
},
type: "text",
type: "dict-select",
dict: dict({
data: [
{ label: "正常", value: "ok", color: "green" },
{ label: "过期", value: "expired", color: "red" }
]
}),
form: {
show: false
},
column: {
width: 100,
sorter: true
sorter: true,
show: false
}
},
certExpiresTime: {
@@ -166,7 +189,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false
},
column: {
sorter: true
sorter: true,
cellRender({ value }) {
if (!value) {
return "-";
}
const expireDate = dayjs(value).format("YYYY-MM-DD");
const leftDays = dayjs(value).diff(dayjs(), "day");
const color = leftDays < 20 ? "red" : "#389e0d";
const percent = (leftDays / 90) * 100;
return <a-progress title={expireDate + "过期"} percent={percent} strokeColor={color} format={(percent: number) => `${leftDays}`} />;
}
}
},
lastCheckTime: {
@@ -187,12 +220,33 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
search: {
show: false
},
type: "text",
type: "dict-select",
dict: dict({
data: [
{ label: "正常", value: "ok", color: "green" },
{ label: "异常", value: "error", color: "red" }
]
}),
form: {
show: false
},
column: {
width: 100,
align: "center",
sorter: true
}
},
error: {
title: "错误信息",
search: {
show: false
},
type: "text",
form: {
show: false
},
column: {
width: 200,
sorter: true
}
},
@@ -205,7 +259,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
type: "number",
column: {
width: 200,
sorter: true
sorter: true,
show: false
}
},
certInfoId: {
@@ -234,7 +289,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
]
}),
form: {
value: true
value: false
},
column: {
width: 100,
@@ -3,7 +3,10 @@
<template #header>
<div class="title">
站点证书监控
<span class="sub">监控网站证书的过期时间并发出提醒未完成开发中</span>
<span class="sub">每天0点检查网站证书的过期时间并发出提醒</span>
</div>
<div class="more">
<a-button type="primary" @click="checkAll">检查全部</a-button>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
@@ -11,15 +14,30 @@
</template>
<script lang="ts" setup>
import { defineComponent, onActivated, onMounted } from "vue";
import { onActivated, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { createApi } from "./api";
import { siteInfoApi } from "./api";
import { Modal, notification } from "ant-design-vue";
defineOptions({
name: "SiteCertMonitor"
});
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
function checkAll() {
Modal.confirm({
title: "确认",
content: "确认触发检查全部站点证书吗?",
onOk: async () => {
await siteInfoApi.CheckAll();
notification.success({
message: "检查任务已提交",
description: "请稍后刷新页面查看结果"
});
}
});
}
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();