add node recommendation

This commit is contained in:
baiYue 2025-12-19 18:28:13 +08:00
parent a2b45ca406
commit 37776d1258
33 changed files with 917 additions and 218 deletions

View File

@ -1373,6 +1373,14 @@ struct ModelTypeInfo{ //类型临时信息
QString sMeta; //该类型元模名 QString sMeta; //该类型元模名
QString sModel; //该类型工程模名 QString sModel; //该类型工程模名
}; };
/*******************传递的数据************************/
struct HttpRecommandInfo{ //推荐数据服务
QString sInput; //输入的前缀
int nOffset = 0; //正确位置计数
QStringList lstRecommand; //推荐列表
};
/** /**
* Constants used for fetching QVariant data from GraphModel. * Constants used for fetching QVariant data from GraphModel.
*/ */

View File

@ -33,6 +33,8 @@ public slots:
void onDeleteClicked(); void onDeleteClicked();
void onModifyClicked(); void onModifyClicked();
void onIndexRbtnClicked(const QPoint &pos); //索引列表右键菜单 void onIndexRbtnClicked(const QPoint &pos); //索引列表右键菜单
void onHttpDataUpdated(HttpRecommandInfo);
private: private:
void initial(); void initial();
private: private:

View File

@ -20,6 +20,7 @@ class CornerMonitorLauncher;
class LoadMonitorPageDlg; class LoadMonitorPageDlg;
class DiagramConnectSetting; class DiagramConnectSetting;
class DataAccessor; class DataAccessor;
struct HttpRecommandInfo;
class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea
{ {
@ -34,6 +35,8 @@ public:
MonitorPanel* getMonitorPanel(QString); MonitorPanel* getMonitorPanel(QString);
void updateSubPos(); void updateSubPos();
void passRecommmandHttpData(HttpRecommandInfo); //传递推荐列表数据
DiagramConnectSetting* getConnectSettingDlg() {return _connectSetting;}
public: public:
void initial(); void initial();
signals: signals:

View File

@ -20,8 +20,11 @@ public:
~DiagramConnectSetting(); ~DiagramConnectSetting();
void showDlg(); void showDlg();
void updateHttpLog(QString sType,QString data);
void updateWebsocketLog(QString);
public slots: public slots:
void onTestHttpClicked(); void onTestHttpRecommandClicked();
void onTestHttpDataClicked();
void onTestWebsocketClicked(); void onTestWebsocketClicked();
void onOkClicked(); void onOkClicked();
void onCancelClicked(); void onCancelClicked();

View File

@ -32,6 +32,7 @@ class ModelProperty;
struct itemPageInfo; struct itemPageInfo;
class EditBaseItem; class EditBaseItem;
class MonitorPanel; class MonitorPanel;
class ItemPropertyDlg;
class FixedPortsModel : public BaseModel, public Serializable class FixedPortsModel : public BaseModel, public Serializable
{ {
@ -112,9 +113,15 @@ public:
void monitorItemSet(QUuid); //运行时item设置完成 void monitorItemSet(QUuid); //运行时item设置完成
void updateMonitorDisplay(); //更新监控图元显示 void updateMonitorDisplay(); //更新监控图元显示
void startAcceptData(); //开始接收实时数据
void stopAcceptData(QString); //停止接收实时数据
QMap<int,QList<QPair<monitorItemState,QString>>>& getMonitorStateMap(){return m_monitorStateMap;} QMap<int,QList<QPair<monitorItemState,QString>>>& getMonitorStateMap(){return m_monitorStateMap;}
void setMonitorDisplaySetting(QMap<monitorItemTypeStruct,QMap<monitorItemStateStruct,monitorItemDisplayInfo>> map){m_monitorDisplaySetting = map;} void setMonitorDisplaySetting(QMap<monitorItemTypeStruct,QMap<monitorItemStateStruct,monitorItemDisplayInfo>> map){m_monitorDisplaySetting = map;}
QMap<monitorItemTypeStruct,QMap<monitorItemStateStruct,monitorItemDisplayInfo>>& getMonitorDisplaySetting(){return m_monitorDisplaySetting;} QMap<monitorItemTypeStruct,QMap<monitorItemStateStruct,monitorItemDisplayInfo>>& getMonitorDisplaySetting(){return m_monitorDisplaySetting;}
/************************数据显示*************************/
void setCurItemPropertyDlg(ItemPropertyDlg* p) {m_curPropertyDlg = p;}
ItemPropertyDlg* getCurItemPropertyDlg() {return m_curPropertyDlg;}
Q_SIGNALS: Q_SIGNALS:
void activatePage(const QString&); //激活当前model所在page void activatePage(const QString&); //激活当前model所在page
void updateCurrentItems(QList<monitorRelationItem>,bool); //更新当前组态元件列表 <名称,uid> void updateCurrentItems(QList<monitorRelationItem>,bool); //更新当前组态元件列表 <名称,uid>
@ -169,6 +176,8 @@ private:
QMap<int,QList<QPair<monitorItemState,QString>>> m_monitorStateMap; //元件状态对照表 <type,<state,状态名>> QMap<int,QList<QPair<monitorItemState,QString>>> m_monitorStateMap; //元件状态对照表 <type,<state,状态名>>
QMap<monitorItemTypeStruct,QMap<monitorItemStateStruct,monitorItemDisplayInfo>> m_monitorDisplaySetting; //元件设置 QMap<monitorItemTypeStruct,QMap<monitorItemStateStruct,monitorItemDisplayInfo>> m_monitorDisplaySetting; //元件设置
QList<monitorRelationItem> m_lstMonitorRelation; //监控item层级关系 QList<monitorRelationItem> m_lstMonitorRelation; //监控item层级关系
ItemPropertyDlg* m_curPropertyDlg;
public: public:
static bool _dataInitialised; static bool _dataInitialised;
}; };

View File

@ -6,18 +6,25 @@
#include <QMap> #include <QMap>
#include <QMutex> #include <QMutex>
class DiagramCavas;
class DataAccessor : public QObject class DataAccessor : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
DataAccessor(QObject *parent = nullptr); DataAccessor(QObject *parent = nullptr);
~DataAccessor(); ~DataAccessor();
void setParent(DiagramCavas* p) {_parentCavas = p;}
public slots: public slots:
void onReceiveHttpData(const QString& sType,const QVariant& data); void onReceiveHttpData(const QString& sType,const QVariant& data);
void onReceiveWebsocketData(const QVariant& data); void onReceiveWebsocketData(const QVariant& data);
private: private:
QMap<QString,QMap<quint64,double>> _realTimeData; QString removeAfterStreamBySplit(const QString& url); //手动处理websocket的config
private:
QMap<QString,QMap<quint64,double>> _realTimeData; //实时数据缓存 todo:自动清理
mutable QMutex m_mutex; mutable QMutex m_mutex;
DiagramCavas* _parentCavas;
}; };
#endif #endif

View File

@ -29,10 +29,13 @@ public:
void setModelController(FixedPortsModel* p) {_curModelController = p;} void setModelController(FixedPortsModel* p) {_curModelController = p;}
auto getModelController() {return _curModelController;} auto getModelController() {return _curModelController;}
auto getCurItem() {return _curItem;} auto getCurItem() {return _curItem;}
public slots: public slots:
void onOkClicked(); void onOkClicked();
void onCancelClicked(); void onCancelClicked();
void onGroupSelected(const QString&); void onGroupSelected(const QString&);
void onHttpDataUpdated(HttpRecommandInfo); //更新推荐列表
private: private:
Ui::itemPropertyDlg *ui; Ui::itemPropertyDlg *ui;
@ -47,6 +50,7 @@ private:
QString _curModel; //当前模型名 QString _curModel; //当前模型名
GraphicsProjectModelItem* _curItem; GraphicsProjectModelItem* _curItem;
FixedPortsModel* _curModelController; FixedPortsModel* _curModelController;
QString _curGroup; //当前属性组
}; };
#endif #endif

View File

