| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- import type { FlowLedgerRow, ScoreItem, VideoRef } from "./types";
- import { asRecord, SOURCE_TYPE_LABELS, textList } from "./format";
- export type BusinessTone = "neutral" | "good" | "warn" | "bad" | "info";
- export type BusinessSection = {
- label: string;
- value?: string;
- tone?: BusinessTone;
- items?: string[];
- };
- const UNKNOWN = "系统原因待补充";
- const ACTION_LABELS: Record<string, string> = {
- ADD_TO_CONTENT_POOL: "入池",
- KEEP_CONTENT_FOR_REVIEW: "待复看",
- REJECT_CONTENT: "淘汰",
- TECHNICAL_RETRY_REQUIRED: "技术问题",
- NOT_JUDGED: "未进入判断",
- 未判断: "未进入判断"
- };
- const REASON_LABELS: Record<string, string> = {
- no_decision: "暂未产生判断结果",
- 无原因: "暂未产生判断原因"
- };
- const SOURCE_LABELS: Record<string, string> = {
- ...SOURCE_TYPE_LABELS,
- pattern_itemset: "来自需求 Pattern",
- pattern_search_query: "来自需求 Pattern",
- pattern_seed_ref: "来自需求 Pattern",
- demand_pattern: "来自需求 Pattern",
- source_seed: "来自需求种子",
- search_query_direct: "直接搜索",
- 来源待确认: "来源待确认"
- };
- const METHOD_LABELS: Record<string, string> = {
- ...SOURCE_TYPE_LABELS,
- query_next_page: "翻页继续找",
- tag_query: "从视频标签继续游走",
- author_works: "从作者继续游走",
- item_single: "使用原始需求词",
- manual: "人工指定搜索词",
- unknown: "生成方式待确认"
- };
- const EFFECT_LABELS: Record<string, string> = {
- success: "已找到可用结果",
- rule_blocked: "找到结果,但未通过内容判断",
- pending: "等待处理",
- failed: "搜索失败",
- skipped: "已跳过"
- };
- const WALK_EDGE_LABELS: Record<string, string> = {
- query_next_page: "翻下一页找更多",
- path_stop: "到这里停止",
- decision_to_asset: "入池沉淀",
- budget_downgrade: "转入待复看",
- tag_query: "从视频标签继续游走",
- hashtag_to_query: "从视频标签继续游走",
- author_works: "从作者继续游走",
- author_to_works: "从作者继续游走",
- terminal: "到这里停止"
- };
- export const WALK_LANE_KEYS = [
- "query_next_page",
- "tag_query",
- "author_works",
- "path_stop"
- ];
- const WALK_STATUS_LABELS: Record<string, string> = {
- success: "已执行",
- skipped: "未继续",
- failed: "执行失败",
- pending: "等待处理"
- };
- const PLATFORM_LABELS: Record<string, string> = {
- douyin: "抖音",
- tiktok: "TikTok",
- bilibili: "B 站",
- kuaishou: "快手",
- shipinhao: "视频号",
- xhs: "小红书"
- };
- export function actionLabel(value: string): string {
- return ACTION_LABELS[value] || "未进入判断";
- }
- export function actionTone(value: string): BusinessTone {
- if (value === "ADD_TO_CONTENT_POOL") return "good";
- if (value === "KEEP_CONTENT_FOR_REVIEW") return "warn";
- if (value === "REJECT_CONTENT") return "bad";
- return "neutral";
- }
- export function reasonLabel(value: string): string {
- return REASON_LABELS[value] || UNKNOWN;
- }
- export function sourceLabel(value: string): string {
- return SOURCE_LABELS[value] || SOURCE_LABELS.来源待确认;
- }
- export function methodLabel(value: string): string {
- return METHOD_LABELS[value] || METHOD_LABELS.unknown;
- }
- export function effectLabel(value: string): string {
- return EFFECT_LABELS[value] || "处理状态待确认";
- }
- export function walkEdgeLabel(value: string): string {
- return WALK_EDGE_LABELS[value] || UNKNOWN;
- }
- export function walkStatusLabel(value: string): string {
- return WALK_STATUS_LABELS[value] || "状态待确认";
- }
- export function scoreBusinessText(value?: string): string | undefined {
- if (!value || value === "无分数") return undefined;
- return `总分 ${value}`;
- }
- export function platformLabel(value?: string | null): string {
- if (!value) return "平台待确认";
- return PLATFORM_LABELS[value.toLowerCase()] || value;
- }
- export function mediaStatusLabel(value?: string | null): string {
- const labels: Record<string, string> = {
- oss_uploaded: "已保存",
- oss_upload_pending: "待补传",
- oss_upload_failed: "补传失败",
- metadata_only: "尚未拿到视频",
- unavailable: "无可用视频"
- };
- return value ? labels[value] || "视频状态待确认" : "视频状态待确认";
- }
- export function scoreItemsText(items: ScoreItem[]): string {
- const visible = items.filter((item) => item.scoreLabel && item.scoreLabel !== "暂无评分");
- if (!visible.length) return "暂无评分";
- return visible.slice(0, 3).map((item) => `${displayScoreLabel(item.label)} ${item.scoreLabel}`).join(" · ");
- }
- export function compactScoreItemsList(items: ScoreItem[]): string[] {
- // 总分 + 各加权维度(group=main:相关性/平台/抖音的适老性),不再截断到 3 项。
- const wanted = items.filter(
- (item) =>
- item.scoreLabel &&
- item.scoreLabel !== "暂无评分" &&
- (displayScoreLabel(item.label) === "总分" || item.group === "main")
- );
- return wanted.map((item) => `${compactScoreLabel(item.label)} ${item.scoreLabel.replace(/\s*分$/, "")}`);
- }
- export function compactScoreItemsText(items: ScoreItem[]): string {
- const list = compactScoreItemsList(items);
- return list.length ? list.join(" · ") : "暂无评分";
- }
- export function scoreItemRows(items: ScoreItem[]): ScoreItem[] {
- return items.filter((item) => item.scoreLabel && item.scoreLabel !== "暂无评分");
- }
- export function displayScoreLabel(label: string): string {
- if (label === "total_score") return "总分";
- if (label === "query_relevance_score") return "是否契合需求";
- if (label === "platform_performance_score") return "平台表现";
- return label;
- }
- function compactScoreLabel(label: string): string {
- const displayLabel = displayScoreLabel(label);
- if (displayLabel === "是否契合需求") return "query相关性";
- if (displayLabel === "平台表现") return "平台数据表现";
- if (displayLabel === "50+老年受众") return "适老性";
- return displayLabel;
- }
- export function metricLabel(video: VideoRef): string {
- const digg = video.statistics.digg_count || video.statistics.like_count || 0;
- const comment = video.statistics.comment_count || 0;
- const share = video.statistics.share_count || 0;
- return `点赞 ${digg} · 评论 ${comment} · 转发 ${share}`;
- }
- export function sourceEvidence(row: FlowLedgerRow): string {
- if (row.source.details.length) return row.source.details.join(" · ");
- if (row.source.terms.length) return `依据:${row.source.terms.join(" / ")}`;
- if (row.source.evidenceLabel && row.source.evidenceLabel !== "来源证据待确认") return row.source.evidenceLabel;
- return "来源证据待确认";
- }
- export function ruleHeadline(row: FlowLedgerRow): string {
- const total = row.ruleSummary.total;
- if (!total) return "首轮内容暂未进入判断";
- if (row.ruleSummary.passCount) return `有 ${row.ruleSummary.passCount} 条内容可进入沉淀`;
- if (row.ruleSummary.reviewCount) return `有 ${row.ruleSummary.reviewCount} 条内容需要人工复看`;
- if (row.ruleSummary.technicalRetryCount) return `有 ${row.ruleSummary.technicalRetryCount} 条内容出现技术问题`;
- return "本轮没有可沉淀内容";
- }
- export function walkSummaryText(row: FlowLedgerRow): string {
- if (!row.walkSummary.total) return "本轮没有继续扩展";
- const stop = Object.entries(row.walkSummary.stopReasons).sort((a, b) => b[1] - a[1])[0]?.[0];
- if (stop) return `${row.walkSummary.total} 次扩展动作,主要因为“${reasonLabel(stop)}”停止`;
- return `${row.walkSummary.total} 次扩展动作`;
- }
- export function assetSummaryText(row: FlowLedgerRow): string {
- const pool = row.finalAssets.assetCount || 0;
- const review = row.finalAssets.reviewCount || 0;
- const technical = row.finalAssets.technicalRetryCount || 0;
- const reject = row.finalAssets.rejectCount || 0;
- const parts = [];
- if (pool) parts.push(`入池 ${pool} 条`);
- if (review) parts.push(`待复看 ${review} 条`);
- if (technical) parts.push(`技术问题 ${technical} 条`);
- if (parts.length) return parts.join(",");
- if (reject) return `没有入池,淘汰 ${reject} 条`;
- return "暂无可沉淀内容";
- }
- export function assetDetailText(row: FlowLedgerRow): string {
- const pool = row.finalAssets.assetCount || 0;
- const review = row.finalAssets.reviewCount || 0;
- const technical = row.finalAssets.technicalRetryCount || 0;
- const reject = row.finalAssets.rejectCount || 0;
- if (pool && review) return "入池内容可后续使用,待复看需要人工确认";
- if (pool) return "已进入后续内容池";
- if (review) return "需人工确认后,再决定是否进入后续使用";
- if (technical) return "视频下载、压缩或模型判断失败,需要系统重试";
- if (reject) return "本轮内容已淘汰,没有进入后续使用";
- return "这轮没有内容进入后续使用";
- }
- export function clueText(row: FlowLedgerRow): string {
- const clue = asRecord(row.query.clue);
- const queries = textList(clue.generated_queries);
- if (queries.length) return `系统还尝试了 ${queries.length} 个相近搜索词`;
- return "";
- }
|