feat: 懒加载面板Catch-up状态回放 + 上一步/下一步向导导航按钮

This commit is contained in:
DXC
2026-06-18 11:18:37 +08:00
parent d6c003a211
commit f61a3dfb1d
2 changed files with 154 additions and 33 deletions

View File

@ -88,8 +88,6 @@ class WaterQualityGUI(QMainWindow):
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(my_appid)
super().__init__()
self._is_syncing = False
icon_path = get_resource_path("data/icons-1/uitubiao.ico")
self.setWindowIcon(QIcon(icon_path))
@ -282,6 +280,7 @@ class WaterQualityGUI(QMainWindow):
self.addToolBar(Qt.TopToolBarArea, banner_toolbar)
def _create_central_layout(self):
from src.gui.styles import ModernStylesheet
central_widget = QWidget()
main_layout = QHBoxLayout()
main_layout.setContentsMargins(0, 0, 0, 0)
@ -295,9 +294,27 @@ class WaterQualityGUI(QMainWindow):
right_layout.setSpacing(10)
self._tab_widget = self._panel_factory.create_tab_widget(icons_dir="data/icons")
self._tab_widget.currentChanged.connect(self._on_tab_changed)
self._tab_widget.tabBar().setVisible(False)
right_layout.addWidget(self._tab_widget, 3)
# 上一步 / 下一步 导航按钮
nav_btn_layout = QHBoxLayout()
nav_btn_layout.setSpacing(10)
self._prev_btn = QPushButton("< 上一步")
self._prev_btn.setMinimumHeight(32)
self._prev_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('default'))
self._prev_btn.clicked.connect(self._on_prev_clicked)
nav_btn_layout.addWidget(self._prev_btn)
self._next_btn = QPushButton("下一步 >")
self._next_btn.setMinimumHeight(32)
self._next_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet('default'))
self._next_btn.clicked.connect(self._on_next_clicked)
nav_btn_layout.addWidget(self._next_btn)
nav_btn_layout.addStretch()
right_layout.addLayout(nav_btn_layout)
right_layout.addWidget(self._log_manager.create_log_panel(), 1)
right_widget.setLayout(right_layout)
@ -419,6 +436,15 @@ class WaterQualityGUI(QMainWindow):
work_dir = data.get('work_dir', '')
self.statusBar().showMessage(f"工作目录: {work_dir}")
# 遍历已加载面板,调用 update_from_config 重建内存级参数和默认输出路径
for step_id, panel in self._panel_factory.get_loaded_panels().items():
if not hasattr(panel, 'update_from_config'):
continue
try:
panel.update_from_config(work_dir=work_dir, pipeline=None)
except Exception:
pass
def _on_run_all_clicked(self):
print("==== 按钮确实被按下了 ====", flush=True)
try:
@ -428,12 +454,11 @@ class WaterQualityGUI(QMainWindow):
traceback.print_exc()
# ================================================================
# 导航 Tab 双向同步(纯 UI 路由
# 导航 Tab 单向路由(左侧 List 驱动右侧 TabTab 头部已隐藏
# ================================================================
def _on_step_list_changed(self, index):
if self._is_syncing:
return
"""左侧导航 → 右侧 Tab 单向路由Tab 头部已隐藏,无反向同步)。"""
if index < 0:
return
item = self._step_list.item(index)
@ -446,36 +471,47 @@ class WaterQualityGUI(QMainWindow):
tab_index = get_tab_index(item_data)
if tab_index < 0:
return
self._is_syncing = True
try:
# ★ 先触发懒加载get_panel 内部 _ensure_loaded 自带 blockSignals
# 保护 removeTab/insertTab面板实例化完成后再切 Tab
# 此时 _ensure_loaded 发现已加载直接返回,不再触发索引偏移
self._panel_factory.get_panel(item_data)
self._tab_widget.setCurrentIndex(tab_index)
finally:
self._is_syncing = False
# 先触发懒加载再切 Tab避免 removeTab/insertTab 与导航事件重叠
self._panel_factory.get_panel(item_data)
self._tab_widget.setCurrentIndex(tab_index)
def _on_tab_changed(self, index):
if self._is_syncing:
return
if index < 0:
return
from src.gui.core.panel_registry import get_step_id_by_tab_index
target_step_id = get_step_id_by_tab_index(index)
if target_step_id is None:
return
for row in range(self._step_list.count()):
item = self._step_list.item(row)
# 动态更新上一步/下一步按钮可用状态
self._prev_btn.setEnabled(self._find_prev_step_row(index) is not None)
self._next_btn.setEnabled(self._find_next_step_row(index) is not None)
def _find_prev_step_row(self, current_row):
"""从 current_row 向上遍历,跳过 stage_header 和空分隔符,返回上一个有效 step 的行号。"""
for i in range(current_row - 1, -1, -1):
item = self._step_list.item(i)
if not item:
continue
if item.data(Qt.UserRole) == target_step_id:
self._is_syncing = True
try:
self._step_list.setCurrentRow(row)
finally:
self._is_syncing = False
break
data = item.data(Qt.UserRole)
if data and data != "stage_header":
return i
return None
def _find_next_step_row(self, current_row):
"""从 current_row 向下遍历,跳过 stage_header 和空分隔符,返回下一个有效 step 的行号。"""
for i in range(current_row + 1, self._step_list.count()):
item = self._step_list.item(i)
if not item:
continue
data = item.data(Qt.UserRole)
if data and data != "stage_header":
return i
return None
def _on_prev_clicked(self):
"""上一步按钮:跳转到上一个有效步骤。"""
row = self._find_prev_step_row(self._step_list.currentRow())
if row is not None:
self._step_list.setCurrentRow(row)
def _on_next_clicked(self):
"""下一步按钮:跳转到下一个有效步骤。"""
row = self._find_next_step_row(self._step_list.currentRow())
if row is not None:
self._step_list.setCurrentRow(row)
# ================================================================
# 横幅自适应