feat(data): DatasetFieldDictionary 解析 arrayType/collectTime 映射+装置字典(纯函数)

This commit is contained in:
gaozheng 2026-06-24 18:08:45 +08:00
parent 1978a31fa7
commit c5b3907fad
5 changed files with 126 additions and 0 deletions

View File

@ -4,6 +4,7 @@ add_library(geopro_data STATIC
parse/SampleParsers.cpp
repo/LocalSampleRepository.cpp
repo/LocalSample3dRepository.cpp
repo/DatasetFieldDictionary.cpp
dto/NavDto.cpp
dto/Vtk3dRequests.cpp
dto/DatasetChartDto.cpp

View File

@ -0,0 +1,49 @@
#include "repo/DatasetFieldDictionary.hpp"
#include <QJsonArray>
namespace geopro::data {
DsTypeFields parseFieldMapping(const QJsonObject& d) {
DsTypeFields f;
for (const QJsonValue& gv : d.value(QStringLiteral("formList")).toArray()) {
for (const QJsonValue& vv : gv.toObject().value(QStringLiteral("values")).toArray()) {
const QJsonObject fo = vv.toObject();
const QString code = fo.value(QStringLiteral("fieldCode")).toString();
const std::string cfid = fo.value(QStringLiteral("confFieldId")).toString().toStdString();
if (code == QStringLiteral("arrayType")) {
f.arrayTypeConfFieldId = cfid;
for (const QJsonValue& ov : fo.value(QStringLiteral("optionsObject")).toArray()) {
const QJsonObject oo = ov.toObject();
f.arrayTypeLabels[oo.value(QStringLiteral("value")).toString().toStdString()] =
oo.value(QStringLiteral("label")).toString().toStdString();
}
} else if (code == QStringLiteral("collectTime")) {
f.collectTimeConfFieldId = cfid;
}
}
}
return f;
}
namespace {
std::string propValue(const DsRow& row, const std::string& cfid) {
if (cfid.empty()) return {};
for (const auto& kv : row.properties)
if (kv.confFieldId == cfid) return kv.value;
return {};
}
} // namespace
std::string arrayValueOf(const DsRow& row, const DsTypeFields& f) {
return propValue(row, f.arrayTypeConfFieldId);
}
std::string collectTimeOf(const DsRow& row, const DsTypeFields& f) {
return propValue(row, f.collectTimeConfFieldId);
}
std::string arrayLabel(const DsTypeFields& f, const std::string& value) {
const auto it = f.arrayTypeLabels.find(value);
return it != f.arrayTypeLabels.end() ? it->second : value; // 缺失回退原值spec §11
}
} // namespace geopro::data

View File

@ -0,0 +1,27 @@
#pragma once
#include <map>
#include <string>
#include <QJsonObject>
#include "repo/RepoTypes.hpp"
namespace geopro::data {
// 某 dsType 的字段映射spec §10
struct DsTypeFields {
std::string arrayTypeConfFieldId; // ds 行 properties 里装置类型项的 confFieldId
std::string collectTimeConfFieldId; // 采集时间项的 confFieldId
std::map<std::string, std::string> arrayTypeLabels; // value→中文来自 optionsObject
};
// 纯函数:从 dsObject/dynamicForm 的 data 解析字段映射formList → fieldCode==arrayType/collectTime
DsTypeFields parseFieldMapping(const QJsonObject& dynamicFormData);
// ds 行的装置类型原始值properties 中 confFieldId==arrayTypeConfFieldId 的 value缺=空)。
std::string arrayValueOf(const DsRow& row, const DsTypeFields& f);
// ds 行的采集时间properties 中 confFieldId==collectTimeConfFieldId 的 value缺=空)。
std::string collectTimeOf(const DsRow& row, const DsTypeFields& f);
// 装置类型 value→中文命中 arrayTypeLabels 取中文否则回退原值spec §11 字典源待坐实时的安全退路)。
std::string arrayLabel(const DsTypeFields& f, const std::string& value);
} // namespace geopro::data

View File

@ -43,6 +43,7 @@ target_sources(geopro_tests PRIVATE data/test_local_repo.cpp)
target_sources(geopro_tests PRIVATE data/test_3d_repo.cpp)
target_sources(geopro_tests PRIVATE data/test_nav_dto.cpp)
target_sources(geopro_tests PRIVATE data/test_vtk3d_requests.cpp)
target_sources(geopro_tests PRIVATE data/test_dataset_field_dictionary.cpp)
target_sources(geopro_tests PRIVATE data/test_dataset_chart_dto.cpp)
target_sources(geopro_tests PRIVATE data/test_measurement_dto.cpp)
target_sources(geopro_tests PRIVATE data/test_gr_dto.cpp)

View File

@ -0,0 +1,48 @@
#include <gtest/gtest.h>
#include <QJsonDocument>
#include "repo/DatasetFieldDictionary.hpp"
using namespace geopro::data;
namespace {
DsTypeFields parse(const char* js) {
return parseFieldMapping(QJsonDocument::fromJson(QByteArray(js)).object());
}
} // namespace
TEST(ParseFieldMapping, ExtractsArrayTypeAndCollectTimeConfFieldIds) {
const DsTypeFields f = parse(R"({"formList":[{"groupName":"","values":[
{"confFieldId":"f_ct","fieldCode":"collectTime","fieldName":"采集时间","optionsObject":null},
{"confFieldId":"f_at","fieldCode":"arrayType","fieldName":"装置类型","optionsObject":[
{"label":"温纳-施伦贝尔排列","value":"v1"},{"label":"全梯度","value":"v2"}]}
]}]})");
EXPECT_EQ(f.arrayTypeConfFieldId, "f_at");
EXPECT_EQ(f.collectTimeConfFieldId, "f_ct");
ASSERT_EQ(f.arrayTypeLabels.count("v1"), 1u);
EXPECT_EQ(f.arrayTypeLabels.at("v1"), "温纳-施伦贝尔排列");
EXPECT_EQ(f.arrayTypeLabels.at("v2"), "全梯度");
}
TEST(DatasetFieldDictionary, ArrayValueAndCollectTimeFromRow) {
DsTypeFields f;
f.arrayTypeConfFieldId = "f_at";
f.collectTimeConfFieldId = "f_ct";
DsRow row;
row.properties = {{"f_at", "v2"}, {"f_ct", "2026-03-25 16:48:57"}, {"other", "x"}};
EXPECT_EQ(arrayValueOf(row, f), "v2");
EXPECT_EQ(collectTimeOf(row, f), "2026-03-25 16:48:57");
}
TEST(DatasetFieldDictionary, MissingPropReturnsEmpty) {
DsTypeFields f;
f.arrayTypeConfFieldId = "f_at";
DsRow row; // 无 properties
EXPECT_EQ(arrayValueOf(row, f), "");
}
TEST(DatasetFieldDictionary, ArrayLabelHitsAndFallsBackToRawValue) {
DsTypeFields f;
f.arrayTypeLabels = {{"v1", "温纳"}};
EXPECT_EQ(arrayLabel(f, "v1"), "温纳");
// spec §11原始值不在 optionsObject 时回退显示原值(如实测 1429468249448449
EXPECT_EQ(arrayLabel(f, "1429468249448449"), "1429468249448449");
}