@ -12,6 +12,7 @@ QT_END_NAMESPACE
class BayInfoDlg; class BayInfoDlg;
struct MeasurementInfo; struct MeasurementInfo;
struct HttpRecommandInfo;
class MeasureSettingDlg : public QDialog class MeasureSettingDlg : public QDialog
{ {
@ -36,6 +37,8 @@ public slots:
void onAddParaClicked(); void onAddParaClicked();
void onDelParaClicked(); void onDelParaClicked();
void onEventStrategyChange(int); //事件策略改变 void onEventStrategyChange(int); //事件策略改变
void onHttpDataUpdated(HttpRecommandInfo); //更新推荐对象列表(若有)
private: private:
void clearData(); void clearData();
private: private:

View File

@ -14,6 +14,8 @@ class QItemSelection;
class QStandardItemModel; class QStandardItemModel;
class QStandardItem; class QStandardItem;
struct monitorItemAttributeInfo; struct monitorItemAttributeInfo;
class QCompleter;
class QStringListModel;
class MonitorConfigDlg : public QDialog class MonitorConfigDlg : public QDialog
{ {
@ -24,6 +26,7 @@ public:
void initial(); void initial();
void updateSelectedItems(); void updateSelectedItems();
void updateRecommandLst(QStringList); //更新当前推荐列表
public slots: public slots:
void onOkClicked(); void onOkClicked();
void onCancelClicked(); void onCancelClicked();
@ -32,6 +35,10 @@ public slots:
void onItemSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); //选中设备事件 void onItemSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); //选中设备事件
void onPropertyCheckChanged(QStandardItem *item); //属性勾选改变信号 void onPropertyCheckChanged(QStandardItem *item); //属性勾选改变信号
void onPropertySelectionChanged(const QModelIndex &current, const QModelIndex &previous); //属性选中事件 void onPropertySelectionChanged(const QModelIndex &current, const QModelIndex &previous); //属性选中事件
void onConnectParamChanged(const QString&); //连接参数变化事件(发送推荐查询)
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private: private:
void savePropertyData(const QModelIndex &current,QUuid uid); //保存属性到uid的属性 void savePropertyData(const QModelIndex &current,QUuid uid); //保存属性到uid的属性
void loadPropertyData(const QModelIndex &current,QUuid uid); void loadPropertyData(const QModelIndex &current,QUuid uid);
@ -42,6 +49,10 @@ private:
QMap<QUuid,QList<monitorItemAttributeInfo>> _tempConfig; QMap<QUuid,QList<monitorItemAttributeInfo>> _tempConfig;
QStandardItemModel* _curItemModel; QStandardItemModel* _curItemModel;
QUuid _curUuid; QUuid _curUuid;
QStringList _curRecommandLst; //当前推荐列表
QCompleter* _recommandCompleter; //自动填充器
QStringListModel* _strLstModel; //自动填充模型
}; };
#endif #endif

View File

@ -35,6 +35,8 @@ public:
void initDisplayState(); //初始化显示状态参照表 void initDisplayState(); //初始化显示状态参照表
void initDisplaySetting(); //初始化显示状态设置 void initDisplaySetting(); //初始化显示状态设置
MonitorConfigDlg* getMonitorConfigDlg() {return _pConfigDlg;}
public: public:
//对层级关系的序列化与反序列化 //对层级关系的序列化与反序列化
QJsonArray serializeRelationToJsonArray(const QList<monitorRelationItem>& data) const; QJsonArray serializeRelationToJsonArray(const QList<monitorRelationItem>& data) const;

View File

@ -443,3 +443,12 @@ void BayInfoDlg::onIndexRbtnClicked(const QPoint &pos)
// 在点击位置显示菜单 // 在点击位置显示菜单
menu.exec(ui->tableWidget_local->mapToGlobal(pos)); menu.exec(ui->tableWidget_local->mapToGlobal(pos));
} }
void BayInfoDlg::onHttpDataUpdated(HttpRecommandInfo info)
{
if(_measureDlg){
if(_measureDlg->isVisible()){
}
}
}

View File

