feat(3d): 异常类型下拉接平台真实类型(去 mock,与平台一致)
AnomalySaveDialog 原硬编码 4 个 mock 类型。改为按标注形态(remarkSourceType)异步拉平台异常类型 (cmdRepo.listExceptionTypes,label→显示/value→id)填充下拉,与平台保持一致。net 层已把扁平 data 数组归一为 value→wireArray 可读。空/失败由 EmptyAwareComboBox 空态提示。 当前面(Polygon)固定 remarkSourceType=3;P2 接点/线后由菜单形态决定 1/2/3。 构建:app 链接通过
This commit is contained in:
parent
75c1327aa4
commit
c6756aafc5
|
|
@ -4,28 +4,23 @@
|
||||||
|
|
||||||
#include "EmptyAwareComboBox.hpp"
|
#include "EmptyAwareComboBox.hpp"
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
#include "FormKit.hpp"
|
#include "FormKit.hpp"
|
||||||
#include "Theme.hpp"
|
#include "Theme.hpp"
|
||||||
|
#include "repo/IDatasetCommandRepository.hpp"
|
||||||
|
|
||||||
namespace geopro::app {
|
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,
|
AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, int shotH,
|
||||||
|
geopro::data::IDatasetCommandRepository* cmdRepo,
|
||||||
|
const QString& projectId, int remarkSourceType,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: QDialog(parent) {
|
: QDialog(parent) {
|
||||||
setWindowTitle(QStringLiteral("保存异常"));
|
setWindowTitle(QStringLiteral("保存异常"));
|
||||||
|
|
@ -42,10 +37,9 @@ AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, i
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("名称")), name_);
|
form->addRow(formkit::editLabel(QStringLiteral("名称")), name_);
|
||||||
|
|
||||||
type_ = new EmptyAwareComboBox();
|
type_ = new EmptyAwareComboBox();
|
||||||
for (const auto& t : kMockTypes)
|
|
||||||
type_->addItem(QString::fromUtf8(t.label), QString::fromUtf8(t.id));
|
|
||||||
formkit::capField(type_);
|
formkit::capField(type_);
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("异常类型")), type_);
|
form->addRow(formkit::editLabel(QStringLiteral("异常类型")), type_);
|
||||||
|
loadTypes(cmdRepo, projectId, remarkSourceType); // 异步拉平台异常类型填充(与平台一致)
|
||||||
|
|
||||||
remark_ = new QPlainTextEdit();
|
remark_ = new QPlainTextEdit();
|
||||||
remark_->setFixedHeight(geopro::app::scaledPx(60));
|
remark_->setFixedHeight(geopro::app::scaledPx(60));
|
||||||
|
|
@ -69,6 +63,23 @@ AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, i
|
||||||
formkit::addDialogButtons(root, this);
|
formkit::addDialogButtons(root, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnomalySaveDialog::loadTypes(geopro::data::IDatasetCommandRepository* cmdRepo,
|
||||||
|
const QString& projectId, int remarkSourceType) {
|
||||||
|
if (cmdRepo == nullptr || projectId.isEmpty()) return; // 无仓储/项目 → 下拉留空(空态提示)
|
||||||
|
QPointer<AnomalySaveDialog> 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 {
|
QString AnomalySaveDialog::anomalyName() const {
|
||||||
const QString n = name_->text().trimmed();
|
const QString n = name_->text().trimmed();
|
||||||
return n.isEmpty() ? QStringLiteral("异常") : n;
|
return n.isEmpty() ? QStringLiteral("异常") : n;
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,23 @@ class QComboBox;
|
||||||
class QPlainTextEdit;
|
class QPlainTextEdit;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
|
||||||
|
namespace geopro::data {
|
||||||
|
class IDatasetCommandRepository;
|
||||||
|
}
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
// 异常保存对话框(#4b,需求 R50):名称 + 异常类型 + 备注 + 截图预览/大小。
|
// 异常保存对话框(#4b,需求 R50):名称 + 异常类型 + 备注 + 截图预览/大小。
|
||||||
// 异常类型本期 mock 列表(真实 exceptionType 端点只读、后续可接)。accept 后取 name/typeName/typeId/remark。
|
// 异常类型从平台按标注形态(remarkSourceType)异步拉取,与平台保持一致。accept 后取 name/typeName/typeId/remark。
|
||||||
class AnomalySaveDialog : public QDialog {
|
class AnomalySaveDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
// screenshotPath:圈定结束截图的本地路径(为空则不显示预览);w/h:截图像素尺寸(R50「确定截图大小」)。
|
// 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 anomalyName() const;
|
||||||
QString typeName() const;
|
QString typeName() const;
|
||||||
|
|
@ -23,6 +31,10 @@ public:
|
||||||
QString remark() const;
|
QString remark() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// 异步拉平台异常类型(label→显示, value→id)填充下拉;空/失败时下拉留空(EmptyAwareComboBox 提示)。
|
||||||
|
void loadTypes(geopro::data::IDatasetCommandRepository* cmdRepo, const QString& projectId,
|
||||||
|
int remarkSourceType);
|
||||||
|
|
||||||
QLineEdit* name_ = nullptr;
|
QLineEdit* name_ = nullptr;
|
||||||
QComboBox* type_ = nullptr;
|
QComboBox* type_ = nullptr;
|
||||||
QPlainTextEdit* remark_ = nullptr;
|
QPlainTextEdit* remark_ = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -503,8 +503,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
// 保存=按"未保存/已保存"分派(新建+链接+自动勾选 / 覆盖位姿);导出统一为「导出▸图片·dat」;
|
// 保存=按"未保存/已保存"分派(新建+链接+自动勾选 / 覆盖位姿);导出统一为「导出▸图片·dat」;
|
||||||
// 正视/翻转/关闭=接现有交互(关闭已保存切片→onSliceClosed 取消列表勾选);创建异常=占位(#4)。
|
// 正视/翻转/关闭=接现有交互(关闭已保存切片→onSliceClosed 取消列表勾选);创建异常=占位(#4)。
|
||||||
interactionMgr->onSliceContextMenuRequested =
|
interactionMgr->onSliceContextMenuRequested =
|
||||||
[&window, interactionMgr, sceneView, scene3dRepo, refreshAnalysis, refreshAnomalies, drawer,
|
[&window, &cmdRepo, &nav, interactionMgr, sceneView, scene3dRepo, refreshAnalysis,
|
||||||
anomalyDrawTool, renderWindowPtr]() {
|
refreshAnomalies, drawer, anomalyDrawTool, renderWindowPtr]() {
|
||||||
QMenu menu(&window);
|
QMenu menu(&window);
|
||||||
QAction* aAnomaly = menu.addAction(QStringLiteral("创建异常"));
|
QAction* aAnomaly = menu.addAction(QStringLiteral("创建异常"));
|
||||||
QAction* aSave = 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();
|
const std::string savedSliceId = interactionMgr->selectedSliceDsId();
|
||||||
anomalyDrawTool->start(
|
anomalyDrawTool->start(
|
||||||
o, normal,
|
o, normal,
|
||||||
[&window, sceneView, scene3dRepo, renderWindowPtr, refreshAnomalies, refreshAnalysis,
|
[&window, &cmdRepo, &nav, sceneView, scene3dRepo, renderWindowPtr, refreshAnomalies,
|
||||||
volId, savedSliceId, normal, o, p1, p2](const std::vector<ri::Vec3>& worldPts) {
|
refreshAnalysis, volId, savedSliceId, normal, o, p1,
|
||||||
|
p2](const std::vector<ri::Vec3>& worldPts) {
|
||||||
// 草稿异常:先临时渲染(让用户在对话框前看到所画,且截图含异常)。
|
// 草稿异常:先临时渲染(让用户在对话框前看到所画,且截图含异常)。
|
||||||
geopro::core::Anomaly a;
|
geopro::core::Anomaly a;
|
||||||
a.markType = geopro::core::AnomalyMarkType::Polygon;
|
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); // 点/线退化框景半径
|
const double minExt = 0.25 * std::min(e1, e2); // 点/线退化框景半径
|
||||||
geopro::app::captureFramedRegionPng(renderWindowPtr, rb, 1.4, minExt,
|
geopro::app::captureFramedRegionPng(renderWindowPtr, rb, 1.4, minExt,
|
||||||
shot.toStdString(), sw, sh);
|
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) {
|
if (dlg.exec() != QDialog::Accepted) {
|
||||||
sceneView->removeAnomaly(draftId);
|
sceneView->removeAnomaly(draftId);
|
||||||
renderWindowPtr->Render();
|
renderWindowPtr->Render();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue