T-577 封面画廊重置图片

This commit is contained in:
chengma
2026-07-09 18:15:14 +08:00
parent d8472c988a
commit 90a054a14d
8 changed files with 135 additions and 287 deletions
+41 -175
View File
@@ -141,10 +141,7 @@ class CoverGalleryDialog(QDialog):
account=None,
parent=None,
config=None,
prompt_values=None,
diagnostic_log_dir=None,
bulk_running_checker=None,
regenerate_running_callback=None,
gallery_updated_callback=None,
visible_tasks=None,
task_index=None,
@@ -160,10 +157,7 @@ class CoverGalleryDialog(QDialog):
self.fallback_account = account
self.account = self._account_for_task(self.task) or account
self.config = config or {}
self.prompt_values = dict(prompt_values or {})
self.diagnostic_log_dir = diagnostic_log_dir
self.bulk_running_checker = bulk_running_checker
self.regenerate_running_callback = regenerate_running_callback
self.gallery_updated_callback = gallery_updated_callback
self.current_path = _normalize_file_path(getattr(task, "new_cover_path", None))
self.selected_path = None
@@ -171,10 +165,6 @@ class CoverGalleryDialog(QDialog):
self.candidate_buttons = {}
self.button_group = QButtonGroup(self)
self.button_group.setExclusive(True)
self.regenerate_worker = None
self.regenerate_thread = None
self.regenerating_task_id = None
self._regenerate_last_error = ""
self.candidates = image_paths.list_task_cover_candidates(image_root, self.task, account=self.account)
self.setWindowTitle(f"封面画廊:{getattr(task, 'item_id', '')}")
@@ -191,9 +181,9 @@ class CoverGalleryDialog(QDialog):
self.next_button.clicked.connect(lambda checked=False: self.switch_task(1))
button_layout.addWidget(self.previous_button)
button_layout.addWidget(self.next_button)
self.regenerate_button = QPushButton("重新生成")
self.regenerate_button.clicked.connect(self.regenerate_cover)
button_layout.addWidget(self.regenerate_button)
self.reset_cover_button = QPushButton("重置图片")
self.reset_cover_button.clicked.connect(self.reset_cover_image)
button_layout.addWidget(self.reset_cover_button)
button_layout.addStretch(1)
self.save_hint_label = QLabel("")
self.save_hint_label.setObjectName("coverGallerySaveHintLabel")
@@ -209,7 +199,7 @@ class CoverGalleryDialog(QDialog):
self._sync_initial_selection()
self._update_status()
self._update_navigation_buttons()
self._update_regenerate_button_state()
self._update_reset_cover_button_state()
self._fit_to_screen()
self._install_navigation_event_filters()
@@ -363,9 +353,6 @@ class CoverGalleryDialog(QDialog):
self._update_status()
def _update_status(self):
if self._is_current_task_regenerating():
self.status_label.setText("封面重新生成中,请稍候")
return
if not self.candidates:
self.status_label.setText("暂无生成封面图片")
self.save_button.setEnabled(False)
@@ -426,17 +413,15 @@ class CoverGalleryDialog(QDialog):
def _set_save_hint(self, message):
self.save_hint_label.setText(str(message or ""))
def regenerate_cover(self, checked=False):
if self.regenerate_thread is not None:
def reset_cover_image(self, checked=False):
if self._is_bulk_generate_running():
self.status_label.setText("AI 生成正在进行,不能重置图片")
self._update_reset_cover_button_state()
return False
if self._bulk_generate_running():
self.status_label.setText("②批量生成正在运行,完成后才能重新生成单个封面")
self._update_regenerate_button_state()
if not str(getattr(self.task, "new_cover_path", "") or "").strip():
self.status_label.setText("当前任务没有可重置的新封面图片")
return False
if not str(getattr(self.task, "new_title", "") or "").strip():
QMessageBox.warning(self, "重新生成封面", "当前任务缺少新标题,不能单独重新生成封面")
return False
if not self._confirm_regenerate():
if self._needs_committed_confirmation() and not self._confirm_committed_reset():
return False
try:
db.reset_generated(
@@ -447,47 +432,22 @@ class CoverGalleryDialog(QDialog):
)
fresh_task = db.get_task(self.task.id, path=self.db_path)
except Exception as exc:
QMessageBox.warning(self, "重新生成封面", str(exc))
self.status_label.setText(f"重新生成封面失败:{exc}")
QMessageBox.warning(self, "重置图片", str(exc))
self.status_label.setText(f"重置图片失败:{exc}")
return False
if fresh_task is None:
QMessageBox.warning(self, "重新生成封面", "任务不存在或已删除")
self.status_label.setText("重新生成封面失败:任务不存在或已删除")
QMessageBox.warning(self, "重置图片", "任务不存在或已删除")
self.status_label.setText("重置图片失败:任务不存在或已删除")
return False
self.regenerating_task_id = getattr(fresh_task, "id", None)
self._reload_task_and_candidates(fresh_task)
self.status_label.setText(f"开始重新生成商品 {getattr(fresh_task, 'item_id', '')} 的封面图片")
worker = GenerateWorker(
[fresh_task],
self.prompt_values,
db_path=self.db_path,
config=_cover_regenerate_config(self.config),
diagnostic_log_dir=self.diagnostic_log_dir,
self.status_label.setText(
"已重置图片,该行图片状态已改为待生成;"
"请在②选择「只生成封面」或「生成标题和封面」后点击开始生成"
)
worker.progress.connect(self._on_regenerate_progress)
worker.row_updated.connect(self._on_regenerate_row_updated)
worker.log.connect(self._on_regenerate_log)
worker.failed.connect(self._on_regenerate_failed)
worker.finished.connect(self._on_regenerate_finished)
worker.cancelled.connect(self._on_regenerate_cancelled)
thread = run_worker(worker, thread_name="CoverRegenerateWorker", start=False)
thread.finished.connect(lambda: self._forget_regenerate_thread(thread))
self.regenerate_worker = worker
self.regenerate_thread = thread
self._set_regenerate_running(True)
thread.start()
if self.gallery_updated_callback is not None:
self.gallery_updated_callback(self.task)
return True
def _confirm_regenerate(self):
box = QMessageBox(self)
box.setWindowTitle("重新生成封面")
box.setText("将重新生成当前商品封面,可能消耗 cmhub 点数。")
confirm_button = box.addButton("重新生成", QMessageBox.AcceptRole)
cancel_button = box.addButton("取消", QMessageBox.RejectRole)
box.setDefaultButton(cancel_button)
box.exec()
return box.clickedButton() is confirm_button
def _needs_committed_confirmation(self):
return int(getattr(self.task, "committed", 0) or 0) == 1 or getattr(self.task, "stage", None) == "applied"
@@ -503,6 +463,18 @@ class CoverGalleryDialog(QDialog):
box.exec()
return box.clickedButton() is save_button
def _confirm_committed_reset(self):
box = QMessageBox(self)
box.setWindowTitle("确认重置图片")
box.setText(
"该商品已经提交过线上。本地重置不会回滚蝦皮,重新生成并更新会再次提交线上。"
)
reset_button = box.addButton("确认重置", QMessageBox.AcceptRole)
cancel_button = box.addButton("取消", QMessageBox.RejectRole)
box.setDefaultButton(cancel_button)
box.exec()
return box.clickedButton() is reset_button
def switch_task(self, offset):
target_index = self.task_index + int(offset)
if target_index < 0 or target_index >= len(self.visible_tasks):
@@ -528,7 +500,7 @@ class CoverGalleryDialog(QDialog):
)
self._reload_task_and_candidates(fresh_task)
self._update_navigation_buttons()
self._update_regenerate_button_state()
self._update_reset_cover_button_state()
def _update_navigation_buttons(self):
self.previous_button.setEnabled(self.task_index > 0)
@@ -611,34 +583,14 @@ class CoverGalleryDialog(QDialog):
dialog = OriginalImageDialog(image_path, self)
dialog.exec()
def _bulk_generate_running(self):
def _is_bulk_generate_running(self):
return bool(self.bulk_running_checker and self.bulk_running_checker())
def _is_current_task_regenerating(self):
return (
self.regenerate_thread is not None
and self.regenerating_task_id is not None
and getattr(self.task, "id", None) == self.regenerating_task_id
)
def _set_regenerate_running(self, running):
self.save_button.setEnabled(not running and self.selected_path is not None)
self.regenerate_button.setEnabled(not running and not self._bulk_generate_running())
self.regenerate_button.setToolTip(
"②批量生成正在运行,完成后才能重新生成单个封面"
if self._bulk_generate_running()
else ("正在重新生成当前商品封面" if running else "")
)
if self.regenerate_running_callback is not None:
self.regenerate_running_callback(bool(running))
def _update_regenerate_button_state(self):
running = self.regenerate_thread is not None
self.regenerate_button.setEnabled(not running and not self._bulk_generate_running())
self.regenerate_button.setToolTip(
"②批量生成正在运行,完成后才能重新生成单个封面"
if self._bulk_generate_running()
else ("正在重新生成当前商品封面" if running else "")
def _update_reset_cover_button_state(self):
running = self._is_bulk_generate_running()
self.reset_cover_button.setEnabled(not running)
self.reset_cover_button.setToolTip(
"AI 生成正在进行,完成后才能重置图片" if running else ""
)
def _reload_task_and_candidates(self, task=None):
@@ -671,58 +623,6 @@ class CoverGalleryDialog(QDialog):
self._sync_candidate_content_size()
self._install_navigation_event_filters()
def _on_regenerate_progress(self, payload):
if payload.get("failed"):
self.status_label.setText("封面重新生成失败,历史候选仍可选择保存")
def _on_regenerate_row_updated(self, task_id, fields):
if self.gallery_updated_callback is not None:
self.gallery_updated_callback(self.task)
def _on_regenerate_log(self, message):
text = str(message or "").strip()
if not text:
return
if text.startswith("[失败]"):
self._regenerate_last_error = text
self.status_label.setText(text)
elif "成功" in text or "完成" in text:
self.status_label.setText(text)
def _on_regenerate_failed(self, task_id, error):
self._regenerate_last_error = str(error or "未知错误")
self.status_label.setText(f"封面重新生成失败:{self._regenerate_last_error}")
def _on_regenerate_finished(self, summary):
self._finish_regenerate(summary, cancelled=False)
def _on_regenerate_cancelled(self, summary):
self._finish_regenerate(summary, cancelled=True)
def _finish_regenerate(self, summary, cancelled=False):
self.regenerating_task_id = None
fresh_task = db.get_task(self.task.id, path=self.db_path)
if fresh_task is not None:
self._reload_task_and_candidates(fresh_task)
self._set_regenerate_running(False)
if self.gallery_updated_callback is not None:
self.gallery_updated_callback(self.task)
if cancelled or summary.get("cancelled"):
self.status_label.setText("封面重新生成已停止,历史候选仍可选择保存")
return
if summary.get("ok") and summary.get("cover_done", 0) > 0:
self.status_label.setText("封面重新生成完成")
return
detail = self._regenerate_last_error or summary.get("error") or "请稍后重试"
self.status_label.setText(f"封面重新生成失败:{detail}")
def _forget_regenerate_thread(self, thread):
if self.regenerate_thread is thread:
self.regenerate_thread = None
self.regenerate_worker = None
self.regenerating_task_id = None
self._set_regenerate_running(False)
def _fit_to_screen(self):
available = _available_geometry()
if available is None:
@@ -747,15 +647,6 @@ def _clear_layout(layout):
widget.deleteLater()
def _cover_regenerate_config(config):
runtime_config = dict(config or {})
ai_settings = appconfig.ai_config(runtime_config)
ai_settings["generate_cover"] = True
ai_settings["generate_mode"] = "cover"
runtime_config["ai"] = ai_settings
return runtime_config
def _build_image_label(image_path, size, empty_text):
label = QLabel()
label.setAlignment(Qt.AlignCenter)
@@ -877,7 +768,6 @@ class GenerateTab(QWidget):
self.generate_worker = None
self.generate_thread = None
self.generate_running = False
self.cover_gallery_regenerate_running = False
self._title_elapsed_start = None
self._cover_elapsed_start = None
self._title_elapsed_seconds = 0
@@ -1458,9 +1348,6 @@ class GenerateTab(QWidget):
self._set_status("封面提示词预览已生成")
def start_generate(self, checked=False):
if self.cover_gallery_regenerate_running:
self._set_status("封面画廊正在重新生成,完成后再开始批量生成")
return
if self.generate_thread is not None:
self._set_status("AI 生成正在进行...")
return
@@ -1737,13 +1624,7 @@ class GenerateTab(QWidget):
account=account,
parent=self,
config=self.config,
prompt_values={
"title": self.title_prompt_edit.toPlainText(),
"cover": self.cover_prompt_edit.toPlainText(),
},
diagnostic_log_dir=diagnostics.DEFAULT_LOG_DIR,
bulk_running_checker=lambda: self.generate_thread is not None,
regenerate_running_callback=self._set_cover_gallery_regenerate_running,
gallery_updated_callback=self._on_cover_gallery_updated,
visible_tasks=list(self.model.tasks),
task_index=row if row >= 0 else 0,
@@ -1758,9 +1639,9 @@ class GenerateTab(QWidget):
def _set_generate_running(self, running):
self.generate_running = bool(running)
self.generate_button.setEnabled(not running and not self.cover_gallery_regenerate_running)
self.generate_button.setEnabled(not running)
self.stop_generate_button.setEnabled(running)
self.reset_generate_button.setEnabled(not running and not self.cover_gallery_regenerate_running)
self.reset_generate_button.setEnabled(not running)
self.refresh_button.setEnabled(not running)
self.batch_filter.setEnabled(not running)
self.shop_filter.setEnabled(not running)
@@ -1774,21 +1655,6 @@ class GenerateTab(QWidget):
self.rename_cover_template_action.setEnabled(not running)
self.delete_cover_template_action.setEnabled(not running)
self.generate_mode_combo.setEnabled(not running)
self._sync_cover_gallery_regenerate_guard()
def _set_cover_gallery_regenerate_running(self, running):
self.cover_gallery_regenerate_running = bool(running)
self._sync_cover_gallery_regenerate_guard()
def _sync_cover_gallery_regenerate_guard(self):
if self.generate_thread is not None or self.generate_running:
return
blocked = bool(self.cover_gallery_regenerate_running)
self.generate_button.setEnabled(not blocked)
self.reset_generate_button.setEnabled(not blocked)
tooltip = "封面画廊正在重新生成,完成后再开始批量生成" if blocked else ""
self.generate_button.setToolTip(tooltip)
self.reset_generate_button.setToolTip(tooltip)
def _on_cover_gallery_updated(self, task):
self.refresh_tasks()