From a21d39281625e75d40433a0535f2b4e5c7be40c3 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 10 Jun 2026 20:09:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(data):=20groupExceptionsByConsortium=20?= =?UTF-8?q?=E6=8C=89=E5=BC=82=E5=B8=B8=E4=BD=93=E5=88=86=E7=BB=84=20+=20?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/data/dto/NavDto.cpp | 27 +++++++++++++++++++++++++++ src/data/dto/NavDto.hpp | 4 ++++ src/data/repo/RepoTypes.hpp | 9 +++++++++ tests/data/test_nav_dto.cpp | 28 ++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/src/data/dto/NavDto.cpp b/src/data/dto/NavDto.cpp index 91dec64..2f91e4a 100644 --- a/src/data/dto/NavDto.cpp +++ b/src/data/dto/NavDto.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace geopro::data::dto { @@ -235,4 +236,30 @@ std::vector parseExceptions(const QJsonArray& arr) { return out; } +GroupedExceptions groupExceptionsByConsortium(const std::vector& rows) { + GroupedExceptions out; + std::unordered_map indexById; // consortiumId → out.consortia 下标 + for (const auto& r : rows) { + if (r.consortiumId.empty()) { + out.loose.push_back(r); + continue; + } + auto it = indexById.find(r.consortiumId); + if (it == indexById.end()) { + ConsortiumGroup g; + g.id = r.consortiumId; + g.name = r.consortiumName; + g.typeName = r.consortiumType; + indexById.emplace(r.consortiumId, out.consortia.size()); + out.consortia.push_back(std::move(g)); + it = indexById.find(r.consortiumId); + } + ConsortiumGroup& g = out.consortia[it->second]; + if (g.name.empty() && !r.consortiumName.empty()) g.name = r.consortiumName; + if (g.typeName.empty() && !r.consortiumType.empty()) g.typeName = r.consortiumType; + g.exceptions.push_back(r); + } + return out; +} + } // namespace geopro::data::dto diff --git a/src/data/dto/NavDto.hpp b/src/data/dto/NavDto.hpp index 1c587eb..48649f9 100644 --- a/src/data/dto/NavDto.hpp +++ b/src/data/dto/NavDto.hpp @@ -48,4 +48,8 @@ DynamicForm parseDynamicForm(const QJsonObject& data); // detailSummary 由 exceptionMarkTypeName/createTime/elevationList/remark 拼成可读多行串。 std::vector parseExceptions(const QJsonArray& arr); +// 把一个对象(TM)的异常行按 consortiumId 分组:同 id 归一组(组名/类型取首个非空); +// consortiumId 空 → loose。保持首次出现顺序稳定。纯函数、可单测。 +GroupedExceptions groupExceptionsByConsortium(const std::vector& rows); + } // namespace geopro::data::dto diff --git a/src/data/repo/RepoTypes.hpp b/src/data/repo/RepoTypes.hpp index 5210d3c..f1ecb2a 100644 --- a/src/data/repo/RepoTypes.hpp +++ b/src/data/repo/RepoTypes.hpp @@ -44,4 +44,13 @@ struct ExceptionRow { std::string consortiumId, consortiumName, consortiumType; std::string detailSummary; }; + +// 异常体分组(树中间层)+ 对象分组(树根层,对应一个被勾选 TM)。 +struct ConsortiumGroup { std::string id, name, typeName; std::vector exceptions; }; +struct ObjectExceptionGroup { + std::string objectId, objectName; + std::vector consortia; + std::vector looseExceptions; +}; +struct GroupedExceptions { std::vector consortia; std::vector loose; }; } // namespace geopro::data diff --git a/tests/data/test_nav_dto.cpp b/tests/data/test_nav_dto.cpp index 1eda3c2..eb4a42f 100644 --- a/tests/data/test_nav_dto.cpp +++ b/tests/data/test_nav_dto.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "dto/NavDto.hpp" using namespace geopro::data; @@ -262,3 +264,29 @@ TEST(NavDto, ParseExceptionsMapsFieldsAndSummary) { EXPECT_TRUE(rows[1].consortiumId.empty()); EXPECT_NE(rows[1].detailSummary.find("手动"), std::string::npos); } + +TEST(NavDto, GroupExceptionsByConsortiumSplitsLooseAndGroups) { + std::vector rows = { + { "e1","空洞A","空洞","t1","c1","体A","溶洞群","" }, + { "e2","空洞B","空洞","t1","c1","","","" }, + { "e3","裂隙X","裂隙","t1","","","","" }, + { "e4","空洞C","空洞","t1","c2","体B","溶洞群","" }, + }; + const auto g = dto::groupExceptionsByConsortium(rows); + ASSERT_EQ(g.consortia.size(), 2u); + EXPECT_EQ(g.consortia[0].id, "c1"); + EXPECT_EQ(g.consortia[0].name, "体A"); + EXPECT_EQ(g.consortia[0].typeName, "溶洞群"); + ASSERT_EQ(g.consortia[0].exceptions.size(), 2u); + EXPECT_EQ(g.consortia[1].id, "c2"); + ASSERT_EQ(g.loose.size(), 1u); + EXPECT_EQ(g.loose[0].id, "e3"); +} + +TEST(NavDto, GroupExceptionsAllLooseWhenNoConsortium) { + std::vector rows = { + { "e1","a","t","t1","","","","" }, { "e2","b","t","t1","","","","" } }; + const auto g = dto::groupExceptionsByConsortium(rows); + EXPECT_TRUE(g.consortia.empty()); + EXPECT_EQ(g.loose.size(), 2u); +}