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 82 additions and 0 deletions
Showing only changes of commit acf71bdaef - Show all commits

View File

@ -1,9 +1,12 @@
#include "dto/NavDto.hpp"
#include <QJsonValue>
#include <QString>
#include <QStringList>
#include <algorithm>
#include <functional>
#include <limits>
#include <set>
namespace geopro::data::dto {
@ -28,6 +31,19 @@ ProjectSummary parseProjectItem(const QJsonObject& o) {
p.status = o.value(QStringLiteral("status")).toInt();
return p;
}
// elevationList 极值拼 "高程 min~max m";空返回空串。
std::string elevationSummary(const QJsonArray& el) {
if (el.isEmpty()) return {};
double lo = std::numeric_limits<double>::max(), hi = -std::numeric_limits<double>::max();
for (const QJsonValue& v : el) {
const double d = v.toDouble();
if (d < lo) lo = d;
if (d > hi) hi = d;
}
return QStringLiteral("高程 %1~%2m")
.arg(lo, 0, 'f', 0).arg(hi, 0, 'f', 0).toStdString();
}
} // namespace
std::vector<Workspace> parseWorkspaces(const QJsonArray& arr) {
@ -192,4 +208,31 @@ DynamicForm parseDynamicForm(const QJsonObject& data) {
return form;
}
std::vector<ExceptionRow> parseExceptions(const QJsonArray& arr) {
std::vector<ExceptionRow> out;
out.reserve(static_cast<size_t>(arr.size()));
for (const QJsonValue& v : arr) {
const QJsonObject o = v.toObject();
ExceptionRow r;
r.id = str(o, "id");
r.name = str(o, "exceptionName");
r.typeName = str(o, "exceptionTypeName");
r.createTime = str(o, "createTime");
r.consortiumId = str(o, "consortiumId");
r.consortiumName = str(o, "consortiumName");
r.consortiumType = str(o, "consortiumType");
QStringList lines;
lines << QStringLiteral("标记 %1 · 创建 %2")
.arg(QString::fromStdString(str(o, "exceptionMarkTypeName")))
.arg(QString::fromStdString(r.createTime));
const std::string elev = elevationSummary(o.value(QStringLiteral("elevationList")).toArray());
if (!elev.empty()) lines << QString::fromStdString(elev);
const std::string remark = str(o, "remark");
if (!remark.empty()) lines << QStringLiteral("备注 %1").arg(QString::fromStdString(remark));
r.detailSummary = lines.join(QLatin1Char('\n')).toStdString();
out.push_back(std::move(r));
}
return out;
}
} // namespace geopro::data::dto

View File

@ -43,4 +43,9 @@ std::vector<StructTreeNode> buildStructTree(const std::vector<StructNode>& flat)
// 表头 name 取 data["name"]。
DynamicForm parseDynamicForm(const QJsonObject& data);
// ExceptionVO 数组 → [ExceptionRow]。字段id、name=exceptionName、typeName=exceptionTypeName、
// createTimeconsortium* 取自 consortiumId/consortiumName/consortiumType来源待 live 验证);
// detailSummary 由 exceptionMarkTypeName/createTime/elevationList/remark 拼成可读多行串。
std::vector<ExceptionRow> parseExceptions(const QJsonArray& arr);
} // namespace geopro::data::dto

View File

@ -37,4 +37,11 @@ struct StructNode { std::string id, name, parentId, typeName, confCode; int type
struct DynamicFormField { std::string name, value; };
struct DynamicFormGroup { std::string name; std::vector<DynamicFormField> fields; };
struct DynamicForm { std::string name; std::vector<DynamicFormGroup> groups; };
// 异常树叶本轮只读。consortium* 空 = 独立异常detailSummary = 详情展开内联显示。
struct ExceptionRow {
std::string id, name, typeName, createTime;
std::string consortiumId, consortiumName, consortiumType;
std::string detailSummary;
};
} // namespace geopro::data

View File

@ -235,3 +235,30 @@ TEST(NavDto, ParseDynamicFormEmptyFormListYieldsNoGroups) {
EXPECT_EQ(form.name, "");
EXPECT_TRUE(form.groups.empty());
}
TEST(NavDto, ParseExceptionsMapsFieldsAndSummary) {
const auto arr = arrOf(R"([
{ "id":"e1", "exceptionName":"空洞A", "exceptionTypeName":"空洞",
"exceptionMarkTypeName":"自动", "createTime":"2026-06-01",
"elevationList":[120.0, 80.0, 100.0], "remark":"复核中",
"consortiumId":"c1", "consortiumName":"体A", "consortiumType":"溶洞群" },
{ "id":"e2", "exceptionName":"裂隙B", "exceptionTypeName":"裂隙",
"exceptionMarkTypeName":"手动", "createTime":"2026-06-02",
"elevationList":[], "remark":"" }
])");
const auto rows = dto::parseExceptions(arr);
ASSERT_EQ(rows.size(), 2u);
EXPECT_EQ(rows[0].id, "e1");
EXPECT_EQ(rows[0].name, "空洞A");
EXPECT_EQ(rows[0].typeName, "空洞");
EXPECT_EQ(rows[0].consortiumId, "c1");
EXPECT_EQ(rows[0].consortiumName, "体A");
EXPECT_EQ(rows[0].consortiumType, "溶洞群");
EXPECT_NE(rows[0].detailSummary.find("自动"), std::string::npos);
EXPECT_NE(rows[0].detailSummary.find("2026-06-01"), std::string::npos);
EXPECT_NE(rows[0].detailSummary.find("80"), std::string::npos);
EXPECT_NE(rows[0].detailSummary.find("120"), std::string::npos);
EXPECT_NE(rows[0].detailSummary.find("复核中"), std::string::npos);
EXPECT_TRUE(rows[1].consortiumId.empty());
EXPECT_NE(rows[1].detailSummary.find("手动"), std::string::npos);
}