format.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import type { RawRecord } from "@/lib/api/types";
  2. export function asRecord(value: unknown): RawRecord {
  3. return value && typeof value === "object" && !Array.isArray(value) ? (value as RawRecord) : {};
  4. }
  5. export function asArray(value: unknown): unknown[] {
  6. return Array.isArray(value) ? value : [];
  7. }
  8. export function text(value: unknown, fallback = "未记录"): string {
  9. if (typeof value === "string" && value.trim()) return value;
  10. if (typeof value === "number" || typeof value === "boolean") return String(value);
  11. return fallback;
  12. }
  13. export function maybeText(value: unknown): string | undefined {
  14. if (typeof value === "string" && value.trim()) return value;
  15. if (typeof value === "number" || typeof value === "boolean") return String(value);
  16. return undefined;
  17. }
  18. export function textList(value: unknown): string[] {
  19. if (!Array.isArray(value)) return [];
  20. return value.map((item) => text(item, "")).filter(Boolean);
  21. }
  22. export function countBy<T>(items: T[], getKey: (item: T) => string | undefined): Record<string, number> {
  23. return items.reduce<Record<string, number>>((acc, item) => {
  24. const key = getKey(item);
  25. if (!key) return acc;
  26. acc[key] = (acc[key] || 0) + 1;
  27. return acc;
  28. }, {});
  29. }
  30. export function compactCountMap(counts: Record<string, number>, limit = 3): string {
  31. const entries = Object.entries(counts).sort((a, b) => b[1] - a[1]);
  32. if (!entries.length) return "无";
  33. return entries.slice(0, limit).map(([key, value]) => `${label(key)} ${value}`).join(" · ");
  34. }
  35. export function label(value: string): string {
  36. const labels: Record<string, string> = {
  37. seed_term: "从需求单的 pattern 词来",
  38. piaoquan_topic_point: "票圈帖子具体的点",
  39. query_seed_point: "票圈帖子具体的点",
  40. category_leaf_element: "分类叶子元素",
  41. item_single: "使用原始需求词",
  42. tag_query: "从视频标签继续游走",
  43. author_works: "从作者继续游走",
  44. query_next_page: "翻页",
  45. search_query_direct: "首轮搜索",
  46. pattern_itemset: "来自需求 Pattern",
  47. pattern_search_query: "来自需求 Pattern",
  48. ADD_TO_CONTENT_POOL: "入池",
  49. KEEP_CONTENT_FOR_REVIEW: "待复看",
  50. REJECT_CONTENT: "淘汰",
  51. success: "成功",
  52. skipped: "跳过",
  53. failed: "失败",
  54. rule_blocked: "规则阻断",
  55. pending: "待处理"
  56. };
  57. return labels[value] || "系统原因待补充";
  58. }
  59. export function scoreLabel(value: unknown): string {
  60. if (typeof value === "number" && Number.isFinite(value)) return `${Math.round(value)}`;
  61. if (typeof value === "string" && value.trim()) return value;
  62. return "未进入打分";
  63. }
  64. export function shortId(value: unknown): string {
  65. const raw = text(value, "");
  66. if (raw.length <= 18) return raw || "未记录";
  67. return `${raw.slice(0, 8)}...${raw.slice(-6)}`;
  68. }