Просмотр исходного кода

Merge ledger source and query columns

Sam Lee 3 недель назад
Родитель
Сommit
5bda1f476d
2 измененных файлов с 71 добавлено и 99 удалено
  1. 55 67
      web2/app/globals.css
  2. 16 32
      web2/features/LedgerPage.tsx

+ 55 - 67
web2/app/globals.css

@@ -359,11 +359,6 @@ a:focus-visible {
   background: var(--source) !important;
   background: var(--source) !important;
 }
 }
 
 
-.group-query,
-.sub-query {
-  background: var(--query) !important;
-}
-
 .group-videos,
 .group-videos,
 .group-rules,
 .group-rules,
 .sub-videos,
 .sub-videos,
@@ -382,10 +377,6 @@ a:focus-visible {
   background: var(--source-sub) !important;
   background: var(--source-sub) !important;
 }
 }
 
 
-.sub-query {
-  background: var(--query-sub) !important;
-}
-
 .sub-videos,
 .sub-videos,
 .sub-rules {
 .sub-rules {
   background: var(--impl-sub) !important;
   background: var(--impl-sub) !important;
@@ -396,8 +387,7 @@ a:focus-visible {
   background: var(--output-sub) !important;
   background: var(--output-sub) !important;
 }
 }
 
 
-.source-cell,
-.query-cell {
+.source-cell {
   background: #f8fafc;
   background: #f8fafc;
 }
 }
 
 
@@ -414,17 +404,9 @@ a:focus-visible {
 .source-cell,
 .source-cell,
 .sub-source,
 .sub-source,
 .group-source {
 .group-source {
-  width: 278px;
-  min-width: 278px;
-  max-width: 278px;
-}
-
-.query-cell,
-.sub-query,
-.group-query {
-  width: 260px;
-  min-width: 260px;
-  max-width: 260px;
+  width: 360px;
+  min-width: 360px;
+  max-width: 360px;
 }
 }
 
 
 .videos-cell {
 .videos-cell {
@@ -452,30 +434,13 @@ a:focus-visible {
   z-index: 3;
   z-index: 3;
 }
 }
 
 
-.sticky-query {
-  position: sticky !important;
-  left: 278px;
-  z-index: 3;
-}
-
-.ledger-table thead .sticky-source,
-.ledger-table thead .sticky-query {
+.ledger-table thead .sticky-source {
   z-index: 6;
   z-index: 6;
 }
 }
 
 
-.ledger-table.source-hidden .sticky-query {
-  left: 0;
-}
-
-.query-cell,
-.sub-query,
-.group-query {
-  box-shadow: 6px 0 8px -4px rgba(0, 0, 0, 0.18);
-}
-
-.source-hidden .query-cell,
-.source-hidden .sub-query,
-.source-hidden .group-query {
+.source-cell,
+.sub-source,
+.group-source {
   box-shadow: 6px 0 8px -4px rgba(0, 0, 0, 0.18);
   box-shadow: 6px 0 8px -4px rgba(0, 0, 0, 0.18);
 }
 }
 
 
@@ -501,7 +466,46 @@ a:focus-visible {
   gap: 3px;
   gap: 3px;
 }
 }
 
 
-.query-text,
+.source-kind-badge {
+  display: inline-block;
+  width: fit-content;
+  padding: 5px 10px;
+  border: 1px solid transparent;
+  border-radius: 5px;
+  font-size: 14px;
+  font-weight: 800;
+  line-height: 1.2;
+}
+
+.source-kind-badge.seed {
+  color: #172554;
+  border-color: #bfdbfe;
+  background: #dbeafe;
+}
+
+.source-kind-badge.piaoquan {
+  color: #713f12;
+  border-color: #fde68a;
+  background: #fef3c7;
+}
+
+.source-kind-badge.category {
+  color: #064e3b;
+  border-color: #bbf7d0;
+  background: #dcfce7;
+}
+
+.source-kind-badge.unknown {
+  color: #334155;
+  border-color: #cbd5e1;
+  background: #e2e8f0;
+}
+
+.source-query-text {
+  font-size: 14px;
+  line-height: 1.45;
+}
+
 .title-link,
 .title-link,
 .cell-stack strong {
 .cell-stack strong {
   color: #0f172a;
   color: #0f172a;
@@ -1130,35 +1134,19 @@ a:focus-visible {
   .source-cell,
   .source-cell,
   .sub-source,
   .sub-source,
   .group-source {
   .group-source {
-    width: 220px;
-    min-width: 220px;
-    max-width: 220px;
+    width: 260px;
+    min-width: 260px;
+    max-width: 260px;
   }
   }
 
 
-  .query-cell,
-  .sub-query,
-  .group-query {
-    width: 220px;
-    min-width: 220px;
-    max-width: 220px;
-  }
-
-  .sticky-query {
-    left: 220px;
-  }
-
-  .sticky-source,
-  .sticky-query {
+  .sticky-source {
     position: static !important;
     position: static !important;
     left: auto;
     left: auto;
   }
   }
 
 
-  .query-cell,
-  .sub-query,
-  .group-query,
-  .source-hidden .query-cell,
-  .source-hidden .sub-query,
-  .source-hidden .group-query {
+  .source-cell,
+  .sub-source,
+  .group-source {
     box-shadow: none;
     box-shadow: none;
   }
   }
 
 

+ 16 - 32
web2/features/LedgerPage.tsx

@@ -8,8 +8,6 @@ import { EmptyState, ErrorState, LoadingState } from "@/components/StateBlocks";
 import {
 import {
   actionLabel,
   actionLabel,
   assetSummaryText,
   assetSummaryText,
-  clueText,
-  methodLabel,
   platformLabel,
   platformLabel,
   ruleHeadline,
   ruleHeadline,
   scoreItemRows,
   scoreItemRows,
@@ -21,11 +19,10 @@ import {
 import type { FlowLedgerRow, VideoRef } from "@/lib/flow-ledger/types";
 import type { FlowLedgerRow, VideoRef } from "@/lib/flow-ledger/types";
 import { useFlowLedger } from "./useFlowLedger";
 import { useFlowLedger } from "./useFlowLedger";
 
 
-type GroupId = "source" | "query" | "videos" | "rules" | "walk" | "assets";
+type GroupId = "source" | "videos" | "rules" | "walk" | "assets";
 
 
 const GROUPS: Array<{ id: GroupId; label: string; tone: string }> = [
 const GROUPS: Array<{ id: GroupId; label: string; tone: string }> = [
   { id: "source", label: "搜索词来源", tone: "gray" },
   { id: "source", label: "搜索词来源", tone: "gray" },
-  { id: "query", label: "搜索词", tone: "yellow" },
   { id: "videos", label: "首轮搜到的视频", tone: "green" },
   { id: "videos", label: "首轮搜到的视频", tone: "green" },
   { id: "rules", label: "内容判断", tone: "green" },
   { id: "rules", label: "内容判断", tone: "green" },
   { id: "walk", label: "继续扩展", tone: "blue" },
   { id: "walk", label: "继续扩展", tone: "blue" },
@@ -38,8 +35,7 @@ export function LedgerPage({ runId }: { runId: string }) {
 
 
   const rows = ledger?.rows || [];
   const rows = ledger?.rows || [];
   const tableClass = [
   const tableClass = [
-    hidden.has("source") ? "source-hidden" : "",
-    hidden.has("query") ? "query-hidden" : ""
+    hidden.has("source") ? "source-hidden" : ""
   ].filter(Boolean).join(" ");
   ].filter(Boolean).join(" ");
 
 
   function toggle(group: GroupId) {
   function toggle(group: GroupId) {
@@ -85,7 +81,7 @@ export function LedgerPage({ runId }: { runId: string }) {
                 </button>
                 </button>
               </span>
               </span>
             ))}
             ))}
-            <span className="legend-hint">点击组名显示/隐藏 · 左侧列固定 · 评分详情按 V4 分项展示</span>
+            <span className="legend-hint">点击组名显示/隐藏 · 左侧来源列固定 · 评分详情按 V4 分项展示</span>
           </div>
           </div>
 
 
           <section className="table-wrap">
           <section className="table-wrap">
@@ -93,15 +89,13 @@ export function LedgerPage({ runId }: { runId: string }) {
               <thead>
               <thead>
                 <tr>
                 <tr>
                   {!hidden.has("source") ? <th className="group-source sticky-source">搜索词来源</th> : null}
                   {!hidden.has("source") ? <th className="group-source sticky-source">搜索词来源</th> : null}
-                  {!hidden.has("query") ? <th className="group-query sticky-query">搜索词</th> : null}
                   {!hidden.has("videos") ? <th className="group-videos">首轮搜到的视频</th> : null}
                   {!hidden.has("videos") ? <th className="group-videos">首轮搜到的视频</th> : null}
                   {!hidden.has("rules") ? <th className="group-rules" colSpan={2}>内容判断</th> : null}
                   {!hidden.has("rules") ? <th className="group-rules" colSpan={2}>内容判断</th> : null}
                   {!hidden.has("walk") ? <th className="group-walk">继续扩展</th> : null}
                   {!hidden.has("walk") ? <th className="group-walk">继续扩展</th> : null}
                   {!hidden.has("assets") ? <th className="group-assets">最终收获</th> : null}
                   {!hidden.has("assets") ? <th className="group-assets">最终收获</th> : null}
                 </tr>
                 </tr>
                 <tr>
                 <tr>
-                  {!hidden.has("source") ? <th className="sub-source sticky-source">从哪里来</th> : null}
-                  {!hidden.has("query") ? <th className="sub-query sticky-query">搜什么 / 怎么来</th> : null}
+                  {!hidden.has("source") ? <th className="sub-source sticky-source">搜什么 / 从哪里来</th> : null}
                   {!hidden.has("videos") ? <th className="sub-videos">预览 / 统计 / 入口</th> : null}
                   {!hidden.has("videos") ? <th className="sub-videos">预览 / 统计 / 入口</th> : null}
                   {!hidden.has("rules") ? <th className="sub-rules">判断结果</th> : null}
                   {!hidden.has("rules") ? <th className="sub-rules">判断结果</th> : null}
                   {!hidden.has("rules") ? <th className="sub-rules">评分详情</th> : null}
                   {!hidden.has("rules") ? <th className="sub-rules">评分详情</th> : null}
@@ -110,10 +104,9 @@ export function LedgerPage({ runId }: { runId: string }) {
                 </tr>
                 </tr>
               </thead>
               </thead>
               <tbody>
               <tbody>
-                {rows.map((row, index) => (
+                {rows.map((row) => (
                   <tr className="ledger-row" key={row.id}>
                   <tr className="ledger-row" key={row.id}>
-                    {!hidden.has("source") ? <SourceCell row={row} index={index} /> : null}
-                    {!hidden.has("query") ? <QueryCell row={row} /> : null}
+                    {!hidden.has("source") ? <SourceCell row={row} /> : null}
                     {!hidden.has("videos") ? <VideoCell runId={runId} row={row} /> : null}
                     {!hidden.has("videos") ? <VideoCell runId={runId} row={row} /> : null}
                     {!hidden.has("rules") ? <RuleSummaryCell row={row} /> : null}
                     {!hidden.has("rules") ? <RuleSummaryCell row={row} /> : null}
                     {!hidden.has("rules") ? (
                     {!hidden.has("rules") ? (
@@ -134,14 +127,13 @@ export function LedgerPage({ runId }: { runId: string }) {
   );
   );
 }
 }
 
 
-function SourceCell({ row, index }: { row: FlowLedgerRow; index: number }) {
+function SourceCell({ row }: { row: FlowLedgerRow }) {
   const details = row.source.details.length ? row.source.details : [sourceEvidence(row)];
   const details = row.source.details.length ? row.source.details : [sourceEvidence(row)];
   return (
   return (
     <td className="source-cell sticky-source">
     <td className="source-cell sticky-source">
-        <div className="idx">第 {index + 1} 条</div>
       <div className="cell-stack">
       <div className="cell-stack">
-        <span className="chip dark">{sourceLabel(row.source.sourceKind)}</span>
-        <strong>{row.source.evidenceLabel}</strong>
+        <span className={`source-kind-badge ${sourceKindClass(row.source.sourceKind)}`}>{sourceLabel(row.source.sourceKind)}</span>
+        <strong className="source-query-text">{row.query.text}</strong>
         <div className="source-detail-list">
         <div className="source-detail-list">
           {details.map((item) => (
           {details.map((item) => (
             <span className="muted" key={item}>{item}</span>
             <span className="muted" key={item}>{item}</span>
@@ -152,21 +144,6 @@ function SourceCell({ row, index }: { row: FlowLedgerRow; index: number }) {
   );
   );
 }
 }
 
 
-function QueryCell({ row }: { row: FlowLedgerRow }) {
-  const clue = clueText(row);
-  return (
-    <td className="query-cell sticky-query">
-      <div className="cell-stack">
-        <strong className="query-text">{row.query.text}</strong>
-        <div className="chip-row">
-          <span className="chip yellow">{methodLabel(row.query.method)}</span>
-        </div>
-        {clue ? <span className="muted">{clue}</span> : null}
-      </div>
-    </td>
-  );
-}
-
 function VideoCell({ runId, row }: { runId: string; row: FlowLedgerRow }) {
 function VideoCell({ runId, row }: { runId: string; row: FlowLedgerRow }) {
   const top = row.firstRoundVideos.slice(0, 3);
   const top = row.firstRoundVideos.slice(0, 3);
   return (
   return (
@@ -192,6 +169,13 @@ function VideoCell({ runId, row }: { runId: string; row: FlowLedgerRow }) {
   );
   );
 }
 }
 
 
+function sourceKindClass(kind: string): string {
+  if (kind === "seed_term") return "seed";
+  if (kind === "piaoquan_topic_point") return "piaoquan";
+  if (kind === "category_leaf_element") return "category";
+  return "unknown";
+}
+
 function VideoMini({ runId, video }: { runId: string; video: VideoRef }) {
 function VideoMini({ runId, video }: { runId: string; video: VideoRef }) {
   return (
   return (
     <Link className="video-mini" href={`/runs/${encodeURIComponent(runId)}/videos/${encodeURIComponent(video.id)}`}>
     <Link className="video-mini" href={`/runs/${encodeURIComponent(runId)}/videos/${encodeURIComponent(video.id)}`}>