@ -23,6 +23,8 @@
#include "diagramCommunication/include/configManager.h" #include "diagramCommunication/include/configManager.h"
#include "instance/dataAccessor.h" #include "instance/dataAccessor.h"
#include "uiCommunicationBus.h" #include "uiCommunicationBus.h"
#include "itemPropertyDlg.h"
#include "monitorConfigDlg.h"
DiagramCavas::DiagramCavas(QWidget *parent) DiagramCavas::DiagramCavas(QWidget *parent)
: QMdiArea(parent) : QMdiArea(parent)
@ -66,6 +68,47 @@ void DiagramCavas::updateSubPos()
_cornerButton->positionAtCorner(); _cornerButton->positionAtCorner();
} }
void DiagramCavas::passRecommmandHttpData(HttpRecommandInfo info)
{
QMdiSubWindow* pSub = currentSubWindow();
if(!pSub)
return;
QWidget* pWindow= pSub->widget();
BaseDrawingPanel* pPanel = dynamic_cast<BaseDrawingPanel*>(pWindow);
if(pPanel)
{
if(pPanel->getMode() == DM_run)
{
auto pMonitor = dynamic_cast<MonitorPanel*>(pPanel);
if(pMonitor){
auto pDlg = pMonitor->getMonitorConfigDlg();
if(pDlg){
QStringList lst;
for(auto &str:info.lstRecommand){
QString sCompleteName = info.sInput+str;
if(!lst.contains(sCompleteName))
lst.append(sCompleteName);
}
pDlg->updateRecommandLst(lst);
}
//FixedPortsModel* pModel = pMonitor->getModelController();
}
}
else if(pPanel->getMode() == DM_edit)
{
auto pDraw = dynamic_cast<DrawingPanel*>(pPanel);
if(pDraw){
FixedPortsModel* pModel = pDraw->getModelController();
ItemPropertyDlg* pDlg = pModel->getCurItemPropertyDlg();
if(pDlg){
pDlg->onHttpDataUpdated(info);
}
}
}
}
}
void DiagramCavas::initial() void DiagramCavas::initial()
{ {
//todo:读取数据并初始化 //todo:读取数据并初始化
@ -99,6 +142,7 @@ void DiagramCavas::initial()
comm->updateWebSocketConfig(config->getWebSocketConfig()); comm->updateWebSocketConfig(config->getWebSocketConfig());
_dataAccessor = new DataAccessor(this); _dataAccessor = new DataAccessor(this);
_dataAccessor->setParent(this);
connect(UiCommunicationBus::instance(), connect(UiCommunicationBus::instance(),
SIGNAL(httpDataProcessed(QString,QVariant)), SIGNAL(httpDataProcessed(QString,QVariant)),
_dataAccessor, _dataAccessor,

View File

@ -1,6 +1,8 @@
#include "diagramConnectSetting.h" #include "diagramConnectSetting.h"
#include "ui_diagramConnectSetting.h" #include "ui_diagramConnectSetting.h"
#include "diagramCommunication/include/configManager.h" #include "diagramCommunication/include/configManager.h"
#include "uiCommunicationBus.h"
#include "communicationManager.h"
DiagramConnectSetting::DiagramConnectSetting(QWidget *parent) DiagramConnectSetting::DiagramConnectSetting(QWidget *parent)
: QDialog(parent) : QDialog(parent)
@ -18,7 +20,8 @@ DiagramConnectSetting::~DiagramConnectSetting()
void DiagramConnectSetting::initial() void DiagramConnectSetting::initial()
{ {
connect(ui->btn_testHttp,&QPushButton::clicked,this,&DiagramConnectSetting::onTestHttpClicked); connect(ui->btn_testRecommand,&QPushButton::clicked,this,&DiagramConnectSetting::onTestHttpRecommandClicked);
connect(ui->btn_testData,&QPushButton::clicked,this,&DiagramConnectSetting::onTestWebsocketClicked);
connect(ui->btn_testWebsoc,&QPushButton::clicked,this,&DiagramConnectSetting::onTestWebsocketClicked); connect(ui->btn_testWebsoc,&QPushButton::clicked,this,&DiagramConnectSetting::onTestWebsocketClicked);
connect(ui->btn_ok,&QPushButton::clicked,this,&DiagramConnectSetting::onOkClicked); connect(ui->btn_ok,&QPushButton::clicked,this,&DiagramConnectSetting::onOkClicked);
connect(ui->btn_cancel,&QPushButton::clicked,this,&DiagramConnectSetting::onCancelClicked); connect(ui->btn_cancel,&QPushButton::clicked,this,&DiagramConnectSetting::onCancelClicked);
@ -49,7 +52,29 @@ void DiagramConnectSetting::showDlg()
updateByConfig(socketInfo,1); updateByConfig(socketInfo,1);
} }
void DiagramConnectSetting::onTestHttpClicked() void DiagramConnectSetting::updateHttpLog(QString sType,QString data)
{
ui->lst_log->addItem("接收http:"+data);
if(sType == "recommend"){
ui->label_httpRecommand->setText("联通");
}
else if(sType == "subscriptions"){
ui->label_httpData->setText("联通");
}
}
void DiagramConnectSetting::updateWebsocketLog(QString str)
{
ui->lst_log->addItem("接收websocket:"+str);
}
void DiagramConnectSetting::onTestHttpRecommandClicked()
{
QString strUrl = ui->le_httpIp->text()+"/measurement/recommend?input=";
UiCommunicationBus::instance()->sendHttpRequest(strUrl);
}
void DiagramConnectSetting::onTestHttpDataClicked()
{ {
} }
@ -61,6 +86,20 @@ void DiagramConnectSetting::onTestWebsocketClicked()
void DiagramConnectSetting::onOkClicked() void DiagramConnectSetting::onOkClicked()
{ {
CommunicationManager* comm = CommunicationManager::instance();
ConfigManager* config = ConfigManager::instance();
// 应用配置
auto httpConfig = config->getHttpConfig();
auto websocketConfig = config->getWebSocketConfig();
httpConfig.endpoint = ui->le_httpIp->text();
httpConfig.timeout = ui->le_httpOver->text().toInt();
websocketConfig.endpoint = ui->le_websocIp->text();
websocketConfig.timeout = ui->le_websocOver->text().toInt();
websocketConfig.heartbeatInterval = ui->le_websocHeart->text().toInt();
comm->updateHttpConfig(httpConfig);
comm->updateWebSocketConfig(config->getWebSocketConfig());
hide(); hide();
} }

View File

@ -47,6 +47,7 @@
#include "projectIconSetting.h" #include "projectIconSetting.h"
#include "monitorPanel.h" #include "monitorPanel.h"
#include "designerView.h" #include "designerView.h"
#include "uiCommunicationBus.h"
#include "global.h" #include "global.h"
bool FixedPortsModel::_dataInitialised = false; bool FixedPortsModel::_dataInitialised = false;
@ -59,6 +60,7 @@ FixedPortsModel::FixedPortsModel(PowerEntity* pEntity)
,m_proModelSettingDlg(nullptr) ,m_proModelSettingDlg(nullptr)
,m_projectIconSettingDlg(nullptr) ,m_projectIconSettingDlg(nullptr)
,m_pBayManager(nullptr) ,m_pBayManager(nullptr)
,m_curPropertyDlg(nullptr)
{ {
_cavas = nullptr; _cavas = nullptr;
loadNodeDataFromDataBase(); loadNodeDataFromDataBase();
@ -1299,7 +1301,7 @@ QPointF FixedPortsModel::getTerminalPos(const QString& sTerminalId)
ElectricConnectLineItem* FixedPortsModel::getLineItemById(const QString& terminalId) ElectricConnectLineItem* FixedPortsModel::getLineItemById(const QString& terminalId)
{ {
for(auto iter:_nodeItem) //获取id所在的lineitem for(auto &iter:_nodeItem) //获取id所在的lineitem
{ {
auto item = dynamic_cast<GraphicsProjectModelItem*>(iter); auto item = dynamic_cast<GraphicsProjectModelItem*>(iter);
if(item) if(item)
@ -1326,6 +1328,7 @@ void FixedPortsModel::showModelDlg(const QString& sName,QUuid uuid,GraphicsProje
if(pDlg) if(pDlg)
{ {
pDlg->showDlg(mapData[sName],uuid,pItem); pDlg->showDlg(mapData[sName],uuid,pItem);
m_curPropertyDlg = pDlg;
} }
else else
qDebug()<<"showModelDlg err"; qDebug()<<"showModelDlg err";
@ -2797,3 +2800,74 @@ void FixedPortsModel::updateMonitorDisplay()
} }
} }
} }
void FixedPortsModel::startAcceptData()
{
QStringList lstTarget; //待订阅的对象
for(auto& lst:m_monitorPara){
for(auto& para:lst){
if(para.bSelected && !para.sConnectPara.isEmpty()){
if(!lstTarget.contains(para.sConnectPara))
lstTarget.append(para.sConnectPara);
}
}
}
QJsonObject obj; //构建开始请求
obj["action"] = "start";
QJsonArray arrMeasure;
QJsonObject objMeasure;
objMeasure["interval"] = "2s";
QJsonArray arrTargets;
for(auto& strTarget:lstTarget){
arrTargets.append(strTarget);
}
objMeasure["targets"] = arrTargets;
arrMeasure.append(objMeasure);
obj["measurements"] = arrMeasure;
QString sPath = "/monitors/data/subscriptions";
QJsonDocument doc(obj);
QVariant variant = doc.toVariant();
UiCommunicationBus::instance()->sendHttpRequest(sPath,variant,"POST");
QList<QPair<QString,QString>> requestLst; //等待请求的队列
for(auto& str:lstTarget){
requestLst.append(qMakePair(str,"request"));
}
UiCommunicationBus::instance()->insertTempRequest(_pageName,requestLst);
}
void FixedPortsModel::stopAcceptData(QString page)
{
if(UiCommunicationBus::instance()->getSesstionMap().contains(page)){
auto& curSession = UiCommunicationBus::instance()->getSesstionMap()[page];
QJsonObject obj; //构建开始请求
obj["action"] = "stop";
obj["client_id"] = curSession.first;
QJsonArray arrMeasure;
QJsonObject objMeasure;
objMeasure["interval"] = "2s";
QJsonArray arrTargets;
for(auto& pairTarget:curSession.second){
arrTargets.append(pairTarget.first);
pairTarget.second = "closing";
}
objMeasure["targets"] = arrTargets;
arrMeasure.append(objMeasure);
obj["measurements"] = arrMeasure;
QString sPath = "/monitors/data/subscriptions";
QJsonDocument doc(obj);
QVariant variant = doc.toVariant();
UiCommunicationBus::instance()->sendHttpRequest(sPath,variant,"POST");
}
}

View File

@ -1,10 +1,17 @@
#include "instance/dataAccessor.h" #include "instance/dataAccessor.h"
#include "communicationManager.h"
#include "uiCommunicationBus.h"
#include "configManager.h"
#include "diagramCavas.h"
#include "diagramConnectSetting.h"
#include <QVariant> #include <QVariant>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
#include "global.h"
DataAccessor::DataAccessor(QObject* parent) DataAccessor::DataAccessor(QObject* parent)
: QObject(parent) : QObject(parent)
,_parentCavas(nullptr)
{ {
} }
@ -17,28 +24,120 @@ DataAccessor::~DataAccessor()
void DataAccessor::onReceiveHttpData(const QString& sType,const QVariant& data) void DataAccessor::onReceiveHttpData(const QString& sType,const QVariant& data)
{ {
if(sType == "subscriptions"){ if(sType == "subscriptions"){
QMap<QString,QList<QPair<QString,QString>>>& tempRequest = UiCommunicationBus::instance()->getTempRequestMap();
QJsonObject dataObj = data.toJsonObject(); QJsonObject dataObj = data.toJsonObject();
QString sClientId = dataObj.value("client_id").toString(); QString sClientId = dataObj.value("client_id").toString();
QMap<QString,QString> lstRequest; QMap<QString,QString> lstTarget;
QJsonArray measureArr = dataObj.value("measurements").toArray(); QJsonArray measureArr = dataObj.value("measurements").toArray();
for(const QJsonValue& value : measureArr){ for(const QJsonValue& value : measureArr){
QJsonObject obj = value.toObject(); QJsonObject obj = value.toObject();
QString sId = obj["id"].toString(); QString sId = obj["id"].toString();
QString sCode = obj["code"].toString(); QString sCode = obj["code"].toString();
if(sId == "1001"){ if(!lstTarget.contains(sId)){
if(!lstRequest.contains(sId)){ lstTarget.insert(sId,sCode);
lstRequest.insert(sId,sCode); }
}
QString sAction;
auto mapSesstion = UiCommunicationBus::instance()->getSesstionMap();
bool bClientExist = false;
for(auto& session:mapSesstion){
if(session.first == sClientId){ //在会话列表中已存在是stop(暂只使用stop和start)
bClientExist = true;
sAction = "stop";
break;
}
}
if(sAction.isEmpty()){ //不是stop的情况
QStringList lstKeys = lstTarget.keys();
for(auto it = tempRequest.begin(); it != tempRequest.end(); ++it){
const QString& page = it.key();
QList<QPair<QString, QString>>& tempList = it.value();
// 从 tempList 提取所有 first 元素
QStringList firstElements;
firstElements.reserve(tempList.size());
for (const auto& pair : tempList)
{
firstElements.append(pair.first);
}
// 对两个列表进行排序(因为 moveMatchingRequests 内部会排序比较)
QStringList sortedFirstElements = firstElements;
QStringList sortedLstKeys = lstKeys;
std::sort(sortedFirstElements.begin(), sortedFirstElements.end());
std::sort(sortedLstKeys.begin(), sortedLstKeys.end());
// 比较两个列表是否相同
if (sortedFirstElements == sortedLstKeys)
{
// 这里需要一个 id 参数,你可以从 lstRequest 中获取或使用其他方式
QString id; // 你需要确定 id 从哪里来
// 调用 moveMatchingRequests
for(auto& pair:tempList){
pair.second = "connecting";
}
UiCommunicationBus::instance()->insertSesstionMap(id, lstTarget);
sAction = "start";
break;
} }
} }
} }
/*QString input = dataObj.value("input").toString();
int offSet = dataObj.value("offset").toInt(); if(!lstTarget.isEmpty()){
QJsonArray recommendedList = dataObj.value("recommended_list").toArray(); if(sAction == "start"){
for(const QJsonValue& value : recommendedList){ auto config = ConfigManager::instance()->getWebSocketConfig();
QString content = value.toString(); QString sPre = removeAfterStreamBySplit(config.endpoint); //手动移除
}*/ config.endpoint = sPre + "/" + sClientId;
CommunicationManager::instance()->updateWebSocketConfig(config,sClientId);
CommunicationManager::instance()->connectWebSocket(sClientId);
}
else if(sAction == "stop"){ //已经停止完毕从session中移除会话
auto &map = UiCommunicationBus::instance()->getSesstionMap();
for(auto iter = map.begin();iter != map.end();++iter){
if(iter->first == sClientId){
iter = map.erase(iter);
break;
}
}
CommunicationManager::instance()->disconnectWebSocket(sClientId);
CommunicationManager::instance()->removeChannel(sClientId);
}
}
}
else if(sType == "recommend"){
QJsonArray dataArr = data.toJsonArray();
for(const QJsonValue& value:dataArr){
QJsonObject dataObj = value.toObject();
QString input = dataObj.value("input").toString();
int offSet = dataObj.value("offset").toInt();
QJsonArray recommendedList = dataObj.value("recommended_list").toArray();
HttpRecommandInfo info;
for(const QJsonValue& value : recommendedList){
QString content = value.toString();
info.lstRecommand.append(content);
}
info.sInput = input.left(offSet);
info.nOffset = offSet;
if(_parentCavas){
_parentCavas->passRecommmandHttpData(info);
}
}
}
if(_parentCavas){
auto pDlg = _parentCavas->getConnectSettingDlg();
if(pDlg){
QJsonObject jsonObj = data.value<QJsonObject>();
QJsonDocument doc(jsonObj);
QString compactJson = doc.toJson(QJsonDocument::Compact);
pDlg->updateHttpLog(sType,compactJson);
}
} }
} }
@ -51,17 +150,52 @@ void DataAccessor::onReceiveWebsocketData(const QVariant& data)
QJsonObject targetObj = value.toObject(); QJsonObject targetObj = value.toObject();
QString targetId = targetObj["id"].toString(); QString targetId = targetObj["id"].toString();
QJsonArray arrData = targetObj["datas"].toArray(); QJsonArray arrData = targetObj["datas"].toArray();
QMap<quint64, double> newInnerMap;
for (const QJsonValue& data : arrData){ for (const QJsonValue& data : arrData){
QJsonObject dataObj = data.toObject(); QJsonObject dataObj = data.toObject();
QString sTime = dataObj["time"].toString(); QString sTime = dataObj["time"].toString();
double dVal = dataObj["value"].toDouble();
bool ok = false; bool ok = false;
quint64 value = sTime.toULongLong(&ok); quint64 value = sTime.toULongLong(&ok);
if (ok) { if (ok) {
// 使用 value newInnerMap.insert(value,dVal);
} }
double dVal = dataObj["value"].toDouble(); }
QMutexLocker locker(&m_mutex);
if (_realTimeData.contains(targetId)) {
_realTimeData[targetId].insert(newInnerMap);
} else {
_realTimeData.insert(targetId, newInnerMap);
} }
} }
} }
QMutexLocker locker(&m_mutex); if(_parentCavas){
auto pDlg = _parentCavas->getConnectSettingDlg();
if(pDlg){
QJsonObject jsonObj = data.value<QJsonObject>();
QJsonDocument doc(jsonObj);
QString compactJson = doc.toJson(QJsonDocument::Compact);
pDlg->updateWebsocketLog(compactJson);
}
}
}
QString DataAccessor::removeAfterStreamBySplit(const QString& url)
{
QStringList parts = url.split('/');
QStringList resultParts;
for (int i = 0; i < parts.size(); i++) {
if (parts[i] == "stream") {
// 找到 "stream" 后,停止添加后续部分
resultParts.append("stream");
break;
}
resultParts.append(parts[i]);
}
return resultParts.join('/');
} }

