Преглед изворни кода

增加寻找视频可视化

xueyiming пре 1 дан
родитељ
комит
28d5c88d14

+ 10 - 0
api/services/video_discovery_records.py

@@ -67,6 +67,13 @@ def _serialize_search_candidate(row: VideoDiscoveryCandidate) -> dict[str, Any]:
         "decision_bucket": row.decision_bucket,
         "play_count": int(row.play_count) if row.play_count is not None else None,
         "like_count": int(row.like_count) if row.like_count is not None else None,
+        "comment_count": (
+            int(row.comment_count) if row.comment_count is not None else None
+        ),
+        "collect_count": (
+            int(row.collect_count) if row.collect_count is not None else None
+        ),
+        "share_count": int(row.share_count) if row.share_count is not None else None,
         "relevance_score": _number(row.relevance_score),
         "elder_score": _number(row.elder_score),
         "share_score": _number(row.share_score),
@@ -309,6 +316,9 @@ def list_video_discovery_searches(
                         VideoDiscoveryCandidate.decision_bucket,
                         VideoDiscoveryCandidate.play_count,
                         VideoDiscoveryCandidate.like_count,
+                        VideoDiscoveryCandidate.comment_count,
+                        VideoDiscoveryCandidate.collect_count,
+                        VideoDiscoveryCandidate.share_count,
                         VideoDiscoveryCandidate.relevance_score,
                         VideoDiscoveryCandidate.elder_score,
                         VideoDiscoveryCandidate.share_score,

+ 3 - 1
prd/09-找视频记录展示设计.md

@@ -57,7 +57,8 @@
 - 创建时间。
 
 展开后优先以卡片展示该搜索记录直接关联的候选视频,包括标题、作者、分池、播放量、
-点赞量和价值评分;同时展示搜索键、完整检索参数、供应方分页状态和错误信息。
+点赞、评论、收藏、转发和价值评分;同时展示搜索键、完整检索参数、供应方分页状态和
+错误信息。标题、作者和互动数据被截断时,鼠标悬浮展示完整内容。
 
 ### 3.4 候选视频
 
@@ -74,6 +75,7 @@
 AIGC 计划明细。
 
 候选支持按分池以及视频 ID、标题、作者筛选。
+候选列表中的标题、作者和互动数据同样提供完整悬浮提示。
 
 页面正文、表格、筛选控件和状态标签使用不小于 11px 的字号,主要操作与正文使用
 12px~14px,避免审计信息过小影响阅读。

+ 3 - 0
tests/api/test_video_discovery_records.py

@@ -172,6 +172,9 @@ def test_lists_searches_and_candidates_with_filters(monkeypatch) -> None:
         "aweme-2",
     ]
     assert searches["items"][0]["candidates"][0]["title"] == "教爸妈设置大字体"
+    assert searches["items"][0]["candidates"][0]["comment_count"] is None
+    assert searches["items"][0]["candidates"][0]["collect_count"] is None
+    assert searches["items"][0]["candidates"][0]["share_count"] is None
 
     candidates = records_service.list_video_discovery_candidates(
         "find-001",

+ 3 - 0
web/src/types/videoDiscoveryRecords.ts

@@ -58,6 +58,9 @@ export interface VideoDiscoverySearchCandidate {
   decision_bucket: string
   play_count: number | null
   like_count: number | null
+  comment_count: number | null
+  collect_count: number | null
+  share_count: number | null
   relevance_score: number | null
   elder_score: number | null
   share_score: number | null

+ 42 - 8
web/src/views/FindAgentRecordsView.vue

@@ -262,6 +262,20 @@ function formatScore(value: number | null): string {
   return value.toFixed(value > 1 ? 2 : 3)
 }
 
+function engagementText(video: {
+  like_count: number | null
+  comment_count: number | null
+  collect_count: number | null
+  share_count: number | null
+}): string {
+  return [
+    `赞 ${formatCount(video.like_count)}`,
+    `评 ${formatCount(video.comment_count)}`,
+    `藏 ${formatCount(video.collect_count)}`,
+    `转 ${formatCount(video.share_count)}`,
+  ].join(' · ')
+}
+
 function formatJson(value: JsonValue): string {
   if (value === null || value === undefined || value === '') return '暂无数据'
   if (typeof value === 'string') return value
@@ -510,14 +524,20 @@ function openCandidate(candidate: VideoDiscoveryCandidateRecord) {
                               <span class="bucket-pill" :class="`bucket-${video.decision_bucket}`">
                                 {{ bucketLabel(video.decision_bucket) }}
                               </span>
-                              <strong>{{ video.title || '未命名视频' }}</strong>
-                              <small>{{ video.author_name || '未知作者' }} · {{ video.aweme_id }}</small>
+                              <strong :title="video.title || '未命名视频'">
+                                {{ video.title || '未命名视频' }}
+                              </strong>
+                              <small :title="`${video.author_name || '未知作者'} · ${video.aweme_id}`">
+                                {{ video.author_name || '未知作者' }} · {{ video.aweme_id }}
+                              </small>
                             </div>
                             <div class="search-video-metrics">
                               <span>{{ formatCount(video.play_count) }} 播放</span>
-                              <span>{{ formatCount(video.like_count) }} 点赞</span>
                               <span>V {{ formatScore(video.value_score) }}</span>
                             </div>
+                            <p class="engagement-line" :title="engagementText(video)">
+                              {{ engagementText(video) }}
+                            </p>
                             <a
                               v-if="video.content_link"
                               :href="video.content_link"
@@ -577,14 +597,17 @@ function openCandidate(candidate: VideoDiscoveryCandidateRecord) {
                       </span>
                     </td>
                     <td class="wide-cell video-cell">
-                      <strong>{{ item.title || '未命名视频' }}</strong>
-                      <small>{{ item.author_name || '未知作者' }} · {{ item.aweme_id }}</small>
+                      <strong :title="item.title || '未命名视频'">
+                        {{ item.title || '未命名视频' }}
+                      </strong>
+                      <small :title="`${item.author_name || '未知作者'} · ${item.aweme_id}`">
+                        {{ item.author_name || '未知作者' }} · {{ item.aweme_id }}
+                      </small>
                     </td>
                     <td>
                       <strong>{{ formatCount(item.play_count) }} 播放</strong>
-                      <small>
-                        赞 {{ formatCount(item.like_count) }} · 评 {{ formatCount(item.comment_count) }}
-                        · 藏 {{ formatCount(item.collect_count) }} · 转 {{ formatCount(item.share_count) }}
+                      <small :title="engagementText(item)">
+                        {{ engagementText(item) }}
                       </small>
                     </td>
                     <td>
@@ -1206,6 +1229,17 @@ td small {
   text-align: right;
   white-space: nowrap;
 }
+.search-video-grid .engagement-line {
+  grid-column: 1 / -1;
+  margin: 0;
+  overflow: hidden;
+  color: #626a7a;
+  font-size: 12px;
+  line-height: 1.5;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  cursor: help;
+}
 .search-video-grid article a {
   width: fit-content;
   color: #5b5dc7;