feat: 完成PySide6 worker基座

- 新增 BaseWorker 通用 signals、取消标记和统一 run 入口

- 新增 run_worker QThread 包装与生命周期清理

- 新增 worker 单元测试覆盖 signal、取消、异常和类型校验

- 更新任务看板、API 合约、架构、当前状态和进度记录
This commit is contained in:
chengma
2026-06-27 10:05:29 +08:00
parent b8318c881d
commit 479ab5c41d
7 changed files with 276 additions and 12 deletions
+12 -2
View File
@@ -225,9 +225,11 @@ TAB_TITLES: list[str] # 固定 Tab 顺序
`MainWindow` 目前只实现五 Tab 空壳与基础状态栏;业务控件按后续 Tab 任务逐步填充。缺 PySide6 时 `main()` 返回 1 并输出明确提示。
## workers 模块(`app/workers.py`,待建,PySide6)
## workers 模块(`app/workers.py`,已建,PySide6)
```python
QT_IMPORT_ERROR: Exception|None
class WorkerError(RuntimeError): ...
# worker 约定
class BaseWorker(QObject):
@@ -238,16 +240,24 @@ class BaseWorker(QObject):
finished = Signal(dict) # summary
cancelled = Signal(dict)
def cancel(self) -> None: ...
def is_cancelled(self) -> bool: ...
def should_cancel(self) -> bool: ...
def execute(self) -> dict|None: ... # 子类实现;不要直接操作 QWidget
def run(self) -> None: ... # QThread.started 触发,统一发 terminal signal
run_worker(worker: BaseWorker) -> QThread # 绑定 signals、启动、收尾 deleteLater
run_worker(worker: BaseWorker, thread_name=None, start=True) -> QThread
# moveToThread + 绑定 started/finished/cancelled + 收尾 deleteLater;
# 默认立即 start;测试或调用方需要先连额外信号时可 start=False 后手动 thread.start()
```
要点:
- GUI 线程只操作 Qt widget;后台 worker 不直接访问 QWidget。
- `workers.py` 不导入 `QtWidgets`;业务 worker 子类只通过 signal 回传 UI 所需数据。
- 采集、AI 生成、更新、Excel 回写都通过 worker 执行,用 signal 回传进度。
- 每个 worker/线程按需创建自己的 SQLite connection,不跨线程共享连接。
- ③ 的批量确认弹窗在 GUI 主线程完成;用户确认后才创建 `ApplyWorker`。
- `execute()` 未捕获异常会发 `failed(-1, error)` 与 `finished({"ok": False, "error": ...})`;普通单行失败由业务 worker 自己发 `failed(task_id, error)` 后继续处理。
## 启动入口