diff --git a/server/internal/service/baike_term_sync.go b/server/internal/service/baike_term_sync.go index ca4070b..2837181 100644 --- a/server/internal/service/baike_term_sync.go +++ b/server/internal/service/baike_term_sync.go @@ -247,7 +247,7 @@ func (s *BaikeTermSyncService) syncOneTerm(name string) error { } extraJSON, _ := json.Marshal(extra) - content := cleanTermHTML(lemma.Abstract) + content := trimTruncatedTail(cleanTermHTML(lemma.Abstract)) brief := extra["meaning"] if brief == "" { brief = firstSentence(content) @@ -365,3 +365,34 @@ func cleanTermHTML(s string) string { s = reTermSpace.ReplaceAllString(s, " ") return strings.TrimSpace(s) } + +// trimTruncatedTail 清理百度百科摘要的截断结尾: +// 摘要以「...」「…」等结尾说明被接口截断,先去掉省略号; +// 若去掉后末句不是完整句(不以 。!? 结尾),回退到最后一个完整句标点,避免半截话 +func trimTruncatedTail(s string) string { + // 去掉结尾的省略号(英文 ... / 中文 … / 多个点) + s = strings.TrimRight(s, ".… ") + if s == "" { + return s + } + // 末字符已是完整句标点则无需回退 + last := []rune(s) + if len(last) == 0 { + return s + } + if strings.ContainsRune("。!?", last[len(last)-1]) { + return s + } + // 回退到最后一个完整句标点(LastIndex 未找到返回 -1,需先判断 j >= 0) + idx := -1 + for _, sep := range []string{"。", "!", "?"} { + if j := strings.LastIndex(s, sep); j >= 0 && j+len(sep) > idx { + idx = j + len(sep) + } + } + if idx > 0 { + return s[:idx] + } + // 没有完整句标点则保留原文(避免清空) + return s +} diff --git a/server/internal/service/baike_term_sync_test.go b/server/internal/service/baike_term_sync_test.go index 4115e9e..6fea34c 100644 --- a/server/internal/service/baike_term_sync_test.go +++ b/server/internal/service/baike_term_sync_test.go @@ -128,3 +128,24 @@ func TestTermSort(t *testing.T) { t.Errorf("termSort(不存在) = %d, want 0", termSort("不存在")) } } + +func TestTrimTruncatedTail(t *testing.T) { + cases := []struct { + name string + in string + want string + }{ + {"完整句号结尾不动", "夏至后人们普遍食用清补凉汤来避暑。", "夏至后人们普遍食用清补凉汤来避暑。"}, + {"英文省略号回退", "表达感谢的心情。唐宋时期,冬至...", "表达感谢的心情。"}, + {"中文省略号回退", "表达感谢的心情。唐宋时期,冬至…", "表达感谢的心情。"}, + {"无句号半截话保留", "可明显感觉到早春的气...", "可明显感觉到早春的气"}, + {"多点省略号", "农事谚语....", "农事谚语"}, + {"结尾空白加省略号", "冬至大如年。 ...", "冬至大如年。"}, + {"空字符串", "", ""}, + } + for _, c := range cases { + if got := trimTruncatedTail(c.in); got != c.want { + t.Errorf("%s: trimTruncatedTail(%q) = %q, want %q", c.name, c.in, got, c.want) + } + } +}