From 219a850d93374beb77ad85661efe76cbffc07709 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 27 Aug 2026 16:58:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E9=92=89=E9=92=89=E9=80=9A=E7=9F=A5):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Markdown=20=E6=B6=88=E6=81=AF=E6=8D=A2?= =?UTF-8?q?=E8=A1=8C=E8=A2=AB=E6=8A=98=E5=8F=A0=E5=AF=BC=E8=87=B4=E6=8E=92?= =?UTF-8?q?=E7=89=88=E9=94=99=E4=B9=B1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Motivation: 钉钉 Markdown 渲染时会将单个换行符折叠为空格,导致推送的通知内容被压缩成一行,严重影响消息可读性。 Changes: * 发送前将消息正文中的单个换行统一转换为段落分隔(\n\n),确保模板换行在钉钉中正确渲染 * 归一化 \r\n 与 \r 换行,并合并已有连续换行,避免产生多余空行 * 新增换行转换逻辑的单元测试 --- internal/adapter/dingtalk.go | 15 ++++++++++++++- internal/adapter/dingtalk_test.go | 9 +++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/internal/adapter/dingtalk.go b/internal/adapter/dingtalk.go index 5f4cd03..7e5a467 100644 --- a/internal/adapter/dingtalk.go +++ b/internal/adapter/dingtalk.go @@ -10,6 +10,7 @@ import ( "fmt" "net/http" "net/url" + "strings" "time" ) @@ -69,7 +70,7 @@ func (s *DingTalkSender) Send(title, content string, config json.RawMessage) err MsgType: "markdown", Markdown: &dingtalkMD{ Title: title, - Text: content, + Text: dingtalkMarkdownText(content), }, } @@ -86,6 +87,18 @@ func (s *DingTalkSender) Send(title, content string, config json.RawMessage) err return nil } +// dingtalkMarkdownText turns template newlines into DingTalk markdown paragraph +// breaks. A single \n is collapsed to a space by DingTalk markdown, so each +// logical line must be separated by \n\n. +func dingtalkMarkdownText(content string) string { + content = strings.ReplaceAll(content, "\r\n", "\n") + content = strings.ReplaceAll(content, "\r", "\n") + for strings.Contains(content, "\n\n") { + content = strings.ReplaceAll(content, "\n\n", "\n") + } + return strings.ReplaceAll(content, "\n", "\n\n") +} + func dingtalkSign(timestamp int64, secret string) string { mac := hmac.New(sha256.New, []byte(secret)) fmt.Fprintf(mac, "%d\n%s", timestamp, secret) diff --git a/internal/adapter/dingtalk_test.go b/internal/adapter/dingtalk_test.go index 0716e19..bb00def 100644 --- a/internal/adapter/dingtalk_test.go +++ b/internal/adapter/dingtalk_test.go @@ -2,6 +2,15 @@ package adapter import "testing" +func TestDingTalkMarkdownTextDoublesNewlines(t *testing.T) { + in := "空单开仓\n交易品种: ETHUSDT\n开仓价格: 2542.33\n\n推送时间: 2026.08.27 16:30:12" + got := dingtalkMarkdownText(in) + want := "空单开仓\n\n交易品种: ETHUSDT\n\n开仓价格: 2542.33\n\n推送时间: 2026.08.27 16:30:12" + if got != want { + t.Fatalf("got %q\nwant %q", got, want) + } +} + func TestDingtalkConfigWebhookURL(t *testing.T) { tests := []struct { name string