feat:完成事件确认的全部流程逻辑

This commit is contained in:
duanshengchao 2025-12-09 20:31:08 +08:00
parent 8e3239fe71
commit 6a68212a9a
4 changed files with 107 additions and 43 deletions

View File

@ -26,13 +26,13 @@ public:
void start();
void stop();
void queryHistoricalEvents(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus = -1);
void confirmEvents(const QStringList& uuids);
void confirmEvents(const QStringList& uuids, QVariant context = QVariant());
signals:
void realTimeEventReceived(const EventData& event);
void historicalQueryError(const QString& msg);
void historicalQueryData(const QList<EventData>& events);
void confirmEventsResult(bool success, const QString& mesg, const QStringList& successUuids);
void confirmEventsResult(bool success, const QString& mesg, const QStringList& successUuids, QVariant context);
private slots:
void onRabbitMQConnected();
@ -58,7 +58,6 @@ private:
void cancelReconnect();
//实时信息处理
MessageHandleResult processMessage(const QAmqpMessage& message);
EventData parseEventFromMessage(const QByteArray& data, QString& errorString);
bool validateEvent(const EventData& event);
//历史数据处理
QUrl bulidHistoricalQueryUrl(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus);
@ -89,6 +88,8 @@ private:
QSettings* m_settings;
QString m_settingsFile;
bool m_isVaildSettingsFile;
quint64 m_currentRequestId;
};
#endif

View File

@ -83,7 +83,7 @@ private slots:
void onRealTimeEventReceived(const EventData& event);
void onHistoricalEventsReceived(const QList<EventData>& events);
void onHistoricalQueryError(const QString&);
void onConfirmEventsResult(bool success, const QString& mesg, const QStringList& successUuids);
void onConfirmEventsResult(bool success, const QString& mesg, const QStringList& successUuids, QVariant context);
private:
void iniHeaderData();
@ -104,6 +104,7 @@ private:
AlarmDataMode m_dataMode;
AlarmEventDataFilter m_currentFilter;
int m_maxRealTimeEvents;
quint64 m_lastRequestId; //请求ID在实例化的不同对象调用某同一个对象(此处是AlarmEventDataService)的某个函数并触发其emit某个signal进而触发自身的某个slot时做判别用
//QMap<qint64, QVector<QModelIndex>> m_confirmedEvents;
};

View File

