测试修改
This commit is contained in:
@ -20,18 +20,23 @@ from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSettings
|
||||
from PyQt5.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QFormLayout,
|
||||
QLabel, QCheckBox, QPushButton, QLineEdit,
|
||||
QMessageBox, QFileDialog,
|
||||
QMessageBox, QFileDialog, QProgressBar,
|
||||
)
|
||||
|
||||
from src.gui.styles import ModernStylesheet
|
||||
from src.gui.dialogs import AISettingsDialog, AI_SETTINGS_ORG, AI_SETTINGS_APP
|
||||
|
||||
|
||||
class ReportGenerateThread(QThread):
|
||||
"""后台生成 Word 报告(避免阻塞 UI)。"""
|
||||
finished_ok = pyqtSignal(str)
|
||||
failed = pyqtSignal(str)
|
||||
log_message = pyqtSignal(str, str)
|
||||
class ReportWorkerThread(QThread):
|
||||
"""后台生成 Word 报告(避免阻塞 UI)。
|
||||
三信号协议:
|
||||
- progress(int, str):报告进度百分比 + 当前文案
|
||||
- finished(str):生成的报告绝对路径
|
||||
- error(str):异常信息(含 traceback)
|
||||
"""
|
||||
progress = pyqtSignal(int, str)
|
||||
finished = pyqtSignal(str)
|
||||
error = pyqtSignal(str)
|
||||
|
||||
def __init__(self, work_dir: str, output_dir: Optional[str], report_title: str, enable_ai: bool):
|
||||
super().__init__()
|
||||
@ -44,7 +49,6 @@ class ReportGenerateThread(QThread):
|
||||
try:
|
||||
from src.postprocessing.report_word import WaterQualityReportGenerator, ReportGenerationConfig
|
||||
|
||||
# 唯一数据源:直接从 QSettings 读取 AI 配置
|
||||
s = QSettings(AI_SETTINGS_ORG, AI_SETTINGS_APP)
|
||||
provider = s.value("ai_provider", "minimax", type=str)
|
||||
timeout = int(s.value("timeout_s", 120, type=int))
|
||||
@ -68,10 +72,6 @@ class ReportGenerateThread(QThread):
|
||||
enable_ai_analysis=self.enable_ai,
|
||||
)
|
||||
|
||||
self.log_message.emit(
|
||||
f"报告生成:工作目录={self.work_dir},AI={'开' if self.enable_ai else '关'},Provider={provider}",
|
||||
"info",
|
||||
)
|
||||
gen = WaterQualityReportGenerator(
|
||||
work_dir=self.work_dir,
|
||||
output_dir=self.output_dir,
|
||||
@ -80,10 +80,11 @@ class ReportGenerateThread(QThread):
|
||||
out_path = gen.generate_report(
|
||||
work_dir=self.work_dir,
|
||||
report_title=self.report_title or "水质参数反演分析报告",
|
||||
on_progress=lambda pct, text: self.progress.emit(int(pct), str(text)),
|
||||
)
|
||||
self.finished_ok.emit(str(out_path))
|
||||
self.finished.emit(str(out_path))
|
||||
except Exception as e:
|
||||
self.failed.emit(f"{e}\n{traceback.format_exc()}")
|
||||
self.error.emit(f"{e}\n{traceback.format_exc()}")
|
||||
|
||||
|
||||
class Step13ReportPanel(QWidget):
|
||||
@ -117,11 +118,14 @@ class Step13ReportPanel(QWidget):
|
||||
|
||||
wd_row = QHBoxLayout()
|
||||
self.work_dir_edit = QLineEdit()
|
||||
self.work_dir_edit.setPlaceholderText("选择流程工作目录(含 14_visualization)…")
|
||||
self.work_dir_edit.setPlaceholderText("流程工作目录(含 14_visualization)…")
|
||||
self.work_dir_edit.setReadOnly(True)
|
||||
wd_browse = QPushButton("浏览…")
|
||||
wd_browse.clicked.connect(self.browse_work_dir)
|
||||
wd_browse.setVisible(False)
|
||||
sync_btn = QPushButton("同步主窗口工作目录")
|
||||
sync_btn.clicked.connect(self.sync_work_dir_from_main)
|
||||
sync_btn.setVisible(False)
|
||||
wd_row.addWidget(self.work_dir_edit, 1)
|
||||
wd_row.addWidget(wd_browse)
|
||||
wd_row.addWidget(sync_btn)
|
||||
@ -179,12 +183,27 @@ class Step13ReportPanel(QWidget):
|
||||
btn_row.addStretch()
|
||||
layout.addLayout(btn_row)
|
||||
|
||||
# ── 进度条 + 状态文案 ────────────────────────────────────────────────
|
||||
progress_row = QHBoxLayout()
|
||||
self.progress_label = QLabel("就绪")
|
||||
self.progress_label.setMinimumWidth(220)
|
||||
progress_row.addWidget(self.progress_label)
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setRange(0, 100)
|
||||
self.progress_bar.setValue(0)
|
||||
self.progress_bar.setTextVisible(True)
|
||||
progress_row.addWidget(self.progress_bar, 1)
|
||||
layout.addLayout(progress_row)
|
||||
|
||||
layout.addStretch()
|
||||
self.setLayout(layout)
|
||||
|
||||
# 刷新引擎提示文字
|
||||
self._refresh_ai_label()
|
||||
|
||||
# 初次构建时尝试同步主窗口工作目录
|
||||
self._auto_pull_work_dir()
|
||||
|
||||
def _refresh_ai_label(self):
|
||||
"""从 QSettings 读取当前 Provider 并更新只读标签。"""
|
||||
s = QSettings(AI_SETTINGS_ORG, AI_SETTINGS_APP)
|
||||
@ -229,6 +248,28 @@ class Step13ReportPanel(QWidget):
|
||||
if work_dir:
|
||||
self.work_dir_edit.setText(str(work_dir))
|
||||
|
||||
def _auto_pull_work_dir(self):
|
||||
"""从主窗口自动同步工作目录到 work_dir_edit(无需用户操作)。"""
|
||||
mw = self.main_window
|
||||
if mw is not None and getattr(mw, "work_dir", None):
|
||||
wd = str(mw.work_dir)
|
||||
cur = self.work_dir_edit.text().strip()
|
||||
if wd and wd != cur:
|
||||
self.work_dir_edit.setText(wd)
|
||||
|
||||
def update_from_config(self, work_dir=None, pipeline=None):
|
||||
"""切入面板时由主窗口统一调用,把当前 work_dir 同步到本面板。
|
||||
解耦手动 browse:work_dir_edit 已 ReadOnly,外部只能通过此入口更新。
|
||||
"""
|
||||
if work_dir:
|
||||
self.work_dir_edit.setText(str(work_dir))
|
||||
self._auto_pull_work_dir()
|
||||
|
||||
def showEvent(self, event):
|
||||
"""Tab 切换到本面板时再次兜底同步一次(应对 init_ui 时尚未绑定 main_window 的场景)。"""
|
||||
super().showEvent(event)
|
||||
self._auto_pull_work_dir()
|
||||
|
||||
def get_config(self):
|
||||
"""返回路径和标题配置(AI 配置不由本面板持有)。"""
|
||||
return {
|
||||
@ -271,14 +312,15 @@ class Step13ReportPanel(QWidget):
|
||||
title = self.report_title_edit.text().strip() or "水质参数反演分析报告"
|
||||
enable_ai = self.enable_ai_cb.isChecked()
|
||||
|
||||
# 重置进度条并禁用按钮
|
||||
self.generate_btn.setEnabled(False)
|
||||
self._report_thread = ReportGenerateThread(wd, out, title, enable_ai)
|
||||
self._report_thread.log_message.connect(self._forward_log, Qt.QueuedConnection)
|
||||
self._report_thread.finished_ok.connect(self._on_report_ok, Qt.QueuedConnection)
|
||||
self._report_thread.failed.connect(self._on_report_fail, Qt.QueuedConnection)
|
||||
self._report_thread.finished.connect(
|
||||
lambda: self.generate_btn.setEnabled(True), Qt.QueuedConnection
|
||||
)
|
||||
self.progress_bar.setValue(0)
|
||||
self.progress_label.setText("正在准备生成…")
|
||||
|
||||
self._report_thread = ReportWorkerThread(wd, out, title, enable_ai)
|
||||
self._report_thread.progress.connect(self._on_progress, Qt.QueuedConnection)
|
||||
self._report_thread.finished.connect(self._on_finished, Qt.QueuedConnection)
|
||||
self._report_thread.error.connect(self._on_error, Qt.QueuedConnection)
|
||||
self._report_thread.start()
|
||||
self._forward_log("已开始生成 Word 报告…", "info")
|
||||
|
||||
@ -289,10 +331,22 @@ class Step13ReportPanel(QWidget):
|
||||
else:
|
||||
print(f"[{level}] {msg}")
|
||||
|
||||
def _on_report_ok(self, path: str):
|
||||
def _on_progress(self, pct: int, text: str):
|
||||
"""接收 ReportWorkerThread.progress(int, str) —— 主线程槽。"""
|
||||
self.progress_bar.setValue(int(pct))
|
||||
self.progress_label.setText(text or f"{pct}%")
|
||||
|
||||
def _on_finished(self, path: str):
|
||||
"""报告生成成功 —— 主线程槽。"""
|
||||
self.progress_bar.setValue(100)
|
||||
self.progress_label.setText("完成")
|
||||
self.generate_btn.setEnabled(True)
|
||||
QMessageBox.information(self, "完成", f"报告已生成:\n{path}")
|
||||
self._forward_log(f"Word 报告已保存: {path}", "info")
|
||||
|
||||
def _on_report_fail(self, err: str):
|
||||
def _on_error(self, err: str):
|
||||
"""报告生成异常 —— 主线程槽。"""
|
||||
self.progress_label.setText("失败")
|
||||
self.generate_btn.setEnabled(True)
|
||||
QMessageBox.critical(self, "失败", f"报告生成失败:\n{err[:800]}")
|
||||
self._forward_log(err, "error")
|
||||
Reference in New Issue
Block a user