View File

@ -7,7 +7,7 @@
#include "ui_itemPropertyDlg.h" #include "ui_itemPropertyDlg.h"
#include "baseContentDlg.h" #include "baseContentDlg.h"
#include "baseInfoDlg.h" #include "baseInfoDlg.h"
//#include "topologyManager.h" #include "graphicsDataModel/fixedPortsModel.h"
#include "basePropertyManager.h" #include "basePropertyManager.h"
#include "baseProperty.h" #include "baseProperty.h"
#include "ptExtraInfoDlg.h" #include "ptExtraInfoDlg.h"
@ -131,12 +131,16 @@ void ItemPropertyDlg::onOkClicked()
} }
} }
} }
_curGroup = "";
_curItem = nullptr; _curItem = nullptr;
_curModelController->setCurItemPropertyDlg(nullptr);
hide(); hide();
} }
void ItemPropertyDlg::onCancelClicked() void ItemPropertyDlg::onCancelClicked()
{ {
_curGroup = "";
_curModelController->setCurItemPropertyDlg(nullptr);
hide(); hide();
} }
@ -165,6 +169,7 @@ void ItemPropertyDlg::onGroupSelected(const QString& str)
} }
ui->stackedWidget->setCurrentWidget(groupViews_[str]); ui->stackedWidget->setCurrentWidget(groupViews_[str]);
_curGroup = str;
} }
@ -203,6 +208,17 @@ void ItemPropertyDlg::createGroupView(const QString& str)
ui->stackedWidget->addWidget(contentDlg); ui->stackedWidget->addWidget(contentDlg);
} }
void ItemPropertyDlg::onHttpDataUpdated(HttpRecommandInfo info)
{
if(_curGroup == "bay"){
auto pWidget = groupViews_[_curGroup];
auto pBay = dynamic_cast<BayInfoDlg*>(pWidget);
if(pBay){
pBay->onHttpDataUpdated(info);
}
}
}
void ItemPropertyDlg::showDlg(modelDataInfo dataInfo,QUuid uuid,GraphicsProjectModelItem* pItem) void ItemPropertyDlg::showDlg(modelDataInfo dataInfo,QUuid uuid,GraphicsProjectModelItem* pItem)
{ {
groupValue_ = dataInfo.groupInfo; groupValue_ = dataInfo.groupInfo;

View File

@ -361,3 +361,8 @@ void MeasureSettingDlg::onEventStrategyChange(int n)
ui->sw_event->setCurrentIndex(1); ui->sw_event->setCurrentIndex(1);
} }
} }
void MeasureSettingDlg::onHttpDataUpdated(HttpRecommandInfo info)
{
//
}

View File

