feat(settings): support gateway source switching
This commit is contained in:
@@ -81,6 +81,7 @@ from ..workers import (
|
||||
CMHubModelCatalogWorker,
|
||||
ImageStudioDownloadOriginalWorker,
|
||||
ImageStudioPullImagesWorker,
|
||||
ImageStudioResumeJobsWorker,
|
||||
ProductSuiteAiWriteWorker,
|
||||
ProductSuiteGenerateWorker,
|
||||
ProductSuiteHistoryExportWorker,
|
||||
@@ -723,13 +724,20 @@ class SuiteResultCard(QFrame):
|
||||
status_label.setWordWrap(False)
|
||||
status_label.setToolTip(status_text)
|
||||
footer.addWidget(status_label, 1)
|
||||
self.retry_button = None
|
||||
if status in {"failed", "expired", "cancelled"}:
|
||||
retry_button = QPushButton("重试")
|
||||
retry_button.setMinimumWidth(52)
|
||||
retry_button.clicked.connect(lambda: self.retryRequested.emit(self.job))
|
||||
footer.addWidget(retry_button)
|
||||
self.retry_button = QPushButton("重试")
|
||||
self.retry_button.setMinimumWidth(52)
|
||||
self.retry_button.clicked.connect(lambda: self.retryRequested.emit(self.job))
|
||||
footer.addWidget(self.retry_button)
|
||||
layout.addLayout(footer)
|
||||
|
||||
def set_retry_enabled(self, enabled, tooltip=""):
|
||||
if self.retry_button is None:
|
||||
return
|
||||
self.retry_button.setEnabled(bool(enabled))
|
||||
self.retry_button.setToolTip(str(tooltip or ""))
|
||||
|
||||
|
||||
class SuiteHistoryImageCard(QFrame):
|
||||
"""Read-only image card used by the product-suite history dialog."""
|
||||
@@ -1884,6 +1892,8 @@ class SuiteTaskState:
|
||||
generation_price_worker: object = None
|
||||
generation_price_thread: object = None
|
||||
generation_confirmation_open: bool = False
|
||||
resume_worker: object = None
|
||||
resume_thread: object = None
|
||||
download_queue: list = field(default_factory=list)
|
||||
downloads: dict = field(default_factory=dict)
|
||||
download_tokens: dict = field(default_factory=dict)
|
||||
@@ -1962,6 +1972,10 @@ class ProductSuiteTab(QWidget):
|
||||
if self._prompt_template_init_error:
|
||||
self._status(self._prompt_template_init_error, "danger")
|
||||
|
||||
def showEvent(self, event):
|
||||
super().showEvent(event)
|
||||
self.refresh_gateway_state()
|
||||
|
||||
def _build_ui(self):
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(10, 8, 10, 8)
|
||||
@@ -2111,6 +2125,11 @@ class ProductSuiteTab(QWidget):
|
||||
"QPushButton:hover { background: #245fce; }"
|
||||
)
|
||||
layout.addWidget(self.generate_button)
|
||||
self.resume_submitted_button = QPushButton("继续查询已提交图片")
|
||||
self.resume_submitted_button.setObjectName("suiteResumeSubmittedButton")
|
||||
self.resume_submitted_button.setToolTip("继续查询已提交到默认网关的图片,不会重新生成或再次扣点")
|
||||
self.resume_submitted_button.setVisible(False)
|
||||
layout.addWidget(self.resume_submitted_button)
|
||||
self.generate_helper_label = QLabel("建议填写产品名称、核心卖点、目标人群、使用场景与禁用元素")
|
||||
self.generate_helper_label.setWordWrap(True)
|
||||
self.generate_helper_label.setStyleSheet("color: #6b7280;")
|
||||
@@ -2396,6 +2415,7 @@ class ProductSuiteTab(QWidget):
|
||||
self.custom_category_edit.returnPressed.connect(self._commit_custom_category)
|
||||
self.custom_category_edit.editingFinished.connect(self._finish_custom_category_edit)
|
||||
self.generate_button.clicked.connect(self.toggle_generation)
|
||||
self.resume_submitted_button.clicked.connect(self.resume_submitted_jobs)
|
||||
self.history_button.clicked.connect(self.open_history_dialog)
|
||||
self.undo_button.clicked.connect(self.undo_delete)
|
||||
self.more_button.clicked.connect(self._show_more_menu)
|
||||
@@ -4155,7 +4175,105 @@ class ProductSuiteTab(QWidget):
|
||||
if not state.generation_running():
|
||||
self.generate_button.setText("生成套图(%d)" % total)
|
||||
|
||||
def _is_default_gateway(self):
|
||||
try:
|
||||
return appconfig.ai_backend(self.config) == "cmhub"
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _is_default_gateway_job(job):
|
||||
return (
|
||||
str(getattr(job, "generation_source", "") or "").strip().lower() == "cmhub"
|
||||
and str(getattr(job, "provider", "") or "").strip().lower() == "cmhub"
|
||||
and bool(str(getattr(job, "task_id", "") or "").strip())
|
||||
)
|
||||
|
||||
def _resumable_default_gateway_jobs(self, state):
|
||||
if state is None or state.project_id is None:
|
||||
return []
|
||||
try:
|
||||
jobs = image_studio.list_resumable_jobs(
|
||||
project_id=state.project_id,
|
||||
include_failed_downloads=True,
|
||||
path=self.db_path,
|
||||
)
|
||||
except Exception:
|
||||
return []
|
||||
return [job for job in jobs if self._is_default_gateway_job(job)]
|
||||
|
||||
def refresh_gateway_state(self):
|
||||
state = self._displayed_state
|
||||
if state is not None:
|
||||
self._apply_running_state(state)
|
||||
self._refresh_results(state)
|
||||
|
||||
def _update_resume_submitted_action(self, state):
|
||||
jobs = self._resumable_default_gateway_jobs(state)
|
||||
self.resume_submitted_button.setVisible(bool(jobs))
|
||||
self.resume_submitted_button.setEnabled(
|
||||
bool(jobs)
|
||||
and state.resume_worker is None
|
||||
and not state.generation_running()
|
||||
and state.generation_price_worker is None
|
||||
)
|
||||
|
||||
def resume_submitted_jobs(self, checked=False):
|
||||
state = self._displayed_state
|
||||
if state is None or state.project_id is None:
|
||||
return
|
||||
if state.resume_worker is not None:
|
||||
self._status("正在继续查询已提交图片", "info")
|
||||
return
|
||||
jobs = self._resumable_default_gateway_jobs(state)
|
||||
if not jobs:
|
||||
self._status("当前没有可继续查询的默认网关图片", "info")
|
||||
self._update_resume_submitted_action(state)
|
||||
return
|
||||
worker = ImageStudioResumeJobsWorker(
|
||||
project_id=state.project_id,
|
||||
aspect_ratio=state.settings.get("ratio", "1:1"),
|
||||
db_path=self.db_path,
|
||||
config=self.config,
|
||||
cmhub_config_path=self.cmhub_config_path,
|
||||
)
|
||||
state.resume_worker = worker
|
||||
worker.finished.connect(
|
||||
lambda result, state=state: self._on_resume_submitted_finished(state, result)
|
||||
)
|
||||
worker.cancelled.connect(
|
||||
lambda result, state=state: self._on_resume_submitted_finished(state, result)
|
||||
)
|
||||
state.resume_thread = self._start_thread(worker, "商品套图继续查询")
|
||||
self._apply_running_state(state)
|
||||
self._status("开始继续查询%d张已提交图片,不会重新生成或再次扣点" % len(jobs), "info")
|
||||
|
||||
def _on_resume_submitted_finished(self, state, result):
|
||||
state.resume_worker = None
|
||||
state.resume_thread = None
|
||||
self._refresh_results(state)
|
||||
self._update_resume_submitted_action(state)
|
||||
if result.get("ok") is False:
|
||||
error = str(result.get("error") or "")
|
||||
if "cmhub_not_configured" in error or "缺少" in error:
|
||||
self._message(
|
||||
"继续查询失败",
|
||||
"默认网关配置不可用,请恢复原默认网关配置后继续查询已提交图片。",
|
||||
)
|
||||
else:
|
||||
self._message("继续查询失败", _user_error(error))
|
||||
return
|
||||
self._status("已完成已提交图片查询,请查看生成结果", "success")
|
||||
|
||||
def _require_default_gateway(self, action):
|
||||
if self._is_default_gateway():
|
||||
return True
|
||||
self._message("当前不可用", "%s仅支持默认网关,请到⑤设置切换后再使用。" % action)
|
||||
return False
|
||||
|
||||
def start_ai_write(self, checked=False):
|
||||
if not self._require_default_gateway("商品套图AI帮写"):
|
||||
return
|
||||
state = self._displayed_state
|
||||
if state is None:
|
||||
return
|
||||
@@ -4482,6 +4600,8 @@ class ProductSuiteTab(QWidget):
|
||||
self.start_generation(state)
|
||||
|
||||
def start_generation(self, state, specs=None, *, retry_job_id=None):
|
||||
if not self._require_default_gateway("商品套图生成"):
|
||||
return False
|
||||
if state.generation_running():
|
||||
self._status("当前套图任务仍在生成", "warning")
|
||||
return False
|
||||
@@ -5414,6 +5534,7 @@ class ProductSuiteTab(QWidget):
|
||||
generation_running = state.generation_running()
|
||||
generation_price_pending = state.generation_price_worker is not None
|
||||
pull_running = state.pull_running()
|
||||
default_gateway = self._is_default_gateway()
|
||||
self.pull_button.setText(
|
||||
"正在停止..."
|
||||
if pull_running and state.pull_stop_requested
|
||||
@@ -5439,7 +5560,9 @@ class ProductSuiteTab(QWidget):
|
||||
widget.setEnabled(not generation_running)
|
||||
for row in self.category_rows.values():
|
||||
row.set_controls_enabled(not generation_running)
|
||||
self.generate_button.setEnabled(True)
|
||||
self.generate_button.setEnabled(
|
||||
generation_running or generation_price_pending or default_gateway
|
||||
)
|
||||
if generation_running:
|
||||
self.generate_button.setText(
|
||||
"正在停止..."
|
||||
@@ -5465,8 +5588,17 @@ class ProductSuiteTab(QWidget):
|
||||
)
|
||||
self._refresh_totals(state)
|
||||
ai_running = state.ai_worker is not None or state.ai_price_worker is not None
|
||||
self.ai_write_button.setEnabled(not ai_running and not generation_running)
|
||||
self.ai_write_button.setEnabled(
|
||||
default_gateway and not ai_running and not generation_running
|
||||
)
|
||||
if not default_gateway and not ai_running:
|
||||
self.ai_write_button.setToolTip("商品套图AI帮写仅支持默认网关")
|
||||
self.generate_button.setToolTip("商品套图生成仅支持默认网关")
|
||||
else:
|
||||
self.ai_write_button.setToolTip("")
|
||||
self.generate_button.setToolTip("")
|
||||
self.ai_cancel_button.setVisible(ai_running)
|
||||
self._update_resume_submitted_action(state)
|
||||
self._update_context_actions(state)
|
||||
|
||||
def _refresh_elapsed(self):
|
||||
@@ -5541,6 +5673,8 @@ class ProductSuiteTab(QWidget):
|
||||
card.retryRequested.connect(self.retry_job)
|
||||
card.menuRequested.connect(self._show_job_menu)
|
||||
card.deleteRequested.connect(self.delete_job_asset)
|
||||
if not self._is_default_gateway():
|
||||
card.set_retry_enabled(False, "商品套图重新生成仅支持默认网关")
|
||||
self.result_grid.addWidget(card, index // columns, index % columns)
|
||||
self.result_summary_label.setText("共 %d 张 · 成功 %d 张" % (len(jobs), success))
|
||||
self.undo_button.setVisible(bool(state.undo_records))
|
||||
@@ -5611,6 +5745,8 @@ class ProductSuiteTab(QWidget):
|
||||
ProductSuitePreviewDialog(asset.local_path, "%s预览" % job.job_type, self).exec()
|
||||
|
||||
def retry_job(self, job):
|
||||
if not self._require_default_gateway("商品套图重新生成"):
|
||||
return
|
||||
state = self._displayed_state
|
||||
if state is None:
|
||||
return
|
||||
@@ -5643,6 +5779,9 @@ class ProductSuiteTab(QWidget):
|
||||
copy_action = menu.addAction("复制路径")
|
||||
folder_action = menu.addAction("打开文件夹")
|
||||
retry_action = menu.addAction("重新生成")
|
||||
if not self._is_default_gateway():
|
||||
retry_action.setEnabled(False)
|
||||
retry_action.setToolTip("商品套图重新生成仅支持默认网关")
|
||||
delete_action = menu.addAction("删除")
|
||||
action = menu.exec(global_position)
|
||||
asset = image_studio.get_asset(job.output_asset_id, path=self.db_path) if job.output_asset_id else None
|
||||
|
||||
Reference in New Issue
Block a user