fix(nmNum): 禁止删除固定主分析井

- 固定创建数值分析时绑定的主井编码
- 在数据层和 Map 删除入口阻止主井删除
- 仅在井数据删除成功后解除图元绑定
- 允许删除非主井的当前查看井
feature/pebi-result-snapshot-20260831
lh 2 weeks ago
parent 3cf01e046b
commit 42298f70eb

@ -202,8 +202,25 @@ public:
// 添加井 // 添加井
nmDataWellBase* createWell(NM_WELL_MODEL eWellType); nmDataWellBase* createWell(NM_WELL_MODEL eWellType);
nmDataWellBase* changeWellType(nmDataWellBase* pOldWellData, NM_WELL_MODEL eTargetWellType); nmDataWellBase* changeWellType(nmDataWellBase* pOldWellData, NM_WELL_MODEL eTargetWellType);
/**
* @brief
* @note PrimaryWellCode
*/
bool isPrimaryWell(const nmDataWellBase* pWellData) const;
/**
* @brief
* @note
*/
bool canRemoveWell(const nmDataWellBase* pWellData) const;
/**
* @brief
* @return true false
*/
bool removeWell(nmDataWellBase* pWellData); bool removeWell(nmDataWellBase* pWellData);
// 移除井图元以及数据
/** @brief 同时移除一口非主分析井的图元和实时数据。 */
void removeWellDataAndPlot(nmDataWellBase* pWellData); void removeWellDataAndPlot(nmDataWellBase* pWellData);
/** /**
@ -465,7 +482,10 @@ public:
void beginBackgroundUse(); void beginBackgroundUse();
/** @brief 后台任务结束使用本管理器;最后一个任务退出时唤醒析构等待。 */ /** @brief 后台任务结束使用本管理器;最后一个任务退出时唤醒析构等待。 */
void endBackgroundUse(); void endBackgroundUse();
/** @brief 设置主分析井 WellCode空编码用于清空主井。 */ /**
* @brief WellCode
* @note clear
*/
void setPrimaryWellCode(const QString& sWellCode); void setPrimaryWellCode(const QString& sWellCode);
/** @brief 返回当前主分析井 WellCode。 */ /** @brief 返回当前主分析井 WellCode。 */
QString getPrimaryWellCode() const; QString getPrimaryWellCode() const;

@ -79,7 +79,10 @@ public:
/** @brief 返回主分析井的项目唯一 WellCode。 */ /** @brief 返回主分析井的项目唯一 WellCode。 */
QString getPrimaryWellCode() const; QString getPrimaryWellCode() const;
/** @brief 设置主分析井;同时移除包含列表中的同井项并使网格失效。 */ /**
* @brief 使
* @note clear()
*/
void setPrimaryWellCode(const QString& sWellCode); void setPrimaryWellCode(const QString& sWellCode);
/** @brief 返回主分析井在本次方案中的主动井或观察井角色。 */ /** @brief 返回主分析井在本次方案中的主动井或观察井角色。 */

@ -146,8 +146,11 @@ public:
// 调用:从文件加载,绑定已有井数据到已有图元 // 调用:从文件加载,绑定已有井数据到已有图元
void bindWellToGraphic(nmObjPointWell* pGraphic, nmDataWellBase* pData); void bindWellToGraphic(nmObjPointWell* pGraphic, nmDataWellBase* pData);
// 调用:删除井图元前 /**
void removeWellBinding(nmObjPointWell* pGraphic); * @brief
* @return true false
*/
bool removeWellBinding(nmObjPointWell* pGraphic);
// 兜底同步:位置、名称,由井图元在 paintBack 中调用 // 兜底同步:位置、名称,由井图元在 paintBack 中调用
void syncWellData(nmObjPointWell* pGraphic); void syncWellData(nmObjPointWell* pGraphic);
@ -171,8 +174,8 @@ public:
// 判断井图元是否已绑定井数据 // 判断井图元是否已绑定井数据
bool hasWellDataFor(nmObjPointWell* pGraphic) const; bool hasWellDataFor(nmObjPointWell* pGraphic) const;
// 判断井图元是否为当前分析井 /** @brief 判断井图元是否对应创建分析时绑定的固定主井。 */
bool isCurrentWellGraphic(nmObjPointWell* pGraphic) const; bool isPrimaryWellGraphic(nmObjPointWell* pGraphic) const;
// 图元移动后,同步井位置及裂缝位置 // 图元移动后,同步井位置及裂缝位置
void syncWellMoveFromGraphic(nmObjPointWell* pGraphic, NM_WELL_MODEL wellType, const QPointF& newLocation); void syncWellMoveFromGraphic(nmObjPointWell* pGraphic, NM_WELL_MODEL wellType, const QPointF& newLocation);
// 选择已有井后,确保图元已创建并绑定对应的井数据 // 选择已有井后,确保图元已创建并绑定对应的井数据

