From 92fa48bb01580ea3fbe1955ebc3ab259df4086d8 Mon Sep 17 00:00:00 2001 From: ila Date: Sat, 4 Jul 2026 17:04:23 +0800 Subject: [PATCH] feat: color title wait status --- docs/11-ai-outfit.md | 2 ++ src/app/widgets/ai_outfit_panel.py | 24 ++++++++++++++++-------- tasks.md | 27 +++++++++++++++++++++++++++ tests/test_ai_outfit_panel.py | 14 ++++++++++++++ 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/docs/11-ai-outfit.md b/docs/11-ai-outfit.md index f0913b0..4805706 100644 --- a/docs/11-ai-outfit.md +++ b/docs/11-ai-outfit.md @@ -551,8 +551,10 @@ Excel 行 → `OutfitTask` 列表的转换由 `excel_service` 完成;核心只 - 计时每秒刷新,直到请求返回、失败、超时或用户停止。 - 请求返回后进入 Excel 写回阶段时,文案可改为 `写入中 已完成/总数`;全部写回后显示 `完成 N 条` 并在短暂停留后复位。 - 超时或失败时显示 `等待超时` / `生成失败`,同时保留弹窗和日志里的详细原因。 +- 文字颜色按状态变化:`等待中` 使用信息蓝 `#0078d4`,`写入中` / `完成 N 条` 使用完成绿 `#107c10`,`等待超时` / `生成失败` / `完成 N 条,失败 M` 使用错误红 `#c42b1c`。 产品边界: - 这不是模型真实进度条,不能用百分比暗示“已生成多少”。它只表达“已等待多久 / 最长等多久”。 - 现有右栏本次进度条继续按 Excel 行/写回进度推进;标题 label 右侧计时只覆盖“单次标题请求等待”这段长等待空窗。 +- 只给文字本身上色,不加背景色、不做闪烁、不放大字号,避免在左栏窄空间里形成过强干扰。 diff --git a/src/app/widgets/ai_outfit_panel.py b/src/app/widgets/ai_outfit_panel.py index 635a104..e6f16fe 100644 --- a/src/app/widgets/ai_outfit_panel.py +++ b/src/app/widgets/ai_outfit_panel.py @@ -55,7 +55,12 @@ logger = logging.getLogger(__name__) _RESOLUTIONS = ["512", "1K", "2K", "4K"] _QUALITIES = ["小文件", "均衡", "高清"] _COLS = ["行", "标题", "货号", "衣服图", "状态", "结果 / 原因"] - +_TITLE_WAIT_COLORS = { + "waiting": "#0078d4", # 信息蓝:请求已发出,等待模型返回 + "writing": "#107c10", # 完成绿:已拿到标题,正在写回 Excel + "success": "#107c10", + "error": "#c42b1c", +} # --------------------------------------------------------------------------- # Background worker @@ -1027,7 +1032,7 @@ class AiOutfitPanel(QWidget): def _on_title_progress(self, completed, total, result): if self._title_wait_timer.isActive(): self._title_wait_timer.stop() - self._set_title_wait_text("写入中 {}/{}".format(completed, total)) + self._set_title_wait_text("写入中 {}/{}".format(completed, total), "writing") row = self._row_to_table.get(result.task.row_index) if row is not None: @@ -1046,9 +1051,9 @@ class AiOutfitPanel(QWidget): def _on_title_finished(self, success, fail): self._set_title_running(False) if fail: - self._finish_title_wait("完成 {} 条,失败 {}".format(success, fail)) + self._finish_title_wait("完成 {} 条,失败 {}".format(success, fail), "error") else: - self._finish_title_wait("完成 {} 条".format(success)) + self._finish_title_wait("完成 {} 条".format(success), "success") msg = "标题生成结束:成功 {},失败 {}".format(success, fail) self._append_log(msg) self._reload_after_titles() @@ -1061,7 +1066,7 @@ class AiOutfitPanel(QWidget): def _on_title_failed(self, message): self._set_title_running(False) - self._finish_title_wait("生成失败") + self._finish_title_wait("生成失败", "error") self._append_log("标题生成无法开始:" + message) QMessageBox.warning(self, "无法开始", message) @@ -1115,13 +1120,15 @@ class AiOutfitPanel(QWidget): self._format_wait_seconds(elapsed), self._format_wait_seconds(self._title_wait_limit_seconds))) - def _set_title_wait_text(self, text): + def _set_title_wait_text(self, text, tone="waiting"): self._title_wait_label.setText(str(text)) + color = _TITLE_WAIT_COLORS.get(tone, _TITLE_WAIT_COLORS["waiting"]) + self._title_wait_label.setStyleSheet("color:{};".format(color)) self._title_wait_label.setVisible(bool(text)) - def _finish_title_wait(self, text): + def _finish_title_wait(self, text, tone="success"): self._title_wait_timer.stop() - self._set_title_wait_text(text) + self._set_title_wait_text(text, tone) token = self._title_wait_generation QTimer.singleShot(4000, lambda: self._reset_title_wait_label(token)) @@ -1130,6 +1137,7 @@ class AiOutfitPanel(QWidget): return self._title_wait_timer.stop() self._title_wait_label.clear() + self._title_wait_label.setStyleSheet("") self._title_wait_label.setVisible(False) def _format_wait_seconds(self, seconds): diff --git a/tasks.md b/tasks.md index 0e916d8..bda26c2 100644 --- a/tasks.md +++ b/tasks.md @@ -1616,3 +1616,30 @@ - [x] 计时文案不暗示模型内部完成百分比 - [x] 标题生成和图片生成互斥、原有进度/明细行为不回退 - [x] 验证:`python -m py_compile src/app/widgets/ai_outfit_panel.py tests/test_ai_outfit_panel.py`、`python tests/test_ai_outfit_panel.py`、离屏启动主窗口通过;全套 `python -m unittest discover -s tests` 仅失败于既有未提交 `packaging/default_config/ai_models.json` 含非空 `api_key`,与本任务无关 + +### 19.33 标题等待计时状态颜色 — docs/11 §17.10 + +前置阅读: + +- `docs/11-ai-outfit.md`(§17.10) +- `src/app/widgets/ai_outfit_panel.py`(`_title_wait_label`、`_set_title_wait_text`、`_finish_title_wait`) +- `tests/test_ai_outfit_panel.py`(标题等待计时离屏测试) + +背景: + +标题等待计时 label 已能显示 `等待中 mm:ss / MM:SS`,但纯黑文字在左栏里容易被标题和提示词区域淹没。需要用低干扰状态色提高可见性,但不能做成真实进度或强警告。 + +任务: + +- [x] `等待中` 使用信息蓝 `#0078d4` +- [x] `写入中` 和纯成功完成使用完成绿 `#107c10` +- [x] `生成失败`、`等待超时`、部分失败完成使用错误红 `#c42b1c` +- [x] 只改变文字颜色,不增加背景色、闪烁或字号变化 +- [x] 测试:离屏断言等待、写入、成功、失败状态使用对应颜色 + +验收: + +- [x] 长等待时 label 更醒目但不喧宾夺主 +- [x] 成功/失败状态一眼可辨 +- [x] 不影响原有等待计时、写回进度和复位行为 +- [x] 验证:`python -m py_compile src/app/widgets/ai_outfit_panel.py tests/test_ai_outfit_panel.py`、`python tests/test_ai_outfit_panel.py`、离屏启动主窗口通过;全套 `python -m unittest discover -s tests` 仅失败于既有未提交 `packaging/default_config/ai_models.json` 含非空 `api_key`,与本任务无关 diff --git a/tests/test_ai_outfit_panel.py b/tests/test_ai_outfit_panel.py index f584261..a483520 100644 --- a/tests/test_ai_outfit_panel.py +++ b/tests/test_ai_outfit_panel.py @@ -131,8 +131,10 @@ class TestAiOutfitPanelDefaults(unittest.TestCase): self.assertFalse(panel._title_wait_label.isHidden()) self.assertEqual(panel._title_wait_label.text(), "等待中 01:35 / 10:00") + self.assertIn("#0078d4", panel._title_wait_label.styleSheet()) self.assertTrue(panel._title_wait_timer.isActive()) panel._reset_title_wait_label() + self.assertEqual(panel._title_wait_label.styleSheet(), "") def test_title_wait_limit_uses_model_timeout_override(self): from services.ai_image_service import AiModelConfig @@ -162,6 +164,18 @@ class TestAiOutfitPanelDefaults(unittest.TestCase): self.assertFalse(panel._title_wait_timer.isActive()) self.assertFalse(panel._title_wait_label.isHidden()) self.assertEqual(panel._title_wait_label.text(), "写入中 1/3") + self.assertIn("#107c10", panel._title_wait_label.styleSheet()) + panel._reset_title_wait_label() + + def test_title_wait_finish_uses_success_and_error_colors(self): + panel = self._panel() + + panel._finish_title_wait("完成 3 条", "success") + self.assertFalse(panel._title_wait_label.isHidden()) + self.assertIn("#107c10", panel._title_wait_label.styleSheet()) + + panel._finish_title_wait("生成失败", "error") + self.assertIn("#c42b1c", panel._title_wait_label.styleSheet()) panel._reset_title_wait_label() def test_prompt_buttons_save_row_insert_title_and_preview(self):