diff --git a/Include/nmNum/nmData/nmDataWellBase.h b/Include/nmNum/nmData/nmDataWellBase.h index 0afc902..797b98e 100644 --- a/Include/nmNum/nmData/nmDataWellBase.h +++ b/Include/nmNum/nmData/nmDataWellBase.h @@ -168,6 +168,13 @@ public: void selectPressureGaugeCode(const QString& sGaugeCode); /** @brief 按 Gauge Code 选中一条流量记录;传入空字符串表示无选中。 */ void selectFlowGaugeCode(const QString& sGaugeCode); + /** + * @brief 切换选中流量记录:把当前 m_nIndexF 写回旧记录的 nIndexF, + * 再用新记录的 nIndexF 恢复并按新记录的真实段数校验当前索引。 + * @note UI 层切换流量记录下拉时必须调用本方法,而不是直接调用 selectFlowGaugeCode, + * 否则流动段索引不会跟随记录切换正确恢复。 + */ + void switchSelectedFlowGaugeCode(const QString& sGaugeCode); /** @brief 返回当前选中的压力记录 Gauge Code,未选中时为空。 */ QString getSelectedPressureGaugeCode() const; /** @brief 返回当前选中的流量记录 Gauge Code,未选中时为空。 */ diff --git a/Include/nmNum/nmSubWxs/nmWellPressureFlowPage.h b/Include/nmNum/nmSubWxs/nmWellPressureFlowPage.h index c3c66ac..f87fa2a 100644 --- a/Include/nmNum/nmSubWxs/nmWellPressureFlowPage.h +++ b/Include/nmNum/nmSubWxs/nmWellPressureFlowPage.h @@ -1,6 +1,8 @@ #pragma once #include "nmSubWxs_global.h" +#include "nmDefines.h" +#include "nmDataGaugeRecord.h" #include #include @@ -11,6 +13,7 @@ class iUnitGroup; class iUnitItem; class nmDataWellBase; class nmWxPressFlowChartWidget; +class QComboBox; class QSplitter; class QStackedWidget; class QTableWidget; @@ -55,10 +58,37 @@ private slots: /** @brief 将流量曲线点击时间映射为表格行选择。 */ void slotFlowChartPointClicked(double dTimePoint); + /** @brief 切换压力记录下拉框,按新选中的 Gauge Code 重新读取数据。 */ + void slotPressureGaugeChanged(int nIndex); + + /** @brief 切换流量记录下拉框,按新选中的 Gauge Code 恢复流动段索引并重新读取数据。 */ + void slotFlowGaugeChanged(int nIndex); + + /** @brief 切换显示相下拉框,仅重新按新相取点刷新视图,不改变井数据。 */ + void slotDisplayPhaseChanged(int nIndex); + private: /** @brief 创建左右分栏、上下图表和只读流量表格。 */ void createUi(); + /** @brief 创建顶部压力/流量记录与显示相三个下拉框所在行。 */ + void createRecordSelectionBar(); + + /** @brief 按 m_pWell->getPressureRecords() 填充压力记录下拉框,恢复当前选中项。 */ + void populatePressureGaugeCombo(); + + /** @brief 按 m_pWell->getFlowRecords() 填充流量记录下拉框,恢复当前选中项。 */ + void populateFlowGaugeCombo(); + + /** @brief 按当前选中流量记录的真实相填充显示相下拉框;至多 1 项时隐藏整行。 */ + void populateDisplayPhaseCombo(const nmFlowGaugeRecord* pRecord); + + /** @brief 返回记录的默认显示相:优先井别参考相,否则记录中第一个有真实数据的相。 */ + NM_PHASE_TYPE defaultDisplayPhase(const nmFlowGaugeRecord* pRecord) const; + + /** @brief 按 m_pWell->getSelectedFlowGaugeCode() 在流量记录列表中查找当前选中记录。 */ + const nmFlowGaugeRecord* currentFlowRecord() const; + /** @brief 重新获取框架单位组并同步双行表头。 */ void initializeUnitSupport(); @@ -129,4 +159,12 @@ private: int m_nTimeDigit; int m_nFlowDigit; int m_nSelectedFlowSegment; + + QWidget* m_pRecordSelectionBar; ///< 顶部压力/流量记录与显示相下拉框所在行容器。 + QComboBox* m_pPressureGaugeCombo; ///< 压力记录下拉框,itemData 存 Gauge Code。 + QComboBox* m_pFlowGaugeCombo; ///< 流量记录下拉框,itemData 存 Gauge Code。 + QComboBox* m_pDisplayPhaseCombo; ///< 显示相下拉框,itemData 存 NM_PHASE_TYPE。 + QWidget* m_pDisplayPhaseContainer; ///< 承载显示相下拉框与标签,整体隐藏用。 + NM_PHASE_TYPE m_eDisplayPhase; ///< 当前预览的流量相,纯展示状态,不写回井对象。 + QVector m_vecFlowGaugeRecords; ///< 每次填充流量下拉框时缓存的记录列表,供 currentFlowRecord() 安全返回内部指针。 }; diff --git a/Src/nmNum/nmData/nmDataWellBase.cpp b/Src/nmNum/nmData/nmDataWellBase.cpp index aa91bb5..e7de6f1 100644 --- a/Src/nmNum/nmData/nmDataWellBase.cpp +++ b/Src/nmNum/nmData/nmDataWellBase.cpp @@ -838,6 +838,32 @@ void nmDataWellBase::selectFlowGaugeCode(const QString& sGaugeCode) m_sSelectedFlowGaugeCode = sGaugeCode; } +// 切换选中流量记录:把当前 m_nIndexF 写回旧记录的 nIndexF, +// 再用新记录的 nIndexF 恢复并按新记录的真实段数校验当前索引。 +void nmDataWellBase::switchSelectedFlowGaugeCode(const QString& sGaugeCode) +{ + nmFlowGaugeRecord* pOldRecord = + findGaugeRecordByCode(m_vecFlowRecords, m_sSelectedFlowGaugeCode); + if(pOldRecord != nullptr) { + pOldRecord->nIndexF = m_nIndexF; + } + + m_sSelectedFlowGaugeCode = sGaugeCode; + + nmFlowGaugeRecord* pNewRecord = + findGaugeRecordByCode(m_vecFlowRecords, m_sSelectedFlowGaugeCode); + const int nSegmentCount = getFlowSegmentCount(); + if(pNewRecord == nullptr || nSegmentCount <= 0) { + m_nIndexF = 0; + return; + } + int nRestoredIndex = pNewRecord->nIndexF; + if(nRestoredIndex < 1 || nRestoredIndex > nSegmentCount) { + nRestoredIndex = nSegmentCount; + } + m_nIndexF = nRestoredIndex; +} + QString nmDataWellBase::getSelectedPressureGaugeCode() const { return m_sSelectedPressureGaugeCode; diff --git a/Src/nmNum/nmSubWxs/nmWellEditorSession.cpp b/Src/nmNum/nmSubWxs/nmWellEditorSession.cpp index 6622407..6a9c164 100644 --- a/Src/nmNum/nmSubWxs/nmWellEditorSession.cpp +++ b/Src/nmNum/nmSubWxs/nmWellEditorSession.cpp @@ -375,13 +375,13 @@ bool nmWellEditorSession::copySharedWellData( pTarget->setLeakSkin(pSource->getLeakSkin()); // 第二步:保留输入历史和已有计算结果,切换井型不应丢失曲线数据。 - pTarget->setPressurePoints(pSource->getPressurePoints()); - pTarget->setFlowPoints(PHASE_Oil, - pSource->getFlowPoints(PHASE_Oil)); - pTarget->setFlowPoints(PHASE_Gas, - pSource->getFlowPoints(PHASE_Gas)); - pTarget->setFlowPoints(PHASE_Water, - pSource->getFlowPoints(PHASE_Water)); + // 必须整体拷贝记录列表和选中 Code,不能用 setPressurePoints/setFlowPoints(phase) + // 逐点写入——目标对象是刚构造的新井,尚未选中任何记录,逐点写入会按阶段一的 + // 兼容语义各自新建 1 条匿名占位记录,丢失全部真实计量记录和已选中的 Gauge Code。 + pTarget->setPressureRecords(pSource->getPressureRecords()); + pTarget->setFlowRecords(pSource->getFlowRecords()); + pTarget->selectPressureGaugeCode(pSource->getSelectedPressureGaugeCode()); + pTarget->selectFlowGaugeCode(pSource->getSelectedFlowGaugeCode()); pTarget->setIndexF(pSource->getIndexF()); pTarget->setHistoryPressure(pSource->getHistoryPressure()); pTarget->setHistoryLogLog(pSource->getHistoryLogLog()); diff --git a/Src/nmNum/nmSubWxs/nmWellPressureFlowPage.cpp b/Src/nmNum/nmSubWxs/nmWellPressureFlowPage.cpp index 4512cbd..50f2a26 100644 --- a/Src/nmNum/nmSubWxs/nmWellPressureFlowPage.cpp +++ b/Src/nmNum/nmSubWxs/nmWellPressureFlowPage.cpp @@ -9,12 +9,16 @@ #include "ZxTableHeaderViewUnit.h" #include +#include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -80,6 +84,75 @@ QString displayValueText(double dValue, int nDigit) } return ZxBaseUtil::getValidStr(dValue, nDigit); } + +// 判断某相流量点是否至少包含一个真实流动段,去除可选首个(0,0)占位点后非空即为真实。 +// 与 nmDataAnalyzeManager.cpp 中同名判断语义一致,但该处是其它文件的 file-static 函数, +// 无法跨文件复用,因此在本文件内新增等价判断。 +bool hasRealPhaseData(const QVector& vecPoints) +{ + if (vecPoints.isEmpty()) + { + return false; + } + if (vecPoints.size() == 1 && + vecPoints.first().x() == 0.0 && vecPoints.first().y() == 0.0) + { + return false; + } + return true; +} + +// 压力/流量记录下拉项文本:优先显示计量名称,否则回退到 Gauge Code;再拼接测量时间。 +QString formatGaugeRecordLabel(const QString& sGaugeName, + const QString& sGaugeCode, + const QString& sGaugeTime) +{ + QString sBaseLabel = sGaugeName.isEmpty() ? sGaugeCode : sGaugeName; + if (sGaugeTime.isEmpty()) + { + return sBaseLabel; + } + return sBaseLabel + QLatin1String(" | ") + sGaugeTime; +} + +// 统一向压力/流量记录下拉框追加一项:身份无效的记录禁用不可选,空/损坏记录仍可选但追加提示后缀。 +void appendGaugeComboItem(QComboBox* pCombo, + const QString& sGaugeName, + const QString& sGaugeCode, + const QString& sGaugeTime, + NM_GAUGE_RECORD_STATUS eStatus) +{ + QString sLabel = formatGaugeRecordLabel(sGaugeName, sGaugeCode, sGaugeTime); + switch (eStatus) + { + case NM_GaugeRecord_InvalidIdentity: + sLabel += nmWellPressureFlowPage::tr(" (Invalid)"); + break; + case NM_GaugeRecord_Empty: + sLabel += nmWellPressureFlowPage::tr(" (Empty)"); + break; + case NM_GaugeRecord_Corrupt: + sLabel += nmWellPressureFlowPage::tr(" (Corrupt)"); + break; + default: + break; + } + + pCombo->addItem(sLabel, sGaugeCode); + if (eStatus == NM_GaugeRecord_InvalidIdentity) + { + QStandardItemModel* pModel = + qobject_cast(pCombo->model()); + if (pModel != nullptr) + { + QStandardItem* pItem = pModel->item(pCombo->count() - 1); + if (pItem != nullptr) + { + pItem->setFlags(pItem->flags() & ~Qt::ItemIsEnabled); + } + } + } +} } nmWellPressureFlowPage::nmWellPressureFlowPage(QWidget* pParent) @@ -103,7 +176,13 @@ nmWellPressureFlowPage::nmWellPressureFlowPage(QWidget* pParent) m_sFlowUnit(preferredFlowUnit()), m_nTimeDigit(6), m_nFlowDigit(6), - m_nSelectedFlowSegment(-1) + m_nSelectedFlowSegment(-1), + m_pRecordSelectionBar(nullptr), + m_pPressureGaugeCombo(nullptr), + m_pFlowGaugeCombo(nullptr), + m_pDisplayPhaseCombo(nullptr), + m_pDisplayPhaseContainer(nullptr), + m_eDisplayPhase(PHASE_UNKNOWN) { createUi(); initializeUnitSupport(); @@ -129,12 +208,19 @@ void nmWellPressureFlowPage::refreshData() return; } - // 第一步:井数据只复制到页面基准副本,后续显示换算不会回写井对象。 + // 第一步:先刷新记录下拉框,确保当前选中 Code、显示相与后续取点保持一致。 + populatePressureGaugeCombo(); + populateFlowGaugeCombo(); + populateDisplayPhaseCombo(currentFlowRecord()); + + // 第二步:井数据只复制到页面基准副本,后续显示换算不会回写井对象; + // 流量点按当前展示相读取,切换展示相不影响井别、m_nIndexF 或求解器输入。 QVector vecRawPressurePoints = m_pWell->getPressurePoints(); - QVector vecRawFlowPoints = m_pWell->getFlowPoints(); + QVector vecRawFlowPoints = + m_pWell->getFlowPoints(m_eDisplayPhase); - // 第二步:单位服务可能晚于页面构造完成,再刷新一次可用单位组。 + // 第三步:单位服务可能晚于页面构造完成,再刷新一次可用单位组。 initializeUnitSupport(); m_vecRawPressurePoints = vecRawPressurePoints; @@ -266,6 +352,64 @@ void nmWellPressureFlowPage::slotFlowChartPointClicked(double dTimePoint) findFlowSegmentByTableTime(dTableTimePoint)); } +void nmWellPressureFlowPage::slotPressureGaugeChanged(int nIndex) +{ + if (m_pWell == nullptr || nIndex < 0) + { + return; + } + + const QString sCode = m_pPressureGaugeCombo->itemData(nIndex).toString(); + if (sCode == m_pWell->getSelectedPressureGaugeCode()) + { + return; + } + + m_pWell->selectPressureGaugeCode(sCode); + refreshData(); +} + +void nmWellPressureFlowPage::slotFlowGaugeChanged(int nIndex) +{ + if (m_pWell == nullptr || nIndex < 0) + { + return; + } + + const QString sCode = m_pFlowGaugeCombo->itemData(nIndex).toString(); + if (sCode == m_pWell->getSelectedFlowGaugeCode()) + { + return; + } + + // 必须调用 switchSelectedFlowGaugeCode 而不是 selectFlowGaugeCode,才能根据新记录 + // 自己的 nIndexF 恢复/校验流动段选择,否则换记录后选择器就回帰到默认 0。 + m_pWell->switchSelectedFlowGaugeCode(sCode); + // 换记录后显示相重置为新记录的默认相,m_vecFlowGaugeRecords 仍为本井完整记录列表, + // 因此可在 refreshData() 重新填充下拉框前先用旧缓存安全查找新选中记录。 + m_eDisplayPhase = defaultDisplayPhase(currentFlowRecord()); + refreshData(); +} + +void nmWellPressureFlowPage::slotDisplayPhaseChanged(int nIndex) +{ + if (m_pWell == nullptr || nIndex < 0) + { + return; + } + + NM_PHASE_TYPE eNewPhase = static_cast( + m_pDisplayPhaseCombo->itemData(nIndex).toInt()); + if (eNewPhase == m_eDisplayPhase) + { + return; + } + + // 仅重新按新相取点刷新视图,不改变记录内容、井别、m_nIndexF 或求解器输入。 + m_eDisplayPhase = eNewPhase; + refreshData(); +} + void nmWellPressureFlowPage::createUi() { QVBoxLayout* pMainLayout = new QVBoxLayout(this); @@ -373,6 +517,10 @@ void nmWellPressureFlowPage::createUi() m_pContentStack->addWidget(m_pHorizontalSplitter); m_pContentStack->addWidget(createEmptyLabel( tr("No pressure or flow data"), m_pContentStack)); + + // 顶部插入压力/流量记录与显示相三个下拉框所在行,不改变下方图表/表格结构。 + createRecordSelectionBar(); + pMainLayout->addWidget(m_pRecordSelectionBar); pMainLayout->addWidget(m_pContentStack, 1); connect(m_pFlowHeader, @@ -389,6 +537,283 @@ void nmWellPressureFlowPage::createUi() SLOT(slotFlowChartPointClicked(double))); } +void nmWellPressureFlowPage::createRecordSelectionBar() +{ + m_pRecordSelectionBar = new QWidget(this); + QHBoxLayout* pBarLayout = new QHBoxLayout(m_pRecordSelectionBar); + pBarLayout->setContentsMargins(0, 0, 0, 6); + pBarLayout->setSpacing(6); + + QLabel* pPressureLabel = new QLabel( + tr("Pressure Record:"), m_pRecordSelectionBar); + m_pPressureGaugeCombo = new QComboBox(m_pRecordSelectionBar); + m_pPressureGaugeCombo->setEnabled(false); + m_pPressureGaugeCombo->setMinimumWidth(160); + + QLabel* pFlowLabel = new QLabel( + tr("Flow Record:"), m_pRecordSelectionBar); + m_pFlowGaugeCombo = new QComboBox(m_pRecordSelectionBar); + m_pFlowGaugeCombo->setEnabled(false); + m_pFlowGaugeCombo->setMinimumWidth(160); + + // 显示相是纯展示状态,整体容器随记录是否为多相含数据而隐藏/显示。 + m_pDisplayPhaseContainer = new QWidget(m_pRecordSelectionBar); + QHBoxLayout* pPhaseLayout = new QHBoxLayout(m_pDisplayPhaseContainer); + pPhaseLayout->setContentsMargins(0, 0, 0, 0); + pPhaseLayout->setSpacing(6); + QLabel* pPhaseLabel = new QLabel( + tr("Display Phase:"), m_pDisplayPhaseContainer); + m_pDisplayPhaseCombo = new QComboBox(m_pDisplayPhaseContainer); + m_pDisplayPhaseCombo->setMinimumWidth(80); + pPhaseLayout->addWidget(pPhaseLabel); + pPhaseLayout->addWidget(m_pDisplayPhaseCombo); + m_pDisplayPhaseContainer->setVisible(false); + + pBarLayout->addWidget(pPressureLabel); + pBarLayout->addWidget(m_pPressureGaugeCombo); + pBarLayout->addSpacing(12); + pBarLayout->addWidget(pFlowLabel); + pBarLayout->addWidget(m_pFlowGaugeCombo); + pBarLayout->addSpacing(12); + pBarLayout->addWidget(m_pDisplayPhaseContainer); + pBarLayout->addStretch(1); + + connect(m_pPressureGaugeCombo, + SIGNAL(currentIndexChanged(int)), + this, + SLOT(slotPressureGaugeChanged(int))); + connect(m_pFlowGaugeCombo, + SIGNAL(currentIndexChanged(int)), + this, + SLOT(slotFlowGaugeChanged(int))); + connect(m_pDisplayPhaseCombo, + SIGNAL(currentIndexChanged(int)), + this, + SLOT(slotDisplayPhaseChanged(int))); +} + +void nmWellPressureFlowPage::populatePressureGaugeCombo() +{ + if (m_pPressureGaugeCombo == nullptr) + { + return; + } + + bool bSignalsWereBlocked = m_pPressureGaugeCombo->blockSignals(true); + m_pPressureGaugeCombo->clear(); + + if (m_pWell == nullptr) + { + m_pPressureGaugeCombo->setEnabled(false); + m_pPressureGaugeCombo->blockSignals(bSignalsWereBlocked); + return; + } + + QVector vecRecords = + m_pWell->getPressureRecords(); + m_pPressureGaugeCombo->setEnabled(!vecRecords.isEmpty()); + + const QString sSelectedCode = m_pWell->getSelectedPressureGaugeCode(); + int nCurrentIndex = -1; + for (int nIndex = 0; nIndex < vecRecords.size(); ++nIndex) + { + const nmPressureGaugeRecord& oRecord = vecRecords[nIndex]; + appendGaugeComboItem(m_pPressureGaugeCombo, + oRecord.sGaugeName, oRecord.sGaugeCode, + oRecord.sGaugeTime, oRecord.eStatus); + if (oRecord.sGaugeCode == sSelectedCode) + { + nCurrentIndex = nIndex; + } + } + if (nCurrentIndex >= 0) + { + m_pPressureGaugeCombo->setCurrentIndex(nCurrentIndex); + } + m_pPressureGaugeCombo->blockSignals(bSignalsWereBlocked); +} + +void nmWellPressureFlowPage::populateFlowGaugeCombo() +{ + if (m_pFlowGaugeCombo == nullptr) + { + return; + } + + bool bSignalsWereBlocked = m_pFlowGaugeCombo->blockSignals(true); + m_pFlowGaugeCombo->clear(); + + if (m_pWell == nullptr) + { + m_vecFlowGaugeRecords.clear(); + m_pFlowGaugeCombo->setEnabled(false); + m_pFlowGaugeCombo->blockSignals(bSignalsWereBlocked); + return; + } + + // 缓存整份记录列表供 currentFlowRecord() 安全返回内部指针,记录内容切换记录时不变。 + m_vecFlowGaugeRecords = m_pWell->getFlowRecords(); + m_pFlowGaugeCombo->setEnabled(!m_vecFlowGaugeRecords.isEmpty()); + + const QString sSelectedCode = m_pWell->getSelectedFlowGaugeCode(); + int nCurrentIndex = -1; + for (int nIndex = 0; nIndex < m_vecFlowGaugeRecords.size(); ++nIndex) + { + const nmFlowGaugeRecord& oRecord = m_vecFlowGaugeRecords[nIndex]; + appendGaugeComboItem(m_pFlowGaugeCombo, + oRecord.sGaugeName, oRecord.sGaugeCode, + oRecord.sGaugeTime, oRecord.eStatus); + if (oRecord.sGaugeCode == sSelectedCode) + { + nCurrentIndex = nIndex; + } + } + if (nCurrentIndex >= 0) + { + m_pFlowGaugeCombo->setCurrentIndex(nCurrentIndex); + } + m_pFlowGaugeCombo->blockSignals(bSignalsWereBlocked); +} + +void nmWellPressureFlowPage::populateDisplayPhaseCombo( + const nmFlowGaugeRecord* pRecord) +{ + if (m_pDisplayPhaseCombo == nullptr || + m_pDisplayPhaseContainer == nullptr) + { + return; + } + + bool bSignalsWereBlocked = m_pDisplayPhaseCombo->blockSignals(true); + m_pDisplayPhaseCombo->clear(); + + if (pRecord == nullptr) + { + m_pDisplayPhaseContainer->setVisible(false); + m_eDisplayPhase = PHASE_UNKNOWN; + m_pDisplayPhaseCombo->blockSignals(bSignalsWereBlocked); + return; + } + + // 仅列出记录中真实含数据的相;若记录只有 1 个相有数据,整行隐藏但仍取该相的点。 + QVector vecAvailablePhases; + QStringList listAvailableLabels; + if (hasRealPhaseData(pRecord->vecOilPoints)) + { + vecAvailablePhases.append(PHASE_Oil); + listAvailableLabels.append(tr("Oil")); + } + if (hasRealPhaseData(pRecord->vecGasPoints)) + { + vecAvailablePhases.append(PHASE_Gas); + listAvailableLabels.append(tr("Gas")); + } + if (hasRealPhaseData(pRecord->vecWaterPoints)) + { + vecAvailablePhases.append(PHASE_Water); + listAvailableLabels.append(tr("Water")); + } + + if (vecAvailablePhases.size() <= 1) + { + m_pDisplayPhaseContainer->setVisible(false); + m_eDisplayPhase = vecAvailablePhases.isEmpty() + ? PHASE_UNKNOWN : vecAvailablePhases.first(); + m_pDisplayPhaseCombo->blockSignals(bSignalsWereBlocked); + return; + } + + m_pDisplayPhaseContainer->setVisible(true); + int nCurrentIndex = -1; + for (int nIndex = 0; nIndex < vecAvailablePhases.size(); ++nIndex) + { + m_pDisplayPhaseCombo->addItem(listAvailableLabels[nIndex], + static_cast(vecAvailablePhases[nIndex])); + if (vecAvailablePhases[nIndex] == m_eDisplayPhase) + { + nCurrentIndex = nIndex; + } + } + if (nCurrentIndex < 0) + { + NM_PHASE_TYPE eDefaultPhase = defaultDisplayPhase(pRecord); + for (int nIndex = 0; nIndex < vecAvailablePhases.size(); ++nIndex) + { + if (vecAvailablePhases[nIndex] == eDefaultPhase) + { + nCurrentIndex = nIndex; + break; + } + } + } + if (nCurrentIndex < 0) + { + nCurrentIndex = 0; + } + m_pDisplayPhaseCombo->setCurrentIndex(nCurrentIndex); + m_eDisplayPhase = static_cast( + m_pDisplayPhaseCombo->itemData(nCurrentIndex).toInt()); + m_pDisplayPhaseCombo->blockSignals(bSignalsWereBlocked); +} + +NM_PHASE_TYPE nmWellPressureFlowPage::defaultDisplayPhase( + const nmFlowGaugeRecord* pRecord) const +{ + if (pRecord == nullptr) + { + return PHASE_UNKNOWN; + } + + // 优先使用井别对应的参考相,前提是该相在本条记录中确有真实数据。 + NM_PHASE_TYPE eReferencePhase = (m_pWell != nullptr) + ? m_pWell->getReferenceFlowPhase() : PHASE_UNKNOWN; + if (eReferencePhase == PHASE_Oil && hasRealPhaseData(pRecord->vecOilPoints)) + { + return PHASE_Oil; + } + if (eReferencePhase == PHASE_Gas && hasRealPhaseData(pRecord->vecGasPoints)) + { + return PHASE_Gas; + } + if (eReferencePhase == PHASE_Water && hasRealPhaseData(pRecord->vecWaterPoints)) + { + return PHASE_Water; + } + + // 参考相无数据时,退回记录中第一个有真实数据的相,固定按油、气、水顺序。 + if (hasRealPhaseData(pRecord->vecOilPoints)) + { + return PHASE_Oil; + } + if (hasRealPhaseData(pRecord->vecGasPoints)) + { + return PHASE_Gas; + } + if (hasRealPhaseData(pRecord->vecWaterPoints)) + { + return PHASE_Water; + } + return PHASE_UNKNOWN; +} + +const nmFlowGaugeRecord* nmWellPressureFlowPage::currentFlowRecord() const +{ + if (m_pWell == nullptr) + { + return nullptr; + } + + const QString sSelectedCode = m_pWell->getSelectedFlowGaugeCode(); + for (int nIndex = 0; nIndex < m_vecFlowGaugeRecords.size(); ++nIndex) + { + if (m_vecFlowGaugeRecords[nIndex].sGaugeCode == sSelectedCode) + { + return &m_vecFlowGaugeRecords[nIndex]; + } + } + return nullptr; +} + void nmWellPressureFlowPage::initializeUnitSupport() { QStringList listTimeCandidates; @@ -768,5 +1193,34 @@ void nmWellPressureFlowPage::resetDataViews() m_vecRawFlowPoints.clear(); m_vecTableFlowPoints.clear(); m_nSelectedFlowSegment = -1; + + // 井绑定切换或清空时先清空并禁用三个记录/相下拉框,等待 refreshData() 重新填充。 + if (m_pPressureGaugeCombo != nullptr) + { + bool bSignalsWereBlocked = m_pPressureGaugeCombo->blockSignals(true); + m_pPressureGaugeCombo->clear(); + m_pPressureGaugeCombo->setEnabled(false); + m_pPressureGaugeCombo->blockSignals(bSignalsWereBlocked); + } + if (m_pFlowGaugeCombo != nullptr) + { + bool bSignalsWereBlocked = m_pFlowGaugeCombo->blockSignals(true); + m_pFlowGaugeCombo->clear(); + m_pFlowGaugeCombo->setEnabled(false); + m_pFlowGaugeCombo->blockSignals(bSignalsWereBlocked); + } + m_vecFlowGaugeRecords.clear(); + if (m_pDisplayPhaseCombo != nullptr) + { + bool bSignalsWereBlocked = m_pDisplayPhaseCombo->blockSignals(true); + m_pDisplayPhaseCombo->clear(); + m_pDisplayPhaseCombo->blockSignals(bSignalsWereBlocked); + } + if (m_pDisplayPhaseContainer != nullptr) + { + m_pDisplayPhaseContainer->setVisible(false); + } + m_eDisplayPhase = PHASE_UNKNOWN; + updateViews(); }