@ -1,6 +1,10 @@
#include "monitorConfigDlg.h" #include "monitorConfigDlg.h"
#include "ui_monitorConfigDlg.h" #include "ui_monitorConfigDlg.h"
#include <QCompleter>
#include <QStringListModel>
#include <QKeyEvent>
#include "monitorPanel.h" #include "monitorPanel.h"
#include "uiCommunicationBus.h"
#include "global.h" #include "global.h"
MonitorConfigDlg::MonitorConfigDlg(QWidget *parent) MonitorConfigDlg::MonitorConfigDlg(QWidget *parent)
@ -8,6 +12,8 @@ MonitorConfigDlg::MonitorConfigDlg(QWidget *parent)
, ui(new Ui::monitorConfigDlg) , ui(new Ui::monitorConfigDlg)
,_parent(nullptr) ,_parent(nullptr)
,_curItemModel(nullptr) ,_curItemModel(nullptr)
,_recommandCompleter(nullptr)
,_strLstModel(nullptr)
{ {
ui->setupUi(this); ui->setupUi(this);
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags()); this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
@ -36,13 +42,44 @@ void MonitorConfigDlg::initial()
connect(_curItemModel,&QStandardItemModel::itemChanged, this,&MonitorConfigDlg::onPropertyCheckChanged); connect(_curItemModel,&QStandardItemModel::itemChanged, this,&MonitorConfigDlg::onPropertyCheckChanged);
connect(ui->treeView_para->selectionModel(), &QItemSelectionModel::currentChanged, connect(ui->treeView_para->selectionModel(), &QItemSelectionModel::currentChanged,
this, &MonitorConfigDlg::onPropertySelectionChanged); this, &MonitorConfigDlg::onPropertySelectionChanged);
_recommandCompleter = new QCompleter(this);
_recommandCompleter->setCaseSensitivity(Qt::CaseInsensitive);
_recommandCompleter->setFilterMode(Qt::MatchContains);
_recommandCompleter->setCompletionMode(QCompleter::PopupCompletion);
_strLstModel = new QStringListModel(this);
_recommandCompleter->setModel(_strLstModel);
ui->le_query->setCompleter(_recommandCompleter);
ui->le_query->installEventFilter(this);
ui->le_query->setPlaceholderText("输入空格获取初始值");
connect(ui->le_query, &QLineEdit::textChanged, this, [=](const QString &text) {
if (text.endsWith(".")) {
onConnectParamChanged(text);
}
});
//connect(ui->le_query,&QLineEdit::textChanged, this,&MonitorConfigDlg::onConnectParamChanged);
} }
void MonitorConfigDlg::updateSelectedItems() void MonitorConfigDlg::updateSelectedItems()
{ {
ui->treeView_item->expandAll(); ui->treeView_item->expandAll();
_tempConfig = _parent->getModelController()->getMonitorPara(); _tempConfig = _parent->getModelController()->getMonitorPara();
int a = 1; }
void MonitorConfigDlg::updateRecommandLst(QStringList lst)
{
for(auto& newName:lst){
if(!newName.isEmpty()){
if(!_curRecommandLst.contains(newName)){
_curRecommandLst.append(newName);
}
}
}
_strLstModel->setStringList(_curRecommandLst);
if (_recommandCompleter->popup()->isVisible()) {
_recommandCompleter->popup()->hide();
}
_recommandCompleter->complete(); // 重新显示补全列表
} }
void MonitorConfigDlg::onOkClicked() void MonitorConfigDlg::onOkClicked()
@ -147,6 +184,33 @@ void MonitorConfigDlg::onPropertySelectionChanged(const QModelIndex &current, co
} }
} }
void MonitorConfigDlg::onConnectParamChanged(const QString& str)
{
QVariantMap map;
map.insert("input",str);
UiCommunicationBus::instance()->sendHttpRequest("/measurement/recommend",QVariant(),"GET",map);
}
bool MonitorConfigDlg::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->le_query && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Space) {
qDebug() << "eventFilter:space";
onConnectParamChanged(ui->le_query->text());
_recommandCompleter->complete();
return true;
}
if (keyEvent->text() == ".") {
qDebug() << "eventFilter:dot";
// 返回false让事件继续传播
}
}
return QDialog::eventFilter(obj, event);
}
void MonitorConfigDlg::savePropertyData(const QModelIndex &previous,QUuid uid) void MonitorConfigDlg::savePropertyData(const QModelIndex &previous,QUuid uid)
{ {
if(_tempConfig.contains(uid)){ if(_tempConfig.contains(uid)){

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>393</width> <width>414</width>
<height>502</height> <height>588</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
@ -98,12 +98,19 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
<string>HTTP服务器配置</string> <string>HTTP服务器配置</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="horizontalSpacing">
<number>4</number>
</property>
<property name="verticalSpacing"> <property name="verticalSpacing">
<number>8</number> <number>8</number>
</property> </property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>连接名称:</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLineEdit" name="le_httpName"/>
</item>
<item row="2" column="2"> <item row="2" column="2">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
@ -118,49 +125,6 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="le_httpIp"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>连接名称:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>217</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLineEdit" name="le_httpName"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="le_httpOver">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>服务器地址</string>
</property>
</widget>
</item>
<item row="3" column="3"> <item row="3" column="3">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
@ -174,6 +138,39 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="le_httpIp"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>服务器地址:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>217</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="le_httpOver">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -182,15 +179,15 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
<property name="title"> <property name="title">
<string>连接测试</string> <string>连接测试</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QGridLayout" name="gridLayout_4">
<item> <item row="0" column="0">
<widget class="QPushButton" name="btn_testHttp"> <widget class="QPushButton" name="btn_testRecommand">
<property name="text"> <property name="text">
<string>测试连接</string> <string>测试节点推荐</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="0" column="1" rowspan="2">
<spacer name="horizontalSpacer_4"> <spacer name="horizontalSpacer_4">
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Orientation::Horizontal</enum>
@ -203,21 +200,21 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</spacer> </spacer>
</item> </item>
<item> <item row="0" column="2">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>状态:</string> <string>状态:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="0" column="3">
<widget class="QLabel" name="label_httpState"> <widget class="QLabel" name="label_httpRecommand">
<property name="text"> <property name="text">
<string>未连接</string> <string>未连接</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="0" column="4" rowspan="2">
<spacer name="horizontalSpacer_5"> <spacer name="horizontalSpacer_5">
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Orientation::Horizontal</enum>
@ -230,6 +227,27 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="0">
<widget class="QPushButton" name="btn_testData">
<property name="text">
<string>测试数据服务</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_16">
<property name="text">
<string>状态:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_httpData">
<property name="text">
<string>未连接</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>641</width> <width>673</width>
<height>504</height> <height>506</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
@ -103,7 +103,7 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
<attribute name="title"> <attribute name="title">
<string>监控参数配置</string> <string>监控参数配置</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_4" columnstretch="2,2,3"> <layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
@ -131,18 +131,12 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_3"> <widget class="QGroupBox" name="groupBox_3">
<property name="title"> <property name="title">
<string>配置详情</string> <string>配置详情</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<property name="horizontalSpacing">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>10</number>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
@ -150,7 +144,7 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="le_name"/> <widget class="QLineEdit" name="le_name"/>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
@ -160,8 +154,14 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="le_query"/> <widget class="QLineEdit" name="le_query">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
</widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
@ -172,6 +172,12 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QComboBox" name="cb_type"> <widget class="QComboBox" name="cb_type">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<item> <item>
<property name="text"> <property name="text">
<string>字符</string> <string>字符</string>
@ -184,7 +190,20 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</item> </item>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2"> <item row="2" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>526</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="3">
<widget class="QStackedWidget" name="stackedWidget"> <widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
@ -206,13 +225,6 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
<property name="verticalSpacing"> <property name="verticalSpacing">
<number>10</number> <number>10</number>
</property> </property>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>接线图中展示:</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="cb_outVisible"> <widget class="QComboBox" name="cb_outVisible">
<item> <item>
@ -240,6 +252,26 @@ font: 12pt &quot;Microsoft YaHei UI&quot;;</string>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>接线图中展示:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="page_2"> <widget class="QWidget" name="page_2">

View File

@ -36,16 +36,17 @@ public:
QString channelId() const { return m_config.channelId; } QString channelId() const { return m_config.channelId; }
ChannelConfig config() const { return m_config; } ChannelConfig config() const { return m_config; }
QUrl endpoint() const { return m_config.endpoint; } QUrl endpoint() const { return m_config.endpoint; }
QString sessionId() const {return m_sessionId;}
// 控制 // 控制
void setAutoReconnect(bool enable); void setAutoReconnect(bool enable);
bool isAutoReconnect() const { return m_autoReconnect; } bool isAutoReconnect() const { return m_autoReconnect; }
signals: signals:
void connected(); void connected(const QString& = "");
void disconnected(); void disconnected(const QString& = "");
void dataReceived(const QByteArray& data); void dataReceived(const QByteArray& data,const QString& = "");
void errorOccurred(const QString& error); void errorOccurred(const QString& error,const QString& = "");
protected: protected:
// 公共方法 // 公共方法
@ -60,6 +61,7 @@ protected:
// 成员变量 // 成员变量
ChannelConfig m_config; ChannelConfig m_config;
bool m_autoReconnect = true; bool m_autoReconnect = true;
QString m_sessionId; //会话idhttp无
private slots: private slots:
void onReconnectTimeout(); void onReconnectTimeout();

View File

@ -23,23 +23,26 @@ public:
bool disconnectHttp(); bool disconnectHttp();
bool sendHttpRequest(const QString& path, bool sendHttpRequest(const QString& path,
const QByteArray& data = QByteArray(), const QByteArray& data = QByteArray(),
const QString& method = "GET"); const QString& method = "GET",
const QVariantMap& query = QVariantMap());
// WebSocket通道操作 // WebSocket通道操作
bool connectWebSocket(); bool connectWebSocket(const QString& sessionId = "");
bool disconnectWebSocket(); bool disconnectWebSocket(const QString& sessionId = "");
bool sendWebSocketMessage(const QByteArray& data); bool removeChannel(const QString& sessionId);
bool sendWebSocketText(const QString& text);
bool sendWebSocketMessage(const QByteArray& data,const QString& sessionId);
bool sendWebSocketText(const QString& text,const QString& sessionId);
// 状态查询 // 状态查询
bool isHttpConnected() const; bool isHttpConnected() const;
bool isWebSocketConnected() const; bool isWebSocketConnected(const QString& sessionId) const;
ChannelConfig getHttpConfig() const; ChannelConfig getHttpConfig() const;
ChannelConfig getWebSocketConfig() const; ChannelConfig getWebSocketConfig() const;
// 配置更新 // 配置更新
void updateHttpConfig(const ChannelConfig& config); void updateHttpConfig(const ChannelConfig& config);
void updateWebSocketConfig(const ChannelConfig& config); void updateWebSocketConfig(const ChannelConfig& config,const QString& sessionId = "");
signals: signals:
// HTTP通道信号 // HTTP通道信号
@ -61,7 +64,7 @@ private:
// 内部初始化 // 内部初始化
void initHttpChannel(); void initHttpChannel();
void initWebSocketChannel(); void initWebSocketChannel(QString sessionId = ""); //服务器回传的会话id
// 配置 // 配置
ChannelConfig m_httpConfig; ChannelConfig m_httpConfig;
@ -69,5 +72,5 @@ private:
// 通道实例 // 通道实例
QSharedPointer<HttpChannel> m_httpChannel; QSharedPointer<HttpChannel> m_httpChannel;
QSharedPointer<WebSocketChannel> m_websocketChannel; QMap<QString,QSharedPointer<WebSocketChannel>> m_websocketChannelMap; //<sessionId,websocketChannel>
}; };

View File

@ -32,6 +32,7 @@ private:
DataProcessor(QObject* parent = nullptr); DataProcessor(QObject* parent = nullptr);
// 通用处理函数 // 通用处理函数
void processJson(const QVariant& data,int conType = 0); //0http 1websocket void processJson(const QVariant& data,int conType = 0); //0http 1websocket
void processJsonArray(const QVariant& data);
// 数据缓存 // 数据缓存
QMap<QString, QVariant> m_dataCache; QMap<QString, QVariant> m_dataCache;

View File

@ -16,7 +16,7 @@ public:
bool send(const QByteArray& data) override; bool send(const QByteArray& data) override;
// HTTP方法 // HTTP方法
bool get(const QString& path = ""); bool get(const QString& path = "",const QVariantMap& queryMap = QVariantMap());
bool post(const QByteArray& data, const QString& path = ""); bool post(const QByteArray& data, const QString& path = "");
bool put(const QByteArray& data, const QString& path = ""); bool put(const QByteArray& data, const QString& path = "");
bool deleteResource(const QString& path = ""); bool deleteResource(const QString& path = "");

View File

@ -16,7 +16,7 @@ public:
static UiCommunicationBus* instance(); static UiCommunicationBus* instance();
// 发送HTTP请求 // 发送HTTP请求
void sendHttpRequest(const QString& endpoint, const QVariant& data = QVariant()); void sendHttpRequest(const QString& endpoint, const QVariant& data = QVariant(),const QString& method = "GET",const QVariantMap& = QVariantMap());
// 发送HTTP请求无回复 // 发送HTTP请求无回复
void sendHttpRequestNoReply(const QString& endpoint, const QVariant& data = QVariant()); void sendHttpRequestNoReply(const QString& endpoint, const QVariant& data = QVariant());
@ -30,6 +30,79 @@ public:
// 注册/注销UI // 注册/注销UI
void registerUi(const QString& uiId, QObject* uiObject); void registerUi(const QString& uiId, QObject* uiObject);
void unregisterUi(const QString& uiId); void unregisterUi(const QString& uiId);
QMap<QString,QList<QPair<QString,QString>>>& getTempRequestMap() {return _tempRequest;}
void insertTempRequest(QString page,QList<QPair<QString,QString>> lst){
if(!_tempRequest.contains(page)){
_tempRequest.insert(page,lst);
}
}
QMap<QString,QPair<QString,QList<QPair<QString,QString>>>>& getSesstionMap() {return _session;}
void insertSesstionMap(QString id,QMap<QString,QString> targetMap){ //从临时列表移除,插入到会话列表
QStringList sortedTargetList; //排序后的target列表
for(auto it = targetMap.begin();it != targetMap.end();++it){
sortedTargetList.append(it.key());
}
sortedTargetList.sort();
auto it = _tempRequest.begin();
while (it != _tempRequest.end())
{
const QString& page = it.key();
QList<QPair<QString, QString>>& tempList = it.value();
// 提取当前 tempList 中所有 first 元素组成的列表
QStringList firstElements;
firstElements.reserve(tempList.size());
for (const auto& pair : tempList)
{
firstElements.append(pair.first);
}
// 先进行简单检查:如果元素数量不同,肯定不匹配
if (firstElements.size() != sortedTargetList.size())
{
++it;
continue;
}
// 排序 firstElements
QStringList sortedFirstElements = firstElements;
sortedFirstElements.sort();
// 比较排序后的列表
if (sortedFirstElements == sortedTargetList)
{
// 匹配成功
// 检查 _session 中是否已有此 page
if (!_session.contains(page))
{
QList<QPair<QString, QString>> newList;
for (const auto& item : tempList) { //如果订阅不成功,从候选列表中移除 todo:记录错误target
auto it = targetMap.find(item.first);
if (it != targetMap.end()) {
if (it.value() == "1001") {
continue; // 跳过
}
}
newList.append(item);
}
tempList = newList;
// _session 中没有此 page可以插入
_session[page] = qMakePair(id, tempList);
}
// 无论 _session 中是否有此 page都从 _tempRequest 删除 *********同一个page中只存在一个会话******
it = _tempRequest.erase(it);
}
else
{
++it;
}
}
}
signals: signals:
void httpDataProcessed(const QString& type,const QVariant& data); //发送分拣过的数据给外部 void httpDataProcessed(const QString& type,const QVariant& data); //发送分拣过的数据给外部
void websocketDataProcessed(const QVariant& data); void websocketDataProcessed(const QVariant& data);
@ -45,4 +118,6 @@ private:
// UI注册表 // UI注册表
QMap<QString, QObject*> m_uiObjects; QMap<QString, QObject*> m_uiObjects;
mutable QMutex m_mutex; mutable QMutex m_mutex;
QMap<QString,QList<QPair<QString,QString>>> _tempRequest; //临时请求队列,一个QList为一次会话 <图名<节点名,状态>>
QMap<QString,QPair<QString,QList<QPair<QString,QString>>>> _session; //会话队列 <图名<会话id<节点名,状态>>>
}; };

