From 071f882ab261619edf5ccc993f42cbc55e63e12d Mon Sep 17 00:00:00 2001 From: duorameng <2997944583@qq.com> Date: Sun, 21 Jun 2026 11:52:44 +0800 Subject: [PATCH] fix(notify): optimize log truncation by rune instead of byte #133 --- internal/services/notification_service.go | 14 ++++++++++---- internal/utils/encoding.go | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/internal/services/notification_service.go b/internal/services/notification_service.go index 4fd6307..abad8dc 100644 --- a/internal/services/notification_service.go +++ b/internal/services/notification_service.go @@ -431,8 +431,9 @@ func (s *NotificationService) handleEvent(bindingType string) eventbus.Handler { if output, ok := payload["output"].(string); ok { // 如果输出包含了压缩后的 Base64 (以 "base64:" 开头),由于是推送到通知,我们尽量不发大段 Base64 // 这里简单处理:如果过长则截断,或者如果是压缩的则记录一下 - if len(output) > 1000 { - payload["output"] = output[len(output)-1000:] + "\n...(截断)" + trimmed := utils.TrimLastRunes(output, 1000) + if len(trimmed) < len(output) { + payload["output"] = trimmed + "\n...(截断)" } } @@ -500,9 +501,14 @@ func (s *NotificationService) handleEvent(bindingType string) eventbus.Handler { if output, ok := payload["output"].(string); ok && output != "" { // 仅保留指定字数的日志内容并移除 ANSI 颜色代码 logSnippet := stripAnsi(output) - if len(logSnippet) > extra.LogLimit { - logSnippet = "...\n" + logSnippet[len(logSnippet)-extra.LogLimit:] + + trimmed := utils.TrimLastRunes(logSnippet, extra.LogLimit) + if len(trimmed) < len(logSnippet) { + logSnippet = "...\n" + trimmed + } else { + logSnippet = trimmed } + currentText += "\n\n[执行日志]\n" + logSnippet } } diff --git a/internal/utils/encoding.go b/internal/utils/encoding.go index 52ee024..4aa9b5d 100644 --- a/internal/utils/encoding.go +++ b/internal/utils/encoding.go @@ -41,3 +41,22 @@ func (r *byteReader) Read(p []byte) (n int, err error) { r.pos += n return n, nil } + +// TrimLastRunes 从字符串尾部保留最多 maxRunes 个字符(不仅限于 ASCII,支持中英文混排的真实字符数量) +func TrimLastRunes(s string, maxRunes int) string { + // 如果字符串的总字节数小于等于 maxRunes,那么它的字符数一定也小于等于 maxRunes + if len(s) <= maxRunes { + return s + } + + count := 0 + for i := len(s); i > 0; { + _, size := utf8.DecodeLastRuneInString(s[:i]) + i -= size + count++ + if count == maxRunes { + return s[i:] + } + } + return s +}