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); }