View File

@ -13,7 +13,7 @@ public:
int heartbeatInterval = 30000; int heartbeatInterval = 30000;
}; };
WebSocketChannel(const ChannelConfig& config, QObject* parent = nullptr); WebSocketChannel(const ChannelConfig& config, QString sessionId,QObject* parent = nullptr);
bool connect() override; bool connect() override;
bool disconnect() override; bool disconnect() override;
@ -24,14 +24,13 @@ public:
void setWebSocketConfig(const WebSocketConfig& config); void setWebSocketConfig(const WebSocketConfig& config);
signals: signals:
void textMessageReceived(const QString& message); void textMessageReceived(const QString& message,const QString& = "");
private slots: private slots:
void onConnected(); void onConnected();
void onDisconnected(); void onDisconnected();
void onTextMessageReceived(const QString& message); void onTextMessageReceived(const QString& message);
void onBinaryMessageReceived(const QByteArray& message); void onBinaryMessageReceived(const QByteArray& message);
private: private:
QWebSocket* m_webSocket = nullptr; QWebSocket* m_webSocket = nullptr;
WebSocketConfig m_wsConfig; WebSocketConfig m_wsConfig;

View File

@ -41,7 +41,7 @@ bool CommunicationManager::initialize()
initHttpChannel(); initHttpChannel();
// 初始化WebSocket通道 // 初始化WebSocket通道
initWebSocketChannel(); //initWebSocketChannel();
qInfo() << "CommunicationManager initialized"; qInfo() << "CommunicationManager initialized";
return true; return true;
@ -81,13 +81,8 @@ void CommunicationManager::initHttpChannel()
this, &CommunicationManager::httpError); this, &CommunicationManager::httpError);
} }
void CommunicationManager::initWebSocketChannel() void CommunicationManager::initWebSocketChannel(QString sessionId)
{ {
if (m_websocketChannel) {
m_websocketChannel->disconnect();
}
// 创建WebSocket通道
WebSocketChannel::ChannelConfig wsConfig; WebSocketChannel::ChannelConfig wsConfig;
wsConfig.endpoint = QUrl(m_websocketConfig.endpoint); wsConfig.endpoint = QUrl(m_websocketConfig.endpoint);
wsConfig.timeout = m_websocketConfig.timeout; wsConfig.timeout = m_websocketConfig.timeout;
@ -95,20 +90,63 @@ void CommunicationManager::initWebSocketChannel()
WebSocketChannel::WebSocketConfig websocketConfig; WebSocketChannel::WebSocketConfig websocketConfig;
websocketConfig.heartbeatInterval = m_websocketConfig.heartbeatInterval; websocketConfig.heartbeatInterval = m_websocketConfig.heartbeatInterval;
m_websocketChannel.reset(new WebSocketChannel(wsConfig)); if(sessionId.isEmpty()){ //没有指定会话初始化已有channel
m_websocketChannel->setWebSocketConfig(websocketConfig); for(auto& pChannel:m_websocketChannelMap){
pChannel->disconnect();
pChannel.reset(new WebSocketChannel(wsConfig,pChannel->sessionId()));
pChannel->setWebSocketConfig(websocketConfig);
// 连接信号 // 连接信号
connect(m_websocketChannel.data(), &WebSocketChannel::connected, connect(pChannel.data(), &WebSocketChannel::connected,
this, &CommunicationManager::websocketConnected); this, &CommunicationManager::websocketConnected);
connect(m_websocketChannel.data(), &WebSocketChannel::disconnected, connect(pChannel.data(), &WebSocketChannel::disconnected,
this, &CommunicationManager::websocketDisconnected); this, &CommunicationManager::websocketDisconnected);
connect(m_websocketChannel.data(), &WebSocketChannel::dataReceived, connect(pChannel.data(), &WebSocketChannel::dataReceived,
this, &CommunicationManager::websocketDataReceived); this, &CommunicationManager::websocketDataReceived);
connect(m_websocketChannel.data(), &WebSocketChannel::errorOccurred, connect(pChannel.data(), &WebSocketChannel::errorOccurred,
this, &CommunicationManager::websocketError); this, &CommunicationManager::websocketError);
connect(m_websocketChannel.data(), &WebSocketChannel::textMessageReceived, connect(pChannel.data(), &WebSocketChannel::textMessageReceived,
this, &CommunicationManager::websocketTextReceived); this, &CommunicationManager::websocketTextReceived);
}
}
else{
for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){ //已存在
pChannel->disconnect();
pChannel.reset(new WebSocketChannel(wsConfig,pChannel->sessionId()));
pChannel->setWebSocketConfig(websocketConfig);
// 连接信号
connect(pChannel.data(), &WebSocketChannel::connected,
this, &CommunicationManager::websocketConnected);
connect(pChannel.data(), &WebSocketChannel::disconnected,
this, &CommunicationManager::websocketDisconnected);
connect(pChannel.data(), &WebSocketChannel::dataReceived,
this, &CommunicationManager::websocketDataReceived);
connect(pChannel.data(), &WebSocketChannel::errorOccurred,
this, &CommunicationManager::websocketError);
connect(pChannel.data(), &WebSocketChannel::textMessageReceived,
this, &CommunicationManager::websocketTextReceived);
return;
}
}
QSharedPointer<WebSocketChannel> newChannel(new WebSocketChannel(wsConfig,sessionId));
newChannel->setWebSocketConfig(websocketConfig);
// 连接信号
connect(newChannel.data(), &WebSocketChannel::connected,
this, &CommunicationManager::websocketConnected);
connect(newChannel.data(), &WebSocketChannel::disconnected,
this, &CommunicationManager::websocketDisconnected);
connect(newChannel.data(), &WebSocketChannel::dataReceived,
this, &CommunicationManager::websocketDataReceived);
connect(newChannel.data(), &WebSocketChannel::errorOccurred,
this, &CommunicationManager::websocketError);
connect(newChannel.data(), &WebSocketChannel::textMessageReceived,
this, &CommunicationManager::websocketTextReceived);
m_websocketChannelMap.insert(sessionId,newChannel);
}
} }
bool CommunicationManager::connectHttp() bool CommunicationManager::connectHttp()
@ -140,7 +178,8 @@ bool CommunicationManager::disconnectHttp()
bool CommunicationManager::sendHttpRequest(const QString& path, bool CommunicationManager::sendHttpRequest(const QString& path,
const QByteArray& data, const QByteArray& data,
const QString& method) const QString& method,
const QVariantMap& query)
{ {
if (!m_httpChannel || !m_httpChannel->isConnected()) { if (!m_httpChannel || !m_httpChannel->isConnected()) {
qWarning() << "HTTP channel not connected"; qWarning() << "HTTP channel not connected";
@ -148,7 +187,7 @@ bool CommunicationManager::sendHttpRequest(const QString& path,
} }
if (method == "GET") { if (method == "GET") {
return m_httpChannel->get(path); return m_httpChannel->get(path,query);
} else if (method == "POST") { } else if (method == "POST") {
return m_httpChannel->post(data, path); return m_httpChannel->post(data, path);
} else if (method == "PUT") { } else if (method == "PUT") {
@ -161,51 +200,108 @@ bool CommunicationManager::sendHttpRequest(const QString& path,
return false; return false;
} }
bool CommunicationManager::connectWebSocket() bool CommunicationManager::connectWebSocket(const QString& sessionId)
{ {
if (!m_websocketChannel) { if(sessionId.isEmpty()){
qWarning() << "WebSocket channel not initialized"; for(auto& pChannel:m_websocketChannelMap){
return false; if (!pChannel->isConnected()) {
} pChannel->connect();
}
if (m_websocketChannel->isConnected()) { }
return true; return true;
} }
else
{
for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){
if (pChannel->isConnected()) {
return true;
}
return m_websocketChannel->connect(); return pChannel->connect();
} }
}
bool CommunicationManager::disconnectWebSocket()
{
if (!m_websocketChannel) {
return false;
} }
if (!m_websocketChannel->isConnected()) { qWarning() << "WebSocket channel not initialized";
return false;
}
bool CommunicationManager::disconnectWebSocket(const QString& sessionId)
{
if(sessionId.isEmpty()){ //不指定则断开所有通道
for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){
if (pChannel->isConnected()) {
pChannel->disconnect();
}
}
}
return true; return true;
} }
else{
for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){
if (!pChannel->isConnected()) {
return true;
}
return m_websocketChannel->disconnect(); return pChannel->disconnect();
} }
}
bool CommunicationManager::sendWebSocketMessage(const QByteArray& data)
{
if (!m_websocketChannel || !m_websocketChannel->isConnected()) {
qWarning() << "WebSocket channel not connected";
return false;
} }
return m_websocketChannel->send(data); return false;
} }
bool CommunicationManager::sendWebSocketText(const QString& text) bool CommunicationManager::removeChannel(const QString& sessionId)
{ {
if (!m_websocketChannel || !m_websocketChannel->isConnected()) { for(auto& pChannel:m_websocketChannelMap){
qWarning() << "WebSocket channel not connected"; if(pChannel->sessionId() == sessionId){
return false; if (pChannel->isConnected()) {
pChannel->disconnect();
}
m_websocketChannelMap.remove(sessionId);
return true;
}
}
return false;
}
bool CommunicationManager::sendWebSocketMessage(const QByteArray& data,const QString& sessionId)
{
for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){
if(!pChannel->isConnected()){
qWarning() << "WebSocket channel not connected";
return false;
}
return pChannel->send(data);
}
} }
return m_websocketChannel->sendText(text); qWarning() << "WebSocket channel not connected";
return false;
}
bool CommunicationManager::sendWebSocketText(const QString& text,const QString& sessionId)
{
for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){
if(!pChannel->isConnected()){
qWarning() << "WebSocket channel not connected";
return false;
}
return pChannel->sendText(text);
}
}
qWarning() << "WebSocket channel not connected";
return false;
} }
bool CommunicationManager::isHttpConnected() const bool CommunicationManager::isHttpConnected() const
@ -213,9 +309,17 @@ bool CommunicationManager::isHttpConnected() const
return m_httpChannel && m_httpChannel->isConnected(); return m_httpChannel && m_httpChannel->isConnected();
} }
bool CommunicationManager::isWebSocketConnected() const bool CommunicationManager::isWebSocketConnected(const QString& sessionId) const
{ {
return m_websocketChannel && m_websocketChannel->isConnected(); for(auto& pChannel:m_websocketChannelMap){
if(pChannel->sessionId() == sessionId){
if(pChannel->isConnected()){
return true;
}
}
}
return false;
} }
ChannelConfig CommunicationManager::getHttpConfig() const ChannelConfig CommunicationManager::getHttpConfig() const
@ -247,7 +351,7 @@ void CommunicationManager::updateHttpConfig(const ChannelConfig& config)
qInfo() << "HTTP config updated"; qInfo() << "HTTP config updated";
} }
void CommunicationManager::updateWebSocketConfig(const ChannelConfig& config) void CommunicationManager::updateWebSocketConfig(const ChannelConfig& config,const QString& sessionId)
{ {
bool reconnect = false; bool reconnect = false;
@ -256,10 +360,10 @@ void CommunicationManager::updateWebSocketConfig(const ChannelConfig& config)
} }
m_websocketConfig = config; m_websocketConfig = config;
initWebSocketChannel(); initWebSocketChannel(sessionId);
if (reconnect && config.autoConnect) { if (reconnect && config.autoConnect) {
connectWebSocket(); connectWebSocket(sessionId);
} }
qInfo() << "WebSocket config updated"; qInfo() << "WebSocket config updated";