@ -975,11 +975,40 @@ nmDataWellBase* nmDataAnalyzeManager::changeWellType(nmDataWellBase* pOldWellDat
return pNewWellData; return pNewWellData;
} }
// 实现 removeWell 函数 bool nmDataAnalyzeManager::isPrimaryWell(
const nmDataWellBase* pWellData) const
{
if(pWellData == nullptr) {
return false;
}
const QString sPrimaryWellCode =
m_oNumericalAnalysisCase.getPrimaryWellCode();
return !sPrimaryWellCode.isEmpty() &&
pWellData->getWellCode() == sPrimaryWellCode;
}
bool nmDataAnalyzeManager::canRemoveWell(
const nmDataWellBase* pWellData) const
{
if(pWellData == nullptr || isPrimaryWell(pWellData)) {
return false;
}
// 不通过 WellCode 代替所有权判断,避免同编码外部对象误删管理器内的井。
for(int nIndex = 0; nIndex < m_vWellData.size(); ++nIndex) {
if(m_vWellData[nIndex] == pWellData) {
return true;
}
}
return false;
}
bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData) bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData)
{ {
// 第一步:只有当前管理器真正拥有的井才允许删除,非法指针不能先污染分析方案。 // 固定主井及非法指针必须在任何版本递增、图元解绑和对象删除前拒绝。
if(pWellData == nullptr || !m_vWellData.contains(pWellData)) { // 该检查是数据层最终兜底,不能只依赖 Map 界面的提前拦截。
if(!canRemoveWell(pWellData)) {
return false; return false;
} }
@ -1001,11 +1030,6 @@ bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData)
} }
m_oNumericalAnalysisCase.setIncludedWells(vecIncludedWells); m_oNumericalAnalysisCase.setIncludedWells(vecIncludedWells);
// 第四步:主分析井被删除时清空主井;新的主井必须由上层业务明确指定。
if(m_oNumericalAnalysisCase.getPrimaryWellCode() == removedWellCode) {
m_oNumericalAnalysisCase.setPrimaryWellCode(QString());
}
// 如果删的是当前井,切换到其他有效井;如果没有,则清空当前井指针。 // 如果删的是当前井,切换到其他有效井;如果没有,则清空当前井指针。
if(isCurrentWell) { if(isCurrentWell) {
m_pCurDataWell = nullptr; m_pCurDataWell = nullptr;
@ -1048,13 +1072,8 @@ bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData)
void nmDataAnalyzeManager::removeWellDataAndPlot(nmDataWellBase* pWellData) void nmDataAnalyzeManager::removeWellDataAndPlot(nmDataWellBase* pWellData)
{ {
// 参数校验 // 删除图元之前先执行同一业务预检,避免主井数据被拒绝后图元已经消失。
if(pWellData == nullptr) { if(!canRemoveWell(pWellData)) {
return;
}
// 公共删井入口中不允许删除当前井,避免活动井引用失效
if(pWellData == getCurWellData()) {
return; return;
} }
@ -1483,8 +1502,11 @@ void nmDataAnalyzeManager::initCurWellData()
this->setCurWellData(pHFracturedWell); this->setCurWellData(pHFracturedWell);
} }
// 当前流动段井是数值分析入口井;结果井选择独立保存在快照查看状态中。 // 第一次导入的当前流动段井固定为数值分析入口井。后续切换查看井或
if(m_pCurDataWell != nullptr && !m_pCurDataWell->getWellCode().isEmpty()) { // 重复初始化不得改变主井身份及其求解角色。
if(m_oNumericalAnalysisCase.getPrimaryWellCode().isEmpty() &&
m_pCurDataWell != nullptr &&
!m_pCurDataWell->getWellCode().isEmpty()) {
const QString sPrimaryWellCode = m_pCurDataWell->getWellCode(); const QString sPrimaryWellCode = m_pCurDataWell->getWellCode();
m_oNumericalAnalysisCase.setPrimaryWellCode(sPrimaryWellCode); m_oNumericalAnalysisCase.setPrimaryWellCode(sPrimaryWellCode);
m_oNumericalAnalysisCase.setPrimaryWellMode( m_oNumericalAnalysisCase.setPrimaryWellMode(

@ -63,6 +63,12 @@ void nmDataNumericalAnalysisCase::setPrimaryWellCode(const QString& sWellCode)
return; return;
} }
// 主井在创建数值分析时固定。项目重新加载会先调用 clear(),因此加载恢复
// 仍可从空状态初始化,但运行期间不能通过公共接口清空或换成另一口井。
if(!m_sPrimaryWellCode.isEmpty() || sWellCode.isEmpty()) {
return;
}
m_sPrimaryWellCode = sWellCode; m_sPrimaryWellCode = sWellCode;
normalizeIncludedWells(); normalizeIncludedWells();
invalidateGrid(); invalidateGrid();

@ -63,6 +63,7 @@
#include "ZxDataGaugeF.h" #include "ZxDataGaugeF.h"
#include <QMessageBox>
#include <QWidget> #include <QWidget>
nmGuiPlot::nmGuiPlot(bool bUseBtns, QWidget *parent) : nmGuiPlot::nmGuiPlot(bool bUseBtns, QWidget *parent) :
@ -914,8 +915,11 @@ void nmGuiPlot::slotDeleteWell(QString wellID)
return; return;
} }
// 当前井作为活动分析井保留,不允许从地图中直接删除 // 创建分析时绑定的主井是流动段及数值输入基准,不能从数值 Map 单独删除。
if(m_pGraphicBinder && m_pGraphicBinder->isCurrentWellGraphic(obj)) { if(m_pGraphicBinder && m_pGraphicBinder->isPrimaryWellGraphic(obj)) {
QMessageBox::information(this,
tr("Cannot Delete Well"),
tr("The primary analysis well cannot be deleted."));
return; return;
} }
@ -1367,8 +1371,8 @@ void nmGuiPlot::slotDeleteOneObj(QString sName, void* obj)
if(sName != NULL) { if(sName != NULL) {
// 删除前先校验目标对象。 // 删除前先校验目标对象。
// 如果目标不存在,或目标井就是当前活动井,则结束删除工具并直接返回, // 如果目标不存在,或目标井是固定主分析井,则结束删除工具并直接返回。
// 避免当前井被从地图上删除,同时保证界面退出删除状态。 // 预检必须发生在确认对话框和图元删除前,避免数据层拒绝后只剩半套状态。
nmObjDeleteTool* pDeleteTool = static_cast<nmObjDeleteTool*>(obj); nmObjDeleteTool* pDeleteTool = static_cast<nmObjDeleteTool*>(obj);
nmObjBase* nmObj = dynamic_cast<nmObjBase*>(m_pPlot->getObjByName(sName)); nmObjBase* nmObj = dynamic_cast<nmObjBase*>(m_pPlot->getObjByName(sName));
@ -1380,10 +1384,14 @@ void nmGuiPlot::slotDeleteOneObj(QString sName, void* obj)
} }
if(nmObjPointWell* pWellObj = dynamic_cast<nmObjPointWell*>(nmObj)) { if(nmObjPointWell* pWellObj = dynamic_cast<nmObjPointWell*>(nmObj)) {
if(m_pGraphicBinder && m_pGraphicBinder->isCurrentWellGraphic(pWellObj)) { if(m_pGraphicBinder && m_pGraphicBinder->isPrimaryWellGraphic(pWellObj)) {
if(pDeleteTool) { if(pDeleteTool) {
m_pPlot->removeTools(pDeleteTool); m_pPlot->removeTools(pDeleteTool);
} }
QMessageBox::information(
this,
tr("Cannot Delete Well"),
tr("The primary analysis well cannot be deleted."));
return; return;
} }
} }

@ -1605,21 +1605,24 @@ void nmPlotGraphicBinder::bindWellToGraphic(nmObjPointWell* pGraphic, nmDataWell
_connectWell(pGraphic, pData); _connectWell(pGraphic, pData);
} }
// 删除井图元前,断开信号并清理映射 // 删除井图元前,先由数据层确认删除成功,再断开信号并清理映射
void nmPlotGraphicBinder::removeWellBinding(nmObjPointWell* pGraphic) bool nmPlotGraphicBinder::removeWellBinding(nmObjPointWell* pGraphic)
{ {
if (!pGraphic) { if (!pGraphic) {
return; return false;
} }
_disconnectWell(pGraphic);
nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr); nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr);
if (pData && m_pDataMgr) { if (pData) {
m_pDataMgr->removeWell(pData); if (!m_pDataMgr || !m_pDataMgr->removeWell(pData)) {
// 主井等被数据层拒绝的情况必须完整保留现有图元绑定。
return false;
}
} }
_disconnectWell(pGraphic);
m_mapWellData.remove(pGraphic); m_mapWellData.remove(pGraphic);
return true;
} }
// 兜底同步:由井图元在 paintBack 中调用 // 兜底同步:由井图元在 paintBack 中调用
@ -1677,10 +1680,12 @@ bool nmPlotGraphicBinder::hasWellDataFor(nmObjPointWell* pGraphic) const
return m_mapWellData.value(pGraphic, nullptr) != nullptr; return m_mapWellData.value(pGraphic, nullptr) != nullptr;
} }
bool nmPlotGraphicBinder::isCurrentWellGraphic(nmObjPointWell* pGraphic) const bool nmPlotGraphicBinder::isPrimaryWellGraphic(
nmObjPointWell* pGraphic) const
{ {
if (!m_pDataMgr || !pGraphic) return false; if (!m_pDataMgr || !pGraphic) return false;
return m_mapWellData.value(pGraphic, nullptr) == m_pDataMgr->getCurWellData(); return m_pDataMgr->isPrimaryWell(
m_mapWellData.value(pGraphic, nullptr));
} }
void nmPlotGraphicBinder::syncWellMoveFromGraphic(nmObjPointWell* pGraphic, void nmPlotGraphicBinder::syncWellMoveFromGraphic(nmObjPointWell* pGraphic,

@ -1076,8 +1076,9 @@ void nmSubWndMain::updateSelectedWells(QList<ZxDataWell *> wellObjList)
// setp 4执行删除操作 // setp 4执行删除操作
for(int i = 0; i < vDeleteWellPlotList.count(); ++i) { for(int i = 0; i < vDeleteWellPlotList.count(); ++i) {
nmObjPointWell* pWellPlot = vDeleteWellPlotList[i]; nmObjPointWell* pWellPlot = vDeleteWellPlotList[i];
// 如果是当前井,不可删除 (保留您的逻辑) // 选择井列表只能移除普通数值井;固定主井始终保留在本次分析中。
if(m_pWxPlot->graphicBinder() && m_pWxPlot->graphicBinder()->isCurrentWellGraphic(pWellPlot)) if(m_pWxPlot->graphicBinder() &&
m_pWxPlot->graphicBinder()->isPrimaryWellGraphic(pWellPlot))
continue; continue;
// 删除对应的参数类 // 删除对应的参数类

Loading…
Cancel
Save