@ -28,6 +28,7 @@ AlarmEventDataService::AlarmEventDataService()
, m_amqpExchange(nullptr)
, m_reconnectAttempts(0)
, m_maxReconnectAttempts(10)
, m_currentRequestId(1)
{
m_reconnectTimer = new QTimer(this);
m_reconnectTimer->setSingleShot(true);
@ -113,8 +114,10 @@ void AlarmEventDataService::queryHistoricalEvents(const QDateTime& startTime, co
});
}
void AlarmEventDataService::confirmEvents(const QStringList& uuids)
void AlarmEventDataService::confirmEvents(const QStringList& uuids, QVariant context)
{
m_currentRequestId = context.toULongLong();
QUrl url = buildConfirmEventsUrl();
if(!url.isValid())
return;
@ -200,42 +203,37 @@ void AlarmEventDataService::cancelReconnect()
}
MessageHandleResult AlarmEventDataService::processMessage(const QAmqpMessage& message)
{
QString errorString;
EventData event = parseEventFromMessage(message.payload(), errorString);
if(!errorString.isEmpty())
return MessageHandleResult::ParseError;
if(!validateEvent(event))
return MessageHandleResult::ValidationError;
emit realTimeEventReceived(event);
return MessageHandleResult::Success;
}
EventData AlarmEventDataService::parseEventFromMessage(const QByteArray& data, QString& errorString)
{
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
QJsonDocument doc = QJsonDocument::fromJson(message.payload(), &parseError);
if(parseError.error != QJsonParseError::NoError)
{
errorString = QString("JSON parse error: %1 at offset %2")
.arg(parseError.errorString())
.arg(parseError.offset);
return EventData();
// QString errorString = QString("JSON parse error: %1 at offset %2")
// .arg(parseError.errorString())
// .arg(parseError.offset);
return MessageHandleResult::ParseError;
}
if(!doc.isObject())
{
errorString = "JSON document is not an object";
return EventData();
//QString errorString = "JSON document is not an object";
return MessageHandleResult::ValidationError;
}
QJsonObject obj = doc.object();
EventData event = EventData::fromJson(obj);
return event;
//加一层判断,当前实时报警信息和确认同步信息都走该接口,并且没有做消息层面的标识,因此先从消息体结构来判断
if(obj.contains("event_uuid") && obj.contains("event") && obj.contains("type"))
{
EventData event = EventData::fromJson(obj);
if(!validateEvent(event))
return MessageHandleResult::ValidationError;
emit realTimeEventReceived(event);
}
return MessageHandleResult::Success;
}
bool AlarmEventDataService::validateEvent(const EventData& event)
@ -414,6 +412,8 @@ void AlarmEventDataService::onConfirmEventsRequestFinished(QNetworkReply* reply)
if(parseError.error == QJsonParseError::NoError && doc.isObject())
{
QJsonObject docObj = doc.object();
//int code = docObj.value("code").toInt();
QString msg = docObj.value("msg").toString();
QJsonValue dataValue = docObj.value("data");
if(dataValue.isObject())
{
@ -428,19 +428,34 @@ void AlarmEventDataService::onConfirmEventsRequestFinished(QNetworkReply* reply)
successUuids.append(value.toString());
}
emit confirmEventsResult(true, "", successUuids);
return;
emit confirmEventsResult(true, "", successUuids, m_currentRequestId);
}
else
{
QString errorMsg = QString("ConfirmEvents reply error, msg: %1").arg(msg);
LOG_ERROR("Http", errorMsg);
emit confirmEventsResult(false, QString("确认事件失败(%1)").arg(msg), successUuids, m_currentRequestId);
}
}
else
{
QString errorMsg = QString("ConfirmEvents reply Json is not object: %1").arg(QString(data));
LOG_ERROR("Http", errorMsg);
emit confirmEventsResult(false, QString("确认事件失败(Json is not object)"), successUuids, m_currentRequestId);
}
}
else
{
QString errorMsg = QString("ConfirmEvents reply Json parse error: %1").arg(parseError.errorString());
LOG_ERROR("Http", errorMsg);
emit confirmEventsResult(false, QString("确认事件失败(JsonParseError)"), successUuids, m_currentRequestId);
}
emit confirmEventsResult(false, QString("确认事件失败(Json错误)"), successUuids);
}
else
{
QString errorMsg = QString("ConfirmEvents error: %1").arg(reply->errorString());
QString errorMsg = QString("ConfirmEvents reply Network error: %1").arg(reply->errorString());
LOG_ERROR("Http", errorMsg);
emit confirmEventsResult(false, QString("确认事件失败(%1)").arg(errorMsg), successUuids);
emit confirmEventsResult(false, QString("确认事件失败(Reply Network error)"), successUuids, m_currentRequestId);
}
reply->deleteLater();

View File

