geopro/src/data/api/ApiDatasetRepository.cpp

246 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "api/ApiDatasetRepository.hpp"
#include <stdexcept>
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QUrl>
#include <QVariant>
#include "ApiClient.hpp"
#include "ApiBatch.hpp"
#include "api/DatasetLoadHandles.hpp"
#include "dto/DatasetChartDto.hpp"
#include "dto/GrMeasurementDto.hpp"
#include "dto/GridDto.hpp"
#include "dto/MeasurementDto.hpp"
#include "dto/TrajectoryDto.hpp"
#include "model/detail/DetailPayloads.hpp"
namespace geopro::data {
namespace {
QString enc(const std::string& s) {
return QString::fromUtf8(QUrl::toPercentEncoding(QString::fromStdString(s)));
}
// 解析中间态(仅本 .cpp 内部使用,故置匿名命名空间,避免对外双份表示)。
// 原数据加载结果scatter + 散点色阶(type1)。
struct ChartParts {
geopro::core::ScatterField scatter;
geopro::core::ColorScale scatterScale;
QString templateId; // 散点色阶模板 id保存色阶回带对照原版 lvlTemplateId
};
// 网格数据加载结果grid(rows) + 网格色阶(type2) + 异常。
struct GridParts {
geopro::core::Grid grid{1, 1}; // Grid 无默认构造;占位
geopro::core::ColorScale gridScale;
std::vector<geopro::core::Anomaly> anomalies;
QString templateId; // 网格色阶模板 id保存/覆盖回带,对照原版 lvlTemplateId
};
// 失败判定(原 must() 口径):业务码 != 200 或传输错误。
bool isFailure(const geopro::net::ApiResponse& r) {
return r.code != 200 || !r.rawError.isEmpty();
}
QJsonObject colorBody(const std::string& dsId, int type) {
return QJsonObject{{"dsObjectId", QString::fromStdString(dsId)}, {"businessCode", ""}, {"type", type}};
}
// ── 共享批次构造唯一端点定义处old/new 路径复用,避免双份解析逻辑。 ──
// 反演原数据index 0 = scatter(GET)1 = 散点色阶 type1(POST)。
net::ApiBatch* inversionScatterBatch(net::ApiClient& api, const std::string& dsId) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/inversion/getErtRawDataScatterGraph/%1").arg(enc(dsId))),
api.postJsonAsync(QStringLiteral("/business/lvl/colorGradation/getDetail"), colorBody(dsId, 1)),
};
return new net::ApiBatch(calls, &isFailure);
}
ChartParts parseScatterParts(const QList<net::ApiResponse>& r) {
ChartParts p;
p.scatter = dto::parseScatterGraph(r[0].data);
p.scatterScale = dto::parseColorBar(r[1].data);
p.templateId = r[1].data.value(QStringLiteral("templateId")).toVariant().toString();
return p;
}
// 反演网格index 0 = rows(GET,慢)1 = 色阶 type2(POST)2 = 异常(GET)。
net::ApiBatch* inversionGridBatch(net::ApiClient& api, const std::string& dsId) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/inversion/rows/%1").arg(enc(dsId))),
api.postJsonAsync(QStringLiteral("/business/lvl/colorGradation/getDetail"), colorBody(dsId, 2)),
api.getAsync(QStringLiteral("/business/exception/queryException/%1").arg(enc(dsId))),
};
return new net::ApiBatch(calls, &isFailure);
}
GridParts parseGridParts(const QList<net::ApiResponse>& r) {
GridParts p;
p.grid = dto::parseInversionGrid(r[0].data);
p.gridScale = dto::parseColorBar(r[1].data);
p.anomalies = dto::parseDatasetAnomalies(r[2].data.value(QStringLiteral("value")).toArray());
// 顶层 templateId对照原版 lvlConfig?.templateId与散点 parseScatterParts 同范式)。
p.templateId = r[1].data.value(QStringLiteral("templateId")).toVariant().toString();
return p;
}
// measurement 散点index 0 = scatter/graph(GETquery 参数)1 = 色阶 type3(POSTbusinessCode=R0)。
net::ApiBatch* measurementScatterBatch(net::ApiClient& api, const std::string& dsId) {
const QString did = enc(dsId);
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/measurement/scatter/graph?dsObjectId=%1&vFieldCode=").arg(did)),
api.postJsonAsync(QStringLiteral("/business/lvl/colorGradation/getDetail"),
QJsonObject{{"dsObjectId", QString::fromStdString(dsId)},
{"businessCode", "R0"},
{"type", 3}}),
};
return new net::ApiBatch(calls, &isFailure);
}
// measurement 列表:单请求 measurement/rows(GETquery 参数)。
net::ApiBatch* measurementRowsBatch(net::ApiClient& api, const std::string& dsId) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/measurement/rows?dsObjectId=%1").arg(enc(dsId))),
};
return new net::ApiBatch(calls, &isFailure);
}
// 接地电阻gr柱状图与列表同一端点 measurement/gr/rows(GETquery 参数)。
// 响应 data 是 JSON 数组 → ApiResponseParse 包成 {value:[...]},取 r[0].data.value("value").toArray()。
net::ApiBatch* grRowsBatch(net::ApiClient& api, const std::string& dsId) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/measurement/gr/rows?dsObjectId=%1").arg(enc(dsId))),
};
return new net::ApiBatch(calls, &isFailure);
}
// gr 响应数组(包在 data.value 里)。
QJsonArray grDataArray(const QList<net::ApiResponse>& r) {
return r[0].data.value(QStringLiteral("value")).toArray();
}
// 轨迹trajectory列表与高程同一端点 trajectory/rows(GETquery 参数)。
// 响应 data = {rowList[40], gridHeaderDisplay[14], ...}。
net::ApiBatch* trajectoryRowsBatch(net::ApiClient& api, const std::string& dsId) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/trajectory/rows?dsObjectId=%1").arg(enc(dsId))),
};
return new net::ApiBatch(calls, &isFailure);
}
// 轨迹地图:单请求 trajectory/line(GETquery 参数)。frontCrsCode=EPSG:4326原版发 EPSG%3A4326
// 此处用 enc() 对整串 url 编码故 ':' → %3A。响应 data = {electrodelList[...]}。
net::ApiBatch* trajectoryLineBatch(net::ApiClient& api, const std::string& dsId) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/trajectory/line?dsObjectId=%1&frontCrsCode=%2")
.arg(enc(dsId), enc("EPSG:4326"))),
};
return new net::ApiBatch(calls, &isFailure);
}
// dd_grid 白化数据列表(服务端分页):单请求 grid/rows(GETquerydsObjectId/pageNo/pageSize)。
// 响应 data = {rowList[{x,y,id}], gridHeaderDisplay[x,y], total}。
net::ApiBatch* gridRowsBatch(net::ApiClient& api, const std::string& dsId, int pageNo, int pageSize) {
QList<net::IApiCall*> calls{
api.getAsync(QStringLiteral("/business/dd/ert/grid/rows?dsObjectId=%1&pageNo=%2&pageSize=%3")
.arg(enc(dsId))
.arg(pageNo)
.arg(pageSize)),
};
return new net::ApiBatch(calls, &isFailure);
}
} // namespace
ApiDatasetRepository::ApiDatasetRepository(net::ApiClient& api) : api_(api) {}
DetailLoad* ApiDatasetRepository::loadAsync(const std::string& loaderKey, const std::string& dsId,
int pageNo, int pageSize) {
if (loaderKey == "inversion.scatter") return makeInversionScatter(dsId);
if (loaderKey == "inversion.grid") return makeInversionGrid(dsId);
if (loaderKey == "ert_measurement.scatter") return makeMeasurementScatter(dsId);
if (loaderKey == "ert_measurement.rows") return makeMeasurementRows(dsId);
if (loaderKey == "gr.bar") return makeGrBar(dsId);
if (loaderKey == "gr.rows") return makeGrRows(dsId);
if (loaderKey == "traj.rows") return makeTrajectoryRows(dsId);
if (loaderKey == "traj.elev") return makeTrajectoryElevation(dsId);
if (loaderKey == "traj.map") return makeTrajectoryMap(dsId);
if (loaderKey == "grid.rows") return makeGridRows(dsId, pageNo, pageSize);
throw std::runtime_error("unknown loaderKey: " + loaderKey);
}
DetailLoad* ApiDatasetRepository::makeInversionScatter(const std::string& dsId) {
// 复用同一批次 + 解析器,再映射为 ScatterPayload不复制 JSON 解析逻辑)。
return new ApiDetailLoad(inversionScatterBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
ChartParts p = parseScatterParts(r);
core::ScatterPayload payload{p.scatter, p.scatterScale};
payload.templateId = p.templateId; // 色阶保存回带(对照原版 lvlTemplateId
return QVariant::fromValue(payload);
});
}
DetailLoad* ApiDatasetRepository::makeInversionGrid(const std::string& dsId) {
return new ApiDetailLoad(inversionGridBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
GridParts p = parseGridParts(r);
core::ContourPayload payload{p.grid, p.gridScale, p.anomalies};
payload.templateId = p.templateId; // 色阶保存/覆盖回带(对照原版 lvlTemplateId
return QVariant::fromValue(payload);
});
}
DetailLoad* ApiDatasetRepository::makeMeasurementScatter(const std::string& dsId) {
// index 0 = scatter/graph, 1 = colorBar(type3) → 离散上色的 ScatterPayload。
return new ApiDetailLoad(measurementScatterBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseMeasurementScatter(r[0].data, r[1].data));
});
}
DetailLoad* ApiDatasetRepository::makeMeasurementRows(const std::string& dsId) {
return new ApiDetailLoad(measurementRowsBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseMeasurementTable(r[0].data));
});
}
DetailLoad* ApiDatasetRepository::makeGrBar(const std::string& dsId) {
return new ApiDetailLoad(grRowsBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseGrBar(grDataArray(r)));
});
}
DetailLoad* ApiDatasetRepository::makeGrRows(const std::string& dsId) {
return new ApiDetailLoad(grRowsBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseGrTable(grDataArray(r)));
});
}
DetailLoad* ApiDatasetRepository::makeTrajectoryRows(const std::string& dsId) {
return new ApiDetailLoad(trajectoryRowsBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseTrajectoryTable(r[0].data));
});
}
DetailLoad* ApiDatasetRepository::makeTrajectoryElevation(const std::string& dsId) {
return new ApiDetailLoad(trajectoryRowsBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseTrajectoryElevation(r[0].data));
});
}
DetailLoad* ApiDatasetRepository::makeTrajectoryMap(const std::string& dsId) {
return new ApiDetailLoad(trajectoryLineBatch(api_, dsId), [](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseTrajectoryMap(r[0].data));
});
}
DetailLoad* ApiDatasetRepository::makeGridRows(const std::string& dsId, int pageNo, int pageSize) {
// 解析默认值pageNo<=0→1pageSize<=0→50原版默认每页 50 条),再传入 URL 与解析器
// (保证 URL 参数与「序号」列偏移一致)。
const int pn = pageNo > 0 ? pageNo : 1;
const int ps = pageSize > 0 ? pageSize : 50;
return new ApiDetailLoad(gridRowsBatch(api_, dsId, pn, ps),
[pn, ps](const QList<net::ApiResponse>& r) {
return QVariant::fromValue(dto::parseGridTable(r[0].data, pn, ps));
});
}
} // namespace geopro::data