From 652b37b6729c15bf666b321ca70ee521b7c243d5 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Thu, 25 Jun 2026 19:21:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(vtk):=20=E4=BF=AE=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=88=87=E7=89=87/=E5=BC=82=E5=B8=B8=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E4=BD=93=C2=B7=E5=88=87=E7=89=87=E9=80=89=E6=8B=A9(issue1)+?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=89=AF=E6=A0=87=E9=A2=98=E8=A1=A5=E6=97=B6?= =?UTF-8?q?=E9=97=B4+=E6=96=B0=E5=88=87=E7=89=87=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8B=BE=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - issue1 真因:voxel(三维体)段数据来自 mock voxelTree,但 setBuckets 用 splitByCategory 的空桶 (对象树 ds 里无 dd_voxel→必空)先 setDatasets(空) 清掉其勾选,随后 section("voxel")->setDatasets (voxelTree) 重填时勾选已丢→「创建切片/异常后体/切片选择被清空」。修:setBuckets 跳过 voxel 段 - 异常副标题没时间:saveAnomaly 没设 createTime(main 构建 Anomaly 也没设)→补当前时间(mock) - 新切片自动勾选:CategorySection::setChecked(dsId) + 保存切片回调在 refreshAnalysis 后勾选新切片 (恢复旧行为,避免刚存的切片因未勾被 syncSlices 隐藏) 未解(下轮):issue2 选第二个体时第一个体切片消失=单"当前体"模型固有限制(syncSlices 只显示 volumeDsId==currentVolumeDsId 的切片),需多体并发切片渲染改造 构建:app 链接通过 --- src/app/main.cpp | 8 +++++--- src/app/panels/columns/CategoryAnalysisTab.cpp | 4 ++++ src/app/panels/columns/CategorySection.cpp | 9 +++++++++ src/app/panels/columns/CategorySection.hpp | 1 + src/data/api/Api3dRepository.cpp | 3 +++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index 0dd51b7..76aaa46 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -608,10 +608,12 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re if (!ok) return; scene3dRepo->createSlice( spec, name.isEmpty() ? std::string("切片") : name.toStdString(), - [interactionMgr, refreshAnalysis](std::string newId) { + [interactionMgr, refreshAnalysis, drawer](std::string newId) { interactionMgr->tagSelectedSlice(newId); // 链接当前切片 → 新数据集(不重绘) - refreshAnalysis(); // 新行进列表(勾选集不变→不发多余信号) - // TODO:新分段 tab 暂无 setItemChecked,新切片列表默认未勾(已渲染但列表不打勾,待补)。 + refreshAnalysis(); // 新行进列表 + // 新切片自动勾选 → 列表打勾 + 保持渲染(refreshAnalysis 已重建列表,故在其后勾选)。 + if (auto* sec = drawer->analysisTab()->section("voxel")) + sec->setChecked(QString::fromStdString(newId), true); }, [&window](const std::string& m) { QMessageBox::warning(&window, QStringLiteral("保存切片"), diff --git a/src/app/panels/columns/CategoryAnalysisTab.cpp b/src/app/panels/columns/CategoryAnalysisTab.cpp index 1b52992..f9adedf 100644 --- a/src/app/panels/columns/CategoryAnalysisTab.cpp +++ b/src/app/panels/columns/CategoryAnalysisTab.cpp @@ -59,6 +59,10 @@ CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* d void CategoryAnalysisTab::setBuckets(const CategoryBuckets& b) { const auto& cfg = categoryConfigs(); for (std::size_t i = 0; i < cfg.size() && i < b.segments.size(); ++i) { + // voxel(三维体) 段数据来自 mock voxelTree(体/切片/异常),由调用方单独 section("voxel")->setDatasets + // 注入;splitByCategory 对它永远是空桶,若在此用空桶覆盖会先清掉其勾选(随后重填但勾选已丢) → + // 表现为「创建切片/异常后体/切片选择被清空」(用户 issue 1)。故跳过 voxel,勿覆盖。 + if (cfg[i].id == "voxel") continue; if (auto* sec = section(cfg[i].id)) sec->setDatasets(b.segments[i]); } } diff --git a/src/app/panels/columns/CategorySection.cpp b/src/app/panels/columns/CategorySection.cpp index c76e765..a37252f 100644 --- a/src/app/panels/columns/CategorySection.cpp +++ b/src/app/panels/columns/CategorySection.cpp @@ -116,6 +116,15 @@ void CategorySection::setDatasets(const std::vector& rows) { rebuildList(); } +void CategorySection::setChecked(const QString& dsId, bool on) { + for (QTreeWidgetItemIterator it(list_); *it; ++it) + if ((*it)->data(0, kDsIdRole).toString() == dsId && + ((*it)->flags() & Qt::ItemIsUserCheckable)) { + (*it)->setCheckState(0, on ? Qt::Checked : Qt::Unchecked); // 触发 itemChanged→emitChecked→渲染 + return; + } +} + void CategorySection::refreshArrayCombo() { if (!spec_.hasArrayTypeFilter || !arrayCombo_) return; const QString prev = arrayCombo_->currentData().toString(); diff --git a/src/app/panels/columns/CategorySection.hpp b/src/app/panels/columns/CategorySection.hpp index af8c195..7882c57 100644 --- a/src/app/panels/columns/CategorySection.hpp +++ b/src/app/panels/columns/CategorySection.hpp @@ -32,6 +32,7 @@ public: // 对象树同源的扁平 GS/TM 节点(段体容器分层用;Task 12 接入真实结构,当前仅存储)。 void setStructure(const std::vector& nodes); void setDatasets(const std::vector& rows); + void setChecked(const QString& dsId, bool on); // 按 dsId 勾选/取消(新建切片自动勾选等场景) const CategorySpec& spec() const { return spec_; } signals: diff --git a/src/data/api/Api3dRepository.cpp b/src/data/api/Api3dRepository.cpp index 79e8400..02e4e63 100644 --- a/src/data/api/Api3dRepository.cpp +++ b/src/data/api/Api3dRepository.cpp @@ -416,6 +416,9 @@ void Api3dRepository::saveAnomaly(const geopro::core::Anomaly& a, if (id.empty()) id = "anomaly-" + std::to_string(++anomalyCounter_); // 新建 → 生成 id geopro::core::Anomaly stored = a; stored.id = id; + if (stored.createTime.empty()) // mock:构建时未设创建时刻 → 补当前时间(副标题/列表显示) + stored.createTime = + QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd HH:mm")).toStdString(); anomalies_[id] = StoredAnomaly{std::move(stored), screenshotPngPath}; onOk(id); }