feat(ai-outfit): info popup when user switches resolution/model (§19.7)

Connect QComboBox.activated (user-only) on the 分辨率 and AI 模型 dropdowns to
an info-only QMessageBox: resolution shows the per-resolution timeout +
next-run-only; model shows its api_type + billing/effect caveat + next-run-only.
Track last value so re-selecting the same item doesn't pop; programmatic sets
(apply_config/_fill_sample_combo) never pop. Offscreen-verified; suite (12) green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 11:31:56 +08:00
co-authored by Claude Opus 4.8
parent 38bae8166c
commit d851978634
2 changed files with 45 additions and 4 deletions
+41
View File
@@ -146,6 +146,8 @@ class AiOutfitPanel(QWidget):
self._worker = None self._worker = None
self._row_to_table = {} # excel row_index -> table row self._row_to_table = {} # excel row_index -> table row
self._failures = [] # list of OutfitResult (failed) self._failures = [] # list of OutfitResult (failed)
self._last_resolution = "" # for "value actually changed" check (§10.2)
self._last_model = ""
self._build_ui() self._build_ui()
# -- construction --------------------------------------------------- # -- construction ---------------------------------------------------
@@ -246,6 +248,8 @@ class AiOutfitPanel(QWidget):
self._resolution = QComboBox() self._resolution = QComboBox()
self._resolution.addItems(_RESOLUTIONS) self._resolution.addItems(_RESOLUTIONS)
self._resolution.currentIndexChanged.connect(self._refresh_preview) self._resolution.currentIndexChanged.connect(self._refresh_preview)
# activated = user click only; programmatic sets won't pop (docs/11 §10.2)
self._resolution.activated.connect(self._on_resolution_activated)
self._quality = QComboBox() self._quality = QComboBox()
self._quality.addItems(_QUALITIES) self._quality.addItems(_QUALITIES)
@@ -266,6 +270,7 @@ class AiOutfitPanel(QWidget):
# AI 模型 下拉(移到生成设置下方) # AI 模型 下拉(移到生成设置下方)
self._model_combo = QComboBox() self._model_combo = QComboBox()
self._compact_combo(self._model_combo) self._compact_combo(self._model_combo)
self._model_combo.activated.connect(self._on_model_activated)
gv.addWidget(self._field("AI 模型", self._model_combo)) gv.addWidget(self._field("AI 模型", self._model_combo))
return gen return gen
@@ -395,6 +400,11 @@ class AiOutfitPanel(QWidget):
self._model_combo.addItem(m.get("name") or m.get("model") or "(未命名)") self._model_combo.addItem(m.get("name") or m.get("model") or "(未命名)")
self._set_combo(self._model_combo, config.get("outfit_model", "")) self._set_combo(self._model_combo, config.get("outfit_model", ""))
# Snapshot current dropdown values so a later user re-select of the same
# item doesn't trigger the info popup (§10.2).
self._last_resolution = self._resolution.currentText()
self._last_model = self._model_combo.currentText() if self._models else ""
# Fill the preview's sample-row dropdown from the remembered Excel. # Fill the preview's sample-row dropdown from the remembered Excel.
self._reload_sample_rows() self._reload_sample_rows()
@@ -483,6 +493,37 @@ class AiOutfitPanel(QWidget):
else: else:
self._preview_view.setPlainText(render_prompt(template, task, resolution)) self._preview_view.setPlainText(render_prompt(template, task, resolution))
# -- switch info popups (user-only; §10.2) --------------------------
def _on_resolution_activated(self, _index):
res = self._resolution.currentText()
if res == self._last_resolution:
return
self._last_resolution = res
from services.ai_image_service import resolution_timeout
QMessageBox.information(
self, "分辨率已切换",
"已切换分辨率到 {}。\n\n"
"· 单任务超时约 {} 秒,分辨率越高越慢。\n"
"· 仅在下次「开始生成」生效,不影响正在进行的批次。".format(
res, resolution_timeout(res)))
def _on_model_activated(self, _index):
name = self._model_combo.currentText()
if name == self._last_model:
return
self._last_model = name
api_type = "auto"
idx = self._model_combo.currentIndex()
if self._models and 0 <= idx < len(self._models):
api_type = self._models[idx].get("api_type", "auto") or "auto"
QMessageBox.information(
self, "AI 模型已切换",
"已切换模型到 {}。\n\n"
"· 调用方式:{}。\n"
"· 不同模型的计费与效果可能不同。\n"
"· 仅在下次「开始生成」生效。".format(name, api_type))
# -- run control ---------------------------------------------------- # -- run control ----------------------------------------------------
def _start(self): def _start(self):
+4 -4
View File
@@ -1098,7 +1098,7 @@
需求:用户手动切换「分辨率」或「AI 模型」下拉时弹信息框告知影响(**只告知、不拦截、不还原**)。决策:每次实际更换都弹一次。 需求:用户手动切换「分辨率」或「AI 模型」下拉时弹信息框告知影响(**只告知、不拦截、不还原**)。决策:每次实际更换都弹一次。
- [ ] `app/widgets/ai_outfit_panel.py`:给 `_resolution` / `_model_combo` 接 **`activated`** 信号(非 `currentIndexChanged`,避免启动/载配置误弹);仅值实际改变时 `QMessageBox.information`,保持新选项、不回退 - [x] `app/widgets/ai_outfit_panel.py`:给 `_resolution` / `_model_combo` 接 **`activated`** 信号(非 `currentIndexChanged`,避免启动/载配置误弹);仅值实际改变时 `QMessageBox.information`,保持新选项、不回退
- [ ] 分辨率文案带 `ai_image_service.resolution_timeout` 的超时秒数(512/1K/2K/4K→180/240/360/600)+「下次生效」 - [x] 分辨率文案带 `ai_image_service.resolution_timeout` 的超时秒数(512/1K/2K/4K→180/240/360/600)+「下次生效」
- [ ] AI 模型文案带该模型 `api_type` + 计费/效果可能不同 +「下次生效」 - [x] AI 模型文案带该模型 `api_type` + 计费/效果可能不同 +「下次生效」
- [ ] 离屏验证:程序化赋值(`apply_config`/`_set_combo`/`_fill_sample_combo`)不弹;用户切换才弹 - [x] 离屏验证:程序化赋值(`apply_config`/`_fill_sample_combo`)不弹(0 次);用户 1K→4K 弹 1 次(含 600s)、同项重选不弹、换模型弹(含 api_type)