@ -13,6 +13,7 @@ AlarmEventDataModel::AlarmEventDataModel(AlarmDataMode mode, QObject* parent)
: QAbstractTableModel(parent)
, m_dataMode(mode)
, m_maxRealTimeEvents(5)
, m_lastRequestId(0)
{
m_paginationInfo.entriesPerPage = 100;
m_paginationInfo.currentPage = 1;
@ -36,13 +37,14 @@ AlarmEventDataModel::AlarmEventDataModel(AlarmDataMode mode, QObject* parent)
{
connect(AlarmEventDataService::instance(), &AlarmEventDataService::historicalQueryData, this, &AlarmEventDataModel::onHistoricalEventsReceived);
connect(AlarmEventDataService::instance(), &AlarmEventDataService::historicalQueryError, this, &AlarmEventDataModel::onHistoricalQueryError);
connect(AlarmEventDataService::instance(), &AlarmEventDataService::confirmEventsResult, this, &AlarmEventDataModel::onConfirmEventsResult);
}
connect(AlarmEventDataService::instance(), &AlarmEventDataService::confirmEventsResult, this, &AlarmEventDataModel::onConfirmEventsResult);
//实时数据测试
m_simulatedDataTimer = new QTimer(this);
connect(m_simulatedDataTimer, &QTimer::timeout, this, &AlarmEventDataModel::onTimeoutSimulateData);
m_simulatedDataTimer->start(3000);
m_simulatedDataTimer->start(5000);
}
AlarmEventDataModel::~AlarmEventDataModel()
@ -285,18 +287,47 @@ void AlarmEventDataModel::updateEventData(int index, const EventData& updatedEve
void AlarmEventDataModel::confirmEvent(const QModelIndex index)
{
int row = index.row();
if(m_displayEvents.at(row).status == 3)
{
qDebug() << "the event has been confirmed";
return;
}
QString uuid = m_displayEvents.at(row).id;
QStringList uuids;
uuids.append(uuid);
AlarmEventDataService::instance()->confirmEvents(uuids);
// 为本次请求创建一个唯一标识。
// 简单做法使用对象的唯一性this指针。但要注意对象可能被销毁。
// 更稳健做法使用一个递增的成员变量作为请求ID。
static quint64 s_localRequestId = 0;
quint64 currentRequestId = ++s_localRequestId;
m_lastRequestId = currentRequestId;
// 发送请求,附加上下文标识
AlarmEventDataService::instance()->confirmEvents(uuids, currentRequestId);
}
void AlarmEventDataModel::confirmCurPageEvents()
{
QStringList uuids;
for(const EventData& event : m_displayEvents)
uuids.append(event.id);
AlarmEventDataService::instance()->confirmEvents(uuids);
{
if(event.status != 3)
uuids.append(event.id);
}
if(uuids.isEmpty())
{
qDebug() << "all events have been confirmed";
return;
}
// 为本次请求创建一个唯一标识。
// 简单做法使用对象的唯一性this指针。但要注意对象可能被销毁。
// 更稳健做法使用一个递增的成员变量作为请求ID。
static quint64 s_localRequestId = 0;
quint64 currentRequestId = ++s_localRequestId;
m_lastRequestId = currentRequestId;
// 发送请求,附加上下文标识
AlarmEventDataService::instance()->confirmEvents(uuids, currentRequestId);
}
void AlarmEventDataModel::updateCurPageData()
@ -437,16 +468,25 @@ void AlarmEventDataModel::onHistoricalQueryError(const QString& error)
emit loadDataError(error);
}
void AlarmEventDataModel::onConfirmEventsResult(bool success, const QString& mesg, const QStringList& successUuids)
void AlarmEventDataModel::onConfirmEventsResult(bool success, const QString& mesg, const QStringList& successUuids, QVariant context)
{
// 检查上下文是否匹配此模型的请求
quint64 resultRequestId = context.toULongLong();
if (resultRequestId != m_lastRequestId)
{
//qDebug() << "is not my signal, i am " << this;
return; // 不是本模型发起的请求,直接忽略
}
if(!success)
{
qDebug() << "confirm error: " << mesg;
return;
}
if(m_dataMode == RealTime)
{
beginResetModel();
//beginResetModel();
for(const QString& uuid : successUuids)
{
@ -460,10 +500,17 @@ void AlarmEventDataModel::onConfirmEventsResult(bool success, const QString& mes
}
}
endResetModel();
QModelIndex topLeft = createIndex(0, Status);
QModelIndex bottomRight = createIndex(m_displayEvents.count() - 1, Status);
emit dataChanged(topLeft, bottomRight, {Qt::DisplayRole, Qt::ForegroundRole});
qDebug() << "realtime view confirm refresh";
//endResetModel();
}
else
{
qDebug() << "historical view confirm refresh";
refresh();
}
}
bool AlarmEventDataModel::setCurrentPage(int page)