chore: update startup tasks
This commit is contained in:
@@ -34,10 +34,9 @@ func init() {
|
|||||||
go func() {
|
go func() {
|
||||||
// 完成model的迁移之后,需要加载异步任务
|
// 完成model的迁移之后,需要加载异步任务
|
||||||
migrate.Setup()
|
migrate.Setup()
|
||||||
// 1. 加载日志清除服务(第一次实例化会初始化日志的定时设置,所以要在迁移以后)
|
cron_service.StartTasksRunOnStartup()
|
||||||
cron_service.StartLogsCronRun()
|
// 加载用户自己设定的定时消息任务
|
||||||
// 2. 加载用户自己设定的定时消息任务
|
cron_msg_service.StartUpUserSetupMsgCronTask()
|
||||||
cron_msg_service.StartUpMsgCronTask()
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ func Setup() {
|
|||||||
|
|
||||||
entry.Infof("Init Cron data...")
|
entry.Infof("Init Cron data...")
|
||||||
ss.InitLogConfig()
|
ss.InitLogConfig()
|
||||||
|
ss.InitHostedMsgConfig()
|
||||||
|
|
||||||
entry.Infof("All table data init done.")
|
entry.Infof("All table data init done.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,3 +79,32 @@ func GetHostMessagesTotal(text string, maps map[string]interface{}) (int64, erro
|
|||||||
query.Count(&total)
|
query.Count(&total)
|
||||||
return total, nil
|
return total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteOutDateHostedMessages 删除过期的托管消息,保留最新的 keepNum 条
|
||||||
|
func DeleteOutDateHostedMessages(keepNum int) (int, error) {
|
||||||
|
var affectedRows int
|
||||||
|
|
||||||
|
// 优化方案:使用GORM的Offset和Limit找到临界ID,兼容多种数据库
|
||||||
|
// 1. 获取第 keepNum 条记录的ID作为临界值
|
||||||
|
var threshold HostedMessage
|
||||||
|
result := db.Model(&HostedMessage{}).
|
||||||
|
Select("id").
|
||||||
|
Order("created_on DESC").
|
||||||
|
Offset(keepNum - 1).
|
||||||
|
Limit(1).
|
||||||
|
First(&threshold)
|
||||||
|
|
||||||
|
// 如果记录总数不足keepNum条,则不需要删除
|
||||||
|
if result.Error != nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 删除ID小于临界值的记录
|
||||||
|
deleteResult := db.Where("id < ?", threshold.ID).Delete(&HostedMessage{})
|
||||||
|
if deleteResult.Error != nil {
|
||||||
|
return affectedRows, deleteResult.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
affectedRows = int(deleteResult.RowsAffected)
|
||||||
|
return affectedRows, nil
|
||||||
|
}
|
||||||
|
|||||||
+21
-14
@@ -156,22 +156,29 @@ func GetSendLogsTotal(name string, taskId string, maps map[string]interface{}) (
|
|||||||
// GetSendLogsTotal 获取所有日志总数
|
// GetSendLogsTotal 获取所有日志总数
|
||||||
func DeleteOutDateLogs(keepNum int) (int, error) {
|
func DeleteOutDateLogs(keepNum int) (int, error) {
|
||||||
var affectedRows int
|
var affectedRows int
|
||||||
logt := GetSchema(SendTasksLogs{})
|
|
||||||
sql := fmt.Sprintf(`DELETE FROM %s
|
// 优化方案:使用GORM的Offset和Limit找到临界ID,兼容多种数据库
|
||||||
WHERE id NOT IN (
|
// 1. 获取第 keepNum 条记录的ID作为临界值
|
||||||
SELECT id FROM (
|
var threshold SendTasksLogs
|
||||||
SELECT id
|
result := db.Model(&SendTasksLogs{}).
|
||||||
FROM %s
|
Select("id").
|
||||||
ORDER BY created_on DESC
|
Order("created_on DESC").
|
||||||
LIMIT %d
|
Offset(keepNum - 1).
|
||||||
) tmp
|
Limit(1).
|
||||||
);`, logt, logt, keepNum)
|
First(&threshold)
|
||||||
|
|
||||||
result := db.Exec(sql)
|
// 如果记录总数不足keepNum条,则不需要删除
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return affectedRows, result.Error
|
return 0, nil
|
||||||
}
|
}
|
||||||
affectedRows = int(result.RowsAffected)
|
|
||||||
|
// 2. 删除ID小于临界值的记录
|
||||||
|
deleteResult := db.Where("id < ?", threshold.ID).Delete(&SendTasksLogs{})
|
||||||
|
if deleteResult.Error != nil {
|
||||||
|
return affectedRows, deleteResult.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
affectedRows = int(deleteResult.RowsAffected)
|
||||||
return affectedRows, nil
|
return affectedRows, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package constant
|
|||||||
import "github.com/robfig/cron/v3"
|
import "github.com/robfig/cron/v3"
|
||||||
|
|
||||||
const CleanLogsTaskId = "T-IM1GBswSRY"
|
const CleanLogsTaskId = "T-IM1GBswSRY"
|
||||||
|
const CleanHostedMsgTaskId = "T-HM2KCxwTZQ"
|
||||||
const SiteSettingSectionName = "site_config"
|
const SiteSettingSectionName = "site_config"
|
||||||
|
|
||||||
//const SiteSettingTitleKeyName = "title"
|
//const SiteSettingTitleKeyName = "title"
|
||||||
@@ -22,11 +23,26 @@ var SiteSiteDefaultValueMap = map[string]string{
|
|||||||
const LogsCleanSectionName = "log_config"
|
const LogsCleanSectionName = "log_config"
|
||||||
const LogsCleanCronKeyName = "cron"
|
const LogsCleanCronKeyName = "cron"
|
||||||
const LogsCleanKeepKeyName = "keep_num"
|
const LogsCleanKeepKeyName = "keep_num"
|
||||||
|
const LogsCleanEnabledKeyName = "enabled"
|
||||||
|
|
||||||
// 日志清理默认值
|
// 日志清理默认值
|
||||||
var LogsCleanDefaultValueMap = map[string]string{
|
var LogsCleanDefaultValueMap = map[string]string{
|
||||||
"cron": "1 0 * * *",
|
"cron": "1 0 * * *",
|
||||||
"keep_num": "1000",
|
"keep_num": "1000",
|
||||||
|
"enabled": "true",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 托管消息清理自定义
|
||||||
|
const HostedMsgCleanSectionName = "hosted_msg_config"
|
||||||
|
const HostedMsgCleanCronKeyName = "cron"
|
||||||
|
const HostedMsgCleanKeepKeyName = "keep_num"
|
||||||
|
const HostedMsgCleanEnabledKeyName = "enabled"
|
||||||
|
|
||||||
|
// 托管消息清理默认值
|
||||||
|
var HostedMsgCleanDefaultValueMap = map[string]string{
|
||||||
|
"cron": "30 0 * * *",
|
||||||
|
"keep_num": "50000",
|
||||||
|
"enabled": "false",
|
||||||
}
|
}
|
||||||
|
|
||||||
const AboutSectionName = "about"
|
const AboutSectionName = "about"
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package cron_msg_service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"message-nest/models"
|
"message-nest/models"
|
||||||
"message-nest/pkg/constant"
|
"message-nest/pkg/constant"
|
||||||
"message-nest/service/cron_service"
|
"message-nest/service/cron_service"
|
||||||
"message-nest/service/send_message_service"
|
"message-nest/service/send_message_service"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MsgCronTask struct {
|
type MsgCronTask struct {
|
||||||
@@ -62,6 +63,7 @@ func CronMsgSendF(msg models.CronMessages) {
|
|||||||
}
|
}
|
||||||
sender := send_message_service.SendMessageService{
|
sender := send_message_service.SendMessageService{
|
||||||
TaskID: task.ID,
|
TaskID: task.ID,
|
||||||
|
SendMode: "task",
|
||||||
Title: msg.Title,
|
Title: msg.Title,
|
||||||
Text: msg.Content,
|
Text: msg.Content,
|
||||||
URL: msg.Url,
|
URL: msg.Url,
|
||||||
@@ -104,7 +106,7 @@ func RemoveCronMsgToCronServer(msg models.CronMessages) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StartUpMsgCronTask 启动注册定时任务
|
// StartUpMsgCronTask 启动注册定时任务
|
||||||
func StartUpMsgCronTask() {
|
func StartUpUserSetupMsgCronTask() {
|
||||||
MsgCronTask{}.Register()
|
MsgCronTask{}.Register()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
package cron_service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/robfig/cron/v3"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/unknwon/com"
|
|
||||||
"message-nest/models"
|
|
||||||
"message-nest/pkg/constant"
|
|
||||||
"message-nest/service/send_message_service"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ClearLogsTaskId cron.EntryID
|
|
||||||
|
|
||||||
// ClearLogs 清除日志的定时任务
|
|
||||||
func ClearLogs() {
|
|
||||||
var errStr string
|
|
||||||
sm := send_message_service.SendMessageService{
|
|
||||||
TaskID: constant.CleanLogsTaskId,
|
|
||||||
DefaultLogger: logrus.WithFields(logrus.Fields{
|
|
||||||
"prefix": "[Cron Clear Logs]",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
sm.Status = send_message_service.SendSuccess
|
|
||||||
|
|
||||||
sm.LogsAndStatusMark("开始清除日志", sm.Status)
|
|
||||||
|
|
||||||
setting, err := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanKeepKeyName)
|
|
||||||
if err != nil {
|
|
||||||
errStr = fmt.Sprintf("获取日志的保留数失败,原因:%s", err)
|
|
||||||
sm.LogsAndStatusMark(errStr, send_message_service.SendFail)
|
|
||||||
}
|
|
||||||
|
|
||||||
keepNum := com.StrTo(setting.Value).MustInt()
|
|
||||||
affectedRows, err := models.DeleteOutDateLogs(keepNum)
|
|
||||||
if err != nil {
|
|
||||||
errStr = fmt.Sprintf("删除日志失败,原因:%s", err)
|
|
||||||
sm.LogsAndStatusMark(errStr, send_message_service.SendFail)
|
|
||||||
} else {
|
|
||||||
errStr = fmt.Sprintf("删除日志成功,删除条数:%d,保留数目:%d", affectedRows, keepNum)
|
|
||||||
sm.LogsAndStatusMark(errStr, sm.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
sm.RecordSendLog()
|
|
||||||
}
|
|
||||||
|
|
||||||
type CronService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartLogsCronRun 启动注册清除任务定时任务
|
|
||||||
func (cs *CronService) StartLogsCronRun() {
|
|
||||||
// 注册任务
|
|
||||||
setting, err := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanCronKeyName)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(fmt.Sprintf("获取日志的cron失败,原因:%s", err))
|
|
||||||
}
|
|
||||||
ClearLogsTaskId = AddTask(ScheduledTask{
|
|
||||||
Schedule: setting.Value,
|
|
||||||
Job: ClearLogs,
|
|
||||||
})
|
|
||||||
|
|
||||||
// 添加任务
|
|
||||||
err = models.AddSendTaskWithID("日志定时清除", constant.CleanLogsTaskId, "admin")
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(fmt.Sprintf("添加日志定时清除任务失败,原因:%s", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateLogsCronRun 更新清除任务定时任务
|
|
||||||
func (cs *CronService) UpdateLogsCronRun(cron string) {
|
|
||||||
RemoveTask(ClearLogsTaskId)
|
|
||||||
ClearLogsTaskId = AddTask(ScheduledTask{
|
|
||||||
Schedule: cron,
|
|
||||||
Job: ClearLogs,
|
|
||||||
})
|
|
||||||
logrus.Error(fmt.Sprintf("更新日志的cron成功,%s", cron))
|
|
||||||
logrus.Error(fmt.Sprintf("所有的定时任务: %s", TaskList))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartLogsCronRun 启动的时候开启定时任务
|
|
||||||
func StartLogsCronRun() {
|
|
||||||
logrus.Infof("开始注册定时清除日志任务...")
|
|
||||||
cs := CronService{}
|
|
||||||
cs.StartLogsCronRun()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
package cron_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"message-nest/models"
|
||||||
|
"message-nest/pkg/constant"
|
||||||
|
"message-nest/service/send_message_service"
|
||||||
|
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/unknwon/com"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ClearLogsTaskId cron.EntryID
|
||||||
|
var ClearHostedMsgTaskId cron.EntryID
|
||||||
|
|
||||||
|
// CleanConfig 清理任务配置
|
||||||
|
type CleanConfig struct {
|
||||||
|
TaskID string
|
||||||
|
TaskName string
|
||||||
|
LogPrefix string
|
||||||
|
SectionName string
|
||||||
|
EnabledKey string
|
||||||
|
KeepNumKey string
|
||||||
|
DeleteFunc func(int) (int, error)
|
||||||
|
ResourceName string // 资源名称,如"日志"、"托管消息"
|
||||||
|
}
|
||||||
|
|
||||||
|
// executeCleanTask 执行清理任务的通用逻辑
|
||||||
|
func executeCleanTask(config CleanConfig) {
|
||||||
|
var errStr string
|
||||||
|
sm := send_message_service.SendMessageService{
|
||||||
|
TaskID: config.TaskID,
|
||||||
|
Name: config.TaskName,
|
||||||
|
DefaultLogger: logrus.WithFields(logrus.Fields{
|
||||||
|
"prefix": config.LogPrefix,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
sm.Status = send_message_service.SendSuccess
|
||||||
|
|
||||||
|
// 检查是否启用
|
||||||
|
enabledSetting, err := models.GetSettingByKey(config.SectionName, config.EnabledKey)
|
||||||
|
if err != nil {
|
||||||
|
errStr = fmt.Sprintf("获取%s清理开关失败,原因:%s", config.ResourceName, err)
|
||||||
|
sm.LogsAndStatusMark(errStr, send_message_service.SendFail)
|
||||||
|
sm.RecordSendLog()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if enabledSetting.Value != "true" {
|
||||||
|
sm.LogsAndStatusMark(fmt.Sprintf("%s清理功能未启用,跳过执行", config.ResourceName), sm.Status)
|
||||||
|
sm.RecordSendLog()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sm.LogsAndStatusMark(fmt.Sprintf("开始清除%s", config.ResourceName), sm.Status)
|
||||||
|
|
||||||
|
setting, err := models.GetSettingByKey(config.SectionName, config.KeepNumKey)
|
||||||
|
if err != nil {
|
||||||
|
errStr = fmt.Sprintf("获取%s的保留数失败,原因:%s", config.ResourceName, err)
|
||||||
|
sm.LogsAndStatusMark(errStr, send_message_service.SendFail)
|
||||||
|
}
|
||||||
|
|
||||||
|
keepNum := com.StrTo(setting.Value).MustInt()
|
||||||
|
affectedRows, err := config.DeleteFunc(keepNum)
|
||||||
|
if err != nil {
|
||||||
|
errStr = fmt.Sprintf("删除%s失败,原因:%s", config.ResourceName, err)
|
||||||
|
sm.LogsAndStatusMark(errStr, send_message_service.SendFail)
|
||||||
|
} else {
|
||||||
|
errStr = fmt.Sprintf("删除%s成功,删除条数:%d,保留数目:%d", config.ResourceName, affectedRows, keepNum)
|
||||||
|
sm.LogsAndStatusMark(errStr, sm.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
sm.RecordSendLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearLogs 清除日志的定时任务
|
||||||
|
func ClearLogs() {
|
||||||
|
executeCleanTask(CleanConfig{
|
||||||
|
TaskID: constant.CleanLogsTaskId,
|
||||||
|
TaskName: "日志定时清除",
|
||||||
|
LogPrefix: "[Cron Clear Logs]",
|
||||||
|
SectionName: constant.LogsCleanSectionName,
|
||||||
|
EnabledKey: constant.LogsCleanEnabledKeyName,
|
||||||
|
KeepNumKey: constant.LogsCleanKeepKeyName,
|
||||||
|
DeleteFunc: models.DeleteOutDateLogs,
|
||||||
|
ResourceName: "日志",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type CronService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// startCleanCronTask 启动清理任务的通用逻辑
|
||||||
|
func startCleanCronTask(sectionName, enabledKey, cronKey, resourceName string, job func(), taskId *cron.EntryID) {
|
||||||
|
// 检查是否启用
|
||||||
|
enabledSetting, err := models.GetSettingByKey(sectionName, enabledKey)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(fmt.Sprintf("获取[%s]清理开关失败,原因:%s", resourceName, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if enabledSetting.Value != "true" {
|
||||||
|
logrus.Info(fmt.Sprintf("[%s]清理功能未启用", resourceName))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册任务
|
||||||
|
setting, err := models.GetSettingByKey(sectionName, cronKey)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(fmt.Sprintf("获取[%s]的cron失败,原因:%s", resourceName, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*taskId = AddTask(ScheduledTask{
|
||||||
|
Schedule: setting.Value,
|
||||||
|
Job: job,
|
||||||
|
})
|
||||||
|
logrus.Info(fmt.Sprintf("[%s]清理任务已启动", resourceName))
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateCleanCronTask 更新清理任务的通用逻辑
|
||||||
|
func updateCleanCronTask(cron string, enabled bool, resourceName string, job func(), taskId *cron.EntryID) {
|
||||||
|
// 先移除旧任务
|
||||||
|
if *taskId > 0 {
|
||||||
|
RemoveTask(*taskId)
|
||||||
|
*taskId = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果启用,则添加新任务
|
||||||
|
if enabled {
|
||||||
|
*taskId = AddTask(ScheduledTask{
|
||||||
|
Schedule: cron,
|
||||||
|
Job: job,
|
||||||
|
})
|
||||||
|
logrus.Info(fmt.Sprintf("更新%s的cron成功,%s", resourceName, cron))
|
||||||
|
} else {
|
||||||
|
logrus.Info(fmt.Sprintf("%s清理任务已停止", resourceName))
|
||||||
|
}
|
||||||
|
logrus.Info(fmt.Sprintf("所有的定时任务总数: %d", len(TaskList)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartLogsCronRun 启动注册清除任务定时任务
|
||||||
|
func (cs *CronService) StartLogsCronRun() {
|
||||||
|
startCleanCronTask(
|
||||||
|
constant.LogsCleanSectionName,
|
||||||
|
constant.LogsCleanEnabledKeyName,
|
||||||
|
constant.LogsCleanCronKeyName,
|
||||||
|
"日志",
|
||||||
|
ClearLogs,
|
||||||
|
&ClearLogsTaskId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLogsCronRun 更新清除任务定时任务
|
||||||
|
func (cs *CronService) UpdateLogsCronRun(cron string, enabled bool) {
|
||||||
|
updateCleanCronTask(cron, enabled, "日志", ClearLogs, &ClearLogsTaskId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearHostedMessages 清除托管消息的定时任务
|
||||||
|
func ClearHostedMessages() {
|
||||||
|
executeCleanTask(CleanConfig{
|
||||||
|
TaskID: constant.CleanHostedMsgTaskId,
|
||||||
|
TaskName: "托管消息定时清除",
|
||||||
|
LogPrefix: "[Cron Clear Hosted Messages]",
|
||||||
|
SectionName: constant.HostedMsgCleanSectionName,
|
||||||
|
EnabledKey: constant.HostedMsgCleanEnabledKeyName,
|
||||||
|
KeepNumKey: constant.HostedMsgCleanKeepKeyName,
|
||||||
|
DeleteFunc: models.DeleteOutDateHostedMessages,
|
||||||
|
ResourceName: "托管消息",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartHostedMsgCronRun 启动注册托管消息清除任务定时任务
|
||||||
|
func (cs *CronService) StartHostedMsgCronRun() {
|
||||||
|
startCleanCronTask(
|
||||||
|
constant.HostedMsgCleanSectionName,
|
||||||
|
constant.HostedMsgCleanEnabledKeyName,
|
||||||
|
constant.HostedMsgCleanCronKeyName,
|
||||||
|
"托管消息",
|
||||||
|
ClearHostedMessages,
|
||||||
|
&ClearHostedMsgTaskId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateHostedMsgCronRun 更新托管消息清除任务定时任务
|
||||||
|
func (cs *CronService) UpdateHostedMsgCronRun(cron string, enabled bool) {
|
||||||
|
updateCleanCronTask(cron, enabled, "托管消息", ClearHostedMessages, &ClearHostedMsgTaskId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartLogsCronRunOnStartup 启动的时候开启定时任务
|
||||||
|
func StartLogsCronRunOnStartup() {
|
||||||
|
logrus.Infof("开始注册定时清除日志任务...")
|
||||||
|
cs := CronService{}
|
||||||
|
cs.StartLogsCronRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartHostedMsgCronRunOnStartup 启动的时候开启托管消息清理定时任务
|
||||||
|
func StartHostedMsgCronRunOnStartup() {
|
||||||
|
logrus.Infof("开始注册定时清除托管消息任务...")
|
||||||
|
cs := CronService{}
|
||||||
|
cs.StartHostedMsgCronRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartTasksRunOnStartup() {
|
||||||
|
StartLogsCronRunOnStartup()
|
||||||
|
StartHostedMsgCronRunOnStartup()
|
||||||
|
}
|
||||||
@@ -41,3 +41,11 @@ func (es *InitSettingService) InitLogConfig() {
|
|||||||
es.CommonAddSetting(section, key, value)
|
es.CommonAddSetting(section, key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitHostedMsgConfig 初始化托管消息清理设置
|
||||||
|
func (es *InitSettingService) InitHostedMsgConfig() {
|
||||||
|
section := constant.HostedMsgCleanSectionName
|
||||||
|
for key, value := range constant.HostedMsgCleanDefaultValueMap {
|
||||||
|
es.CommonAddSetting(section, key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -93,9 +93,25 @@ func (us *UserSettings) EditSettings(section string, key string, value string, c
|
|||||||
data["value"] = value
|
data["value"] = value
|
||||||
data["modified_by"] = currentUser
|
data["modified_by"] = currentUser
|
||||||
err := models.EditSetting(setting.ID, data)
|
err := models.EditSetting(setting.ID, data)
|
||||||
if key == constant.LogsCleanCronKeyName {
|
// 更新日志清理配置
|
||||||
cronService := cron_service.CronService{}
|
if section == constant.LogsCleanSectionName {
|
||||||
cronService.UpdateLogsCronRun(value)
|
if key == constant.LogsCleanCronKeyName || key == constant.LogsCleanEnabledKeyName {
|
||||||
|
cronService := cron_service.CronService{}
|
||||||
|
// 获取最新的cron和enabled值
|
||||||
|
cronSetting, _ := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanCronKeyName)
|
||||||
|
enabledSetting, _ := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanEnabledKeyName)
|
||||||
|
cronService.UpdateLogsCronRun(cronSetting.Value, enabledSetting.Value == "true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 更新托管消息清理配置
|
||||||
|
if section == constant.HostedMsgCleanSectionName {
|
||||||
|
if key == constant.HostedMsgCleanCronKeyName || key == constant.HostedMsgCleanEnabledKeyName {
|
||||||
|
cronService := cron_service.CronService{}
|
||||||
|
// 获取最新的cron和enabled值
|
||||||
|
cronSetting, _ := models.GetSettingByKey(constant.HostedMsgCleanSectionName, constant.HostedMsgCleanCronKeyName)
|
||||||
|
enabledSetting, _ := models.GetSettingByKey(constant.HostedMsgCleanSectionName, constant.HostedMsgCleanEnabledKeyName)
|
||||||
|
cronService.UpdateHostedMsgCronRun(cronSetting.Value, enabledSetting.Value == "true")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 如果是site_config,清除缓存
|
// 如果是site_config,清除缓存
|
||||||
if section == constant.SiteSettingSectionName {
|
if section == constant.SiteSettingSectionName {
|
||||||
@@ -116,6 +132,13 @@ type SiteConfig struct {
|
|||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
Cron string `json:"cron" validate:"required,cron" label:"日志定时表达式"`
|
Cron string `json:"cron" validate:"required,cron" label:"日志定时表达式"`
|
||||||
KeepNum string `json:"keep_num" validate:"required,min=1,max=50" label:"日志保留数"`
|
KeepNum string `json:"keep_num" validate:"required,min=1,max=50" label:"日志保留数"`
|
||||||
|
Enabled string `json:"enabled" validate:"required,oneof=true false" label:"是否启用"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HostedMsgConfig struct {
|
||||||
|
Cron string `json:"cron" validate:"required,cron" label:"托管消息定时表达式"`
|
||||||
|
KeepNum string `json:"keep_num" validate:"required,min=1,max=50" label:"托管消息保留数"`
|
||||||
|
Enabled string `json:"enabled" validate:"required,oneof=true false" label:"是否启用"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCookieExpDays 获取 cookie 过期天数,若无配置则返回默认值 1
|
// GetCookieExpDays 获取 cookie 过期天数,若无配置则返回默认值 1
|
||||||
@@ -157,6 +180,19 @@ func (us *UserSettings) ValidateDiffSetting(section string, data map[string]stri
|
|||||||
var config LogConfig
|
var config LogConfig
|
||||||
config.Cron = data["cron"]
|
config.Cron = data["cron"]
|
||||||
config.KeepNum = data["keep_num"]
|
config.KeepNum = data["keep_num"]
|
||||||
|
config.Enabled = data["enabled"]
|
||||||
|
_, err := cron.ParseStandard(config.Cron)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("%s 不是合法的corn表达式", config.Cron)
|
||||||
|
}
|
||||||
|
_, errStr := app.CommonPlaygroundValid(config)
|
||||||
|
return errStr
|
||||||
|
}
|
||||||
|
if section == constant.HostedMsgCleanSectionName {
|
||||||
|
var config HostedMsgConfig
|
||||||
|
config.Cron = data["cron"]
|
||||||
|
config.KeepNum = data["keep_num"]
|
||||||
|
config.Enabled = data["enabled"]
|
||||||
_, err := cron.ParseStandard(config.Cron)
|
_, err := cron.ParseStandard(config.Cron)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Sprintf("%s 不是合法的corn表达式", config.Cron)
|
return fmt.Sprintf("%s 不是合法的corn表达式", config.Cron)
|
||||||
|
|||||||
@@ -0,0 +1,290 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onMounted } from 'vue'
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||||
|
import { Input } from '@/components/ui/input'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { Switch } from '@/components/ui/switch'
|
||||||
|
import { Label } from '@/components/ui/label'
|
||||||
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
|
import { toast } from 'vue-sonner'
|
||||||
|
import { request } from '@/api/api'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { CONSTANT } from '@/constant'
|
||||||
|
import { HelpCircleIcon } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
// 日志清理状态
|
||||||
|
const logsState = reactive({
|
||||||
|
section: 'log_config',
|
||||||
|
cron: '',
|
||||||
|
keepNum: '1000',
|
||||||
|
enabled: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 托管消息清理状态
|
||||||
|
const hostedMsgState = reactive({
|
||||||
|
section: 'hosted_msg_config',
|
||||||
|
cron: '',
|
||||||
|
keepNum: '50000',
|
||||||
|
enabled: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 提交日志清理配置
|
||||||
|
const handleLogsSubmit = async () => {
|
||||||
|
try {
|
||||||
|
const postData = {
|
||||||
|
section: logsState.section,
|
||||||
|
data: {
|
||||||
|
cron: logsState.cron.trim(),
|
||||||
|
keep_num: logsState.keepNum.trim(),
|
||||||
|
enabled: logsState.enabled ? 'true' : 'false',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const response = await request.post('/settings/set', postData)
|
||||||
|
if (response.data.code === 200) {
|
||||||
|
const statusText = logsState.enabled ? '已打开' : '已关闭'
|
||||||
|
toast.success(`日志清理${statusText}`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('保存失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交托管消息清理配置
|
||||||
|
const handleHostedMsgSubmit = async () => {
|
||||||
|
try {
|
||||||
|
const postData = {
|
||||||
|
section: hostedMsgState.section,
|
||||||
|
data: {
|
||||||
|
cron: hostedMsgState.cron.trim(),
|
||||||
|
keep_num: hostedMsgState.keepNum.trim(),
|
||||||
|
enabled: hostedMsgState.enabled ? 'true' : 'false',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const response = await request.post('/settings/set', postData)
|
||||||
|
if (response.data.code === 200) {
|
||||||
|
const statusText = hostedMsgState.enabled ? '已打开' : '已关闭'
|
||||||
|
toast.success(`托管消息清理${statusText}`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('保存失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看日志清理日志
|
||||||
|
const handleLogsView = () => {
|
||||||
|
router.push({ path: '/sendlogs', query: { taskid: CONSTANT.LOG_TASK_ID } })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看托管消息清理日志
|
||||||
|
const handleHostedMsgView = () => {
|
||||||
|
router.push({ path: '/sendlogs', query: { taskid: CONSTANT.HOSTED_MSG_TASK_ID } })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取日志清理配置
|
||||||
|
const getLogsConfig = async () => {
|
||||||
|
try {
|
||||||
|
const params = { params: { section: 'log_config' } }
|
||||||
|
const response = await request.get('/settings/getsetting', params)
|
||||||
|
if (response.data.code === 200) {
|
||||||
|
const data = response.data.data
|
||||||
|
// 使用Object.assign确保响应式更新
|
||||||
|
Object.assign(logsState, {
|
||||||
|
cron: data.cron || '',
|
||||||
|
keepNum: data.keep_num || '1000',
|
||||||
|
enabled: data.enabled === 'true' || data.enabled === true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('获取日志清理配置失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取托管消息清理配置
|
||||||
|
const getHostedMsgConfig = async () => {
|
||||||
|
try {
|
||||||
|
const params = { params: { section: 'hosted_msg_config' } }
|
||||||
|
const response = await request.get('/settings/getsetting', params)
|
||||||
|
if (response.data.code === 200) {
|
||||||
|
const data = response.data.data
|
||||||
|
// 使用Object.assign确保响应式更新
|
||||||
|
Object.assign(hostedMsgState, {
|
||||||
|
cron: data.cron || '',
|
||||||
|
keepNum: data.keep_num || '50000',
|
||||||
|
enabled: data.enabled === 'true' || data.enabled === true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('获取托管消息清理配置失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getLogsConfig()
|
||||||
|
getHostedMsgConfig()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'CleanSettings'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>数据清理设置</CardTitle>
|
||||||
|
<CardDescription>配置定时数据清除和保留策略</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<!-- 大屏横向,小屏竖向 -->
|
||||||
|
<div class="flex flex-col lg:flex-row gap-6 lg:gap-8">
|
||||||
|
<!-- 日志清理部分 -->
|
||||||
|
<div class="setting-section flex-1">
|
||||||
|
<div class="flex items-center space-x-2 mb-4">
|
||||||
|
<h3 class="text-lg font-semibold">日志清理</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<!-- 启用开关 -->
|
||||||
|
<div class="flex items-center justify-between space-x-2 p-4 border rounded-lg">
|
||||||
|
<div class="space-y-0.5">
|
||||||
|
<Label class="text-base font-medium">启用日志清理</Label>
|
||||||
|
<div class="text-sm text-muted-foreground">
|
||||||
|
开启后将按照规则清理清理日志
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Switch v-model="logsState.enabled" @update:model-value="handleLogsSubmit" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Cron表达式输入 -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label class="text-sm font-medium text-gray-700">定时清除Cron表达式</label>
|
||||||
|
<Input
|
||||||
|
v-model="logsState.cron"
|
||||||
|
placeholder="请输入定时日志清除的Cron表达式"
|
||||||
|
:disabled="!logsState.enabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 保留数量输入 -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label class="text-sm font-medium text-gray-700">保留日志条数</label>
|
||||||
|
<Input
|
||||||
|
v-model="logsState.keepNum"
|
||||||
|
placeholder="请输入要保留的最近的日志条数"
|
||||||
|
:disabled="!logsState.enabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部操作区域 -->
|
||||||
|
<div class="flex items-center justify-between pt-2">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<span class="text-sm text-gray-600">说明</span>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<HelpCircleIcon class="w-4 h-4 text-gray-400 hover:text-gray-600" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent class="max-w-xs">
|
||||||
|
<div class="text-sm">
|
||||||
|
<p>cron如果不设置,默认是在每天的0点1分进行清理</p>
|
||||||
|
<p class="mt-1">保留数目如果不设置,默认保留最近1000条</p>
|
||||||
|
<p class="mt-1">需要先启用开关才能生效</p>
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<Button variant="outline" size="sm" @click="handleLogsView">
|
||||||
|
查看日志
|
||||||
|
</Button>
|
||||||
|
<Button size="sm" @click="handleLogsSubmit">
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 响应式分隔线:小屏横向,大屏竖向 -->
|
||||||
|
<div class="lg:hidden w-full border-t border-gray-200 dark:border-gray-700 my-6"></div>
|
||||||
|
<div class="hidden lg:block w-px bg-border self-stretch"></div>
|
||||||
|
|
||||||
|
<!-- 托管消息清理部分 -->
|
||||||
|
<div class="setting-section flex-1">
|
||||||
|
<div class="flex items-center space-x-2 mb-4">
|
||||||
|
<h3 class="text-lg font-semibold">托管消息清理</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<!-- 启用开关 -->
|
||||||
|
<div class="flex items-center justify-between space-x-2 p-4 border rounded-lg">
|
||||||
|
<div class="space-y-0.5">
|
||||||
|
<Label class="text-base font-medium">启用托管消息清理</Label>
|
||||||
|
<div class="text-sm text-muted-foreground">
|
||||||
|
开启后将按照规则清理托管消息
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Switch v-model="hostedMsgState.enabled" @update:model-value="handleHostedMsgSubmit" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Cron表达式输入 -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label class="text-sm font-medium text-gray-700">定时清除Cron表达式</label>
|
||||||
|
<Input
|
||||||
|
v-model="hostedMsgState.cron"
|
||||||
|
placeholder="请输入定时托管消息清除的Cron表达式"
|
||||||
|
:disabled="!hostedMsgState.enabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 保留数量输入 -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<label class="text-sm font-medium text-gray-700">保留托管消息条数</label>
|
||||||
|
<Input
|
||||||
|
v-model="hostedMsgState.keepNum"
|
||||||
|
placeholder="请输入要保留的最近的托管消息条数"
|
||||||
|
:disabled="!hostedMsgState.enabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部操作区域 -->
|
||||||
|
<div class="flex items-center justify-between pt-2">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<span class="text-sm text-gray-600">说明</span>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<HelpCircleIcon class="w-4 h-4 text-gray-400 hover:text-gray-600" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent class="max-w-xs">
|
||||||
|
<div class="text-sm">
|
||||||
|
<p>cron如果不设置,默认是在每天的0点30分进行清理</p>
|
||||||
|
<p class="mt-1">保留数目如果不设置,默认保留最近5000条</p>
|
||||||
|
<p class="mt-1">需要先启用开关才能生效</p>
|
||||||
|
</div>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<Button variant="outline" size="sm" @click="handleHostedMsgView">
|
||||||
|
查看日志
|
||||||
|
</Button>
|
||||||
|
<Button size="sm" @click="handleHostedMsgSubmit">
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</template>
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive, onMounted } from 'vue'
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
||||||
import { Input } from '@/components/ui/input'
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
||||||
import { toast } from 'vue-sonner'
|
|
||||||
import { request } from '@/api/api'
|
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import { CONSTANT } from '@/constant'
|
|
||||||
import { HelpCircleIcon } from 'lucide-vue-next'
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
section: 'log_config',
|
|
||||||
cron: '',
|
|
||||||
keepNum: '1000',
|
|
||||||
})
|
|
||||||
|
|
||||||
// 提交配置
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
try {
|
|
||||||
const postData = {
|
|
||||||
section: state.section,
|
|
||||||
data: {
|
|
||||||
cron: state.cron.trim(),
|
|
||||||
keep_num: state.keepNum.trim(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const response = await request.post('/settings/set', postData)
|
|
||||||
if (response.data.code === 200) {
|
|
||||||
const msg = response.data.msg
|
|
||||||
toast.success(msg)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
toast.error('保存失败,请稍后重试')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查看日志
|
|
||||||
const handleView = async () => {
|
|
||||||
router.push({ path: '/sendlogs', query: { taskid: CONSTANT.LOG_TASK_ID } })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取站点配置
|
|
||||||
const getSiteConfig = async () => {
|
|
||||||
try {
|
|
||||||
const params = { params: { section: 'log_config' } }
|
|
||||||
const response = await request.get('/settings/getsetting', params)
|
|
||||||
if (response.data.code === 200) {
|
|
||||||
const data = response.data.data
|
|
||||||
state.cron = data.cron || ''
|
|
||||||
state.keepNum = data.keep_num || '1000'
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
toast.error('获取配置失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getSiteConfig()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: 'LogsSettings'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>日志设置</CardTitle>
|
|
||||||
<CardDescription>配置定时日志清除和保留策略</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="setting-container">
|
|
||||||
<div class="space-y-4">
|
|
||||||
<!-- Cron表达式输入 -->
|
|
||||||
<div class="space-y-2">
|
|
||||||
<label class="text-sm font-medium text-gray-700">定时清除Cron表达式</label>
|
|
||||||
<div class="flex">
|
|
||||||
<!-- <div class="inline-flex items-center px-3 text-sm text-gray-500 bg-gray-50 border border-r-0 border-gray-300 rounded-l-md">
|
|
||||||
cron://
|
|
||||||
</div> -->
|
|
||||||
<Input
|
|
||||||
v-model="state.cron"
|
|
||||||
placeholder="请输入定时日志清除的Cron表达式"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 保留数量输入 -->
|
|
||||||
<div class="space-y-2">
|
|
||||||
<label class="text-sm font-medium text-gray-700">保留日志条数</label>
|
|
||||||
<div class="flex">
|
|
||||||
<!-- <div class="inline-flex items-center px-3 text-sm text-gray-500 bg-gray-50 border border-r-0 border-gray-300 rounded-l-md">
|
|
||||||
保留数
|
|
||||||
</div> -->
|
|
||||||
<Input
|
|
||||||
v-model="state.keepNum"
|
|
||||||
placeholder="请输入要保留的最近的日志条数"
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 底部操作区域 -->
|
|
||||||
<div class="flex items-center justify-between mt-6">
|
|
||||||
<div class="flex items-center space-x-2">
|
|
||||||
<span class="text-sm text-gray-600">说明</span>
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<HelpCircleIcon class="w-4 h-4 text-gray-400 hover:text-gray-600" />
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent class="max-w-xs">
|
|
||||||
<div class="text-sm">
|
|
||||||
<p>cron如果不设置,默认是在每天的0点1分进行清理</p>
|
|
||||||
<p class="mt-1">保留数目如果不设置,默认保留最近1000条</p>
|
|
||||||
</div>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex space-x-2">
|
|
||||||
<Button variant="outline" size="sm" @click="handleView">
|
|
||||||
查看日志
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" @click="handleSubmit">
|
|
||||||
确定
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import SettingsSidebar from './SettingsSidebar.vue'
|
import SettingsSidebar from './SettingsSidebar.vue'
|
||||||
import PasswordSettings from './PasswordSettings.vue'
|
import PasswordSettings from './PasswordSettings.vue'
|
||||||
import LogsSettings from './LogsSettings.vue'
|
import CleanSettings from './CleanSettings.vue'
|
||||||
import SiteSettings from './SiteSettings.vue'
|
import SiteSettings from './SiteSettings.vue'
|
||||||
import AboutSettings from './AboutSettings.vue'
|
import AboutSettings from './AboutSettings.vue'
|
||||||
import LoginLogs from './LoginLogs.vue'
|
import LoginLogs from './LoginLogs.vue'
|
||||||
@@ -25,8 +25,8 @@ const activeTab = ref('password')
|
|||||||
<!-- 重置密码 -->
|
<!-- 重置密码 -->
|
||||||
<PasswordSettings v-if="activeTab === 'password'" />
|
<PasswordSettings v-if="activeTab === 'password'" />
|
||||||
|
|
||||||
<!-- 日志清理 -->
|
<!-- 数据清理 -->
|
||||||
<LogsSettings v-if="activeTab === 'logs'" />
|
<CleanSettings v-if="activeTab === 'clean'" />
|
||||||
|
|
||||||
<!-- 站点设置 -->
|
<!-- 站点设置 -->
|
||||||
<SiteSettings v-if="activeTab === 'site'" />
|
<SiteSettings v-if="activeTab === 'site'" />
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ defineEmits<Emits>()
|
|||||||
// 设置菜单项
|
// 设置菜单项
|
||||||
const settingsMenu = [
|
const settingsMenu = [
|
||||||
{ id: 'password', name: '重置密码', icon: KeyIcon },
|
{ id: 'password', name: '重置密码', icon: KeyIcon },
|
||||||
{ id: 'logs', name: '日志清理', icon: TrashIcon },
|
{ id: 'clean', name: '数据清理', icon: TrashIcon },
|
||||||
{ id: 'loginlogs', name: '登录日志', icon: HistoryIcon },
|
{ id: 'loginlogs', name: '登录日志', icon: HistoryIcon },
|
||||||
{ id: 'site', name: '站点设置', icon: SettingsIcon },
|
{ id: 'site', name: '站点设置', icon: SettingsIcon },
|
||||||
{ id: 'about', name: '站点关于', icon: InfoIcon }
|
{ id: 'about', name: '站点关于', icon: InfoIcon }
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { SeparatorProps } from "reka-ui"
|
||||||
|
import type { HTMLAttributes } from "vue"
|
||||||
|
import { reactiveOmit } from "@vueuse/core"
|
||||||
|
import { Separator } from "reka-ui"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<
|
||||||
|
SeparatorProps & { class?: HTMLAttributes["class"] }
|
||||||
|
>(), {
|
||||||
|
orientation: "horizontal",
|
||||||
|
decorative: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, "class")
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Separator
|
||||||
|
data-slot="separator"
|
||||||
|
v-bind="delegatedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default as Separator } from "./Separator.vue"
|
||||||
Vendored
+1
@@ -4,6 +4,7 @@ export interface ConstantType {
|
|||||||
TOTAL: number;
|
TOTAL: number;
|
||||||
DEFALUT_SITE_CONFIG: string;
|
DEFALUT_SITE_CONFIG: string;
|
||||||
LOG_TASK_ID: string;
|
LOG_TASK_ID: string;
|
||||||
|
HOSTED_MSG_TASK_ID: string;
|
||||||
STORE_TOKEN_NAME: string;
|
STORE_TOKEN_NAME: string;
|
||||||
STORE_CUSTOM_NAME: string;
|
STORE_CUSTOM_NAME: string;
|
||||||
NO_AUTH_URL: string[];
|
NO_AUTH_URL: string[];
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const CONSTANT = {
|
|||||||
TOTAL: 0,
|
TOTAL: 0,
|
||||||
DEFALUT_SITE_CONFIG: JSON.stringify({ "logo": "<svg t=\"1702547210136\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"1861\" width=\"200\" height=\"200\"><path d=\"M970.091313 224.033616a14.201535 14.201535 0 0 0-14.100687-3.631838c-88.419556-13.429657-142.919111-12.953859-248.242424 23.762747-69.454869 24.217859-109.056 79.873293-135.267556 116.712728-6.692202 9.403475-18.949172 26.625293-23.77309 29.509818-5.70699-1.303273-21.929374-16.036202-31.762101-24.965172-28.626747-25.994343-64.252121-58.353778-106.767516-58.757172-0.312889-0.005172-0.627071-0.005172-0.939959-0.005171-29.62101 0-54.798222 13.434828-72.857859 38.89907-13.222788 18.651798-17.914828 37.388929-18.106182 38.176323a14.31402 14.31402 0 0 0 2.893576 12.515556 14.336 14.336 0 0 0 11.782465 5.095434l0.409858-0.024565c19.192242-1.152 59.141172-3.545212 65.807516 81.857939 4.288646 54.899071 29.742545 108.631919 69.833697 147.419798 45.499475 44.025535 106.237414 67.298263 175.650909 67.298263 98.97503 0 166.222869-24.480323 205.207272-45.015919 43.172202-22.742626 62.621737-45.918384 63.429819-46.898425a14.170505 14.170505 0 0 0 1.529535-15.874586 14.191192 14.191192 0 0 0-14.166626-7.337373c-37.924202 4.443798-92.767677 6.09099-138.666667-11.298909-7.580444-2.872889-13.878303-5.893172-18.959515-8.691071 20.273131-9.964606 51.000889-28.383677 83.621495-59.93503 34.186343-33.065374 37.722505-69.908687 40.838464-102.423273 2.297535-23.919192 4.666182-48.651636 18.500526-73.091879 28.807758-50.883232 66.645333-74.489535 74.560646-79.035475a14.201535 14.201535 0 0 0 12.135434-7.776969 14.193778 14.193778 0 0 0-2.59103-16.484849z\" fill=\"\" p-id=\"1862\"></path><path d=\"M674.834101 716.481939c-33.422222 4.90796-74.989899 16.884364-117.22602-8.102787-34.843152-20.613172-53.056646-20.993293-77.783919-18.49794-0.156444 0.015515-0.312889 0.015515-0.469334 0.034909-0.274101 0.033616-0.548202 0.060768-0.822303 0.094384-4.697212 0.487434-9.65301 1.065374-14.995394 1.62004-6.702545 0.649051-13.414141 1.19596-20.133495 1.634263-75.333818 4.102465-136.860444-5.381172-163.012525-10.404202-49.488162-9.872808-86.57196-23.921778-108.946101-33.970424-59.832889-26.868364-87.080081-56.671677-87.080081-72.989738 0-1.873455 0.384-2.222545 0.787394-2.585858 2.196687-1.974303 10.616242-6.520242 41.302626-6.004364 24.793212 0.418909 56.970343 3.858101 94.308849 7.853253 40.722101 4.348121 86.873212 9.283232 136.348444 11.686788 6.913293 0.333576 13.959758 0.625778 20.93899 0.858505 9.510788 0.307717 17.545051-7.182222 17.868283-16.707233 0.319354-9.535354-7.175758-17.550222-16.705939-17.868282a1386.24 1386.24 0 0 1-20.419233-0.839112c-48.521051-2.358303-94.161455-7.236525-134.434909-11.544565-90.868364-9.712485-139.353212-13.818828-162.333737 6.833131-8.02004 7.21196-12.262141 17.004606-12.262141 28.317737 0 0.672323 0.029737 1.348525 0.065939 2.026021l0.005172 0.100848c-0.045253 0.524929-0.071111 1.039515-0.071111 1.539879 0 41.464242 9.561212 81.661414 28.414707 119.484768 17.493333 35.088808 42.251636 66.663434 73.583192 93.927434 9.169455-6.551273 20.155475-13.604202 32.524929-20.050748 49.737697-25.921939 97.838545-29.339152 139.099798-9.884444 101.590626 47.906909 142.060606 47.837091 206.198949-0.364606 5.70699-4.287354 13.814949-3.140525 18.103596 2.567758 4.289939 5.708283 3.140525 13.813657-2.567757 18.103595-38.425859 28.877576-69.968162 41.279354-105.143596 41.280647-0.484848 0-0.969697-0.002586-1.457132-0.007758-32.760242-0.316768-69.311354-11.381657-126.16404-38.190545-51.905939-24.47903-106.215434 1.008485-139.548444 23.465374 64.611556 47.922424 146.341495 74.101657 232.704 74.101656 117.55701 0 226.204444-48.934788 292.761858-131.362909l0.002586-0.002586c18.79402-14.959192 12.028121-41.362101-23.442101-36.152889z\" fill=\"\" p-id=\"1863\"></path></svg>", "pagesize": "8", "slogan": "A Message Way Hosted Site", "title": "Message Nest" }),
|
DEFALUT_SITE_CONFIG: JSON.stringify({ "logo": "<svg t=\"1702547210136\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"1861\" width=\"200\" height=\"200\"><path d=\"M970.091313 224.033616a14.201535 14.201535 0 0 0-14.100687-3.631838c-88.419556-13.429657-142.919111-12.953859-248.242424 23.762747-69.454869 24.217859-109.056 79.873293-135.267556 116.712728-6.692202 9.403475-18.949172 26.625293-23.77309 29.509818-5.70699-1.303273-21.929374-16.036202-31.762101-24.965172-28.626747-25.994343-64.252121-58.353778-106.767516-58.757172-0.312889-0.005172-0.627071-0.005172-0.939959-0.005171-29.62101 0-54.798222 13.434828-72.857859 38.89907-13.222788 18.651798-17.914828 37.388929-18.106182 38.176323a14.31402 14.31402 0 0 0 2.893576 12.515556 14.336 14.336 0 0 0 11.782465 5.095434l0.409858-0.024565c19.192242-1.152 59.141172-3.545212 65.807516 81.857939 4.288646 54.899071 29.742545 108.631919 69.833697 147.419798 45.499475 44.025535 106.237414 67.298263 175.650909 67.298263 98.97503 0 166.222869-24.480323 205.207272-45.015919 43.172202-22.742626 62.621737-45.918384 63.429819-46.898425a14.170505 14.170505 0 0 0 1.529535-15.874586 14.191192 14.191192 0 0 0-14.166626-7.337373c-37.924202 4.443798-92.767677 6.09099-138.666667-11.298909-7.580444-2.872889-13.878303-5.893172-18.959515-8.691071 20.273131-9.964606 51.000889-28.383677 83.621495-59.93503 34.186343-33.065374 37.722505-69.908687 40.838464-102.423273 2.297535-23.919192 4.666182-48.651636 18.500526-73.091879 28.807758-50.883232 66.645333-74.489535 74.560646-79.035475a14.201535 14.201535 0 0 0 12.135434-7.776969 14.193778 14.193778 0 0 0-2.59103-16.484849z\" fill=\"\" p-id=\"1862\"></path><path d=\"M674.834101 716.481939c-33.422222 4.90796-74.989899 16.884364-117.22602-8.102787-34.843152-20.613172-53.056646-20.993293-77.783919-18.49794-0.156444 0.015515-0.312889 0.015515-0.469334 0.034909-0.274101 0.033616-0.548202 0.060768-0.822303 0.094384-4.697212 0.487434-9.65301 1.065374-14.995394 1.62004-6.702545 0.649051-13.414141 1.19596-20.133495 1.634263-75.333818 4.102465-136.860444-5.381172-163.012525-10.404202-49.488162-9.872808-86.57196-23.921778-108.946101-33.970424-59.832889-26.868364-87.080081-56.671677-87.080081-72.989738 0-1.873455 0.384-2.222545 0.787394-2.585858 2.196687-1.974303 10.616242-6.520242 41.302626-6.004364 24.793212 0.418909 56.970343 3.858101 94.308849 7.853253 40.722101 4.348121 86.873212 9.283232 136.348444 11.686788 6.913293 0.333576 13.959758 0.625778 20.93899 0.858505 9.510788 0.307717 17.545051-7.182222 17.868283-16.707233 0.319354-9.535354-7.175758-17.550222-16.705939-17.868282a1386.24 1386.24 0 0 1-20.419233-0.839112c-48.521051-2.358303-94.161455-7.236525-134.434909-11.544565-90.868364-9.712485-139.353212-13.818828-162.333737 6.833131-8.02004 7.21196-12.262141 17.004606-12.262141 28.317737 0 0.672323 0.029737 1.348525 0.065939 2.026021l0.005172 0.100848c-0.045253 0.524929-0.071111 1.039515-0.071111 1.539879 0 41.464242 9.561212 81.661414 28.414707 119.484768 17.493333 35.088808 42.251636 66.663434 73.583192 93.927434 9.169455-6.551273 20.155475-13.604202 32.524929-20.050748 49.737697-25.921939 97.838545-29.339152 139.099798-9.884444 101.590626 47.906909 142.060606 47.837091 206.198949-0.364606 5.70699-4.287354 13.814949-3.140525 18.103596 2.567758 4.289939 5.708283 3.140525 13.813657-2.567757 18.103595-38.425859 28.877576-69.968162 41.279354-105.143596 41.280647-0.484848 0-0.969697-0.002586-1.457132-0.007758-32.760242-0.316768-69.311354-11.381657-126.16404-38.190545-51.905939-24.47903-106.215434 1.008485-139.548444 23.465374 64.611556 47.922424 146.341495 74.101657 232.704 74.101656 117.55701 0 226.204444-48.934788 292.761858-131.362909l0.002586-0.002586c18.79402-14.959192 12.028121-41.362101-23.442101-36.152889z\" fill=\"\" p-id=\"1863\"></path></svg>", "pagesize": "8", "slogan": "A Message Way Hosted Site", "title": "Message Nest" }),
|
||||||
LOG_TASK_ID: "T-IM1GBswSRY",
|
LOG_TASK_ID: "T-IM1GBswSRY",
|
||||||
|
HOSTED_MSG_TASK_ID: "T-HM2KCxwTZQ",
|
||||||
STORE_TOKEN_NAME: '__message_nest_token__',
|
STORE_TOKEN_NAME: '__message_nest_token__',
|
||||||
STORE_CUSTOM_NAME: '__message_nest_custom_site__',
|
STORE_CUSTOM_NAME: '__message_nest_custom_site__',
|
||||||
NO_AUTH_URL: [
|
NO_AUTH_URL: [
|
||||||
|
|||||||
Reference in New Issue
Block a user