feat(collect): show skipped reason summaries

This commit is contained in:
chengma
2026-07-13 14:31:58 +08:00
parent a7ac8522bf
commit 0a3a6b99a1
7 changed files with 239 additions and 15 deletions
+17 -5
View File
@@ -2,7 +2,11 @@
from __future__ import annotations
from .. import diagnostics
from ..collect_skip import skipped_stage_text
from .widgets import *
class TaskTableModel(QAbstractTableModel):
"""Table model for task rows shared by workflow tabs."""
@@ -88,11 +92,15 @@ class TaskTableModel(QAbstractTableModel):
if role == Qt.ForegroundRole and index.column() == 3:
return self._stage_color(task)
if role == Qt.ToolTipRole:
if self.is_unmatched(task):
return "别名未匹配账号,采集时将略过"
error = getattr(task, "last_error", "") or ""
if self.is_unmatched(task) or getattr(task, "status", "") == "skipped":
if error:
return diagnostics.redact_log_text(str(error))
if self.is_unmatched(task):
return "别名未匹配账号,采集时将略过"
return "未记录具体略过原因"
if error:
return str(error)
return diagnostics.redact_log_text(str(error))
return None
def flags(self, index):
@@ -124,8 +132,12 @@ class TaskTableModel(QAbstractTableModel):
return bool(error) and any(marker.lower() in error for marker in self.PRODUCT_UNAVAILABLE_MARKERS)
def _stage_text(self, task) -> str:
if self.is_unmatched(task):
return "略过"
unmatched = self.is_unmatched(task)
if unmatched or getattr(task, "status", "") == "skipped":
return skipped_stage_text(
getattr(task, "last_error", ""),
alias_matched=not unmatched,
)
if self._is_product_unavailable(task):
return "商品失效"
if task.status in self.STATUS_TEXT and task.status != "pending":
+22 -3
View File
@@ -2,6 +2,12 @@
from __future__ import annotations
from ...collect_skip import (
ALIAS_UNMATCHED,
LOGIN_REQUIRED,
format_skip_reason_summary,
normalize_skip_reason_counts,
)
from ..models import TaskTableModel
from ..widgets import *
from ..workers import CollectWorker as _RealCollectWorker, WriteBackWorker as _RealWriteBackWorker
@@ -694,9 +700,19 @@ class CollectTab(QWidget):
launched = payload.get("launched_accounts") or []
reused = payload.get("reused_accounts") or []
login_required = payload.get("login_required_accounts") or []
if not launched and not reused and not login_required:
skipped = max(0, int(payload.get("skipped", 0) or 0))
skip_counts = normalize_skip_reason_counts(
payload.get("skip_reason_counts"),
skipped_total=skipped,
)
if not launched and not reused and not login_required and skipped == 0:
return
lines = [message]
skip_summary = format_skip_reason_summary(skip_counts, skipped_total=skipped)
if skip_summary:
lines.append(skip_summary)
if skip_counts[ALIAS_UNMATCHED] > 0:
lines.append("请检查 Excel 别名是否与④账号管理中的账号别名一致。")
if launched:
lines.append(
"本轮已自动启动账号 Chrome:"
@@ -707,9 +723,12 @@ class CollectTab(QWidget):
"以下账号需要补登录:"
+ "、".join(self._account_label(item) for item in login_required)
)
lines.append("采集结束后不会自动关闭账号 Chrome,请按需自行关闭。")
if skip_counts[LOGIN_REQUIRED] > 0:
lines.append("请到④账号管理完成对应账号登录后,再重新采集略过任务。")
if launched or reused or login_required:
lines.append("采集结束后不会自动关闭账号 Chrome,请按需自行关闭。")
text = "\n".join(lines)
if login_required:
if login_required or skip_counts[LOGIN_REQUIRED] > 0:
QMessageBox.warning(self, "采集完成", text)
else:
QMessageBox.information(self, "采集完成", text)
+10 -1
View File
@@ -8,6 +8,7 @@ import threading
import time
from .. import image_studio, image_studio_export, image_studio_generation, image_studio_images
from ..collect_skip import ALIAS_UNMATCHED, LOGIN_REQUIRED, empty_skip_reason_counts
from .widgets import *
@@ -1623,6 +1624,7 @@ class CollectWorker(BaseWorker):
login_skip_reasons = {}
login_required_accounts = {}
preflight_info = {}
skip_reason_counts = empty_skip_reason_counts()
self._run_id = self._create_run_log(eligible, batch_ids)
self._log_run_event(
@@ -1642,7 +1644,10 @@ class CollectWorker(BaseWorker):
failed=failed,
batch_ids=batch_ids,
blocked=True,
extra=blocked,
extra={
**blocked,
"skip_reason_counts": dict(skip_reason_counts),
},
)
self._finish_run_log("blocked", summary)
return summary
@@ -1665,6 +1670,7 @@ class CollectWorker(BaseWorker):
account = account_by_alias.get(str(task.alias).strip())
if account is None:
skipped += 1
skip_reason_counts[ALIAS_UNMATCHED] += 1
done += 1
reason = "别名未匹配账号"
db.mark_skipped(task.id, reason, path=self.db_path)
@@ -1684,6 +1690,7 @@ class CollectWorker(BaseWorker):
alias = str(task.alias).strip()
if alias in login_skip_reasons:
skipped += 1
skip_reason_counts[LOGIN_REQUIRED] += 1
done += 1
reason = login_skip_reasons[alias]
db.mark_skipped(task.id, reason, path=self.db_path)
@@ -1704,6 +1711,7 @@ class CollectWorker(BaseWorker):
if self._is_definitive_logged_out(status):
alias = str(task.alias).strip()
skipped += 1
skip_reason_counts[LOGIN_REQUIRED] += 1
done += 1
reason = self._midrun_login_skip_reason(status)
login_skip_reasons[alias] = reason
@@ -1840,6 +1848,7 @@ class CollectWorker(BaseWorker):
extra={
**preflight_info,
"login_required_accounts": list(login_required_accounts.values()),
"skip_reason_counts": dict(skip_reason_counts),
},
)
self._finish_run_log("cancelled" if self.should_cancel() else "done", summary)