diff --git a/scripts/generate_daily_report.go b/scripts/generate_daily_report.go index bb27c3e..fe7659a 100644 --- a/scripts/generate_daily_report.go +++ b/scripts/generate_daily_report.go @@ -1482,13 +1482,14 @@ func headlineItemFromModelEvent(event ModelEvent) HeadlineItem { switch event.EventType { case "official_release": - item.Label = "官方发布" + item.Label = "一级官方发布" item.Title = fmt.Sprintf("%s 官方发布", event.ModelName) - if event.SourceKindLabel == "权威佐证发布" { - item.Label = "权威佐证" + item.Tone = "official-primary" + if event.SourceKindLabel == "二级权威佐证发布" { + item.Label = "二级权威佐证" item.Title = fmt.Sprintf("%s 进入权威佐证发布时间线", event.ModelName) + item.Tone = "secondary-evidence" } - item.Tone = "info" case "new_model": item.Label = "新模型" item.Title = fmt.Sprintf("%s 进入今日情报池", event.ModelName) @@ -1547,15 +1548,15 @@ func buildPriceEvidenceDetail(changePct, oldPrice, newPrice float64, currency st func buildReleaseSourceKindLabel(dateSourceKind, dateConfidence string) string { switch { case dateSourceKind == "secondary_authoritative_report" || dateConfidence == "secondary_authoritative": - return "权威佐证发布" + return "二级权威佐证发布" case dateSourceKind == "official_announcement" && dateConfidence == "official_primary": - return "官方发布" + return "一级官方发布" case dateSourceKind == "official_product_page": return "官方产品页" case dateSourceKind == "catalog_backfill": return "目录回填" default: - return "官方发布" + return "一级官方发布" } } @@ -2241,6 +2242,42 @@ body { color: var(--ink-soft); margin-bottom: 8px; } +.headline-badge { + display: inline-flex; + align-items: center; + padding: 6px 10px; + border-radius: 999px; + font-weight: 800; + letter-spacing: 0.01em; +} +.badge-official-primary { + background: rgba(18,60,99,0.12); + color: var(--blue); +} +.badge-secondary-evidence { + background: rgba(173,107,17,0.14); + color: var(--amber); +} +.badge-info { + background: rgba(18,60,99,0.10); + color: var(--blue); +} +.badge-success { + background: rgba(31,122,76,0.12); + color: var(--green); +} +.badge-warning { + background: rgba(173,107,17,0.12); + color: var(--amber); +} +.badge-caution { + background: rgba(165,59,42,0.12); + color: var(--red); +} +.badge-neutral { + background: rgba(81,101,121,0.12); + color: var(--ink-soft); +} .card-title { font-size: 1.18rem; font-weight: 800; @@ -2388,6 +2425,14 @@ th { .tone-info { border-color: rgba(18,60,99,0.18); } .tone-caution { border-color: rgba(165,59,42,0.18); } .tone-neutral { border-color: rgba(81,101,121,0.16); } +.tone-official-primary { + border-color: rgba(18,60,99,0.26); + background: linear-gradient(180deg, rgba(18,60,99,0.05), rgba(255,255,255,0.94)); +} +.tone-secondary-evidence { + border-color: rgba(173,107,17,0.24); + background: linear-gradient(180deg, rgba(173,107,17,0.06), rgba(255,255,255,0.94)); +} .footer { text-align: center; } @@ -2455,7 +2500,7 @@ th {
{{range .HeadlineItems}}
-
{{.Label}}
+
{{.Label}}
{{.Title}}
{{.Summary}}
{{if .SourceKindLabel}}
事件来源:{{.SourceKindLabel}}
{{end}} diff --git a/scripts/generate_daily_report_test.go b/scripts/generate_daily_report_test.go index 061c481..f61fd4c 100644 --- a/scripts/generate_daily_report_test.go +++ b/scripts/generate_daily_report_test.go @@ -183,6 +183,34 @@ func TestBuildFreeSourceBreakdown(t *testing.T) { func TestDecorateReportV1BuildsHotDaySummary(t *testing.T) { report := sampleReportForV1() report.ModelEvents = []ModelEvent{ + { + EventType: "official_release", + ModelName: "GLM-5", + ProviderName: "Zhipu", + OperatorName: "Zhipu", + TrustLabel: "官方来源 / 一级证据", + Baseline: "官方首次发布", + Summary: "官方发布新模型,值得优先复查中文通用与推理场景默认选择。", + SourceKindLabel: "一级官方发布", + PrimarySource: "https://open.bigmodel.cn/dev/howuse/model", + UpdatedAt: "2026-05-13 08:30", + EvidenceDetail: "models.release_date = 今日,且 source_url 指向官方文档", + Priority: 120, + }, + { + EventType: "official_release", + ModelName: "Doubao Seed 1.8", + ProviderName: "ByteDance", + OperatorName: "ByteDance Volcano", + TrustLabel: "官方来源 / 二级佐证", + Baseline: "官方首次发布", + Summary: "次级权威报道已形成稳定发布日期信号,适合进入观察池但不应与一级公告混同。", + SourceKindLabel: "二级权威佐证发布", + PrimarySource: "https://developer.volcengine.com/articles/7601918680544641034", + UpdatedAt: "2025-12-18 00:00", + EvidenceDetail: "models.release_date = 今日,发布日期采用次级权威报道佐证,模型来源页保留官方文档", + Priority: 110, + }, { EventType: "new_model", ModelName: "DeepSeek-V4-Flash", @@ -219,8 +247,8 @@ func TestDecorateReportV1BuildsHotDaySummary(t *testing.T) { if report.PageMode != "hot" { t.Fatalf("expected hot page mode, got %q", report.PageMode) } - if !strings.Contains(report.HeroSummary, "2 个新模型") { - t.Fatalf("hero summary missing new model signal: %s", report.HeroSummary) + if !strings.Contains(report.HeroSummary, "GLM-5 已出现官方发布信号") { + t.Fatalf("hero summary missing official release signal: %s", report.HeroSummary) } if len(report.ActionItems) != 3 { t.Fatalf("expected 3 action items, got %d", len(report.ActionItems)) @@ -231,8 +259,8 @@ func TestDecorateReportV1BuildsHotDaySummary(t *testing.T) { if report.ActionItems[0].Evidence == "" { t.Fatalf("expected action item evidence to be populated") } - if !strings.Contains(report.HeadlineItems[0].Title, "DeepSeek-V4-Flash") { - t.Fatalf("expected first headline to come from model events, got %+v", report.HeadlineItems[0]) + if !strings.Contains(report.HeadlineItems[0].Title, "GLM-5") { + t.Fatalf("expected first headline to prioritize official release, got %+v", report.HeadlineItems[0]) } } @@ -286,6 +314,34 @@ func TestGenerateMarkdownV3IncludesTencentSubscriptionSection(t *testing.T) { }, } report.ModelEvents = []ModelEvent{ + { + EventType: "official_release", + ModelName: "GLM-5", + ProviderName: "Zhipu", + OperatorName: "Zhipu", + TrustLabel: "官方来源 / 一级证据", + Baseline: "官方首次发布", + Summary: "官方发布新模型,值得优先复查中文通用与推理场景默认选择。", + SourceKindLabel: "一级官方发布", + PrimarySource: "https://open.bigmodel.cn/dev/howuse/model", + UpdatedAt: "2026-05-13 08:30", + EvidenceDetail: "models.release_date = 今日,且 source_url 指向官方文档", + Priority: 120, + }, + { + EventType: "official_release", + ModelName: "Doubao Seed 1.8", + ProviderName: "ByteDance", + OperatorName: "ByteDance Volcano", + TrustLabel: "官方来源 / 二级佐证", + Baseline: "官方首次发布", + Summary: "次级权威报道已形成稳定发布日期信号,适合进入观察池但不应与一级公告混同。", + SourceKindLabel: "二级权威佐证发布", + PrimarySource: "https://developer.volcengine.com/articles/7601918680544641034", + UpdatedAt: "2025-12-18 00:00", + EvidenceDetail: "models.release_date = 今日,发布日期采用次级权威报道佐证,模型来源页保留官方文档", + Priority: 110, + }, { EventType: "new_model", ModelName: "DeepSeek-V4-Flash", @@ -339,6 +395,34 @@ func TestGenerateHTMLV3IncludesTencentSubscriptionSection(t *testing.T) { path := filepath.Join(t.TempDir(), "daily_report.html") report := sampleReportForV1() report.ModelEvents = []ModelEvent{ + { + EventType: "official_release", + ModelName: "GLM-5", + ProviderName: "Zhipu", + OperatorName: "Zhipu", + TrustLabel: "官方来源 / 一级证据", + Baseline: "官方首次发布", + Summary: "官方发布新模型,值得优先复查中文通用与推理场景默认选择。", + SourceKindLabel: "一级官方发布", + PrimarySource: "https://open.bigmodel.cn/dev/howuse/model", + UpdatedAt: "2026-05-13 08:30", + EvidenceDetail: "models.release_date = 今日,且 source_url 指向官方文档", + Priority: 120, + }, + { + EventType: "official_release", + ModelName: "Doubao Seed 1.8", + ProviderName: "ByteDance", + OperatorName: "ByteDance Volcano", + TrustLabel: "官方来源 / 二级佐证", + Baseline: "官方首次发布", + Summary: "次级权威报道已形成稳定发布日期信号,适合进入观察池但不应与一级公告混同。", + SourceKindLabel: "二级权威佐证发布", + PrimarySource: "https://developer.volcengine.com/articles/7601918680544641034", + UpdatedAt: "2025-12-18 00:00", + EvidenceDetail: "models.release_date = 今日,发布日期采用次级权威报道佐证,模型来源页保留官方文档", + Priority: 110, + }, { EventType: "new_model", ModelName: "DeepSeek-V4-Flash", @@ -384,6 +468,8 @@ func TestGenerateHTMLV3IncludesTencentSubscriptionSection(t *testing.T) { "三条行动建议", "今日头条", "DeepSeek-V4-Flash", + "一级官方发布", + "二级权威佐证", "首次出现", "主来源", "更新时间", @@ -413,7 +499,7 @@ func TestBuildHeadlineItemsUsesModelEvents(t *testing.T) { TrustLabel: "官方来源", Baseline: "官方首次发布", Summary: "官方发布新模型,值得优先复查中文通用与推理场景默认选择。", - SourceKindLabel: "官方发布", + SourceKindLabel: "一级官方发布", PrimarySource: "https://open.bigmodel.cn/dev/howuse/model", UpdatedAt: "2026-05-13 08:30", EvidenceDetail: "models.release_date = 今日,且 source_url 指向官方文档", @@ -455,13 +541,13 @@ func TestBuildHeadlineItemsUsesModelEvents(t *testing.T) { if len(items) < 2 { t.Fatalf("expected at least 2 headline items, got %d", len(items)) } - if !strings.Contains(items[0].Title, "GLM-5") || items[0].Label != "官方发布" { + if !strings.Contains(items[0].Title, "GLM-5") || items[0].Label != "一级官方发布" { t.Fatalf("expected official release event to rank first, got %+v", items[0]) } if items[1].Baseline != "较昨日 -25%" { t.Fatalf("expected price_cut baseline to be preserved, got %+v", items[1]) } - if items[0].SourceKindLabel != "官方发布" || items[0].PrimarySource != "https://open.bigmodel.cn/dev/howuse/model" { + if items[0].SourceKindLabel != "一级官方发布" || items[0].PrimarySource != "https://open.bigmodel.cn/dev/howuse/model" { t.Fatalf("expected official release evidence fields to be preserved, got %+v", items[0]) } } @@ -556,24 +642,27 @@ func TestHeadlineItemFromOfficialReleaseEvent(t *testing.T) { TrustLabel: "官方来源", Baseline: "官方首次发布", Summary: "官方发布新模型。", - SourceKindLabel: "官方发布", + SourceKindLabel: "一级官方发布", PrimarySource: "https://docs.anthropic.com/en/release-notes/api", UpdatedAt: "2026-05-13 07:00", EvidenceDetail: "models.release_date = 今日,且 source_url 指向官方发布页", }) - if item.Label != "官方发布" { - t.Fatalf("expected label to be 官方发布, got %+v", item) + if item.Label != "一级官方发布" { + t.Fatalf("expected label to be 一级官方发布, got %+v", item) } if !strings.Contains(item.Title, "官方发布") { t.Fatalf("expected title to mention 官方发布, got %+v", item) } - if item.SourceKindLabel != "官方发布" { - t.Fatalf("expected source kind label to be 官方发布, got %+v", item) + if item.SourceKindLabel != "一级官方发布" { + t.Fatalf("expected source kind label to be 一级官方发布, got %+v", item) } if item.PrimarySource != "https://docs.anthropic.com/en/release-notes/api" { t.Fatalf("expected primary source to be preserved, got %+v", item) } + if item.Tone != "official-primary" { + t.Fatalf("expected tone to be official-primary, got %+v", item) + } } func TestHeadlineItemFromSecondaryReleaseEvent(t *testing.T) { @@ -583,16 +672,19 @@ func TestHeadlineItemFromSecondaryReleaseEvent(t *testing.T) { TrustLabel: "官方来源 / 二级佐证", Baseline: "官方首次发布", Summary: "模型进入正式发布日期观察池。", - SourceKindLabel: "权威佐证发布", + SourceKindLabel: "二级权威佐证发布", PrimarySource: "https://developer.volcengine.com/articles/7601918680544641034", UpdatedAt: "2025-12-18 00:00", EvidenceDetail: "models.release_date = 今日,发布日期采用次级权威报道佐证,模型来源页保留官方文档", }) - if item.Label != "权威佐证" { - t.Fatalf("expected label to be 权威佐证, got %+v", item) + if item.Label != "二级权威佐证" { + t.Fatalf("expected label to be 二级权威佐证, got %+v", item) } if !strings.Contains(item.Title, "权威佐证发布时间线") { t.Fatalf("expected title to mention 权威佐证发布时间线, got %+v", item) } + if item.Tone != "secondary-evidence" { + t.Fatalf("expected tone to be secondary-evidence, got %+v", item) + } }