feat/object-selection-panels #4

Merged
gaozheng merged 18 commits from feat/object-selection-panels into main 2026-06-10 21:33:30 +08:00
4 changed files with 68 additions and 0 deletions
Showing only changes of commit a21d392816 - Show all commits

View File

@ -8,6 +8,7 @@
#include <functional> #include <functional>
#include <limits> #include <limits>
#include <set> #include <set>
#include <unordered_map>
namespace geopro::data::dto { namespace geopro::data::dto {
@ -235,4 +236,30 @@ std::vector<ExceptionRow> parseExceptions(const QJsonArray& arr) {
return out; return out;
} }
GroupedExceptions groupExceptionsByConsortium(const std::vector<ExceptionRow>& rows) {
GroupedExceptions out;
std::unordered_map<std::string, size_t> 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 } // namespace geopro::data::dto

View File

@ -48,4 +48,8 @@ DynamicForm parseDynamicForm(const QJsonObject& data);
// detailSummary 由 exceptionMarkTypeName/createTime/elevationList/remark 拼成可读多行串。 // detailSummary 由 exceptionMarkTypeName/createTime/elevationList/remark 拼成可读多行串。
std::vector<ExceptionRow> parseExceptions(const QJsonArray& arr); std::vector<ExceptionRow> parseExceptions(const QJsonArray& arr);
// 把一个对象(TM)的异常行按 consortiumId 分组:同 id 归一组(组名/类型取首个非空);
// consortiumId 空 → loose。保持首次出现顺序稳定。纯函数、可单测。
GroupedExceptions groupExceptionsByConsortium(const std::vector<ExceptionRow>& rows);
} // namespace geopro::data::dto } // namespace geopro::data::dto

View File

@ -44,4 +44,13 @@ struct ExceptionRow {
std::string consortiumId, consortiumName, consortiumType; std::string consortiumId, consortiumName, consortiumType;
std::string detailSummary; std::string detailSummary;
}; };
// 异常体分组(树中间层)+ 对象分组(树根层,对应一个被勾选 TM
struct ConsortiumGroup { std::string id, name, typeName; std::vector<ExceptionRow> exceptions; };
struct ObjectExceptionGroup {
std::string objectId, objectName;
std::vector<ConsortiumGroup> consortia;
std::vector<ExceptionRow> looseExceptions;
};
struct GroupedExceptions { std::vector<ConsortiumGroup> consortia; std::vector<ExceptionRow> loose; };
} // namespace geopro::data } // namespace geopro::data

View File

@ -4,6 +4,8 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <vector>
#include "dto/NavDto.hpp" #include "dto/NavDto.hpp"
using namespace geopro::data; using namespace geopro::data;
@ -262,3 +264,29 @@ TEST(NavDto, ParseExceptionsMapsFieldsAndSummary) {
EXPECT_TRUE(rows[1].consortiumId.empty()); EXPECT_TRUE(rows[1].consortiumId.empty());
EXPECT_NE(rows[1].detailSummary.find("手动"), std::string::npos); EXPECT_NE(rows[1].detailSummary.find("手动"), std::string::npos);
} }
TEST(NavDto, GroupExceptionsByConsortiumSplitsLooseAndGroups) {
std::vector<ExceptionRow> 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<ExceptionRow> 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);
}