View File

@ -153,8 +153,8 @@ ChannelConfig ConfigManager::getDefaultHttpConfig() const
config.id = "http_channel"; config.id = "http_channel";
config.name = "SCADA数据接口"; config.name = "SCADA数据接口";
config.endpoint = "http://192.168.1.100:8080/api"; config.endpoint = "http://192.168.46.100:10080";
config.timeout = 30000; config.timeout = 10000;
config.enabled = true; config.enabled = true;
config.autoConnect = true; config.autoConnect = true;
config.username = ""; config.username = "";
@ -178,7 +178,7 @@ ChannelConfig ConfigManager::getDefaultWebSocketConfig() const
config.id = "websocket_channel"; config.id = "websocket_channel";
config.name = "实时数据推送"; config.name = "实时数据推送";
config.endpoint = "ws://192.168.1.101:8888/ws"; config.endpoint = "ws://192.168.1.101:8888/ws";
config.timeout = 30000; config.timeout = 10000;
config.enabled = true; config.enabled = true;
config.autoConnect = false; config.autoConnect = false;
config.connected = false; config.connected = false;

View File

@ -27,10 +27,15 @@ DataProcessor::DataProcessor(QObject* parent)
void DataProcessor::processData(const QVariant& data,int conType) void DataProcessor::processData(const QVariant& data,int conType)
{ {
qDebug() << "处理数据_size:" << data.toString().size(); qDebug() << "data_size:" << data.toJsonObject().size();
// 根据数据类型处理 // 根据数据类型处理
processJson(data.toJsonObject(),conType); if (data.canConvert<QJsonObject>()) {
processJson(data.toJsonObject(),conType);
}
else if(data.canConvert<QJsonArray>()){
processJsonArray(data);
}
} }
void DataProcessor::processJson( const QVariant& data,int conType) void DataProcessor::processJson( const QVariant& data,int conType)
@ -38,9 +43,6 @@ void DataProcessor::processJson( const QVariant& data,int conType)
QJsonObject dataObj = data.toJsonObject(); QJsonObject dataObj = data.toJsonObject();
if(conType == 0){ if(conType == 0){
if(dataObj.contains("client_id")){ //实时数据相关 if(dataObj.contains("client_id")){ //实时数据相关
emit httpProcessed("recommend",data);
}
else if(dataObj.contains("input")){
emit httpProcessed("subscriptions",data); emit httpProcessed("subscriptions",data);
} }
} }
@ -49,21 +51,11 @@ void DataProcessor::processJson( const QVariant& data,int conType)
emit websocketProcessed(data); emit websocketProcessed(data);
} }
} }
}
if(dataObj.contains("client_id")){ //实时数据相关 void DataProcessor::processJsonArray(const QVariant& data)
/*QString clientId = dataObj.value("client_id").toString(); {
QJsonArray arrTarget = dataObj.value("targets").toArray(); emit httpProcessed("recommend",data);
for (const QJsonValue& value : arrTarget) {
QJsonObject obj = value.toObject();
QString targetId = obj["id"].toString();
QString sCode = obj["code"].toString();
}*/
}
else if(dataObj.contains("input")){
}
//QMutexLocker locker(&m_mutex);
//m_dataCache[dataType] = data;
} }
QVariant DataProcessor::getProcessedData(const QString& key) const QVariant DataProcessor::getProcessedData(const QString& key) const

