feat: add soft delete for import batches
This commit is contained in:
+105
-4
@@ -1820,12 +1820,14 @@ if QT_IMPORT_ERROR is None:
|
||||
config=None,
|
||||
status_callback=None,
|
||||
open_accounts_callback=None,
|
||||
refresh_workflow_callback=None,
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.config = appconfig.load_config() if config is None else config
|
||||
self.db_path = _database_path(db_path, self.config)
|
||||
self.status_callback = status_callback
|
||||
self.open_accounts_callback = open_accounts_callback
|
||||
self.refresh_workflow_callback = refresh_workflow_callback
|
||||
self.current_batch_id = None
|
||||
self.has_import_result = False
|
||||
self.last_import_stats = None
|
||||
@@ -1841,10 +1843,18 @@ if QT_IMPORT_ERROR is None:
|
||||
self.stop_collect_button = QPushButton("停止")
|
||||
self.write_back_button = QPushButton("回写旧数据到 Excel")
|
||||
self.stop_collect_button.setEnabled(False)
|
||||
self.batch_filter = QComboBox()
|
||||
self.batch_filter.setObjectName("collectBatchFilter")
|
||||
self.delete_batch_button = QPushButton("删除批次")
|
||||
self.delete_batch_button.setObjectName("deleteBatchButton")
|
||||
self.delete_batch_button.setEnabled(False)
|
||||
|
||||
toolbar = QHBoxLayout()
|
||||
toolbar.addWidget(self.import_button)
|
||||
toolbar.addWidget(self.refresh_button)
|
||||
toolbar.addWidget(QLabel("批次"))
|
||||
toolbar.addWidget(self.batch_filter, 2)
|
||||
toolbar.addWidget(self.delete_batch_button)
|
||||
toolbar.addWidget(self.collect_button)
|
||||
toolbar.addWidget(self.stop_collect_button)
|
||||
toolbar.addWidget(self.write_back_button)
|
||||
@@ -1890,6 +1900,8 @@ if QT_IMPORT_ERROR is None:
|
||||
|
||||
self.import_button.clicked.connect(self.import_excel)
|
||||
self.refresh_button.clicked.connect(self.refresh_tasks)
|
||||
self.batch_filter.currentIndexChanged.connect(self.refresh_tasks)
|
||||
self.delete_batch_button.clicked.connect(self.delete_current_batch)
|
||||
self.collect_button.clicked.connect(self.collect_old_data)
|
||||
self.stop_collect_button.clicked.connect(self.stop_collect)
|
||||
self.write_back_button.clicked.connect(self.write_back_old_data)
|
||||
@@ -1981,10 +1993,14 @@ if QT_IMPORT_ERROR is None:
|
||||
def refresh_tasks(self, checked=False):
|
||||
try:
|
||||
db.init_db(self.db_path)
|
||||
if self.current_batch_id is None and self.has_import_result:
|
||||
task_rows = []
|
||||
else:
|
||||
task_rows = db.list_tasks(batch_id=self.current_batch_id, path=self.db_path)
|
||||
batches = db.list_batches(path=self.db_path)
|
||||
selected_batch = self.batch_filter.currentData()
|
||||
if self.current_batch_id and self.batch_filter.findData(self.current_batch_id) < 0:
|
||||
selected_batch = self.current_batch_id
|
||||
self._populate_batch_filter(batches, selected_batch)
|
||||
selected_batch = self.batch_filter.currentData()
|
||||
self.current_batch_id = selected_batch
|
||||
task_rows = db.list_tasks(batch_id=selected_batch, path=self.db_path)
|
||||
account_rows = accounts.list_accounts(path=self.db_path, config=self.config)
|
||||
except Exception as exc:
|
||||
self.model.set_tasks([], [])
|
||||
@@ -1994,6 +2010,80 @@ if QT_IMPORT_ERROR is None:
|
||||
self.model.set_tasks(task_rows, account_rows)
|
||||
self._update_summary(task_rows, account_rows)
|
||||
self._update_empty_label(len(task_rows))
|
||||
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
|
||||
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.blockSignals(False)
|
||||
|
||||
def _batch_label(self, batch):
|
||||
source_files = batch.source_files
|
||||
first_file = os.path.basename(source_files[0]) if source_files else batch.id
|
||||
return f"{batch.created_at} · {first_file}"
|
||||
|
||||
def _selected_batch_id(self):
|
||||
return self.batch_filter.currentData()
|
||||
|
||||
def _update_delete_batch_button(self):
|
||||
running = bool(self.collect_thread or self.write_back_thread)
|
||||
self.delete_batch_button.setEnabled((not running) and bool(self._selected_batch_id()))
|
||||
|
||||
def delete_current_batch(self, checked=False):
|
||||
batch_id = self._selected_batch_id()
|
||||
if not batch_id:
|
||||
self._set_status("请先选择一个具体批次")
|
||||
return
|
||||
batch = db.get_batch(batch_id, path=self.db_path)
|
||||
if batch is None:
|
||||
self._set_status("批次不存在或已删除")
|
||||
self.current_batch_id = None
|
||||
self.refresh_tasks()
|
||||
return
|
||||
tasks = db.list_tasks(batch_id=batch_id, path=self.db_path)
|
||||
committed_count = sum(1 for task in tasks if int(getattr(task, "committed", 0) or 0) == 1)
|
||||
lines = [
|
||||
f"确定要软删除批次 {self._batch_label(batch)} 吗?",
|
||||
f"任务数:{len(tasks)}",
|
||||
f"已提交线上:{committed_count}",
|
||||
"",
|
||||
"软删除后,该批次不会再出现在①/②/③页面、筛选、采集、生成、更新或回写入口中。",
|
||||
"软删除只隐藏本地批次,不会回滚 Shopee 线上修改,不删除原始 Excel,也不删除本地图片。",
|
||||
]
|
||||
answer = QMessageBox.question(
|
||||
self,
|
||||
"删除批次",
|
||||
"\n".join(lines),
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No,
|
||||
)
|
||||
if answer != QMessageBox.Yes:
|
||||
self._set_status("已取消删除批次")
|
||||
return
|
||||
try:
|
||||
result = db.delete_batch(batch_id, reason="用户在导入采集页软删除", path=self.db_path)
|
||||
except Exception as exc:
|
||||
QMessageBox.warning(self, "删除批次", str(exc))
|
||||
self._set_status(f"删除批次失败:{exc}")
|
||||
return
|
||||
self.current_batch_id = None
|
||||
self.has_import_result = False
|
||||
self.refresh_tasks()
|
||||
if self.refresh_workflow_callback is not None:
|
||||
self.refresh_workflow_callback()
|
||||
message = "已软删除批次:任务{task_count},已提交线上{committed_count}".format(
|
||||
task_count=result.get("task_count", 0),
|
||||
committed_count=result.get("committed_count", 0),
|
||||
)
|
||||
self._set_status(message)
|
||||
QMessageBox.information(self, "删除批次", message)
|
||||
|
||||
def collect_old_data(self, checked=False):
|
||||
tasks = list(self.model.all_tasks)
|
||||
@@ -2077,12 +2167,16 @@ if QT_IMPORT_ERROR is None:
|
||||
self.collect_button.setEnabled(not running)
|
||||
self.write_back_button.setEnabled(not running)
|
||||
self.stop_collect_button.setEnabled(running)
|
||||
self.batch_filter.setEnabled(not running)
|
||||
self._update_delete_batch_button()
|
||||
|
||||
def _set_write_back_running(self, running):
|
||||
self.import_button.setEnabled(not running)
|
||||
self.refresh_button.setEnabled(not running)
|
||||
self.collect_button.setEnabled(not running)
|
||||
self.write_back_button.setEnabled(not running)
|
||||
self.batch_filter.setEnabled(not running)
|
||||
self._update_delete_batch_button()
|
||||
|
||||
def _forget_collect_thread(self, thread):
|
||||
if self.collect_thread is thread:
|
||||
@@ -4629,6 +4723,7 @@ if QT_IMPORT_ERROR is None:
|
||||
config=self.config,
|
||||
status_callback=self.statusBar().showMessage,
|
||||
open_accounts_callback=lambda: self.open_accounts_tab(),
|
||||
refresh_workflow_callback=lambda: self.refresh_task_tabs(),
|
||||
)
|
||||
if title == "② AI生成":
|
||||
return GenerateTab(
|
||||
@@ -4656,6 +4751,12 @@ if QT_IMPORT_ERROR is None:
|
||||
status_callback=self.statusBar().showMessage,
|
||||
)
|
||||
|
||||
def refresh_task_tabs(self):
|
||||
for index in range(self.tabs.count()):
|
||||
widget = self.tabs.widget(index)
|
||||
if hasattr(widget, "refresh_tasks"):
|
||||
widget.refresh_tasks()
|
||||
|
||||
def _on_tab_changed(self, index):
|
||||
self.statusBar().showMessage(f"当前:{self.tabs.tabText(index)}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user