geopro/src/data/api/ApiDatasetCommandRepository...

445 lines
21 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/ApiDatasetCommandRepository.hpp"
#include <utility>
#include <QUrl>
#include "ApiBatch.hpp"
#include "ApiClient.hpp"
#include "IApiCall.hpp"
#include "dto/MeasurementDto.hpp" // parseMeasurementScatterV 值重载复用初始加载解析)
#include "dto/DatasetChartDto.hpp" // parseInversionGrid/parseColorBar/parseDatasetAnomalies网格重载
namespace geopro::data {
namespace {
// 失败判定与色阶/详情仓储一致:业务码 != 200 或传输错误rawError 非空)。
bool isOk(const net::ApiResponse& r) { return r.code == 200 && r.rawError.isEmpty(); }
// URL 路径段编码(动态 id与现有 enc 用法一致。
QString enc(const QString& s) { return QString::fromUtf8(QUrl::toPercentEncoding(s)); }
// 三类回调骨架:统一「句柄判空 → connect → finished 取值」,消除样板重复。
// 仅状态:(bool ok, QString msg)。
void wireStatus(net::IApiCall* call, std::function<void(bool, QString)> cb) {
if (call == nullptr) {
if (cb) cb(false, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (cb) cb(isOk(resp), resp.msg);
});
}
// 返回数组:(bool ok, QJsonArray list, QString msg)。顶层数组被 buildResponse 包成 data.value。
void wireArray(net::IApiCall* call, std::function<void(bool, QJsonArray, QString)> cb) {
if (call == nullptr) {
if (cb) cb(false, {}, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (!cb) return;
if (!isOk(resp)) {
cb(false, {}, resp.msg);
return;
}
cb(true, resp.data.value(QStringLiteral("value")).toArray(), resp.msg);
});
}
// 返回字符串:(bool ok, QString value, QString msg)。
// 原版 res.data 为纯字符串时parseBody 会包成 {"value": "<string>"},故取 data.value。
void wireString(net::IApiCall* call, std::function<void(bool, QString, QString)> cb) {
if (call == nullptr) {
if (cb) cb(false, {}, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (!cb) return;
if (!isOk(resp)) {
cb(false, {}, resp.msg);
return;
}
cb(true, resp.data.value(QStringLiteral("value")).toString(), resp.msg);
});
}
// 返回对象:(bool ok, QJsonObject data, QString msg)。
void wireObject(net::IApiCall* call, std::function<void(bool, QJsonObject, QString)> cb) {
if (call == nullptr) {
if (cb) cb(false, {}, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (!cb) return;
if (!isOk(resp)) {
cb(false, {}, resp.msg);
return;
}
cb(true, resp.data, resp.msg);
});
}
} // namespace
ApiDatasetCommandRepository::ApiDatasetCommandRepository(net::ApiClient& api) : api_(api) {}
void ApiDatasetCommandRepository::listInversionScripts(
const QString& dsObjectId, std::function<void(bool, QJsonArray, QString)> cb) {
auto* call = api_.getAsync(
QStringLiteral("/business/outerInversion/query/script?dsObjectId=%1")
.arg(QString::fromUtf8(QUrl::toPercentEncoding(dsObjectId))));
if (call == nullptr) {
if (cb) cb(false, {}, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (!cb) return;
if (!isOk(resp)) {
cb(false, {}, resp.msg);
return;
}
// 模型列表data 顶层为数组buildResponse 包成 {"value": [...]}。
cb(true, resp.data.value(QStringLiteral("value")).toArray(), resp.msg);
});
}
void ApiDatasetCommandRepository::getDynamicForm(
const QString& projectId, const QString& typeId,
std::function<void(bool, QJsonObject, QString)> cb) {
QJsonObject body{{QStringLiteral("projectId"), projectId},
{QStringLiteral("type"), 6},
{QStringLiteral("typeId"), typeId}};
auto* call = api_.postJsonAsync(QStringLiteral("/business/project/getDynamicForm"), body);
if (call == nullptr) {
if (cb) cb(false, {}, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (!cb) return;
if (!isOk(resp)) {
cb(false, {}, resp.msg);
return;
}
// 动态表单data 为对象(含 formList 数组)。
cb(true, resp.data, resp.msg);
});
}
void ApiDatasetCommandRepository::submitInversionTask(const QString& dsId, const QString& scriptId,
const QJsonObject& properties,
std::function<void(bool, QString)> cb) {
QJsonObject body{{QStringLiteral("dsId"), dsId},
{QStringLiteral("scriptId"), scriptId},
{QStringLiteral("properties"), properties}};
auto* call =
api_.postJsonAsync(QStringLiteral("/business/outerInversion/submitInversionTask"), body);
if (call == nullptr) {
if (cb) cb(false, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (cb) cb(isOk(resp), resp.msg);
});
}
void ApiDatasetCommandRepository::createVisualResistivityData(
const QString& dsObjectId, const QString& scriptId, const QJsonObject& scriptParamListJsonStr,
std::function<void(bool, QString)> cb) {
QJsonObject body{{QStringLiteral("dsObjectId"), dsObjectId},
{QStringLiteral("scriptId"), scriptId},
{QStringLiteral("scriptParamListJsonStr"), scriptParamListJsonStr}};
auto* call = api_.postJsonAsync(
QStringLiteral("/business/dd/ert/measurement/createVisualResistivityData"), body);
if (call == nullptr) {
if (cb) cb(false, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (cb) cb(isOk(resp), resp.msg);
});
}
// ============================ measurement 散点相关 ============================
void ApiDatasetCommandRepository::saveDisplayStatus(const QString& dsObjectId,
const QJsonArray& ids, int status,
std::function<void(bool, QString)> cb) {
QJsonObject body{{QStringLiteral("dsObjectId"), dsObjectId},
{QStringLiteral("ids"), ids},
{QStringLiteral("status"), status}};
wireStatus(api_.postJsonAsync(QStringLiteral("/business/dd/ert/measurement/saveDisplayStatus"),
body),
std::move(cb));
}
void ApiDatasetCommandRepository::getScatterFilterConfig(
const QString& dsObjectId, const QString& vFieldCode,
std::function<void(bool, QJsonObject, QString)> cb) {
wireObject(
api_.getAsync(QStringLiteral(
"/business/scatterPlotDataFilter/getDataFilterConfig?dsObjectId=%1&vFieldCode=%2")
.arg(enc(dsObjectId), enc(vFieldCode))),
std::move(cb));
}
void ApiDatasetCommandRepository::applyScatterFilter(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/scatterPlotDataFilter"), body),
std::move(cb));
}
void ApiDatasetCommandRepository::saveRawData(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/dd/ert/measurement/saveRawData"), body),
std::move(cb));
}
void ApiDatasetCommandRepository::exportMeasurementDat(
const QString& dsId, int electrodePosition, int ipDataMark, int typeMeasurement,
std::function<void(bool, QString, QString, QString)> cb) {
auto* call = api_.getAsync(
QStringLiteral("/business/dd/ert/measurement/rs2d/"
"export?dsId=%1&electrodePosition=%2&ipDataMark=%3&typeMeasurement=%4")
.arg(enc(dsId))
.arg(electrodePosition)
.arg(ipDataMark)
.arg(typeMeasurement));
if (call == nullptr) {
if (cb) cb(false, {}, {}, QStringLiteral("请求创建失败"));
return;
}
QObject::connect(call, &net::IApiCall::finished, call,
[cb = std::move(cb)](const net::ApiResponse& resp) {
if (!cb) return;
if (!isOk(resp)) {
cb(false, {}, {}, resp.msg);
return;
}
// 导出data 含 base64 fileData 与 fileName落盘交由 UI 层。
cb(true, resp.data.value(QStringLiteral("fileName")).toString(),
resp.data.value(QStringLiteral("fileData")).toString(), resp.msg);
});
}
void ApiDatasetCommandRepository::loadMeasurementScatter(
const QString& dsObjectId, const QString& vFieldCode,
std::function<void(bool, geopro::core::ScatterPayload, QString)> cb) {
// 并发拉 scatter/graph(带 vFieldCode) + 色阶 getDetail(type3, businessCode=vFieldCode)。
// 与 ApiDatasetRepository::measurementScatterBatch 同端点/同解析(仅 vFieldCode 可变)。
QList<net::IApiCall*> calls{
api_.getAsync(
QStringLiteral("/business/dd/ert/measurement/scatter/graph?dsObjectId=%1&vFieldCode=%2")
.arg(enc(dsObjectId), enc(vFieldCode))),
api_.postJsonAsync(QStringLiteral("/business/lvl/colorGradation/getDetail"),
QJsonObject{{QStringLiteral("dsObjectId"), dsObjectId},
{QStringLiteral("businessCode"), vFieldCode},
{QStringLiteral("type"), 3}}),
};
auto* batch = new net::ApiBatch(calls, [](const net::ApiResponse& r) {
return r.code != 200 || !r.rawError.isEmpty();
});
QObject::connect(batch, &net::ApiBatch::succeeded, batch,
[cb](const QList<net::ApiResponse>& r) {
if (cb) cb(true, dto::parseMeasurementScatter(r[0].data, r[1].data), {});
});
QObject::connect(batch, &net::ApiBatch::failed, batch,
[cb](int, const net::ApiResponse& resp) {
if (cb) cb(false, {}, resp.msg);
});
// ApiBatch 完成/失败后各 call 自行 deleteLaterbatch 本身随末次信号后 deleteLater。
QObject::connect(batch, &net::ApiBatch::succeeded, batch, &QObject::deleteLater);
QObject::connect(batch, &net::ApiBatch::failed, batch, &QObject::deleteLater);
}
// ============================ 色阶lvl相关 ============================
void ApiDatasetCommandRepository::saveColorGradation(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/lvl/colorGradation"), body),
std::move(cb));
}
// ============================ inversion 相关 ============================
void ApiDatasetCommandRepository::saveInversionAsData(const QString& dsObjectId,
const QString& name,
std::function<void(bool, QString)> cb) {
QJsonObject body{{QStringLiteral("dsObjectId"), dsObjectId}, {QStringLiteral("name"), name}};
wireStatus(api_.postJsonAsync(QStringLiteral("/business/dd/ert/inversion/saveAsData"), body),
std::move(cb));
}
void ApiDatasetCommandRepository::loadInversionGrid(
const QString& dsObjectId,
std::function<void(bool, geopro::core::ContourPayload, QString)> cb) {
// 与 ApiDatasetRepository::inversionGridBatch 同端点/同解析rows(慢) + 色阶 type2 + 异常。
QList<net::IApiCall*> calls{
api_.getAsync(QStringLiteral("/business/dd/ert/inversion/rows/%1").arg(enc(dsObjectId))),
api_.postJsonAsync(QStringLiteral("/business/lvl/colorGradation/getDetail"),
QJsonObject{{QStringLiteral("dsObjectId"), dsObjectId},
{QStringLiteral("businessCode"), QString()},
{QStringLiteral("type"), 2}}),
api_.getAsync(
QStringLiteral("/business/exception/queryException/%1").arg(enc(dsObjectId))),
};
auto* batch = new net::ApiBatch(calls, [](const net::ApiResponse& r) {
return r.code != 200 || !r.rawError.isEmpty();
});
QObject::connect(batch, &net::ApiBatch::succeeded, batch,
[cb](const QList<net::ApiResponse>& r) {
if (!cb) return;
geopro::core::ContourPayload p{
dto::parseInversionGrid(r[0].data),
dto::parseColorBar(r[1].data),
dto::parseDatasetAnomalies(
r[2].data.value(QStringLiteral("value")).toArray())};
cb(true, p, {});
});
QObject::connect(batch, &net::ApiBatch::failed, batch,
[cb](int, const net::ApiResponse& resp) {
if (cb) cb(false, {}, resp.msg);
});
QObject::connect(batch, &net::ApiBatch::succeeded, batch, &QObject::deleteLater);
QObject::connect(batch, &net::ApiBatch::failed, batch, &QObject::deleteLater);
}
void ApiDatasetCommandRepository::listGridAlgorithm(
const QString& dsObjectId, std::function<void(bool, QJsonArray, QString)> cb) {
wireArray(api_.getAsync(QStringLiteral("/business/dd/ert/inversion/queryAlgorithmModel/%1")
.arg(enc(dsObjectId))),
std::move(cb));
}
void ApiDatasetCommandRepository::getGridRawDataParams(
const QString& dsObjectId, std::function<void(bool, QJsonObject, QString)> cb) {
wireObject(api_.getAsync(QStringLiteral("/business/dd/ert/inversion/getRawData/%1")
.arg(enc(dsObjectId))),
std::move(cb));
}
void ApiDatasetCommandRepository::toGrid(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/dd/ert/inversion/grid"), body),
std::move(cb));
}
// ============================ 白化相关 ============================
void ApiDatasetCommandRepository::listWhitenedData(
const QString& projectId, const QString& tmObjectId,
std::function<void(bool, QJsonArray, QString)> cb) {
QJsonObject body{{QStringLiteral("projectId"), projectId},
{QStringLiteral("tmObjectId"), tmObjectId}};
wireArray(api_.postJsonAsync(QStringLiteral("/business/dsObject/queryWhitenedDataList"), body),
std::move(cb));
}
void ApiDatasetCommandRepository::whitenData(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/dd/ert/inversion/whitenedData"), body),
std::move(cb));
}
// ============================ 滤波相关 ============================
void ApiDatasetCommandRepository::listFilters(std::function<void(bool, QJsonArray, QString)> cb) {
wireArray(api_.getAsync(QStringLiteral("/business/filter/queryFilter")), std::move(cb));
}
void ApiDatasetCommandRepository::newFilter(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/filter"), body), std::move(cb));
}
void ApiDatasetCommandRepository::deleteFilter(const QString& id,
std::function<void(bool, QString)> cb) {
wireStatus(api_.deleteAsync(QStringLiteral("/business/filter/delete/%1").arg(enc(id))),
std::move(cb));
}
void ApiDatasetCommandRepository::applyFilter(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/dd/ert/inversion/filterData"), body),
std::move(cb));
}
// ============================ 异常 CRUD ============================
void ApiDatasetCommandRepository::listExceptionTypes(
const QString& projectId, const QString& remarkSourceType,
std::function<void(bool, QJsonArray, QString)> cb) {
wireArray(api_.getAsync(
QStringLiteral(
"/business/exceptionType/queryExceptionTypeByProjectIdAndType/%1/%2")
.arg(enc(projectId), enc(remarkSourceType))),
std::move(cb));
}
void ApiDatasetCommandRepository::getExceptionName(
const QString& exceptionTypeId, const QString& remarkSourceId,
std::function<void(bool, QString, QString)> cb) {
QJsonObject body{{QStringLiteral("exceptionTypeId"), exceptionTypeId},
{QStringLiteral("remarkSourceId"), remarkSourceId}};
// 原版 res.data 直接是名称字符串,回传纯字符串。
wireString(api_.postJsonAsync(QStringLiteral("/business/exception/getExceptionName"), body),
std::move(cb));
}
void ApiDatasetCommandRepository::newException(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/exception"), body), std::move(cb));
}
void ApiDatasetCommandRepository::deleteException(const QString& id,
std::function<void(bool, QString)> cb) {
wireStatus(api_.deleteAsync(QStringLiteral("/business/exception/%1").arg(enc(id))),
std::move(cb));
}
void ApiDatasetCommandRepository::updateException(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.putJsonAsync(QStringLiteral("/business/exception"), body), std::move(cb));
}
// ============================ 自动标注 ============================
void ApiDatasetCommandRepository::executeExceptionMark(
const QJsonObject& body, std::function<void(bool, QJsonObject, QString)> cb) {
wireObject(
api_.postJsonAsync(QStringLiteral("/business/exception/exception-mark/execute"), body),
std::move(cb));
}
void ApiDatasetCommandRepository::batchCreateException(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
wireStatus(api_.postJsonAsync(QStringLiteral("/business/exception/batch/create"), body),
std::move(cb));
}
// ============================ 描述 / dsObject ============================
void ApiDatasetCommandRepository::getDsObjectDetail(
const QString& dsObjectId, std::function<void(bool, QJsonObject, QString)> cb) {
wireObject(
api_.getAsync(QStringLiteral("/business/dsObject/getDetail/%1").arg(enc(dsObjectId))),
std::move(cb));
}
void ApiDatasetCommandRepository::updateDsObject(const QJsonObject& body,
std::function<void(bool, QString)> cb) {
// 原版 URL 末尾带斜杠updateProfileInversionDescription
wireStatus(api_.putJsonAsync(QStringLiteral("/business/dsObject/updateDsObject/"), body),
std::move(cb));
}
} // namespace geopro::data