feat(new-arch):主窗口全功能增强(图标系统 + 全链路参数同步 + 服务输出统一解析 + Step12 分类浏览)

1. main_view.py:图标系统 + 全链路参数自动传导
   - 新增 _res() 解析项目根的相对路径,PyInstaller 打包后兼容 sys._MEIPASS。
   - 新增 QListWidgetItem / QMessageBox 导入,左侧导航列表支持右键菜单 + 错误弹窗。
   - ROUTES 12 条全部新增 icon 字段("1.png" 等),侧边栏显示业务图标。
   - 新增 step_outputs 缓存机制:每个 step 完成后把 output_path 写入 self.step_outputs。
   - 新增 _sync_dependencies() 同步函数 + _safe_set_config() 包装器,
     按依赖图把上游产物推给下游 view:
       step1 → step6 water_mask_path
       step3 → step4 / step6 / step10 deglint_img_path / bsq_path
       step4 → step9 sampling_csv_path
       step5 → step6 csv_path
       step6 → step7 / step8 training_csv_path
       step8 → step9 models_dir(父目录)
       step9 → step11 prediction_csv_dir / prediction_csv_path(双推)
       step10 → step11 geotiff_dir / geotiff_path(双推)

2. services/step1-13:统一输出解析器集成
   - 新增 src/new/services/_output_resolver.py,提供 resolve_output_dir /
     copy_to_user_path / get_user_output_path / is_user_specified 四个共享工具。
   - 每个 service 把原有的私有 _resolve_xxx_dir 改为调用 resolve_output_dir,
     强制执行"用户优先"规则(用户指定 output_path 时用其父目录,否则用 work_dir/<subdir>)。
   - 用户指定文件名 vs 底层硬编码文件名的"事后劫持"通过 copy_to_user_path 完成
     (覆盖 step2、step4、step7、step8 等底层 step 不接受 output_path 关键字的步骤)。

3. views/step12_view.py:恢复 ImageCategoryTree + ImageViewerWidget 高级组件
   - 删掉精简版占位 Label,挂回旧版的 ImageCategoryTree(按"模型评估/光谱分析/
     统计图表/处理结果/含量分布图"五类自动归类工作目录下的图像文件)。
   - 挂回 ImageViewerWidget(滚轮缩放 0.1x-5x + 50ms 防抖 + FastTransformation/
     SmoothTransformation 智能切换 + Ctrl+Wheel + 工具栏)。
   - 扫描按钮接通 image_tree.scan_directory(),选中节点即时加载到 image_viewer。
   - 按钮样式切换为 ModernStylesheet(success/primary)统一视觉。
This commit is contained in:
DXC
2026-06-17 13:28:58 +08:00
parent 9cb3c8ed0d
commit 6a962f5e8f
15 changed files with 607 additions and 116 deletions

View File

@ -33,13 +33,21 @@ from pathlib import Path
from typing import Any, Dict
from src.core.steps.data_preparation_step import DataPreparationStep
from src.new.services._output_resolver import (
copy_to_user_path,
get_user_output_path,
is_user_specified,
resolve_output_dir,
)
def _resolve_output_dir(output_path: str | None, work_dir: str) -> Path:
"""根据 output_path / work_dir 计算清洗后 CSV 输出目录"""
if output_path:
return Path(output_path).parent
return Path(work_dir) / "5_Data_Cleaning"
def _resolve_output_dir(config: Dict[str, Any], work_dir: str) -> tuple[Path, str]:
"""根据 output_path / work_dir 计算清洗后 CSV 输出目录
使用共享解析器强制执行"用户优先"规则——用户指定 output_path 时用其父目录,
否则用 work_dir/5_Data_Cleaning 默认。
"""
return resolve_output_dir(config, work_dir, "5_Data_Cleaning", "output_path", "output_dir")
def execute_step5(config: Dict[str, Any]) -> Dict[str, Any]:
@ -57,7 +65,7 @@ def execute_step5(config: Dict[str, Any]) -> Dict[str, Any]:
output_path = config.get("output_path")
work_dir = config.get("work_dir") or "."
output_dir = _resolve_output_dir(output_path, work_dir)
output_dir, _source = _resolve_output_dir(config, work_dir)
mode = "csv_clean"
# ---------- 提前失败检查 ----------
@ -128,6 +136,14 @@ def execute_step5(config: Dict[str, Any]) -> Dict[str, Any]:
"mode": mode,
}
# ---------- 事后劫持:用户指定文件名 vs 底层硬编码文件名 ----------
# process_csv 内部硬编码输出文件名 processed_data.csv
# 用户浏览指定的文件名(无论是 .csv 还是别的格式)被底层忽略。
user_path = config.get("output_path")
if user_path:
result_path = copy_to_user_path(result_path, user_path)
p = Path(result_path)
return {
"status": "completed",
"output_path": str(p).replace("\\", "/"),