feat(data): Api3dRepository.anomalyRows 按 remarkSourceId 供三级树注入(Task11 Step2)

This commit is contained in:
gaozheng 2026-06-24 20:45:55 +08:00
parent 52830bbcb0
commit 07be3aef21
3 changed files with 52 additions and 0 deletions

View File

@ -134,6 +134,22 @@ std::vector<DsRow> Api3dRepository::volumeRows() const {
return rows;
}
std::vector<DsRow> Api3dRepository::anomalyRows() const {
std::vector<DsRow> rows;
rows.reserve(anomalies_.size());
for (const auto& [id, sa] : anomalies_) {
DsRow r;
r.id = id;
r.dsName = sa.a.name;
r.ddCode = "dd_anomaly";
r.typeName = sa.a.typeName.empty() ? std::string("异常") : sa.a.typeName;
r.createTime = sa.a.createTime;
r.parentId = sa.a.remarkSourceId; // 挂归属实体(体/切片)下;三级树按 parentId 自动挂载
rows.push_back(std::move(r));
}
return rows;
}
bool Api3dRepository::volumeInfo(const std::string& dsId, VolumeInfo& out) const {
auto it = volumes_.find(dsId);
if (it == volumes_.end()) return false;

View File

@ -62,6 +62,9 @@ public:
bool volumeInfo(const std::string& dsId, VolumeInfo& out) const;
// 已保存切片的列表行ddCode="dd_slice"parentId=所属体 dsId → 树中挂父体下),供三维分析栏合并。
std::vector<DsRow> sliceRows() const;
// 异常列表行ddCode="dd_anomaly"parentId=remarkSourceId=归属实体[体/切片] dsId → 三级树自动挂载),
// 供三维体段「体→切片/异常」三级树合并注入spec §8
std::vector<DsRow> anomalyRows() const;
// 该 dsId 是否为已保存切片3b分析栏勾选 dd_slice 走切片重渲染路径,不进控制器帘面/体素路径)。
bool isSliceDataset(const std::string& dsId) const;
// 取回已保存切片位姿(还原渲染用);不存在返回 false。

View File

@ -156,3 +156,36 @@ TEST(Api3dRepo, VolumeInfoUnknownIdReturnsFalse) {
Api3dRepository::VolumeInfo info;
EXPECT_FALSE(repo.volumeInfo("not-a-volume", info));
}
// anomalyRows异常按 remarkSourceId 存;行 parentId=归属实体 id挂体/挂切片各回得来)。
TEST(Api3dRepo, AnomalyRowsCarryMountAsParent) {
StubAsyncRepo dsRepo;
auto frame = std::make_shared<geopro::core::GeoLocalFrame>(22.0, 114.0);
Api3dRepository repo(dsRepo, frame);
geopro::core::Anomaly onVol;
onVol.name = "异常A"; onVol.typeName = "断层"; onVol.remarkSourceId = "vol-1";
geopro::core::Anomaly onSlice;
onSlice.name = "异常B"; onSlice.remarkSourceId = "slice-9"; // 已保存切片
std::string idV, idS;
repo.saveAnomaly(onVol, "", [&](std::string id) { idV = id; }, [](const std::string&) {});
repo.saveAnomaly(onSlice, "", [&](std::string id) { idS = id; }, [](const std::string&) {});
const auto rows = repo.anomalyRows();
ASSERT_EQ(rows.size(), 2u);
auto find = [&](const std::string& id) -> const geopro::data::DsRow* {
for (const auto& r : rows)
if (r.id == id) return &r;
return nullptr;
};
const auto* rv = find(idV);
ASSERT_NE(rv, nullptr);
EXPECT_EQ(rv->ddCode, "dd_anomaly");
EXPECT_EQ(rv->parentId, "vol-1"); // 挂体
EXPECT_EQ(rv->dsName, "异常A");
EXPECT_EQ(rv->typeName, "断层");
const auto* rs = find(idS);
ASSERT_NE(rs, nullptr);
EXPECT_EQ(rs->parentId, "slice-9"); // 挂切片
EXPECT_EQ(rs->typeName, "异常"); // typeName 空 → 回退"异常"
}