From 53b7cd6b372e7d91f04bce0c038a45f423e6d086 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 26 Aug 2026 15:23:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E7=B2=BE=E7=AE=80?= =?UTF-8?q?=E7=89=87=E6=AE=B5=E5=AE=A1=E6=A0=B8=E7=B4=AF=E8=AE=A1=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DEVELOPMENT_LOG.md | 9 +++ NEXT_STEPS.md | 7 +++ app/services/task_query_service.py | 56 +++++++++--------- app/static/css/styles.css | 4 ++ app/templates/clips_overview.html | 6 +- docs/UI_REFERENCE.md | 7 +++ .../2026-08-26-clip-review-summary.md | 57 +++++++++++++++++++ tests/test_task_query_service.py | 51 ++++++++++++++--- 8 files changed, 158 insertions(+), 39 deletions(-) create mode 100644 docs/agent_tasks/2026-08-26-clip-review-summary.md diff --git a/DEVELOPMENT_LOG.md b/DEVELOPMENT_LOG.md index e0375c9..fbbe5dc 100644 --- a/DEVELOPMENT_LOG.md +++ b/DEVELOPMENT_LOG.md @@ -1,5 +1,14 @@ # Development Log +## 2026-08-26 片段审核累计统计精简 + +- `/clips` 顶部统计从“待 AI 分析、待检查、可生成切片、已完成、异常任务”五项过程指标,精简为“累计审核任务、已通过视频、已完成任务”三项累计结果。 +- “累计审核任务”按当前未删除任务中已有未删除候选片段的任务数计算,表示已经进入候选片段审核流程;不把自动流程写入的 `reviewed` 字段误称为纯人工审核。 +- “已通过视频”按当前未删除任务下启用且未删除的候选片段数计算,卡片说明明确为“当前启用的视频片段”。 +- “已完成任务”兼容 `completed`、`completed_with_errors` 和历史大写 `COMPLETED`,并排除已删除任务;审核队列的状态徽标使用同一套规范化口径,不再把历史大写完成状态误显示为“待检查”。 +- 三项统计使用独立三列布局,不改变字幕工作台继续复用的五列统计样式;窄屏仍按现有响应式规则切换为单列。 +- 当前活动库按新口径显示 `20 / 163 / 20`;定向统计与性能回归 `35 passed`、完整回归 `793 passed`,Python Compileall、Ruff 和 `git diff --check` 均通过,未触发真实 AI、切片或平台发布。 + ## 2026-08-26 任务详情实时进度与日志统一 - `/api/tasks/{task_id}/live-status` 扩展为任务详情唯一实时快照:同一次响应返回主任务状态、活动 Workflow Job、转写细分进度、最新运行日志、候选/输出数量和发布任务汇总。 diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index 0c4191d..6e997ed 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -1,5 +1,12 @@ # Next Steps +## 2026-08-26 片段审核累计统计检查 + +1. 打开 `http://127.0.0.1:8001/clips`,顶部应只显示“累计审核任务、已通过视频、已完成任务”三张卡片,不再出现待 AI、待检查、可生成切片和异常任务统计。 +2. 当前活动库预期显示累计审核任务 `20`、已通过视频 `163`、已完成任务 `20`;以后新增、启用、停用或删除任务/候选片段后,数值会按当前未删除数据重新计算。 +3. “已通过视频”指当前处于启用状态的视频片段,可能来自人工审核或全自动选片,不应理解为全部都经过人工逐条点击确认。 +4. 本轮只调整查询统计与展示,不需要运行 AI、重新切片或点击发送中心,也不会触发抖音/B站投稿。 + ## 2026-08-26 任务详情实时进度检查 1. 打开 `http://127.0.0.1:8001/tasks/3210d91ee1fb`,状态概览应显示“托管发布中 · 9/12”,并分别显示总流程 `97%`、当前操作“托管发布” `75%`;实际数值会随后续排期发送继续变化。 diff --git a/app/services/task_query_service.py b/app/services/task_query_service.py index 322aff3..a3f2a2a 100644 --- a/app/services/task_query_service.py +++ b/app/services/task_query_service.py @@ -320,19 +320,20 @@ def get_clips_overview_context() -> dict: enabled_count = counts["enabled"] review_ready = clip_count > 0 can_cut = enabled_count > 0 and task["source_exists"] - if task["status"] == TaskStatus.failed.value: + normalized_status = str(task.get("status") or "").lower() + if normalized_status == TaskStatus.failed.value: review_stage = "异常" review_tone = "red" - elif task["status"] == TaskStatus.completed.value: + elif normalized_status == TaskStatus.completed.value: review_stage = "已完成" review_tone = "green" - elif task["status"] == TaskStatus.completed_with_errors.value: + elif normalized_status == TaskStatus.completed_with_errors.value: review_stage = "部分完成" review_tone = "amber" - elif task["status"] == TaskStatus.pending_review.value or review_ready: + elif normalized_status == TaskStatus.pending_review.value or review_ready: review_stage = "待检查" review_tone = "purple" - elif task["status"] in {TaskStatus.pending_ai.value, TaskStatus.ai_analyzing.value}: + elif normalized_status in {TaskStatus.pending_ai.value, TaskStatus.ai_analyzing.value}: review_stage = "待 AI" review_tone = "blue" else: @@ -351,42 +352,39 @@ def get_clips_overview_context() -> dict: } ) + completed_statuses = { + TaskStatus.completed.value, + TaskStatus.completed_with_errors.value, + } + reviewed_task_count = sum(1 for task in enriched_tasks if task["real_clip_count"] > 0) + passed_clip_count = sum(task["enabled_clip_count"] for task in enriched_tasks) + completed_task_count = sum( + 1 + for task in tasks + if str(task.get("status") or "").lower() in completed_statuses + ) + return { "tasks": enriched_tasks, "stats": [ { - "label": "待 AI 分析", - "value": sum( - 1 - for task in tasks - if task["status"] in {TaskStatus.pending_ai.value, TaskStatus.ai_analyzing.value} - ), + "label": "累计审核任务", + "value": reviewed_task_count, + "note": "已进入候选片段审核流程", "tone": "blue", }, { - "label": "待检查", - "value": sum(1 for task in enriched_tasks if task["review_stage"] == "待检查"), - "tone": "purple", - }, - { - "label": "可生成切片", - "value": sum(1 for task in enriched_tasks if task["can_cut"]), + "label": "已通过视频", + "value": passed_clip_count, + "note": "当前启用的视频片段", "tone": "green", }, { - "label": "已完成", - "value": sum( - 1 - for task in tasks - if task["status"] in {TaskStatus.completed.value, TaskStatus.completed_with_errors.value} - ), + "label": "已完成任务", + "value": completed_task_count, + "note": "含手动与全自动完成状态", "tone": "green", }, - { - "label": "异常任务", - "value": sum(1 for task in tasks if task["status"] == TaskStatus.failed.value), - "tone": "red", - }, ], } diff --git a/app/static/css/styles.css b/app/static/css/styles.css index d2b68fe..6174240 100644 --- a/app/static/css/styles.css +++ b/app/static/css/styles.css @@ -1809,6 +1809,10 @@ button:disabled { grid-template-columns: repeat(5, minmax(150px, 1fr)); } +.clip-review-stat-grid { + grid-template-columns: repeat(3, minmax(180px, 1fr)); +} + .review-board { display: grid; gap: 12px; diff --git a/app/templates/clips_overview.html b/app/templates/clips_overview.html index f00539e..03a4d80 100644 --- a/app/templates/clips_overview.html +++ b/app/templates/clips_overview.html @@ -6,18 +6,18 @@

