diff --git a/src/data/CMakeLists.txt b/src/data/CMakeLists.txt index 684633e..09478ae 100644 --- a/src/data/CMakeLists.txt +++ b/src/data/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(geopro_data STATIC dto/GridDto.cpp api/ApiProjectRepository.cpp api/ApiDatasetRepository.cpp + api/Api3dRepository.cpp api/DatasetLoadHandles.cpp api/NavRequest.cpp) target_include_directories(geopro_data PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/data/api/Api3dRepository.cpp b/src/data/api/Api3dRepository.cpp new file mode 100644 index 0000000..8bf329f --- /dev/null +++ b/src/data/api/Api3dRepository.cpp @@ -0,0 +1,120 @@ +#include "api/Api3dRepository.hpp" + +#include +#include +#include +#include + +#include "api/DatasetLoadHandles.hpp" +#include "model/detail/DetailPayloads.hpp" +#include "repo/IAsyncDatasetRepository.hpp" + +namespace geopro::data { + +namespace { +constexpr const char* kNotReady = "后端三维端点未就绪"; +} // namespace + +Api3dRepository::Api3dRepository(IAsyncDatasetRepository& dsRepo) : dsRepo_(dsRepo) {} + +DsDimension Api3dRepository::dimensionOf(const DsRow& ds) const { + // 与 LocalSample3dRepository::dimensionOf 同口径(spec §6.1 ddCode→维度)。 + // TODO(P3): 与 LocalSample3dRepository 重复,宜提取共享映射(后续清理)。 + const std::string& c = ds.ddCode; + if (c == "dd_voxel" || c == "dd_Structual3D" || c == "dd_Property3D" || c == "dd_section" || + c == "dd_inversion_data") { + return DsDimension::Dim3D; + } + if (c == "dd_slice") return DsDimension::Analysis3D; + if (c == "dd_trajectory_data") return DsDimension::Dim2D; + return DsDimension::Other; +} + +void Api3dRepository::loadSection(const std::string& dsId, std::function onOk, + OnError onErr) { + // 真实帘面:复用 ApiDatasetRepository 的 ERT 反演网格端点(loaderKey="inversion.grid")。 + // 命中载荷 = core::ContourPayload{grid, scale, anomalies};取 grid+scale 填 SectionData。 + DetailLoad* load = dsRepo_.loadAsync("inversion.grid", dsId); + if (load == nullptr) { + onErr("Api3dRepository::loadSection: loadAsync 返回空句柄"); + return; + } + // 以 load 为连接上下文 → 它 deleteLater 时自动断开;单线程下创建后立即连接安全。 + QObject::connect(load, &DetailLoad::done, load, + [onOk = std::move(onOk)](const QVariant& payload) { + const auto cp = qvariant_cast(payload); + SectionData s; + s.grid = cp.grid; + s.scale = cp.scale; + onOk(std::move(s)); + }); + QObject::connect(load, &DetailLoad::failed, load, + [onErr = std::move(onErr)](const QString& message) { + onErr(message.toStdString()); + }); +} + +void Api3dRepository::loadVolume(const std::string& /*dsId*/, + std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); // 后端三维体端点未就绪 +} + +void Api3dRepository::loadTerrainPaths(std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); // 后端地形 DEM/影像端点未就绪 +} + +// ── 切片 CRUD(后端未就绪 → 变更走 onErr,给用户明确"未实现")────────────── + +void Api3dRepository::createSlice(const SliceSpec& /*spec*/, const std::string& /*name*/, + std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); +} + +void Api3dRepository::saveSlice(const std::string& /*dsId*/, const SliceSpec& /*spec*/, + std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); +} + +void Api3dRepository::deleteSlice(const std::string& /*dsId*/, std::function /*onOk*/, + OnError onErr) { + onErr(kNotReady); +} + +// ── 异常 / 异常体(load 回空树避免 UI 崩;变更走 onErr)───────────────────── + +void Api3dRepository::loadAnomalyTree(const std::string& /*objectId*/, + std::function onOk, OnError /*onErr*/) { + onOk(AnomalyTree{}); // 后端未就绪 → 空树 +} + +void Api3dRepository::saveAnomaly(const geopro::core::Anomaly& /*a*/, + const std::string& /*screenshotPngPath*/, + std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); +} + +void Api3dRepository::deleteAnomaly(const std::string& /*anomalyId*/, + std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); +} + +void Api3dRepository::deleteAnomalyGroup(const std::string& /*bodyId*/, + std::function /*onOk*/, OnError onErr) { + onErr(kNotReady); +} + +// ── 任务管理(load 回空列表避免 UI 崩)────────────────────────────────────── + +void Api3dRepository::loadTaskRecords(const std::string& /*dsId*/, + std::function)> onOk, + OnError /*onErr*/) { + onOk({}); // 后端未就绪 → 空记录 +} + +void Api3dRepository::loadUsableTasks(const std::string& /*ddCode*/, + std::function)> onOk, + OnError /*onErr*/) { + onOk({}); // 后端未就绪 → 空列表 +} + +} // namespace geopro::data diff --git a/src/data/api/Api3dRepository.hpp b/src/data/api/Api3dRepository.hpp new file mode 100644 index 0000000..5e9819d --- /dev/null +++ b/src/data/api/Api3dRepository.hpp @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#include + +#include "repo/I3dSceneRepository.hpp" + +namespace geopro::data { + +class IAsyncDatasetRepository; + +// 真实后端实现 I3dSceneRepository: +// loadSection(帘面) 走真实 ERT 反演端点 —— 复用 ApiDatasetRepository(loaderKey="inversion.grid"), +// 不重复网络层;命中 core::ContourPayload{grid, scale, anomalies},取 grid+scale 填 SectionData。 +// dimensionOf 同步纯函数(ddCode→维度,同 LocalSample3dRepository 映射)。 +// 三维体/地形/切片/异常/任务端点后端尚未就绪 → 暂 stub: +// - load 类(loadTree/loadRecords/loadTasks) 回调空,避免 UI 崩; +// - loadVolume/loadTerrainPaths 及一切 create/save/delete 变更 → 走 onErr("后端未就绪"), +// 给用户明确"未实现"而非假成功。 +class Api3dRepository : public I3dSceneRepository { +public: + explicit Api3dRepository(IAsyncDatasetRepository& dsRepo); + + DsDimension dimensionOf(const DsRow& ds) const override; + + void loadVolume(const std::string& dsId, std::function onOk, + OnError onErr) override; + void loadSection(const std::string& dsId, std::function onOk, + OnError onErr) override; + void loadTerrainPaths(std::function onOk, OnError onErr) override; + + // 切片 CRUD(后端未就绪 → 变更走 onErr) + void createSlice(const SliceSpec& spec, const std::string& name, + std::function onOk, OnError onErr) override; + void saveSlice(const std::string& dsId, const SliceSpec& spec, + std::function onOk, OnError onErr) override; + void deleteSlice(const std::string& dsId, + std::function onOk, OnError onErr) override; + + // 异常 / 异常体(后端未就绪 → load 回空树,变更走 onErr) + void loadAnomalyTree(const std::string& objectId, + std::function onOk, OnError onErr) override; + void saveAnomaly(const geopro::core::Anomaly& a, const std::string& screenshotPngPath, + std::function onOk, OnError onErr) override; + void deleteAnomaly(const std::string& anomalyId, + std::function onOk, OnError onErr) override; + void deleteAnomalyGroup(const std::string& bodyId, + std::function onOk, OnError onErr) override; + + // 任务管理(后端未就绪 → load 回空列表) + void loadTaskRecords(const std::string& dsId, + std::function)> onOk, + OnError onErr) override; + void loadUsableTasks(const std::string& ddCode, + std::function)> onOk, + OnError onErr) override; + +private: + IAsyncDatasetRepository& dsRepo_; +}; + +} // namespace geopro::data