diff --git a/app/gui/tabs/apply.py b/app/gui/tabs/apply.py index 77ab29d..13ddc69 100644 --- a/app/gui/tabs/apply.py +++ b/app/gui/tabs/apply.py @@ -376,14 +376,20 @@ class ApplyTab(QWidget): ) def _populate_batch_filter(self, batches, selected_batch): - previous = selected_batch if selected_batch in {batch.id for batch in batches} else None + had_previous_items = self.batch_filter.count() > 0 self.batch_filter.blockSignals(True) self.batch_filter.clear() self.batch_filter.addItem("全部批次", None) for batch in batches: self.batch_filter.addItem(self._batch_label(batch), batch.id) - index = self.batch_filter.findData(previous) - self.batch_filter.setCurrentIndex(index if index >= 0 else 0) + self.batch_filter.setCurrentIndex( + _batch_filter_current_index( + self.batch_filter, + batches, + selected_batch, + had_previous_items, + ) + ) self.batch_filter.blockSignals(False) def _populate_shop_filter(self, tasks, account_rows, selected_shop): diff --git a/app/gui/tabs/collect.py b/app/gui/tabs/collect.py index fbf4725..30c6182 100644 --- a/app/gui/tabs/collect.py +++ b/app/gui/tabs/collect.py @@ -375,15 +375,20 @@ class CollectTab(QWidget): self._update_delete_batch_button() def _populate_batch_filter(self, batches, selected_batch): - batch_ids = {batch.id for batch in batches} - previous = selected_batch if selected_batch in batch_ids else None + had_previous_items = self.batch_filter.count() > 0 self.batch_filter.blockSignals(True) self.batch_filter.clear() self.batch_filter.addItem("全部批次", None) for batch in batches: self.batch_filter.addItem(self._batch_label(batch), batch.id) - index = self.batch_filter.findData(previous) - self.batch_filter.setCurrentIndex(index if index >= 0 else 0) + self.batch_filter.setCurrentIndex( + _batch_filter_current_index( + self.batch_filter, + batches, + selected_batch, + had_previous_items, + ) + ) self.batch_filter.blockSignals(False) def _batch_label(self, batch): diff --git a/app/gui/tabs/generate.py b/app/gui/tabs/generate.py index beb8da8..8541669 100644 --- a/app/gui/tabs/generate.py +++ b/app/gui/tabs/generate.py @@ -1000,14 +1000,20 @@ class GenerateTab(QWidget): _set_empty_state(self.empty_state_card, self.empty_state_label, self.empty_state_button) def _populate_batch_filter(self, batches, selected_batch): - previous = selected_batch if selected_batch in {batch.id for batch in batches} else None + had_previous_items = self.batch_filter.count() > 0 self.batch_filter.blockSignals(True) self.batch_filter.clear() self.batch_filter.addItem("全部批次", None) for batch in batches: self.batch_filter.addItem(self._batch_label(batch), batch.id) - index = self.batch_filter.findData(previous) - self.batch_filter.setCurrentIndex(index if index >= 0 else 0) + self.batch_filter.setCurrentIndex( + _batch_filter_current_index( + self.batch_filter, + batches, + selected_batch, + had_previous_items, + ) + ) self.batch_filter.blockSignals(False) def _populate_shop_filter(self, tasks, account_rows, selected_shop): diff --git a/app/gui/widgets.py b/app/gui/widgets.py index 1f98fca..355ccd1 100644 --- a/app/gui/widgets.py +++ b/app/gui/widgets.py @@ -405,6 +405,19 @@ def _set_batch_progress_overview(label, tasks): label.setText(_format_batch_progress(summary) if active else "") +def _batch_filter_current_index(combo, batches, selected_batch, had_previous_items): + batch_ids = {batch.id for batch in batches} + if selected_batch in batch_ids: + index = combo.findData(selected_batch) + if index >= 0: + return index + if selected_batch is None and had_previous_items: + index = combo.findData(None) + if index >= 0: + return index + return 1 if batches else 0 + + def _database_path(db_path=None, config=None) -> str: return db_path or appconfig.db_path(config) diff --git a/docs/tasks/T-550.md b/docs/tasks/T-550.md index c4c27c4..aec2320 100644 --- a/docs/tasks/T-550.md +++ b/docs/tasks/T-550.md @@ -3,7 +3,7 @@ id: T-550 title: ①②③ 批次下拉默认选中最新批次 phase: 7 deps: [T-523, T-206] -status: TODO +status: DONE created: 2026-07-08 --- @@ -41,4 +41,7 @@ created: 2026-07-08 ## 执行记录 -(做完在此记录:改了哪些文件、跑的验证命令与结果、决策) +- 2026-07-08:完成 T-550。 +- 代码:`app/gui/widgets.py` 新增批次下拉默认索引 helper;①`CollectTab`、②`GenerateTab`、③`ApplyTab` 的 `_populate_batch_filter` 改为“有效已选批次优先;用户手动选过全部批次则保留;无有效已记住选择且存在批次时默认选 index 1 最新批次;无批次回退 index 0”。 +- 测试:`tests/test_gui.py` 新增 ①②③ 批次下拉默认最新批次、无批次回退、已记住批次优先、手动全部批次保留的覆盖;导入测试补充断言 ① 导入后仍自动选中新批次;原②③列表筛选测试显式手动选择「全部批次」,保持原测试目标。 +- 验证:`py -3.10 -m unittest discover -s tests -p "test_gui.py"` 通过(103 tests);`python -m ruff check app tests main.py` 通过;`py -3.10 -m compileall app main.py` 通过;`git diff --check` 通过;`py -3.10 -m unittest discover -s tests` 通过(253 tests)。 diff --git a/tests/test_gui.py b/tests/test_gui.py index b694ab6..f5c950f 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -86,6 +86,17 @@ class GuiTests(TempDirMixin, unittest.TestCase): self.assertIsNotNone(value) self.assertEqual(color, value.name()) + def set_batch_created_at(self, cfg, batch_id, created_at): + conn = db.connect(cfg["db_path"]) + try: + with conn: + conn.execute( + "UPDATE batches SET created_at = ?, updated_at = ? WHERE id = ?", + (created_at, created_at, batch_id), + ) + finally: + conn.close() + def make_fake_message_box(self, selected_label): boxes = [] @@ -511,6 +522,53 @@ class GuiTests(TempDirMixin, unittest.TestCase): self.assert_removed(temp_dir) + def test_workflow_batch_filters_default_to_latest_batch_and_remember_selection(self): + with self.make_temp_dir() as temp_dir: + cfg = self.make_config(temp_dir) + + for tab_class in (CollectTab, GenerateTab, ApplyTab): + tab = tab_class(config=cfg) + self.addCleanup(tab.close) + self.assertEqual(0, tab.batch_filter.currentIndex()) + self.assertIsNone(tab.batch_filter.currentData()) + + accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg) + older_batch = db.create_batch(["older.xlsx"], path=cfg["db_path"]) + newer_batch = db.create_batch(["newer.xlsx"], path=cfg["db_path"]) + self.set_batch_created_at(cfg, older_batch, "2026-07-08T10:00:00") + self.set_batch_created_at(cfg, newer_batch, "2026-07-08T11:00:00") + for batch_id, item_id in ((older_batch, "1001"), (newer_batch, "2001")): + db.insert_tasks( + batch_id, + [ + { + "source_file_abs": os.path.join(temp_dir, f"{item_id}.xlsx"), + "source_sheet": "商品", + "source_row": 2, + "account_name": "Excel主店", + "alias": "alias-a", + "item_id": item_id, + } + ], + path=cfg["db_path"], + ) + + for tab_class in (CollectTab, GenerateTab, ApplyTab): + tab = tab_class(config=cfg) + self.addCleanup(tab.close) + self.assertEqual(newer_batch, tab.batch_filter.currentData()) + self.assertEqual(1, tab.batch_filter.currentIndex()) + + tab.batch_filter.setCurrentIndex(tab.batch_filter.findData(older_batch)) + tab.refresh_tasks() + self.assertEqual(older_batch, tab.batch_filter.currentData()) + + tab.batch_filter.setCurrentIndex(tab.batch_filter.findData(None)) + tab.refresh_tasks() + self.assertIsNone(tab.batch_filter.currentData()) + + self.assert_removed(temp_dir) + def test_settings_tab_loads_ai_models_and_masks_key_field(self): with self.make_temp_dir() as temp_dir: cfg = self.make_config(temp_dir) @@ -2750,6 +2808,7 @@ class GuiTests(TempDirMixin, unittest.TestCase): tab = ApplyTab(config=cfg) self.addCleanup(tab.close) + tab.batch_filter.setCurrentIndex(tab.batch_filter.findData(None)) self.assertIsInstance(tab.task_table, QTableView) self.assertEqual(["店铺", "商品ID", "新标题", "新封面", "阶段", "结果"], tab.model.HEADERS) @@ -3718,6 +3777,7 @@ class GuiTests(TempDirMixin, unittest.TestCase): tab = GenerateTab(config=cfg) self.addCleanup(tab.close) + tab.batch_filter.setCurrentIndex(tab.batch_filter.findData(None)) self.assertEqual("generateItemFilter", tab.item_filter.objectName()) self.assertEqual(4, tab.model.rowCount()) @@ -4243,9 +4303,11 @@ class GuiTests(TempDirMixin, unittest.TestCase): statuses = [] tab = CollectTab(config=cfg, status_callback=statuses.append) self.addCleanup(tab.close) + created = {} def fake_import(file_paths, path=None): batch_id = db.create_batch(file_paths, path=path) + created["batch_id"] = batch_id db.insert_tasks( batch_id, [ @@ -4290,6 +4352,7 @@ class GuiTests(TempDirMixin, unittest.TestCase): self.assertIn("匹配1", tab.summary_label.text()) self.assertEqual("", tab.show_unmatched_button.styleSheet()) self.assertIn("入库1", statuses[-1]) + self.assertEqual(created["batch_id"], tab.batch_filter.currentData()) self.assert_removed(temp_dir)