fix: Step 7 路由 + 发送端字符串对齐(消除 KeyError)+ 配套防御性补强
核心修复 - panel_registry: step7_index class_ref 换绑 Step7View(最小侵入式对位,保持 step_id 保护全项目 18 处下游引用) - step7_view._on_run_single_clicked: 'step7' → 'step7_index'(wrapped_config key + step_name 同步对齐,消除 PipelineScheduler 抛 KeyError "未注册的步骤: 'step7'") 配套防御性补强 - pipeline_executor.run_single_step_handler: 后台 is_running 时改 QMessageBox 警告 + LogMessage,防多次点击死锁 - worker_thread.run_single_step: 兼容嵌套/扁平 config 格式,嵌套子 dict 为空时回退扁平读取 - 公式 ListWidget layout 修复:setUniformItemSizes + stretch=1 + update(),消除 step7_view 加载后坍塌/不刷新
This commit is contained in:
@ -18,7 +18,7 @@ from src.gui.panels.step3_panel import Step3Panel
|
||||
from src.gui.panels.step4_sampling_panel import Step4SamplingPanel
|
||||
from src.gui.panels.step5_clean_panel import Step5CleanPanel
|
||||
from src.gui.panels.step6_feature_panel import Step6FeaturePanel
|
||||
from src.gui.panels.step7_index_panel import Step7IndexPanel
|
||||
from src.new.views.step7_view import Step7View
|
||||
from src.gui.panels.step8_ml_train_panel import Step8MlTrainPanel
|
||||
from src.gui.panels.step9_ml_predict_panel import Step9MlPredictPanel
|
||||
from src.gui.panels.step10_watercolor_panel import Step10WatercolorPanel
|
||||
@ -112,7 +112,7 @@ PANEL_REGISTRY = [
|
||||
},
|
||||
{
|
||||
'step_id': 'step7_index',
|
||||
'class_ref': Step7IndexPanel,
|
||||
'class_ref': Step7View,
|
||||
'title': '水质光谱指数计算',
|
||||
'icon': '7.png',
|
||||
'stage': '阶段二:样本数据准备',
|
||||
|
||||
@ -409,6 +409,8 @@ class PipelineExecutor(QObject):
|
||||
step_name = data.get('step_name')
|
||||
config = data.get('config')
|
||||
|
||||
print(f"==== Executor 收到单步请求: {step_name} ====", flush=True)
|
||||
|
||||
if not step_name:
|
||||
global_event_bus.publish('LogMessage', {
|
||||
'message': '[单步执行] 请求缺少 step_name,忽略',
|
||||
@ -416,6 +418,18 @@ class PipelineExecutor(QObject):
|
||||
})
|
||||
return
|
||||
|
||||
# ★ 防死锁:若已有 Worker 在运行,不静默吞掉,而是通知用户
|
||||
if self.is_running:
|
||||
global_event_bus.publish('LogMessage', {
|
||||
'message': f'[单步执行] 后台正在运行中,无法启动 {step_name}。请等待当前任务完成或手动停止后再试。',
|
||||
'level': 'warning',
|
||||
})
|
||||
QMessageBox.warning(
|
||||
self.parent(), "后台忙碌",
|
||||
f"后台正在运行中,无法启动 {step_name}。\n\n请等待当前任务完成,或点击「停止」按钮后再试。"
|
||||
)
|
||||
return
|
||||
|
||||
global_event_bus.publish('LogMessage', {
|
||||
'message': f'[单步执行] 收到 {step_name} 的执行请求',
|
||||
'level': 'info',
|
||||
|
||||
@ -338,8 +338,18 @@ class WorkerThread(QThread):
|
||||
pass
|
||||
|
||||
def run_single_step(self, scheduler, step_name, config):
|
||||
"""使用新调度器运行单个步骤。"""
|
||||
step_config = dict(config.get(step_name, {}))
|
||||
"""使用新调度器运行单个步骤。
|
||||
|
||||
config 兼容两种格式:
|
||||
嵌套格式:{'step7': {'training_csv_path': ..., ...}}
|
||||
扁平格式:{'training_csv_path': ..., 'formula_names': [...], ...}
|
||||
优先检测嵌套格式;若 step_name 对应的子 dict 为空,则回退到扁平格式。
|
||||
"""
|
||||
nested = config.get(step_name)
|
||||
if nested and isinstance(nested, dict) and len(nested) > 0:
|
||||
step_config = dict(nested)
|
||||
else:
|
||||
step_config = dict(config)
|
||||
|
||||
# 透传外部预训练模型(非空才覆盖)
|
||||
for key in ('_external_model', '_external_model_path',
|
||||
|
||||
@ -123,6 +123,7 @@ class Step7IndexPanel(QWidget):
|
||||
|
||||
self.formula_list = QListWidget()
|
||||
self.formula_list.setSelectionMode(QAbstractItemView.MultiSelection)
|
||||
self.formula_list.setMinimumHeight(300)
|
||||
self.formula_list.itemChanged.connect(self._on_item_changed)
|
||||
self.formula_layout.addWidget(self.formula_list)
|
||||
|
||||
|
||||
@ -129,9 +129,10 @@ class Step7View(BaseView):
|
||||
self.formula_list.setSelectionMode(QListWidget.MultiSelection)
|
||||
self.formula_list.setMinimumHeight(300)
|
||||
self.formula_list.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
self.formula_list.setUniformItemSizes(True)
|
||||
# view 层不需要 itemChanged 副作用;service 接管时再启用
|
||||
self.formula_list.blockSignals(True)
|
||||
formula_outer_layout.addWidget(self.formula_list)
|
||||
formula_outer_layout.addWidget(self.formula_list, stretch=1)
|
||||
|
||||
self.formula_group.setLayout(formula_outer_layout)
|
||||
layout.addWidget(self.formula_group)
|
||||
@ -233,6 +234,8 @@ class Step7View(BaseView):
|
||||
self.index_checkboxes[name] = item
|
||||
self.formula_list.blockSignals(False)
|
||||
self.formula_list.adjustSize()
|
||||
self.formula_list.updateGeometry()
|
||||
self.update()
|
||||
|
||||
for btn in (self.select_all_btn, self.deselect_all_btn,
|
||||
self.select_ratio_btn, self.select_conc_btn, self.refresh_button):
|
||||
@ -319,6 +322,14 @@ class Step7View(BaseView):
|
||||
# 执行入口
|
||||
# ------------------------------------------------------------------
|
||||
def _on_run_single_clicked(self):
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
config = self.get_config()
|
||||
global_event_bus.publish('RequestRunSingleStep', {'step_name': 'step7', 'config': config})
|
||||
import traceback
|
||||
print("==== Step 7 计算按钮物理按下 ====", flush=True)
|
||||
try:
|
||||
from src.gui.core.event_bus import global_event_bus
|
||||
config = self.get_config()
|
||||
wrapped_config = {'step7_index': config}
|
||||
global_event_bus.publish('RequestRunSingleStep', {'step_name': 'step7_index', 'config': wrapped_config})
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
QMessageBox.critical(self, "Step7 发射失败", f"收集配置或发送请求时异常:\n\n{e}")
|
||||
|
||||
Reference in New Issue
Block a user