perf: 账号即将过期通知

v2
xiaojunnuo 2025-07-18 18:18:01 +08:00
parent ffc0c7bb7b
commit e40345095f
2 changed files with 69 additions and 8 deletions

View File

@ -1,10 +1,11 @@
import * as api from "./api"; import * as api from "./api";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud"; import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { useUserStore } from "/@/store/user"; import { useUserStore } from "/@/store/user";
import { Modal, notification } from "ant-design-vue"; import { Modal, notification } from "ant-design-vue";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useSettingStore } from "/@/store/settings"; import { useSettingStore } from "/@/store/settings";
import { useI18n } from "/src/locales"; import { useI18n } from "/src/locales";
import { computed } from "vue";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet { export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { t } = useI18n(); const { t } = useI18n();
@ -26,7 +27,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
const userStore = useUserStore(); const userStore = useUserStore();
const settingStore = useSettingStore(); const settingStore = useSettingStore();
const userValidTimeEnabled = compute(() => { const userValidTimeEnabled = computed(() => {
return settingStore.sysPublic.userValidTimeEnabled === true; return settingStore.sysPublic.userValidTimeEnabled === true;
}); });
return { return {
@ -226,7 +227,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
column: { column: {
align: "center", align: "center",
sorter: true, sorter: true,
width: 100, width: 160,
show: userValidTimeEnabled, show: userValidTimeEnabled,
cellRender({ value }) { cellRender({ value }) {
if (value == null || value === 0) { if (value == null || value === 0) {

View File

@ -1,15 +1,16 @@
import { Autoload, Config, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core'; import {Autoload, Config, Init, Inject, Scope, ScopeEnum} from '@midwayjs/core';
import { PipelineService } from '../pipeline/service/pipeline-service.js'; import {PipelineService} from '../pipeline/service/pipeline-service.js';
import { logger } from '@certd/basic'; import {logger} from '@certd/basic';
import {SysSettingsService, SysSiteInfo} from '@certd/lib-server'; import {SysSettingsService, SysSiteInfo} from '@certd/lib-server';
import { SiteInfoService } from '../monitor/index.js'; import {SiteInfoService} from '../monitor/index.js';
import { Cron } from '../cron/cron.js'; import {Cron} from '../cron/cron.js';
import {UserSettingsService} from "../mine/service/user-settings-service.js"; import {UserSettingsService} from "../mine/service/user-settings-service.js";
import {UserSiteMonitorSetting} from "../mine/service/models.js"; import {UserSiteMonitorSetting} from "../mine/service/models.js";
import {getPlusInfo} from "@certd/plus-core"; import {getPlusInfo} from "@certd/plus-core";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {NotificationService} from "../pipeline/service/notification-service.js"; import {NotificationService} from "../pipeline/service/notification-service.js";
import {UserService} from "../sys/authority/service/user-service.js"; import {UserService} from "../sys/authority/service/user-service.js";
import {Between} from "typeorm";
@Autoload() @Autoload()
@Scope(ScopeEnum.Request, { allowDowngrade: true }) @Scope(ScopeEnum.Request, { allowDowngrade: true })
@ -58,6 +59,8 @@ export class AutoCRegisterCron {
await this.registerPlusExpireCheckCron(); await this.registerPlusExpireCheckCron();
await this.registerUserExpireCheckCron()
} }
async registerSiteMonitorCron() { async registerSiteMonitorCron() {
@ -137,4 +140,61 @@ export class AutoCRegisterCron {
} }
}) })
} }
registerUserExpireCheckCron() {
// 添加plus即将到期检查任务
this.cron.register({
name: 'user-expire-check',
cron: `0 20 9 * * *`, // 一天只能检查一次,否则会重复发送通知
job: async () => {
const getExpiresDaysUsers = async (days: number) => {
const targetDate = dayjs().add(days, 'day')
const startTime = targetDate.startOf('day').valueOf()
const endTime = targetDate.endOf('day').valueOf()
return await this.userService.find({
where: {
validTime: Between(startTime, endTime),
status: 1
}
})
}
const notifyExpiresDaysUsers = async (days: number) => {
const list = await getExpiresDaysUsers(days)
if (list.length === 0) {
return
}
let title = `账号即将到期`
let content = `您的账号剩余${days}天到期,请及时续期,以免影响业务`
if (days <= 0) {
title = `账号已过期`
content = `您的账号已过期${Math.abs(days)}天,请尽快续期,以免影响业务`
}
const url = await this.notificationService.getBindUrl("");
for (const user of list) {
logger.info(`发送到期通知给用户:${user.username}`)
await this.notificationService.send({
useDefault: true,
logger: logger,
body: {
title,
content,
errorMessage: title,
url
}
}, user.id)
}
}
await notifyExpiresDaysUsers(7)
await notifyExpiresDaysUsers(3)
await notifyExpiresDaysUsers(1)
await notifyExpiresDaysUsers(0)
await notifyExpiresDaysUsers(-1)
await notifyExpiresDaysUsers(-3)
}
})
}
} }