From c6756aafc5a8ddd01a47a32f309fe45ba744a510 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Fri, 26 Jun 2026 10:28:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(3d):=20=E5=BC=82=E5=B8=B8=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=B8=8B=E6=8B=89=E6=8E=A5=E5=B9=B3=E5=8F=B0=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=E7=B1=BB=E5=9E=8B(=E5=8E=BB=20mock,=E4=B8=8E=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E4=B8=80=E8=87=B4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AnomalySaveDialog 原硬编码 4 个 mock 类型。改为按标注形态(remarkSourceType)异步拉平台异常类型 (cmdRepo.listExceptionTypes,label→显示/value→id)填充下拉,与平台保持一致。net 层已把扁平 data 数组归一为 value→wireArray 可读。空/失败由 EmptyAwareComboBox 空态提示。 当前面(Polygon)固定 remarkSourceType=3;P2 接点/线后由菜单形态决定 1/2/3。 构建:app 链接通过 --- src/app/AnomalySaveDialog.cpp | 37 +++++++++++++++++++++++------------ src/app/AnomalySaveDialog.hpp | 16 +++++++++++++-- src/app/main.cpp | 14 ++++++++----- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/app/AnomalySaveDialog.cpp b/src/app/AnomalySaveDialog.cpp index e4279be..db2d4d0 100644 --- a/src/app/AnomalySaveDialog.cpp +++ b/src/app/AnomalySaveDialog.cpp @@ -4,28 +4,23 @@ #include "EmptyAwareComboBox.hpp" #include +#include +#include #include #include #include #include +#include #include "FormKit.hpp" #include "Theme.hpp" +#include "repo/IDatasetCommandRepository.hpp" namespace geopro::app { -namespace { -// 异常类型 mock 列表(label, id)。真实 exceptionType 端点只读、后续接。 -struct TypeItem { const char* label; const char* id; }; -const TypeItem kMockTypes[] = { - {"断层", "mock-fault"}, - {"破碎带", "mock-fracture"}, - {"含水构造", "mock-water"}, - {"其它", "mock-other"}, -}; -} // namespace - AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, int shotH, + geopro::data::IDatasetCommandRepository* cmdRepo, + const QString& projectId, int remarkSourceType, QWidget* parent) : QDialog(parent) { setWindowTitle(QStringLiteral("保存异常")); @@ -42,10 +37,9 @@ AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, i form->addRow(formkit::editLabel(QStringLiteral("名称")), name_); type_ = new EmptyAwareComboBox(); - for (const auto& t : kMockTypes) - type_->addItem(QString::fromUtf8(t.label), QString::fromUtf8(t.id)); formkit::capField(type_); form->addRow(formkit::editLabel(QStringLiteral("异常类型")), type_); + loadTypes(cmdRepo, projectId, remarkSourceType); // 异步拉平台异常类型填充(与平台一致) remark_ = new QPlainTextEdit(); remark_->setFixedHeight(geopro::app::scaledPx(60)); @@ -69,6 +63,23 @@ AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, i formkit::addDialogButtons(root, this); } +void AnomalySaveDialog::loadTypes(geopro::data::IDatasetCommandRepository* cmdRepo, + const QString& projectId, int remarkSourceType) { + if (cmdRepo == nullptr || projectId.isEmpty()) return; // 无仓储/项目 → 下拉留空(空态提示) + QPointer self(this); + cmdRepo->listExceptionTypes( + projectId, QString::number(remarkSourceType), + [self](bool ok, QJsonArray list, const QString&) { + if (!self || !ok) return; // 对话框已关 / 失败 → 留空 + for (const QJsonValue& v : list) { + const QJsonObject o = v.toObject(); + // 平台响应项:{label:类型名, value:类型id}(实测扁平 data 数组,net 层已归一 value)。 + self->type_->addItem(o.value(QStringLiteral("label")).toString(), + o.value(QStringLiteral("value")).toString()); + } + }); +} + QString AnomalySaveDialog::anomalyName() const { const QString n = name_->text().trimmed(); return n.isEmpty() ? QStringLiteral("异常") : n; diff --git a/src/app/AnomalySaveDialog.hpp b/src/app/AnomalySaveDialog.hpp index 1bb8f10..7220eaa 100644 --- a/src/app/AnomalySaveDialog.hpp +++ b/src/app/AnomalySaveDialog.hpp @@ -7,15 +7,23 @@ class QComboBox; class QPlainTextEdit; class QLabel; +namespace geopro::data { +class IDatasetCommandRepository; +} + namespace geopro::app { // 异常保存对话框(#4b,需求 R50):名称 + 异常类型 + 备注 + 截图预览/大小。 -// 异常类型本期 mock 列表(真实 exceptionType 端点只读、后续可接)。accept 后取 name/typeName/typeId/remark。 +// 异常类型从平台按标注形态(remarkSourceType)异步拉取,与平台保持一致。accept 后取 name/typeName/typeId/remark。 class AnomalySaveDialog : public QDialog { Q_OBJECT public: // screenshotPath:圈定结束截图的本地路径(为空则不显示预览);w/h:截图像素尺寸(R50「确定截图大小」)。 - AnomalySaveDialog(const QString& screenshotPath, int shotW, int shotH, QWidget* parent = nullptr); + // cmdRepo/projectId:异步拉取平台异常类型填充下拉(与平台一致);remarkSourceType:标注形态 1点/2线/3面, + // 决定查询哪一类平台异常类型。cmdRepo 为空则下拉留空(空态由 EmptyAwareComboBox 提示)。 + AnomalySaveDialog(const QString& screenshotPath, int shotW, int shotH, + geopro::data::IDatasetCommandRepository* cmdRepo, const QString& projectId, + int remarkSourceType, QWidget* parent = nullptr); QString anomalyName() const; QString typeName() const; @@ -23,6 +31,10 @@ public: QString remark() const; private: + // 异步拉平台异常类型(label→显示, value→id)填充下拉;空/失败时下拉留空(EmptyAwareComboBox 提示)。 + void loadTypes(geopro::data::IDatasetCommandRepository* cmdRepo, const QString& projectId, + int remarkSourceType); + QLineEdit* name_ = nullptr; QComboBox* type_ = nullptr; QPlainTextEdit* remark_ = nullptr; diff --git a/src/app/main.cpp b/src/app/main.cpp index a1f396c..3f3e198 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -503,8 +503,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re // 保存=按"未保存/已保存"分派(新建+链接+自动勾选 / 覆盖位姿);导出统一为「导出▸图片·dat」; // 正视/翻转/关闭=接现有交互(关闭已保存切片→onSliceClosed 取消列表勾选);创建异常=占位(#4)。 interactionMgr->onSliceContextMenuRequested = - [&window, interactionMgr, sceneView, scene3dRepo, refreshAnalysis, refreshAnomalies, drawer, - anomalyDrawTool, renderWindowPtr]() { + [&window, &cmdRepo, &nav, interactionMgr, sceneView, scene3dRepo, refreshAnalysis, + refreshAnomalies, drawer, anomalyDrawTool, renderWindowPtr]() { QMenu menu(&window); QAction* aAnomaly = menu.addAction(QStringLiteral("创建异常")); QAction* aSave = menu.addAction(QStringLiteral("保存")); @@ -537,8 +537,9 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re const std::string savedSliceId = interactionMgr->selectedSliceDsId(); anomalyDrawTool->start( o, normal, - [&window, sceneView, scene3dRepo, renderWindowPtr, refreshAnomalies, refreshAnalysis, - volId, savedSliceId, normal, o, p1, p2](const std::vector& worldPts) { + [&window, &cmdRepo, &nav, sceneView, scene3dRepo, renderWindowPtr, refreshAnomalies, + refreshAnalysis, volId, savedSliceId, normal, o, p1, + p2](const std::vector& worldPts) { // 草稿异常:先临时渲染(让用户在对话框前看到所画,且截图含异常)。 geopro::core::Anomaly a; a.markType = geopro::core::AnomalyMarkType::Polygon; @@ -575,7 +576,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re const double minExt = 0.25 * std::min(e1, e2); // 点/线退化框景半径 geopro::app::captureFramedRegionPng(renderWindowPtr, rb, 1.4, minExt, shot.toStdString(), sw, sh); - geopro::app::AnomalySaveDialog dlg(shot, sw, sh, &window); + // 异常类型按标注形态拉平台类型(与平台一致)。当前仅面(Polygon)→remarkSourceType=3; + // P2 接入点/线后由菜单形态决定 1/2/3。 + geopro::app::AnomalySaveDialog dlg(shot, sw, sh, &cmdRepo, + nav.currentProjectId(), 3, &window); if (dlg.exec() != QDialog::Accepted) { sceneView->removeAnomaly(draftId); renderWindowPtr->Render();