View File

@ -5,6 +5,7 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QAuthenticator> #include <QAuthenticator>
#include <QDebug> #include <QDebug>
#include <QUrlQuery>
HttpChannel::HttpChannel(const ChannelConfig& config, QObject* parent) HttpChannel::HttpChannel(const ChannelConfig& config, QObject* parent)
: BaseChannel(config, parent) : BaseChannel(config, parent)
@ -35,16 +36,30 @@ bool HttpChannel::send(const QByteArray& data)
return post(data); return post(data);
} }
bool HttpChannel::get(const QString& path) bool HttpChannel::get(const QString& path,const QVariantMap& queryMap)
{ {
if (!m_config.endpoint.isValid()) { if (!m_config.endpoint.isValid()) {
emit errorOccurred("Invalid endpoint"); emit errorOccurred("Invalid endpoint");
return false; return false;
} }
QUrl url = m_config.endpoint; QUrl url;
if (!path.isEmpty()) { if(path.contains("http")){ //url全部输入
url.setPath(url.path() + "/" + path); url = QUrl(path);
}
else{ //url部分输入
url = m_config.endpoint;
if (!path.isEmpty()) {
url.setPath(url.path() + path);
}
if(!queryMap.isEmpty()){
QUrlQuery query;
for(auto iter = queryMap.begin();iter != queryMap.end();++iter){
query.addQueryItem(iter.key(),iter.value().toString());
};
url.setQuery(query);
}
} }
QNetworkAccessManager* manager = new QNetworkAccessManager(this); QNetworkAccessManager* manager = new QNetworkAccessManager(this);
@ -57,21 +72,25 @@ bool HttpChannel::get(const QString& path)
} }
}); });
if(url.isEmpty())
qDebug()<<"http url empty!";
QNetworkRequest request(url); QNetworkRequest request(url);
// 设置头 // 设置头
for (auto it = m_headers.begin(); it != m_headers.end(); ++it) { // for (auto it = m_headers.begin(); it != m_headers.end(); ++it) {
request.setRawHeader(it.key().toUtf8(), it.value().toUtf8()); // request.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
} // }
QNetworkReply* reply = manager->get(request); QNetworkReply* reply = manager->get(request);
QObject::connect(reply, &QNetworkReply::finished, [this, reply, manager]() { QObject::connect(reply, &QNetworkReply::finished, this,[this, reply, manager]() {
if (reply->error() == QNetworkReply::NoError) { if (reply->error() == QNetworkReply::NoError) {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
emit dataReceived(data); emit dataReceived(data);
} else { } else {
emit errorOccurred(reply->errorString()); emit errorOccurred(reply->errorString());
qDebug()<<reply->errorString();
} }
reply->deleteLater(); reply->deleteLater();
@ -90,7 +109,7 @@ bool HttpChannel::post(const QByteArray& data, const QString& path)
QUrl url = m_config.endpoint; QUrl url = m_config.endpoint;
if (!path.isEmpty()) { if (!path.isEmpty()) {
url.setPath(url.path() + "/" + path); url.setPath(url.path() + path);
} }
QNetworkAccessManager* manager = new QNetworkAccessManager(this); QNetworkAccessManager* manager = new QNetworkAccessManager(this);

View File

@ -39,10 +39,9 @@ UiCommunicationBus::UiCommunicationBus(QObject* parent)
DataProcessor* processor = DataProcessor::instance(); DataProcessor* processor = DataProcessor::instance();
connect(processor, &DataProcessor::httpProcessed, connect(processor, &DataProcessor::httpProcessed,
this, [this](const QString& dataType, const QVariant& data) { this, [this](const QString& dataType, const QVariant& data) {
if(dataType == "recommend"){ // if(dataType == "recommend"){
// 推荐列表请求将数据分发回订阅ui // broadcastToUis(dataType, data);
broadcastToUis(dataType, data); // }
}
emit httpDataProcessed(dataType,data); emit httpDataProcessed(dataType,data);
}); });
@ -54,12 +53,12 @@ UiCommunicationBus::UiCommunicationBus(QObject* parent)
qDebug() << "UiCommunicationBus initialized"; qDebug() << "UiCommunicationBus initialized";
} }
void UiCommunicationBus::sendHttpRequest(const QString& endpoint, const QVariant& data) void UiCommunicationBus::sendHttpRequest(const QString& endpoint, const QVariant& data,const QString& method,const QVariantMap& query)
{ {
CommunicationManager* comm = CommunicationManager::instance(); CommunicationManager* comm = CommunicationManager::instance();
QJsonDocument doc = QJsonDocument::fromVariant(data); QJsonDocument doc = QJsonDocument::fromVariant(data);
bool success = comm->sendHttpRequest(endpoint, doc.toJson()); bool success = comm->sendHttpRequest(endpoint, doc.toJson(),method,query);
if (success) { if (success) {
qDebug() << "HTTP请求已发送:" << endpoint; qDebug() << "HTTP请求已发送:" << endpoint;
@ -102,7 +101,7 @@ void UiCommunicationBus::onHttpDataReceived(const QByteArray& data)
} }
} }
qDebug() << "HTTP响应已处理"; qDebug() << "HTTP ";
} }
void UiCommunicationBus::onWebSocketDataReceived(const QByteArray& data) void UiCommunicationBus::onWebSocketDataReceived(const QByteArray& data)

View File

@ -2,7 +2,7 @@
#include "webSocketChannel.h" #include "webSocketChannel.h"
#include <QDebug> #include <QDebug>
WebSocketChannel::WebSocketChannel(const ChannelConfig& config, QObject* parent) WebSocketChannel::WebSocketChannel(const ChannelConfig& config, QString sessionId, QObject* parent)
: BaseChannel(config, parent) : BaseChannel(config, parent)
, m_webSocket(new QWebSocket) , m_webSocket(new QWebSocket)
{ {
@ -14,6 +14,7 @@ WebSocketChannel::WebSocketChannel(const ChannelConfig& config, QObject* parent)
this, &WebSocketChannel::onTextMessageReceived); this, &WebSocketChannel::onTextMessageReceived);
QObject::connect(m_webSocket, &QWebSocket::binaryMessageReceived, QObject::connect(m_webSocket, &QWebSocket::binaryMessageReceived,
this, &WebSocketChannel::onBinaryMessageReceived); this, &WebSocketChannel::onBinaryMessageReceived);
m_sessionId = sessionId;
} }
bool WebSocketChannel::connect() bool WebSocketChannel::connect()
@ -27,7 +28,24 @@ bool WebSocketChannel::connect()
return false; return false;
} }
m_webSocket->open(m_config.endpoint); // 1. 从 WebSocket URL 提取 host 和 port
QUrl url(m_config.endpoint);
QString host = url.host();
int port = url.port(80); // 默认端口 80
// 2. 构建 Origin URL
QString origin = QString("http://%1:%2").arg(host).arg(port);
// 3. 创建 QNetworkRequest 并设置 Origin
QNetworkRequest request(url);
request.setRawHeader("Origin", origin.toUtf8());
// 4. 使用 QWebSocket 连接
QWebSocket *socket = new QWebSocket();
socket->open(request);
qDebug() << "WebSocket URL:" << m_config.endpoint;
qDebug() << "Origin:" << origin;
return true; return true;
} }
@ -73,21 +91,21 @@ void WebSocketChannel::setWebSocketConfig(const WebSocketConfig& config)
void WebSocketChannel::onConnected() void WebSocketChannel::onConnected()
{ {
emit connected(); emit connected(m_sessionId);
} }
void WebSocketChannel::onDisconnected() void WebSocketChannel::onDisconnected()
{ {
emit disconnected(); emit disconnected(m_sessionId);
} }
void WebSocketChannel::onTextMessageReceived(const QString& message) void WebSocketChannel::onTextMessageReceived(const QString& message)
{ {
emit textMessageReceived(message); emit textMessageReceived(message,m_sessionId);
emit dataReceived(message.toUtf8()); emit dataReceived(message.toUtf8(),m_sessionId);
} }
void WebSocketChannel::onBinaryMessageReceived(const QByteArray& message) void WebSocketChannel::onBinaryMessageReceived(const QByteArray& message)
{ {
emit dataReceived(message); emit dataReceived(message,m_sessionId);
} }

View File

@ -51,7 +51,7 @@ void MonitorPagesDlg::onItemClicked(const QModelIndex &index)
{ {
QStandardItem* item = _pModel->itemFromIndex(index); QStandardItem* item = _pModel->itemFromIndex(index);
int nLevel = getLevel(item); int nLevel = getLevel(item);
if(nLevel == 0) //顶层不响应 if(nLevel == 0 || nLevel == -1) //顶层不响应
return; return;
QStandardItem* parent = item->parent(); QStandardItem* parent = item->parent();
if(item) if(item)