diff --git a/api/timer/trigger.go b/api/timer/trigger.go index b7f984f..9f648b6 100644 --- a/api/timer/trigger.go +++ b/api/timer/trigger.go @@ -57,11 +57,14 @@ func HandleTriggerTimer(c *gin.Context) { defer cancel() // 并发执行所有规则,收集失败信息 + // + // fails 必须初始化为空切片:nil 切片会被序列化成 JSON null, + // 前端读 failed.length 时会抛异常,把全部成功误报成触发失败。 var ( - wg sync.WaitGroup - mu sync.Mutex - fails []string + wg sync.WaitGroup + mu sync.Mutex ) + fails := []string{} for i := range rules { rule := rules[i] wg.Add(1) diff --git a/handler/logstore/logstore.go b/handler/logstore/logstore.go index 654b049..66cba78 100644 --- a/handler/logstore/logstore.go +++ b/handler/logstore/logstore.go @@ -42,18 +42,23 @@ func trim(uid uint) { return } - var cutoff model.ExecutionLog - err = gormDB.Where("uid = ?", uid). + // 用 Find 而不是 First:日志没超出保留条数是常态, + // First 找不到记录会返回 ErrRecordNotFound,每写一条日志都刷一行 gorm 警告。 + var cutoff []model.ExecutionLog + if err := gormDB.Where("uid = ?", uid). Order("id DESC"). Offset(config.LogRetainCount). Limit(1). - First(&cutoff).Error - if err != nil { + Find(&cutoff).Error; err != nil { + log.Printf("清理执行日志失败: %v", err) + return + } + if len(cutoff) == 0 { // 没有超出保留条数 return } - if err := gormDB.Where("uid = ? AND id <= ?", uid, cutoff.ID). + if err := gormDB.Where("uid = ? AND id <= ?", uid, cutoff[0].ID). Delete(&model.ExecutionLog{}).Error; err != nil { log.Printf("清理执行日志失败: %v", err) } diff --git a/web/dist/.gitkeep b/web/dist/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/web/frontend/src/views/TimersView.vue b/web/frontend/src/views/TimersView.vue index 6e43ece..682eb42 100644 --- a/web/frontend/src/views/TimersView.vue +++ b/web/frontend/src/views/TimersView.vue @@ -147,12 +147,11 @@ async function trigger(timer: Timer) { triggeringId.value = timer.id try { const result = await timerApi.trigger(timer.id) - if (result.failed.length === 0) { + const failed = result.failed ?? [] + if (failed.length === 0) { ElMessage.success(`已执行 ${result.total} 条规则,全部成功`) } else { - ElMessage.warning( - `已执行 ${result.total} 条规则,${result.failed.length} 条失败,详情见执行日志`, - ) + ElMessage.warning(`已执行 ${result.total} 条规则,${failed.length} 条失败,详情见执行日志`) } } catch (error) { ElMessage.error(error instanceof ApiError ? error.message : '触发失败')