fix(product-suite): validate item id before generation
This commit is contained in:
@@ -14,6 +14,7 @@ from PySide6.QtCore import (
|
||||
QIODevice,
|
||||
QPointF,
|
||||
QRect,
|
||||
QRegularExpression,
|
||||
QSize,
|
||||
Qt,
|
||||
QTimer,
|
||||
@@ -29,6 +30,7 @@ from PySide6.QtGui import (
|
||||
QKeySequence,
|
||||
QPainter,
|
||||
QPixmap,
|
||||
QRegularExpressionValidator,
|
||||
QWheelEvent,
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
@@ -2163,6 +2165,9 @@ class ProductSuiteTab(QWidget):
|
||||
self.item_id_edit = QLineEdit()
|
||||
self.item_id_edit.setObjectName("suiteItemIdEdit")
|
||||
self.item_id_edit.setPlaceholderText("输入商品ID")
|
||||
self.item_id_edit.setValidator(
|
||||
QRegularExpressionValidator(QRegularExpression("^[0-9]*$"), self.item_id_edit)
|
||||
)
|
||||
item_width = max(
|
||||
120,
|
||||
min(140, self.item_id_edit.fontMetrics().horizontalAdvance("0" * 13) + 30),
|
||||
@@ -2776,7 +2781,6 @@ class ProductSuiteTab(QWidget):
|
||||
if self._loading or state is None:
|
||||
return
|
||||
state.account_alias = str(self.account_combo.currentData() or "")
|
||||
state.item_id = self.item_id_edit.text().strip()
|
||||
state.prompt = self.prompt_edit.toPlainText()
|
||||
state.settings = self._settings_from_controls()
|
||||
|
||||
@@ -2791,6 +2795,7 @@ class ProductSuiteTab(QWidget):
|
||||
if index >= 0:
|
||||
self.account_combo.setCurrentIndex(index)
|
||||
self.item_id_edit.setText(state.item_id)
|
||||
self.item_id_edit.setStyleSheet("")
|
||||
self.prompt_edit.setPlainText(state.prompt)
|
||||
self._set_combo_value(self.platform_combo, state.settings.get("platform"))
|
||||
self._set_combo_value(self.country_combo, state.settings.get("country"))
|
||||
@@ -2861,32 +2866,46 @@ class ProductSuiteTab(QWidget):
|
||||
self.account_combo.setToolTip(self.account_combo.currentText())
|
||||
|
||||
def _on_item_finished(self):
|
||||
if self._loading or self._displayed_state is None:
|
||||
return
|
||||
state = self._displayed_state
|
||||
item_id = self.item_id_edit.text().strip()
|
||||
if item_id and not item_id.isdigit():
|
||||
self._commit_item_id(self._displayed_state)
|
||||
|
||||
def _restore_committed_item_id(self, state):
|
||||
self._loading = True
|
||||
try:
|
||||
self.item_id_edit.setText(state.item_id)
|
||||
finally:
|
||||
self._loading = False
|
||||
|
||||
def _commit_item_id(self, state):
|
||||
"""Validate and commit the visible product ID before an operation uses it."""
|
||||
|
||||
if self._loading or state is None:
|
||||
return False
|
||||
raw_item_id = self.item_id_edit.text()
|
||||
item_id = image_studio.normalize_item_id_input(raw_item_id)
|
||||
if item_id != raw_item_id:
|
||||
self._loading = True
|
||||
try:
|
||||
self.item_id_edit.setText(item_id)
|
||||
finally:
|
||||
self._loading = False
|
||||
if item_id and not image_studio.is_formal_item_id(item_id):
|
||||
self.item_id_edit.setStyleSheet("border: 1px solid #9a6700;")
|
||||
self._status("商品ID只能输入数字", "warning")
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return False
|
||||
self.item_id_edit.setStyleSheet("")
|
||||
if self._is_draft_state(state):
|
||||
if not item_id:
|
||||
state.item_id = ""
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return True
|
||||
if not self._confirm(
|
||||
"绑定正式商品",
|
||||
"将当前临时草稿绑定到商品%s吗?\n已添加图片和生成记录会继续保留。" % item_id,
|
||||
):
|
||||
self._loading = True
|
||||
try:
|
||||
self.item_id_edit.setText(state.item_id)
|
||||
finally:
|
||||
self._loading = False
|
||||
self._restore_committed_item_id(state)
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return False
|
||||
self._flush_prompt_save(state)
|
||||
try:
|
||||
project = image_studio.bind_draft_project(
|
||||
@@ -2896,47 +2915,36 @@ class ProductSuiteTab(QWidget):
|
||||
)
|
||||
except image_studio.ImageStudioProjectConflictError as exc:
|
||||
self._message("商品项目已存在", _user_error(exc))
|
||||
self._loading = True
|
||||
try:
|
||||
self.item_id_edit.setText(state.item_id)
|
||||
finally:
|
||||
self._loading = False
|
||||
self._restore_committed_item_id(state)
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return False
|
||||
except Exception as exc:
|
||||
self._message("绑定正式商品失败", _user_error(exc))
|
||||
self._loading = True
|
||||
try:
|
||||
self.item_id_edit.setText(state.item_id)
|
||||
finally:
|
||||
self._loading = False
|
||||
self._restore_committed_item_id(state)
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return False
|
||||
state.item_id = project.item_id
|
||||
state.project_binding_state = project.binding_state
|
||||
self._set_task_title(state)
|
||||
self._status("临时草稿已绑定商品%s" % project.item_id, "success")
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return True
|
||||
if state.project_id is not None and item_id != state.item_id:
|
||||
if not self._confirm(
|
||||
"切换商品",
|
||||
"切换商品ID后,原图和生成结果会按新商品重新载入。确认继续吗?",
|
||||
):
|
||||
self._loading = True
|
||||
try:
|
||||
self.item_id_edit.setText(state.item_id)
|
||||
finally:
|
||||
self._loading = False
|
||||
return
|
||||
self._restore_committed_item_id(state)
|
||||
return False
|
||||
self._clear_project_binding(state)
|
||||
state.item_id = item_id
|
||||
if not item_id:
|
||||
self._update_context_actions(state)
|
||||
return
|
||||
return True
|
||||
if item_id and state.account_alias:
|
||||
self._bind_project(state, load_existing=True)
|
||||
self._update_context_actions(state)
|
||||
return True
|
||||
|
||||
def _clear_project_binding(self, state):
|
||||
self._flush_prompt_save(state)
|
||||
@@ -3012,7 +3020,7 @@ class ProductSuiteTab(QWidget):
|
||||
def _valid_context(self, state, *, show_message=True):
|
||||
if not self._has_account_context(state, show_message=show_message):
|
||||
return False
|
||||
if not state.item_id or not state.item_id.isdigit():
|
||||
if not image_studio.is_formal_item_id(state.item_id):
|
||||
if show_message:
|
||||
self._message("商品ID无效", "请输入正确的数字商品ID。")
|
||||
return False
|
||||
@@ -3465,6 +3473,8 @@ class ProductSuiteTab(QWidget):
|
||||
state = self._displayed_state
|
||||
if state is None:
|
||||
return
|
||||
if not self._commit_item_id(state):
|
||||
return
|
||||
self._save_controls_to_state(state)
|
||||
state.import_created_draft = False
|
||||
created_project = state.project_id is None
|
||||
@@ -3662,6 +3672,8 @@ class ProductSuiteTab(QWidget):
|
||||
if state.pull_running():
|
||||
self._request_stop_pull(state)
|
||||
return
|
||||
if not self._commit_item_id(state):
|
||||
return
|
||||
self._save_controls_to_state(state)
|
||||
if self._is_draft_state(state):
|
||||
self._message(
|
||||
@@ -4801,6 +4813,10 @@ class ProductSuiteTab(QWidget):
|
||||
retry_job_id=None,
|
||||
confirm_direct_retry=False,
|
||||
):
|
||||
if state is self._displayed_state:
|
||||
if not self._commit_item_id(state):
|
||||
return False
|
||||
self._save_controls_to_state(state)
|
||||
if self.subscription_preflight_callback is not None and not self.subscription_preflight_callback("生成商品套图"):
|
||||
return False
|
||||
if not self._ensure_generation_gateway():
|
||||
@@ -4811,8 +4827,6 @@ class ProductSuiteTab(QWidget):
|
||||
retry_job_id = int(retry_job_id) if retry_job_id is not None else None
|
||||
retrying = retry_job_id is not None
|
||||
confirm_batch = specs is None and not retrying
|
||||
if state is self._displayed_state:
|
||||
self._save_controls_to_state(state)
|
||||
template_text = None
|
||||
if specs is None:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user