From bac0a198ffcca52e9b08333a8ae376f2ac3085ea Mon Sep 17 00:00:00 2001 From: gaozheng Date: Thu, 11 Jun 2026 17:00:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E7=BD=91=E6=A0=BC=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=87=92=E5=8A=A0=E8=BD=BD=E6=8E=A5=E7=BA=BF(?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=99=A8=20gridReady=20+=20=E9=A1=B5?= =?UTF-8?q?=E7=AD=BE=E9=A6=96=E6=AC=A1=E6=BF=80=E6=B4=BB=E8=A7=A6=E5=8F=91?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DatasetDetailController 新增 GridData 内嵌结构 + loadGridData slot (busy 守卫, 仅 dd_inversion_data; 拉 rows+色阶type2+异常) + gridReady 信号。 buildTabbedPanel 暴露 tabGroup 供调用方监听页签切换。 DatasetDetailPage 在「网格数据」页签首次激活且未加载时 emit gridDataNeeded; setGridData 转发给 GridDataChartView 并标记已加载(切 ds 重置)。 DatasetDetailPanel 透传 gridDataNeeded / 按 dsId 路由 setGridData。 main.cpp 接线 gridDataNeeded->loadGridData, gridReady->setGridData。 Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app/PanelHeader.cpp | 1 + src/app/PanelHeader.hpp | 5 ++++- src/app/main.cpp | 8 ++++++++ src/app/panels/DatasetDetailPage.cpp | 22 ++++++++++++++++++++++ src/app/panels/DatasetDetailPage.hpp | 7 +++++++ src/app/panels/DatasetDetailPanel.cpp | 11 ++++++++++- src/app/panels/DatasetDetailPanel.hpp | 4 +++- src/controller/DatasetDetailController.cpp | 20 ++++++++++++++++++++ src/controller/DatasetDetailController.hpp | 11 +++++++++++ 9 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/app/PanelHeader.cpp b/src/app/PanelHeader.cpp index 61e1021..8b2fea7 100644 --- a/src/app/PanelHeader.cpp +++ b/src/app/PanelHeader.cpp @@ -125,6 +125,7 @@ TabbedPanel buildTabbedPanel(const QVector& tabs, const QVector
badges; + QButtonGroup* tabGroup = nullptr; }; // 构建带 Tab 表头的面板(首个 Tab 默认激活;点击 Tab 切换下方堆叠内容)。 diff --git a/src/app/main.cpp b/src/app/main.cpp index 22925f8..b979cd4 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -508,6 +508,14 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re detailPanel, [detailPanel](const QString& dsId) { detailPanel->focusDataset(dsId); }); + // ── 网格数据懒加载:网格页首次激活 → 拉 rows+色阶type2+异常 → 回填对应页 ── + QObject::connect(detailPanel, &geopro::app::DatasetDetailPanel::gridDataNeeded, &detailCtrl, + &geopro::controller::DatasetDetailController::loadGridData); + QObject::connect( + &detailCtrl, &geopro::controller::DatasetDetailController::gridReady, detailPanel, + [detailPanel](const geopro::controller::DatasetDetailController::GridData& d) { + detailPanel->setGridData(d); + }); QObject::connect(&detailCtrl, &geopro::controller::DatasetDetailController::loadFailed, &window, [&window](const QString& dsId, const QString& msg) { window.statusBar()->showMessage( diff --git a/src/app/panels/DatasetDetailPage.cpp b/src/app/panels/DatasetDetailPage.cpp index 2c8b7b7..5cf559f 100644 --- a/src/app/panels/DatasetDetailPage.cpp +++ b/src/app/panels/DatasetDetailPage.cpp @@ -1,5 +1,6 @@ #include "panels/DatasetDetailPage.hpp" +#include #include #include "Glyphs.hpp" @@ -9,6 +10,10 @@ namespace geopro::app { +namespace { +constexpr int kGridTabIndex = 1; // 「网格数据」页签在 tabs 中的索引 +} + DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) { auto* lay = new QVBoxLayout(this); lay->setContentsMargins(0, 0, 0, 0); @@ -27,12 +32,29 @@ DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) { auto tabbedPanel = buildTabbedPanel(tabs, actions); lay->addWidget(tabbedPanel.container); + + // 「网格数据」页签首次激活 → 懒加载网格数据(rows 服务端网格化慢,故不随开页同步拉)。 + if (tabbedPanel.tabGroup) { + connect(tabbedPanel.tabGroup, &QButtonGroup::idClicked, this, [this](int idx) { + if (idx != kGridTabIndex || gridRequested_ || dsId_.isEmpty()) return; + gridRequested_ = true; + emit gridDataNeeded(dsId_, ddCode_); + }); + } } void DatasetDetailPage::setData(const geopro::controller::DatasetDetailController::ChartData& d) { dsId_ = d.dsId; + ddCode_ = d.ddCode; + gridRequested_ = false; // 新数据集 → 网格数据需重新按需加载 rawView_->setData(d); gridView_->setData(d); } +void DatasetDetailPage::setGridData( + const geopro::controller::DatasetDetailController::GridData& d) { + gridRequested_ = true; // 已加载,切回网格页不再重复请求 + gridView_->setGridData(d.grid, d.gridScale, d.anomalies); +} + } // namespace geopro::app diff --git a/src/app/panels/DatasetDetailPage.hpp b/src/app/panels/DatasetDetailPage.hpp index ba1e29f..4f46f57 100644 --- a/src/app/panels/DatasetDetailPage.hpp +++ b/src/app/panels/DatasetDetailPage.hpp @@ -14,9 +14,16 @@ class DatasetDetailPage : public QWidget { public: explicit DatasetDetailPage(QWidget* parent = nullptr); void setData(const geopro::controller::DatasetDetailController::ChartData& d); + // 网格数据到达(懒加载结果)→ 下发给 GridDataChartView 并标记已加载。 + void setGridData(const geopro::controller::DatasetDetailController::GridData& d); QString dsId() const { return dsId_; } +signals: + // 「网格数据」页签首次激活且本页网格数据未加载 → 请求懒加载。 + void gridDataNeeded(const QString& dsId, const QString& ddCode); private: QString dsId_; + QString ddCode_; + bool gridRequested_ = false; // 已请求过(避免重复发信号) RawDataChartView* rawView_; GridDataChartView* gridView_; }; diff --git a/src/app/panels/DatasetDetailPanel.cpp b/src/app/panels/DatasetDetailPanel.cpp index a5267a3..3f5583e 100644 --- a/src/app/panels/DatasetDetailPanel.cpp +++ b/src/app/panels/DatasetDetailPanel.cpp @@ -20,10 +20,19 @@ DatasetDetailPage* DatasetDetailPanel::pageFor(const QString& dsId) const { void DatasetDetailPanel::openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d) { auto* p = pageFor(d.dsId); - if (!p) { p = new DatasetDetailPage(this); addTab(p, d.dsId); } // 标题后续可换 ds 名 + if (!p) { + p = new DatasetDetailPage(this); + addTab(p, d.dsId); // 标题后续可换 ds 名 + // 页内「网格数据」页签首次激活 → 冒泡为面板信号(外部接控制器懒加载)。 + connect(p, &DatasetDetailPage::gridDataNeeded, this, &DatasetDetailPanel::gridDataNeeded); + } p->setData(d); setCurrentWidget(p); } + +void DatasetDetailPanel::setGridData(const geopro::controller::DatasetDetailController::GridData& d) { + if (auto* p = pageFor(d.dsId)) p->setGridData(d); +} void DatasetDetailPanel::focusDataset(const QString& dsId) { if (auto* p = pageFor(dsId)) setCurrentWidget(p); } diff --git a/src/app/panels/DatasetDetailPanel.hpp b/src/app/panels/DatasetDetailPanel.hpp index 3df160a..ddee714 100644 --- a/src/app/panels/DatasetDetailPanel.hpp +++ b/src/app/panels/DatasetDetailPanel.hpp @@ -10,9 +10,11 @@ class DatasetDetailPanel : public QTabWidget { public: explicit DatasetDetailPanel(QWidget* parent = nullptr); void openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d); // 双击/数据到达 + void setGridData(const geopro::controller::DatasetDetailController::GridData& d); // 网格数据懒加载到达 void focusDataset(const QString& dsId); // 单击聚焦已开页 signals: - void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表 + void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表 + void gridDataNeeded(const QString& dsId, const QString& ddCode); // 网格页首次激活 → 请求懒加载 private: DatasetDetailPage* pageFor(const QString& dsId) const; }; diff --git a/src/controller/DatasetDetailController.cpp b/src/controller/DatasetDetailController.cpp index 12f4995..ba07695 100644 --- a/src/controller/DatasetDetailController.cpp +++ b/src/controller/DatasetDetailController.cpp @@ -31,5 +31,25 @@ void DatasetDetailController::openDataset(const QString& dsId, const QString& dd } } +void DatasetDetailController::loadGridData(const QString& dsId, const QString& ddCode) { + if (busy_) return; // 防重入(同步网络期间 QEventLoop 可重入) + if (ddCode != QLatin1String("dd_inversion_data")) return; // 仅 ERT 反演有网格数据 + busy_ = true; + const std::string id = dsId.toStdString(); + try { + GridData d; + d.dsId = dsId; + // 网格数据:rows(服务端网格化,慢) + 色阶 type2 + 异常 queryException。 + d.grid = repo_.loadGrid(id); + d.gridScale = repo_.loadColorScale(id); + d.anomalies = repo_.loadAnomalies(id); + busy_ = false; + emit gridReady(d); + } catch (const std::exception& e) { + busy_ = false; + emit loadFailed(dsId, QString::fromStdString(e.what())); + } +} + void DatasetDetailController::focusDataset(const QString& dsId) { emit focusRequested(dsId); } } // namespace geopro::controller diff --git a/src/controller/DatasetDetailController.hpp b/src/controller/DatasetDetailController.hpp index 31a753b..a870647 100644 --- a/src/controller/DatasetDetailController.hpp +++ b/src/controller/DatasetDetailController.hpp @@ -21,12 +21,23 @@ public: geopro::core::ColorScale gridScale; std::vector anomalies; }; + // 网格数据(inversion/rows + 色阶 type2 + 异常):随「网格数据」页签首次激活按需懒加载。 + struct GridData { + QString dsId; + geopro::core::Grid grid{1, 1}; // Grid 无默认构造;占位值初始化,loadGridData 会覆盖 + geopro::core::ColorScale gridScale; + std::vector anomalies; + }; + explicit DatasetDetailController(data::IDatasetRepository& repo, QObject* parent = nullptr); public slots: void openDataset(const QString& dsId, const QString& ddCode); // 双击=新建/聚焦页 void focusDataset(const QString& dsId); // 单击=聚焦已开页 + // 网格数据懒加载:网格页首次激活时调用(rows 服务端网格化 1-4s,故不随 openDataset 拉)。 + void loadGridData(const QString& dsId, const QString& ddCode); signals: void chartReady(const ChartData& data); + void gridReady(const GridData& data); void focusRequested(const QString& dsId); void loadFailed(const QString& dsId, const QString& message); private: