feat: add first-run empty state guidance
This commit is contained in:
+141
-1
@@ -165,6 +165,35 @@ if QT_IMPORT_ERROR is None:
|
||||
return QIcon(pixmap)
|
||||
|
||||
|
||||
def _build_empty_state_card(object_name, button_text="前往账号管理"):
|
||||
card = QWidget()
|
||||
card.setObjectName(object_name)
|
||||
card.setStyleSheet(
|
||||
f"QWidget#{object_name} {{ "
|
||||
"background: #f6f8fa; border: 1px solid #d0d7de; "
|
||||
"border-radius: 6px; padding: 10px; "
|
||||
"}"
|
||||
)
|
||||
layout = QHBoxLayout(card)
|
||||
layout.setContentsMargins(12, 10, 12, 10)
|
||||
label = QLabel("")
|
||||
label.setWordWrap(True)
|
||||
button = QPushButton(button_text)
|
||||
button.setObjectName(f"{object_name}Button")
|
||||
button.setVisible(False)
|
||||
layout.addWidget(label, 1)
|
||||
layout.addWidget(button)
|
||||
card.setVisible(False)
|
||||
return card, label, button
|
||||
|
||||
|
||||
def _set_empty_state(card, label, button, message=None, show_button=False):
|
||||
active = bool(message)
|
||||
card.setVisible(active)
|
||||
label.setText(message or "")
|
||||
button.setVisible(active and show_button)
|
||||
|
||||
|
||||
def _database_path(db_path=None, config=None) -> str:
|
||||
return db_path or appconfig.db_path(config)
|
||||
|
||||
@@ -696,11 +725,13 @@ if QT_IMPORT_ERROR is None:
|
||||
status_callback=None,
|
||||
title_prompt_path=None,
|
||||
cover_prompts_dir=None,
|
||||
open_accounts_callback=None,
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.config = appconfig.load_config() if config is None else config
|
||||
self.db_path = _database_path(db_path, self.config)
|
||||
self.status_callback = status_callback
|
||||
self.open_accounts_callback = open_accounts_callback
|
||||
self.title_prompt_path = title_prompt_path or prompts.TITLE_PROMPT_PATH
|
||||
self.cover_prompts_dir = cover_prompts_dir or prompts.COVER_PROMPTS_DIR
|
||||
self.current_cover_template = None
|
||||
@@ -779,6 +810,13 @@ if QT_IMPORT_ERROR is None:
|
||||
filter_layout.addWidget(self.refresh_button)
|
||||
|
||||
self.summary_label = QLabel("任务 0 条")
|
||||
(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
) = _build_empty_state_card("generateEmptyStateCard")
|
||||
if self.open_accounts_callback is not None:
|
||||
self.empty_state_button.clicked.connect(self.open_accounts_callback)
|
||||
self.task_table = QTableView()
|
||||
self.model = GenerateTaskTableModel(self.task_table, db_path=self.db_path, status_callback=self._set_status)
|
||||
self.task_table.setModel(self.model)
|
||||
@@ -799,6 +837,7 @@ if QT_IMPORT_ERROR is None:
|
||||
right_layout.setContentsMargins(12, 0, 0, 0)
|
||||
right_layout.addLayout(filter_layout)
|
||||
right_layout.addWidget(self.summary_label)
|
||||
right_layout.addWidget(self.empty_state_card)
|
||||
right_layout.addWidget(self.task_table, 1)
|
||||
right_layout.addWidget(QLabel("AI生成运行日志"))
|
||||
right_layout.addWidget(self.run_log_view)
|
||||
@@ -1271,12 +1310,42 @@ if QT_IMPORT_ERROR is None:
|
||||
except Exception as exc:
|
||||
self.model.set_tasks([], [])
|
||||
self.summary_label.setText("任务读取失败")
|
||||
_set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button)
|
||||
self._set_status(f"AI 生成任务读取失败:{exc}")
|
||||
return
|
||||
self.model.set_tasks(filtered_tasks, accounts_rows)
|
||||
self.summary_label.setText(
|
||||
f"任务 {len(filtered_tasks)}/{len(batch_tasks)} 条"
|
||||
)
|
||||
self._update_empty_state(batch_tasks, filtered_tasks, accounts_rows)
|
||||
|
||||
def _update_empty_state(self, batch_tasks, filtered_tasks, account_rows):
|
||||
if not account_rows:
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"第一步:前往『④账号管理』配置并登录账号,再回到②生成标题和封面。",
|
||||
self.open_accounts_callback is not None,
|
||||
)
|
||||
return
|
||||
if not batch_tasks:
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"还没有可生成任务。请先在①导入采集完成旧标题和旧封面采集。",
|
||||
)
|
||||
return
|
||||
if not filtered_tasks:
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"当前筛选没有匹配的生成任务,请调整批次、店铺、商品ID或状态筛选。",
|
||||
)
|
||||
return
|
||||
_set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button)
|
||||
|
||||
def _populate_batch_filter(self, batches, selected_batch):
|
||||
previous = selected_batch if selected_batch in {batch.id for batch in batches} else None
|
||||
@@ -1403,6 +1472,13 @@ if QT_IMPORT_ERROR is None:
|
||||
|
||||
self.summary_label = QLabel("任务 0 条")
|
||||
self.risk_label = QLabel("可先点击「检查本轮更新」确认当前筛选范围;点击「开始更新」后会再次确认并按批提交线上。")
|
||||
(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
) = _build_empty_state_card("applyEmptyStateCard")
|
||||
if self.open_accounts_callback is not None:
|
||||
self.empty_state_button.clicked.connect(self.open_accounts_callback)
|
||||
self.task_table = QTableView()
|
||||
self.model = ApplyTaskTableModel(self.task_table)
|
||||
self.task_table.setModel(self.model)
|
||||
@@ -1449,6 +1525,7 @@ if QT_IMPORT_ERROR is None:
|
||||
layout.addLayout(filter_layout)
|
||||
layout.addWidget(self.risk_label)
|
||||
layout.addWidget(self.summary_label)
|
||||
layout.addWidget(self.empty_state_card)
|
||||
layout.addWidget(self.task_table, 1)
|
||||
layout.addWidget(QLabel("运行日志"))
|
||||
layout.addWidget(self.run_log_view)
|
||||
@@ -1499,14 +1576,44 @@ if QT_IMPORT_ERROR is None:
|
||||
except Exception as exc:
|
||||
self.model.set_tasks([], [])
|
||||
self.summary_label.setText("任务读取失败")
|
||||
_set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button)
|
||||
self._set_status(f"更新任务读取失败:{exc}")
|
||||
return
|
||||
self.model.set_tasks(filtered_tasks, account_rows)
|
||||
self.summary_label.setText(
|
||||
f"任务 {len(filtered_tasks)}/{len(batch_tasks)} 条"
|
||||
)
|
||||
self._update_empty_state(batch_tasks, filtered_tasks, account_rows)
|
||||
self._update_write_back_button()
|
||||
|
||||
def _update_empty_state(self, batch_tasks, filtered_tasks, account_rows):
|
||||
if not account_rows:
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"第一步:前往『④账号管理』配置并登录账号,再回到③更新 Shopee。",
|
||||
self.open_accounts_callback is not None,
|
||||
)
|
||||
return
|
||||
if not batch_tasks:
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"还没有可更新任务。请先在②AI生成完成新标题或新封面。",
|
||||
)
|
||||
return
|
||||
if not filtered_tasks:
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"当前筛选没有可更新任务,请调整批次、店铺、商品ID或状态筛选。",
|
||||
)
|
||||
return
|
||||
_set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button)
|
||||
|
||||
def start_update(self, checked=False):
|
||||
self._start_update(dry_run=False)
|
||||
|
||||
@@ -2184,12 +2291,20 @@ if QT_IMPORT_ERROR is None:
|
||||
self.run_log_view.setPlaceholderText("采集运行日志")
|
||||
|
||||
self.empty_label = QLabel("")
|
||||
(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
) = _build_empty_state_card("collectEmptyStateCard")
|
||||
if self.open_accounts_callback is not None:
|
||||
self.empty_state_button.clicked.connect(self.open_accounts_callback)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(18, 18, 18, 18)
|
||||
layout.addLayout(toolbar)
|
||||
layout.addLayout(summary_layout)
|
||||
layout.addWidget(self.match_detail_label)
|
||||
layout.addWidget(self.empty_state_card)
|
||||
layout.addWidget(self.table, 1)
|
||||
layout.addWidget(QLabel("采集运行日志"))
|
||||
layout.addWidget(self.run_log_view)
|
||||
@@ -2401,11 +2516,12 @@ if QT_IMPORT_ERROR is None:
|
||||
except Exception as exc:
|
||||
self.model.set_tasks([], [])
|
||||
self.empty_label.setText("任务读取失败")
|
||||
_set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button)
|
||||
self._set_status(f"任务读取失败:{exc}")
|
||||
return
|
||||
self.model.set_tasks(task_rows, account_rows)
|
||||
self._update_summary(task_rows, account_rows)
|
||||
self._update_empty_label(len(task_rows))
|
||||
self._update_empty_state(task_rows, account_rows)
|
||||
self._update_delete_batch_button()
|
||||
|
||||
def _populate_batch_filter(self, batches, selected_batch):
|
||||
@@ -2774,6 +2890,29 @@ if QT_IMPORT_ERROR is None:
|
||||
}
|
||||
return sum(1 for task in task_rows if str(task.alias).strip() not in aliases)
|
||||
|
||||
def _update_empty_state(self, task_rows, account_rows):
|
||||
if not account_rows:
|
||||
self.empty_label.setText("")
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"第一步:前往『④账号管理』配置并登录账号,再回到①导入 Excel。",
|
||||
self.open_accounts_callback is not None,
|
||||
)
|
||||
return
|
||||
if not task_rows:
|
||||
self.empty_label.setText("")
|
||||
_set_empty_state(
|
||||
self.empty_state_card,
|
||||
self.empty_state_label,
|
||||
self.empty_state_button,
|
||||
"还没有导入任务。请点击「导入 Excel...」导入待处理商品。",
|
||||
)
|
||||
return
|
||||
_set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button)
|
||||
self._update_empty_label(len(task_rows))
|
||||
|
||||
def _update_empty_label(self, total_rows):
|
||||
if total_rows == 0:
|
||||
self.empty_label.setText("暂无任务")
|
||||
@@ -5668,6 +5807,7 @@ if QT_IMPORT_ERROR is None:
|
||||
db_path=self.db_path,
|
||||
config=self.config,
|
||||
status_callback=self.statusBar().showMessage,
|
||||
open_accounts_callback=lambda: self.open_accounts_tab(),
|
||||
)
|
||||
if title == "③ 更新shopee":
|
||||
return ApplyTab(
|
||||
|
||||
Reference in New Issue
Block a user