Clip Review

片段审核工作台

-

按工作流查看每个任务是否已经进入 AI 分析、人工审核、切片生成或异常排查阶段。

+

集中查看累计审核任务、通过视频和已完成任务,并继续进入单任务审核。

新建任务 -
+
{% for item in stats %}
{{ item.label }} {{ item.value }} - 来自当前任务库 + {{ item.note }}
{% endfor %}
diff --git a/docs/UI_REFERENCE.md b/docs/UI_REFERENCE.md index ea822b4..e6eef52 100644 --- a/docs/UI_REFERENCE.md +++ b/docs/UI_REFERENCE.md @@ -1,5 +1,12 @@ # UI 参考说明 +## 2026-08-26 更新:片段审核累计统计 + +- 片段审核工作台顶部只保留三项结果指标:“累计审核任务、已通过视频、已完成任务”,移除待 AI、待检查、可生成切片和异常任务等过程型统计。 +- “累计审核任务”表示当前任务库中已经生成候选片段并进入审核流程的未删除任务;“已通过视频”表示这些任务下当前启用且未删除的视频片段;“已完成任务”兼容手动、全自动和部分完成状态,任务行徽标也按同一大小写规范化口径显示。 +- 每张卡片显示自己的业务说明,不再统一写“来自当前任务库”,避免把自动启用片段误解为全部人工确认。 +- 桌面端三张卡片等宽排列;1180px 及以下沿用现有单列响应式规则。该布局使用片段审核专属类,不影响字幕工作台的统计卡片。 + ## 2026-08-26 更新:任务详情实时进度同步 - 状态概览新增“总流程进度”和“当前操作”两层信息:总进度保留全流程位置,当前操作显示转写、AI、切片或托管发布的独立百分比和最新说明。 diff --git a/docs/agent_tasks/2026-08-26-clip-review-summary.md b/docs/agent_tasks/2026-08-26-clip-review-summary.md new file mode 100644 index 0000000..4fff001 --- /dev/null +++ b/docs/agent_tasks/2026-08-26-clip-review-summary.md @@ -0,0 +1,57 @@ +# 片段审核累计统计精简 + +## 背景 + +`/clips` 顶部当前显示“待 AI 分析、待检查、可生成切片、已完成、异常任务”五项阶段统计。用户希望只保留累计审核任务、已通过视频和已完成任务三个长期有用的汇总指标。 + +## 目标 + +- 将顶部统计精简为三项:累计审核任务、已通过视频、已完成任务。 +- 每项使用明确、可验证且排除软删除数据的 SQLite 口径。 +- 保持审核队列、单任务指标和操作入口不变。 + +## 允许修改范围 + +- `app/services/task_query_service.py` +- `app/templates/clips_overview.html` +- `app/static/css/styles.css` +- `tests/test_task_query_service.py` +- `tests/test_p1_1_db_performance.py`(仅相关回归需要时) +- `DEVELOPMENT_LOG.md`、`NEXT_STEPS.md`、`docs/UI_REFERENCE.md` + +## 禁止修改范围 + +- 任务、候选片段、切片和发布状态机。 +- SQLite Schema、迁移和真实数据。 +- AI Provider、Prompt、账号、Cookie、Token、`.env` 和认证配置。 +- 真实 AI、切片、字幕或平台发布流程。 + +## 已确定实现要求 + +- “累计审核任务”统计当前未删除任务中至少有一条未删除候选片段的去重任务数;当前数据库没有可靠的任务级人工审核事件,不能把 `reviewed=1` 冒充纯人工审核。 +- “已通过视频”统计上述未删除任务中 `is_deleted=0 AND enabled=1` 的候选片段总数,页面说明为“当前启用的视频片段”。 +- “已完成任务”兼容 `completed / completed_with_errors / COMPLETED`,统一大小写后统计当前未删除任务。 +- 三张卡分别提供自己的统计说明,不再统一显示“来自当前任务库”。 +- 统计网格由五列改为三列;现有响应式折叠逻辑继续保留。 + +## 验收标准 + +- `/clips` 顶部只显示“累计审核任务、已通过视频、已完成任务”。 +- 当前活动库预期显示 `20 / 163 / 20`;数值随数据变化时以同一口径实时渲染。 +- 软删除任务和软删除候选片段不计入累计审核与通过数。 +- 大写自动完成状态 `COMPLETED` 不再被漏算。 +- 审核队列结构、任务行指标、详情和进入审核按钮保持不变。 +- 桌面与 390px 窄屏无横向溢出。 + +## 测试命令 + +- `.venv\Scripts\python.exe -m pytest tests/test_task_query_service.py tests/test_p1_1_db_performance.py -q` +- `.venv\Scripts\python.exe -m pytest -q` +- `.venv\Scripts\python.exe -m compileall -q app tests` +- `.venv\Scripts\python.exe -m ruff check app/services/task_query_service.py tests/test_task_query_service.py` +- `git diff --check` +- 浏览器刷新 `http://127.0.0.1:8001/clips`,核对三项指标、审核队列、窄屏布局和页面错误。 + +## 返回格式 + +报告统计口径、修改文件、测试与浏览器证据、分支、提交、推送和 PR;不得把本地统计验证描述为真实 AI、切片或平台发布验证。 diff --git a/tests/test_task_query_service.py b/tests/test_task_query_service.py index f96fc08..2228c69 100644 --- a/tests/test_task_query_service.py +++ b/tests/test_task_query_service.py @@ -399,8 +399,9 @@ def test_empty_clips_overview_fields_complete(self): assert context["tasks"] == [] stat_labels = {s["label"] for s in context["stats"]} - expected_labels = {"待 AI 分析", "待检查", "可生成切片", "已完成", "异常任务"} + expected_labels = {"累计审核任务", "已通过视频", "已完成任务"} assert stat_labels == expected_labels + assert all(stat["value"] == 0 for stat in context["stats"]) def test_clips_overview_with_tasks_and_clips(self): """有任务和候选片段时统计字段正确""" @@ -433,6 +434,12 @@ def test_clips_overview_with_tasks_and_clips(self): assert task["review_ready"] is True assert task["can_cut"] is False # source_exists 为 False + stat_map = {stat["label"]: stat for stat in context["stats"]} + assert stat_map["累计审核任务"]["value"] == 1 + assert stat_map["已通过视频"]["value"] == 2 + assert stat_map["已通过视频"]["note"] == "当前启用的视频片段" + assert stat_map["已完成任务"]["value"] == 0 + def test_clips_overview_with_deleted_clips(self): """已删除的候选片段不计入统计""" task_id = uuid4().hex[:12] @@ -449,20 +456,50 @@ def test_clips_overview_with_deleted_clips(self): assert task["enabled_clip_count"] == 1 def test_clips_overview_stats_correct(self): - """统计卡片数值正确""" + """累计审核、启用片段和完成任务统计正确,且排除已删除数据""" task_id_1 = uuid4().hex[:12] task_id_2 = uuid4().hex[:12] + task_id_3 = uuid4().hex[:12] + task_id_4 = uuid4().hex[:12] today = datetime.now(timezone.utc).isoformat(timespec="seconds") - _insert_test_task(task_id_1, "待AI", status="pending_ai", created_at=today) - _insert_test_task(task_id_2, "失败", status="failed", created_at=today) + _insert_test_task(task_id_1, "待检查", status="pending_review", created_at=today) + _insert_test_task(task_id_2, "大写完成", status="COMPLETED", created_at=today) + _insert_test_task( + task_id_3, + "部分完成", + status="completed_with_errors", + created_at=today, + ) + _insert_test_task( + task_id_4, + "已删除任务", + status="completed", + is_deleted=1, + created_at=today, + ) + _insert_test_clip_candidate("clip_stats_1", task_id_1, "启用片段", enabled=1) + _insert_test_clip_candidate("clip_stats_2", task_id_1, "未启用片段", enabled=0) + _insert_test_clip_candidate("clip_stats_3", task_id_2, "完成片段", enabled=1) + _insert_test_clip_candidate("clip_stats_4", task_id_4, "已删除任务片段", enabled=1) + _insert_test_clip_candidate( + "clip_stats_5", + task_id_1, + "已删除片段", + enabled=1, + is_deleted=1, + ) context = get_clips_overview_context() stat_map = {s["label"]: s["value"] for s in context["stats"]} + task_map = {task["id"]: task for task in context["tasks"]} - assert stat_map["待 AI 分析"] == 1 - assert stat_map["待检查"] == 0 - assert stat_map["异常任务"] == 1 + assert stat_map == { + "累计审核任务": 2, + "已通过视频": 2, + "已完成任务": 2, + } + assert task_map[task_id_2]["review_stage"] == "已完成" # ── Subtitle Workflow Context ──────────────────────────────────────