refactor(monitoring): simplify brand dashboard and harden citation rendering

- drop brand_time_buckets and sparkline/coverage UI; dashboard now returns a single day
- compute mention rate from total actual samples instead of averaging per-platform rates
- canonicalize ai_platform_id across services and aggregate platform-overview snapshots
- strip mojibake and non-answer noise from callback payloads and question detail answers
- keep Kimi citations panel-only; still store raw search_results for audit
- render linked [n] inline citations for qwen/yuanbao answers with scroll-to-source behavior
- restrict立即采集 to today's business date with a clear i18n hint
- refresh content-citations into an ant-design table with truncation and hover styling

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 09:11:53 +08:00
parent ce028c56bf
commit 4f4f063200
13 changed files with 1469 additions and 744 deletions
@@ -55,7 +55,7 @@ func (s *MonitoringCallbackService) rebuildBrandDailyProjection(ctx context.Cont
desiredSampleCount := enabledQuestionCount * int64(len(platforms))
coverageRate := divideAsPointer(brandAgg.ActualSampleCount, brandAgg.PlannedSampleCount)
mentionRate := averageMonitoringPlatformMentionRate(platformAggs)
mentionRate := divideAsPointer(brandAgg.MentionedCount, brandAgg.ActualSampleCount)
top1MentionRate := divideAsPointer(brandAgg.Top1MentionedCount, brandAgg.ActualSampleCount)
firstRecommendRate := divideAsPointer(brandAgg.FirstRecommendedCount, brandAgg.ActualSampleCount)
positiveMentionRate := divideAsPointer(brandAgg.PositiveMentionedCount, brandAgg.ActualSampleCount)
@@ -151,7 +151,7 @@ func loadMonitoringProjectionPlatforms(ctx context.Context, businessPool *pgxpoo
if len(enabledJSON) > 0 {
var configured []string
if jsonErr := json.Unmarshal(enabledJSON, &configured); jsonErr == nil && len(configured) > 0 {
enabled = configured
enabled = monitoringPlatformIDs(defaultMonitoringPlatforms)
}
}
@@ -372,29 +372,6 @@ func (s *MonitoringCallbackService) loadMonitoringPlatformDailyAggregates(ctx co
return items, nil
}
func averageMonitoringPlatformMentionRate(items []monitoringPlatformDailyAggregate) *float64 {
if len(items) == 0 {
return nil
}
total := 0.0
count := 0
for _, item := range items {
rate := divideAsPointer(item.MentionedCount, item.ActualSampleCount)
if rate == nil {
continue
}
total += *rate
count++
}
if count == 0 {
return nil
}
average := total / float64(count)
return &average
}
func (s *MonitoringCallbackService) replaceMonitoringPlatformDailyProjection(ctx context.Context, tx pgx.Tx, tenantID, brandID int64, businessDate time.Time, items []monitoringPlatformDailyAggregate) error {
dateText := monitoringBusinessDateText(businessDate)