From dc9506c2605f2cf5fc2cea27a6f30704fe57f307 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Thu, 11 Jun 2026 20:59:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(app):=20=E7=BD=91=E6=A0=BC=E6=87=92?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E3=80=8C=E5=8A=A0=E8=BD=BD=E4=B8=AD=E3=80=8D?= =?UTF-8?q?=E9=81=AE=E7=BD=A9(LoadingOverlay)=20=E6=8E=A5=20loadStarted/?= =?UTF-8?q?=E9=9A=90=E8=97=8F=E4=BA=8E=E5=B0=B1=E7=BB=AA=E6=88=96=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/CMakeLists.txt | 1 + src/app/main.cpp | 10 +++++++- src/app/panels/DatasetDetailPage.cpp | 7 ++++++ src/app/panels/DatasetDetailPage.hpp | 4 ++++ src/app/panels/DatasetDetailPanel.cpp | 3 +++ src/app/panels/DatasetDetailPanel.hpp | 1 + src/app/panels/LoadingOverlay.cpp | 33 +++++++++++++++++++++++++++ src/app/panels/LoadingOverlay.hpp | 18 +++++++++++++++ 8 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/app/panels/LoadingOverlay.cpp create mode 100644 src/app/panels/LoadingOverlay.hpp diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index a20d844..f98119e 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable(geopro_desktop WIN32 panels/chart/ContourPlotItem.cpp panels/chart/LivePanner.cpp panels/AnomalyTablePanel.cpp + panels/LoadingOverlay.cpp panels/DatasetDetailPage.cpp panels/DatasetDetailPanel.cpp CentralScene.cpp diff --git a/src/app/main.cpp b/src/app/main.cpp index b305b01..e193ece 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -520,8 +520,16 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re [detailPanel](const geopro::controller::DatasetDetailController::GridData& d) { detailPanel->setGridData(d); }); + QObject::connect( + &detailCtrl, &geopro::controller::DatasetDetailController::loadStarted, detailPanel, + [detailPanel](const QString& dsId, + geopro::controller::DatasetDetailController::LoadPhase phase) { + if (phase == geopro::controller::DatasetDetailController::LoadPhase::Grid) + detailPanel->setGridLoading(dsId, true); + }); QObject::connect(&detailCtrl, &geopro::controller::DatasetDetailController::loadFailed, &window, - [&window](const QString& dsId, const QString& msg) { + [&window, detailPanel](const QString& dsId, const QString& msg) { + detailPanel->setGridLoading(dsId, false); window.statusBar()->showMessage( QStringLiteral("数据集 %1 加载失败:%2").arg(dsId, msg), 5000); }); diff --git a/src/app/panels/DatasetDetailPage.cpp b/src/app/panels/DatasetDetailPage.cpp index 5cf559f..061cbb6 100644 --- a/src/app/panels/DatasetDetailPage.cpp +++ b/src/app/panels/DatasetDetailPage.cpp @@ -5,6 +5,7 @@ #include "Glyphs.hpp" #include "PanelHeader.hpp" +#include "panels/LoadingOverlay.hpp" #include "panels/chart/GridDataChartView.hpp" #include "panels/chart/RawDataChartView.hpp" @@ -21,6 +22,7 @@ DatasetDetailPage::DatasetDetailPage(QWidget* parent) : QWidget(parent) { rawView_ = new RawDataChartView(this); gridView_ = new GridDataChartView(this); + gridOverlay_ = new LoadingOverlay(gridView_); // 父为 gridView_,随其尺寸覆盖网格图区 const QVector tabs = { {Glyph::Detail, QStringLiteral("原数据"), rawView_, false}, @@ -55,6 +57,11 @@ void DatasetDetailPage::setGridData( const geopro::controller::DatasetDetailController::GridData& d) { gridRequested_ = true; // 已加载,切回网格页不再重复请求 gridView_->setGridData(d.grid, d.gridScale, d.anomalies); + setGridLoading(false); // 数据到达,隐藏遮罩 +} + +void DatasetDetailPage::setGridLoading(bool on) { + if (on) gridOverlay_->showOver(); else gridOverlay_->hide(); } } // namespace geopro::app diff --git a/src/app/panels/DatasetDetailPage.hpp b/src/app/panels/DatasetDetailPage.hpp index 4f46f57..b408d06 100644 --- a/src/app/panels/DatasetDetailPage.hpp +++ b/src/app/panels/DatasetDetailPage.hpp @@ -6,6 +6,7 @@ namespace geopro::app { class RawDataChartView; class GridDataChartView; +class LoadingOverlay; // 单个数据集详情页:下划线页签「原数据 / 网格数据」+ 右侧「导出」操作。 // 内部分别由 RawDataChartView / GridDataChartView 实现各自三层布局。 @@ -16,6 +17,8 @@ public: void setData(const geopro::controller::DatasetDetailController::ChartData& d); // 网格数据到达(懒加载结果)→ 下发给 GridDataChartView 并标记已加载。 void setGridData(const geopro::controller::DatasetDetailController::GridData& d); + // 网格懒加载进行中(true)/结束(false)时切换遮罩显隐。 + void setGridLoading(bool on); QString dsId() const { return dsId_; } signals: // 「网格数据」页签首次激活且本页网格数据未加载 → 请求懒加载。 @@ -26,6 +29,7 @@ private: bool gridRequested_ = false; // 已请求过(避免重复发信号) RawDataChartView* rawView_; GridDataChartView* gridView_; + LoadingOverlay* gridOverlay_; // 网格懒加载期间覆盖 gridView_ 的遮罩 }; } // namespace geopro::app diff --git a/src/app/panels/DatasetDetailPanel.cpp b/src/app/panels/DatasetDetailPanel.cpp index 3f5583e..765a002 100644 --- a/src/app/panels/DatasetDetailPanel.cpp +++ b/src/app/panels/DatasetDetailPanel.cpp @@ -33,6 +33,9 @@ void DatasetDetailPanel::openOrUpdate(const geopro::controller::DatasetDetailCon void DatasetDetailPanel::setGridData(const geopro::controller::DatasetDetailController::GridData& d) { if (auto* p = pageFor(d.dsId)) p->setGridData(d); } +void DatasetDetailPanel::setGridLoading(const QString& dsId, bool on) { + if (auto* p = pageFor(dsId)) p->setGridLoading(on); +} 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 ddee714..344c882 100644 --- a/src/app/panels/DatasetDetailPanel.hpp +++ b/src/app/panels/DatasetDetailPanel.hpp @@ -11,6 +11,7 @@ public: explicit DatasetDetailPanel(QWidget* parent = nullptr); void openOrUpdate(const geopro::controller::DatasetDetailController::ChartData& d); // 双击/数据到达 void setGridData(const geopro::controller::DatasetDetailController::GridData& d); // 网格数据懒加载到达 + void setGridLoading(const QString& dsId, bool on); // 网格懒加载进行中/结束 → 转发给对应页 void focusDataset(const QString& dsId); // 单击聚焦已开页 signals: void activeDatasetChanged(const QString& dsId); // 反向联动数据集列表 diff --git a/src/app/panels/LoadingOverlay.cpp b/src/app/panels/LoadingOverlay.cpp new file mode 100644 index 0000000..3b7e446 --- /dev/null +++ b/src/app/panels/LoadingOverlay.cpp @@ -0,0 +1,33 @@ +#include "panels/LoadingOverlay.hpp" +#include +#include +#include +#include + +namespace geopro::app { + +LoadingOverlay::LoadingOverlay(QWidget* parent) : QWidget(parent), label_(new QLabel(this)) { + setAttribute(Qt::WA_StyledBackground, true); + setStyleSheet(QStringLiteral("background: rgba(255,255,255,160);")); + label_->setText(QStringLiteral("加载中…")); + label_->setAlignment(Qt::AlignCenter); + auto* lay = new QVBoxLayout(this); + lay->addWidget(label_); + if (parent) parent->installEventFilter(this); + hide(); +} + +void LoadingOverlay::showOver() { + if (parentWidget()) setGeometry(parentWidget()->rect()); + raise(); + show(); +} + +bool LoadingOverlay::eventFilter(QObject* obj, QEvent* ev) { + if (obj == parentWidget() && ev->type() == QEvent::Resize && isVisible()) { + setGeometry(parentWidget()->rect()); + } + return QWidget::eventFilter(obj, ev); +} + +} // namespace geopro::app diff --git a/src/app/panels/LoadingOverlay.hpp b/src/app/panels/LoadingOverlay.hpp new file mode 100644 index 0000000..624b4eb --- /dev/null +++ b/src/app/panels/LoadingOverlay.hpp @@ -0,0 +1,18 @@ +#pragma once +#include +class QLabel; +namespace geopro::app { + +// 半透明「加载中…」遮罩。贴在目标视图上层,showOver()/hide() 切换,几何随父 resize 跟随。 +class LoadingOverlay : public QWidget { + Q_OBJECT +public: + explicit LoadingOverlay(QWidget* parent); + void showOver(); // 铺满父尺寸、置顶、显示 +protected: + bool eventFilter(QObject* obj, QEvent* ev) override; // 跟随父 resize +private: + QLabel* label_; +}; + +} // namespace geopro::app