diff --git a/internal/adapter/dingtalk.go b/internal/adapter/dingtalk.go index 7e5a467..426e827 100644 --- a/internal/adapter/dingtalk.go +++ b/internal/adapter/dingtalk.go @@ -69,7 +69,7 @@ func (s *DingTalkSender) Send(title, content string, config json.RawMessage) err msg := dingtalkMessage{ MsgType: "markdown", Markdown: &dingtalkMD{ - Title: title, + Title: dingtalkTitle(title, content), Text: dingtalkMarkdownText(content), }, } @@ -87,6 +87,23 @@ func (s *DingTalkSender) Send(title, content string, config json.RawMessage) err return nil } +// dingtalkTitle is the markdown.Title shown on DingTalk PC as the card header +// and in the session-list preview. Prefer the first content line (e.g. 空单开仓) +// over the internal "source: event" title. +func dingtalkTitle(fallback, content string) string { + content = strings.ReplaceAll(content, "\r\n", "\n") + content = strings.ReplaceAll(content, "\r", "\n") + line, _, _ := strings.Cut(content, "\n") + line = strings.TrimSpace(line) + if line != "" { + return line + } + if strings.TrimSpace(fallback) != "" { + return fallback + } + return "通知" +} + // 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. diff --git a/internal/adapter/dingtalk_test.go b/internal/adapter/dingtalk_test.go index bb00def..fe10830 100644 --- a/internal/adapter/dingtalk_test.go +++ b/internal/adapter/dingtalk_test.go @@ -2,6 +2,20 @@ package adapter import "testing" +func TestDingTalkTitleUsesFirstContentLine(t *testing.T) { + got := dingtalkTitle("trade-signal: trade", "空单开仓\n交易品种: ETHUSDT") + if got != "空单开仓" { + t.Fatalf("got %q", got) + } +} + +func TestDingTalkTitleFallsBackWhenContentEmpty(t *testing.T) { + got := dingtalkTitle("trade-signal: trade", " \n") + if got != "trade-signal: trade" { + t.Fatalf("got %q", got) + } +} + func TestDingTalkMarkdownTextDoublesNewlines(t *testing.T) { in := "空单开仓\n交易品种: ETHUSDT\n开仓价格: 2542.33\n\n推送时间: 2026.08.27 16:30:12" got := dingtalkMarkdownText(in) @@ -40,4 +54,4 @@ func TestDingtalkConfigWebhookURL(t *testing.T) { } }) } -} \ No newline at end of file +}