现场调试问题修改;本地服务端从qt5升级到qt6

This commit is contained in:
lixiaoyuan
2025-11-19 15:07:51 +08:00
parent 450aff0eff
commit 8735a31b18
185 changed files with 1239 additions and 363633 deletions

View File

@@ -34,10 +34,11 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Od /Ob2")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
# Qt_PATH 为 Qt 的安装地址
#set(QT_PATH "D:/Programs/Qt5/5.15.2/msvc2019_64")
set(QT_PATH "D:/Programs/Qt6/6.7.3/msvc2019_64")
set(QT_PATH "D:/Programs/Qt6/6.10.0/msvc2022_64")
set(CMAKE_PREFIX_PATH ${QT_PATH}/lib/cmake)
# 开启自动编译

View File

@@ -134,6 +134,14 @@ void Application::runThreadStat()
//spdlog::info("保存历史数据倒计时: {}", 600 - offset);
}
static TimeTick ttStatPredict;
if (ttStatPredict.elapse(600))
{
for (auto item : appdata.mapStation)
{
item.second->predict();
}
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}

View File

@@ -712,7 +712,7 @@ void Station::predict()
/// 预测实现方案:
// 查询前7天的历史数据(不包含今天)根据历史数据计算今日数据每10分钟一个数据一天共144个数据点
string sql = "SELECT * FROM predict_day pd WHERE pd.station_id='" + std::to_string(stationId)
+ "' AND dt>='" + dt1 + " AND dt<'" + dt2 + "';";
+ "' AND dt>='" + dt1 + "' AND dt<='" + dt2 + "';";
vector<Fields> result;
DAO::exec(NULL, sql, result);
@@ -741,7 +741,7 @@ void Station::predict()
for (int i = 0; i<vdptr->size() && i<vec.size(); ++i)
{
auto& v0 = vec[i];
if (v0 > 0)
//if (v0 > 0)
{
(*vdptr)[i] += v0;
if (datatype == 1) { countStorageIn[i]++; }
@@ -759,4 +759,13 @@ void Station::predict()
if (countCharge[i] > 0) { predictCharge[i] = predictCharge[i] / countCharge[i]; }
}
//for (int i = 1; i < predictStorageIn.size(); ++i)
//{
// int v1 = predictStorageIn[i] - predictStorageIn[i - 1];
// int v2 = predictStorageOut[i] - predictStorageOut[i - 1];
// int v3 = predictCharge[i] - predictCharge[i - 1];
// predictStorageIn[i] = v1 >=0 ? v1 : 0;
// predictStorageOut[i] = v2 >= 0 ? v2 : 0;
// predictCharge[i] = v3 >= 0 ? v3 : 0;
//}
}

View File

@@ -2,9 +2,9 @@ cd %~dp0
cd ..
@REM rd /S /Q .build
mkdir #buildmsvc2019
cd #buildmsvc2019
mkdir #buildmsvc2022
cd #buildmsvc2022
@REM Visual Studio 16 2019/Visual Studio 17 2022
@REM Win32/x64
cmake ../src -G "Visual Studio 16 2019" -A x64
cmake ../src -G "Visual Studio 17 2022" -A x64

View File

@@ -617,11 +617,8 @@ Errcode DAO::queryStatStationList(PageInfo& pageInfo, Fields& params, vector<Fie
}
if (!sqlCondition.empty()) { sqlCondition = " WHERE " + sqlCondition; }
std::string sqlFields = "ss.*, d.name device_name, ddt.name device_type";
std::string sqlFrom = R"(FROM stat_day ss
LEFT JOIN device d ON d.device_id = ss.device_id
LEFT JOIN def_device_type ddt ON ddt.device_type_id = d.`type`)" + sqlCondition;
std::string sqlFields = "ss.* ";
std::string sqlFrom = R"(FROM stat_day ss )" + sqlCondition;
return QueryPagination(sqlFields, sqlFrom, pageInfo, result);
}

View File

@@ -8,7 +8,6 @@
#include <fstream>
#include <filesystem>
#include <QApplication>
#include <QtWebEngineWidgets/QtWebEngineWidgets>
#include "common/Utils.h"
#include "common/Snowflake.h"
@@ -167,28 +166,6 @@ void OpensslSM2_test()
int main(int argc, char** argv)
{
{
stringstream ss;
float v = 3.123456;
float ratio = 0.1;
std::cout << Utils::toStr(v, 0) << std::endl;
std::cout << Utils::toStr(v, 1) << std::endl;
ratio = 1;
if (ratio == 1.0f)
{
std::cout << Utils::toStr(ratio, 2) << std::endl;
}
std::cout << Utils::toFloat("1") << std::endl;
//ss << "(" << setw(2) << setfill('0') << 1 << ")";
//std::cout << ss.str();
std::cout << "======================" << std::endl;
}
// 设置控制台输出为 UTF-8 编码
SetConsoleOutputCP(CP_UTF8);
// 设置控制台输入为 UTF-8 编码(如果需要输入中文)
@@ -214,6 +191,7 @@ int main(int argc, char** argv)
{
QApplication qapp(argc, argv);
QFontDatabase::addApplicationFont(QCoreApplication::applicationDirPath() + "/assets/fonts/优设标题黑.ttf");
QFont font("微软雅黑", 10, 600);
QApplication::setFont(font);
MainApp mainApp;

View File

@@ -476,7 +476,6 @@ Errcode HttpEntity::deletePermission(const httplib::Request& req, njson& json, s
return DAO::deletePermissionById(permissionId);
}
Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std::string& errmsg)
{
std::string token = req.get_param_value("page");
@@ -497,52 +496,49 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
{
return err;
}
std::map<std::string, std::vector<Fields>> mapP;
for (int i = 0; i<vecPermission.size(); ++i)
std::map<std::string, std::vector<int>> mapRole;
std::map<std::string, std::vector<int>> mapChildren;
for (int i=0; i<vecPermission.size(); ++i)
{
auto& item = vecPermission[i];
std::string roleId = item.value("role_id");
std::string id = item.value("permission_id");
std::string parentId = item.value("parent_id");
mapP[roleId].push_back(vecPermission[i]);
mapRole[roleId].push_back(i);
if (parentId != "")
{
mapChildren[roleId + "-" + parentId].push_back(i);
}
}
for (auto& item : json["data"])
{
auto jsonpermission = njson::array();
std::string roleId = item["role_id"];
std::vector<Fields>& vecP = mapP[roleId];
std::map<std::string, int> mapParentPos;
for (int i = 0; i<vecP.size(); ++i)
for (auto& fieldsPos : mapRole[roleId])
{
auto& item = vecPermission[i];
if (item.value("parent_id") == "")
auto& fields = vecPermission[fieldsPos];
string parentId = fields.value("parent_id");
string permissionId = fields.value("permission_id");
if (parentId == "")
{
mapParentPos[item.value("permission_id")] = i;
njson node;
FieldsToJson(item, node);
node["children"] = njson::array();
jsonpermission.push_back(node);
}
}
// 重新遍历处理二级子权限,防止父权限信息还未创建时导致错误
for (int i = 0; i<vecP.size(); ++i)
{
auto& item = vecP[i];
std::string id = item.value("permission_id");
std::string parentId = item.value("parent_id");
if (parentId != "")
{
auto iter = mapParentPos.find(parentId);
if (iter != mapParentPos.end())
FieldsToJson(fields, node);
njson nodeChildren = njson::array();
auto iter = mapChildren.find(roleId + "-" + permissionId);
if (iter != mapChildren.end())
{
njson node;
FieldsToJson(item, node);
jsonpermission[iter->second]["children"].push_back(node);
for (auto& fieldsChildPos : iter->second)
{
njson nodeChild;
FieldsToJson(vecPermission[fieldsChildPos], nodeChild);
nodeChildren.push_back(nodeChild);
}
}
node["children"] = nodeChildren;
jsonpermission.push_back(node);
}
}
item["permission"] = jsonpermission;
@@ -565,6 +561,19 @@ Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::st
GetRequestParams(req, {"name", "describe", "is_open", "permission"}, params);
return DAO::insertRole(params);
};
static void JsonToFieldsRole(string roleId, njson& item, Fields& fields)
{
fields.set("role_id", roleId);
fields.set("permission_id", item["permission_id"].get<std::string>());
fields.set("is_open", item["is_open"].get<std::string>());
fields.set("is_view", item["is_view"].get<std::string>());
fields.set("is_add", item["is_add"].get<std::string>());
fields.set("is_edit", item["is_edit"].get<std::string>());
fields.set("is_del", item["is_del"].get<std::string>());
}
Errcode HttpEntity::updateRole(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
@@ -588,14 +597,18 @@ Errcode HttpEntity::updateRole(const httplib::Request& req, njson& json, std::st
for (auto& item: jsonarray)
{
Fields fields;
fields.set("role_id", roleId);
fields.set("permission_id", item["permission_id"].get<std::string>());
fields.set("is_open", item["is_open"].get<std::string>());
fields.set("is_view", item["is_view"].get<std::string>());
fields.set("is_add", item["is_add"].get<std::string>());
fields.set("is_edit", item["is_edit"].get<std::string>());
fields.set("is_del", item["is_del"].get<std::string>());
JsonToFieldsRole(roleId, item, fields);
vecFields.push_back(fields);
if (item.contains("children"))
{
for (auto& item : item["children"])
{
Fields fields;
JsonToFieldsRole(roleId, item, fields);
vecFields.push_back(fields);
}
}
}
err = DAO::updateRolePermission(dao, roleId, vecFields);
}
@@ -1094,14 +1107,21 @@ Errcode HttpEntity::queryPredictionDetail(const httplib::Request& req, njson& js
{
const int num = 144;
std::vector<int> vecStoreIn(num, 0), vecStoreOut(num, 0), vecCharge(num, 0), vecSolar(num, 0), vecSolarP(num, 0);
for (int i = 0; i<num; ++i)
for (auto& item : Application::data().mapStation)
{
vecStoreIn[i] = 0;
vecStoreOut[i] = 0;
vecCharge[i] = 0;
vecSolar[i] = 0;
vecSolarP[i] = 0;
auto& station = item.second;
for (int i = 0; i < num; ++i)
{
vecStoreIn[i] += station->predictStorageIn[i];
vecStoreOut[i] += station->predictStorageOut[i];
vecCharge[i] += station->predictCharge[i];
vecSolar[i] = 0;
vecSolarP[i] = 0;
}
}
json["data"] = {
{"W_store_in", vecStoreIn},
{"W_store_out", vecStoreOut},
@@ -1263,13 +1283,14 @@ Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std
jsondata["launch_date"] = station->launchDate;
}
auto& appdata = Application::data();
std::vector<Fields> result;
DaoEntity::execOnce(sql, result);
if (result.size() > 0)
{
auto& fields = result[0];
// jsondata["launch_date"] = "2025-09-01"; //场站上线日期
//jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd
// jsondata["station_id"] = station_id;
jsondata["storage_elect_in"] = fields.value("storage_elect_in"); //储能充电电量kWh精度0.001
jsondata["storage_elect_out"] = fields.value("storage_elect_out"); //储能放电电量kWh精度0.001

View File

@@ -10,181 +10,169 @@
#include "app/Station.h"
#include "protocol/MqttEntity.h"
MainApp::MainApp()
{
// 设置背景色
QPalette palette(this->palette());
palette.setColor(QPalette::Window, QColor(11, 33, 77));
this->setAutoFillBackground(true);
this->setPalette(palette);
this->setStyleSheet("color: white;");
// 设置背景色
QPalette palette(this->palette());
palette.setColor(QPalette::Window, QColor(14, 35, 74));
this->setAutoFillBackground(true);
this->setPalette(palette);
this->setStyleSheet("color: white;");
this->setFixedSize(1440, 900);
this->show();
this->setAttribute(Qt::WA_StyledBackground, true); // 启用样式表背景绘制
this->resize(1440, 900);
this->show();
widgetMenu = MyQUI::Widget(this, "menu", "background-color:rgba(120,120,120,30); border-radius:5px;");
widgetWorkspace = MyQUI::Widget(this, "workspace", "background-color:rgba(120,120,120,30); border-radius:5px;");
//ui.bkg.setGeometry(0, 0, 1440, 900);
//ui.bkg.setStyleSheet("background-color: rgb(17, 36, 102);");
this->initMenu();
this->setMyLayout();
this->setActiveMenu("系统总览");
//ui.weburl = std::make_shared<LabelPair>(this, 10, 10, 240, 30);
//ui.weburl->setTitle("页面地址:");
//ui.weburl->setValue("http://www.baidu.com");
timer = std::make_shared<QTimer>(this);
QObject::connect(timer.get(), &QTimer::timeout, this, &MainApp::onTimer);
timer->start(1000); // 每隔1000毫秒更新一次
}
ui.widgetMenu = std::make_shared<QWidget>(this);
ui.widgetMenu->setObjectName("menu");
ui.widgetMenu->setStyleSheet("#menu { background-color:rgba(120,120,120,30); border-radius:5px; }");
//ui.widgetMenu->show();
ui.widgetWorkspace = std::make_shared<QWidget>(this);
ui.widgetWorkspace->setObjectName("workspace");
ui.widgetWorkspace->setStyleSheet("#workspace { background-color:rgba(120,120,120,30); border-radius:5px; }");
MainApp::~MainApp()
{
}
this->initMenu();
this->setMyLayout();
this->onActiveMenu("系统总览");
timer = std::make_shared<QTimer>(this);
connect(timer.get(), &QTimer::timeout, this, &MainApp::onTimer);
timer->start(1000); // 每隔1000毫秒更新一次
QPushButton* MainApp::addMenuItem(int index, string itemName)
{
auto itemBtn = new QPushButton(itemName.c_str());
itemBtn->setStyleSheet(QSS_BTN_MENU.c_str());
mapMenuBtn[itemName] = itemBtn;
QObject::connect(itemBtn, &QPushButton::clicked, this, [=]() { this->setActiveMenu(itemName); });
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
itemBtn->setSizePolicy(sizePolicy);
layoutMenu->addWidget(itemBtn, index, 0, 1, 1);
// 设置列宽和行高
layoutMenu->setRowMinimumHeight(index, 50); // 设置第0列的最小宽度为100像素
// 设置列和行的伸缩因子
layoutMenu->setRowStretch(index, 0); // 设置第0列的伸缩因子为0不伸缩
layoutMenu->setRowStretch(index + 1, 2); // 设置第1列的伸缩因子为2使其更宽
return itemBtn;
}
void MainApp::initMenu()
{
ui.vecMenuItems.reserve(20);
layoutMenu = new QGridLayout(widgetMenu.get());
layoutMenu->setSpacing(2);
layoutMenu->setContentsMargins(2, 2, 2, 2);
ui.layoutMenu = std::make_shared<QGridLayout>(ui.widgetMenu.get());
ui.layoutMenu->setSpacing(2);
ui.layoutMenu->setContentsMargins(2, 2, 2, 2);
labelDT = new QLabel(); // 由其父对象layout自动释放
labelDT->setAlignment(Qt::AlignCenter);
labelDT->setFont(QFont("优设标题黑", 18));
this->setLabelDateTime();
layoutMenu->addWidget(labelDT, 0, 0, 1, 1);
layoutMenu->setRowMinimumHeight(0, 80); // 设置第0列的最小高度
layoutMenu->setRowStretch(0, 0); // 设置第0列的伸缩因子为0不伸缩
ui.labelDT = std::make_shared< QLabel>();
ui.labelDT->setAlignment(Qt::AlignCenter);
ui.labelDT->setText(Utils::timeStr().c_str());
ui.labelDT->setFont(QFont("微软雅黑", 14));
ui.layoutMenu->addWidget(ui.labelDT.get(), 0, 0, 1, 1);
// 设置列宽和行高
ui.layoutMenu->setRowMinimumHeight(0, 40); // 设置第0列的最小宽度为100像素
// 设置列和行的伸缩因子
ui.layoutMenu->setRowStretch(0, 0); // 设置第0列的伸缩因子为0不伸缩
std::vector<std::string > menuItems = {"系统总览", "运行监控", "统计分析", "系统管理"};
for (auto& name: menuItems)
{
int row = ui.vecMenuItems.size() + 1;
auto itemBtn = std::make_shared<QPushButton>(ui.widgetMenu.get());
ui.vecMenuItems.push_back(itemBtn);
itemBtn->setText(name.c_str());
itemBtn->setStyleSheet(QSS_BTN_MENU.c_str());
if (!ui.curActiveMenuBtn)
{
ui.curActiveMenuBtn = itemBtn;
ui.curActiveMenuBtn->setStyleSheet(QSS_BTN_MENU_ACTIVE.c_str());
}
connect(itemBtn.get(), &QPushButton::clicked, this, [=]()
{
if (ui.curActiveMenuBtn == itemBtn) { return; }
if (ui.curActiveMenuBtn) { ui.curActiveMenuBtn->setStyleSheet(QSS_BTN_MENU.c_str()); }
ui.curActiveMenuBtn = itemBtn;
if (ui.curActiveMenuBtn)
{
ui.curActiveMenuBtn->setStyleSheet(QSS_BTN_MENU_ACTIVE.c_str());
this->onActiveMenu(name);
}
});
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
itemBtn->setSizePolicy(sizePolicy);
ui.layoutMenu->addWidget(itemBtn.get(), row, 0, 1, 1);
// 设置列宽和行高
ui.layoutMenu->setRowMinimumHeight(row, 50); // 设置第0列的最小宽度为100像素
// 设置列和行的伸缩因子
ui.layoutMenu->setRowStretch(row, 0); // 设置第0列的伸缩因子为0不伸缩
ui.layoutMenu->setRowStretch(row+1, 2); // 设置第1列的伸缩因子为2使其更宽
}
ui.widgetMenu->show();
std::vector<std::string > menuItems = {"系统总览", "运行监控", "统计分析", "系统管理"};
for (int i=0; i< menuItems.size(); ++i)
{
auto itemBtn = this->addMenuItem(i + 1, menuItems[i]);
}
widgetMenu->show();
}
void MainApp::setActiveMenu(string menuName)
{
auto iter = mapMenuBtn.find(menuName);
if (iter == mapMenuBtn.end()) return;
auto itemBtn = iter->second;
if (curActiveMenuBtn == itemBtn) { return; }
if (curActiveMenuBtn) { curActiveMenuBtn->setStyleSheet(QSS_BTN_MENU.c_str()); }
curActiveMenuBtn = itemBtn;
if (curActiveMenuBtn)
{
curActiveMenuBtn->setStyleSheet(QSS_BTN_MENU_ACTIVE.c_str());
std::shared_ptr<MyWidget> widget = getWorkWidget(menuName);
if (widget == curActiveWidget) { return; }
if (curActiveWidget)
{
curActiveWidget->hide();
}
if (widget)
{
widget->setParent(widgetWorkspace.get());
widget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
widget->show();
}
curActiveWidget = widget;
}
}
void MainApp::setMyLayout()
{
layoutMain = new QGridLayout(this);
layoutMain->setObjectName(QString::fromUtf8("layout.main"));
layoutMain->setSpacing(6);
layoutMain->setContentsMargins(11, 11, 11, 11);
//// 设置间距和边距
//layout->setHorizontalSpacing(10); // 设置列间距为10像素
//layout->setVerticalSpacing(10); // 设置行间距为10像素
//layout->setContentsMargins(10, 10, 10, 10); // 设置内容边距为10像素
// 布局左侧菜单widget
widgetMenu->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
layoutMain->addWidget(widgetMenu.get(), 0, 0, 1, 1);
// 布局右侧工作区widget
widgetWorkspace->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
layoutMain->addWidget(widgetWorkspace.get(), 0, 1, 1, 1);
layout.main = std::make_shared<QGridLayout>(this);
// 设置列宽和行高
layoutMain->setColumnMinimumWidth(0, 200); // 设置第0列的最小宽度为100像素
//gridLayout->setRowMinimumHeight(0, 200); // 设置第0行的最小高度为50像素
layout.main->setObjectName(QString::fromUtf8("layout.main"));
layout.main->setSpacing(6);
layout.main->setContentsMargins(11, 11, 11, 11);
//// 设置间距和边距
//layout->setHorizontalSpacing(10); // 设置列间距为10像素
//layout->setVerticalSpacing(10); // 设置行间距为10像素
//layout->setContentsMargins(10, 10, 10, 10); // 设置内容边距为10像素
// 布局左侧菜单widget
ui.widgetMenu->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
layout.main->addWidget(ui.widgetMenu.get(), 0, 0, 1, 1);
// 布局右侧工作区widget
ui.widgetWorkspace->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
layout.main->addWidget(ui.widgetWorkspace.get(), 0, 1, 1, 1);
// 设置列宽和行高
layout.main->setColumnMinimumWidth(0, 200); // 设置第0列的最小宽度为100像素
//gridLayout->setRowMinimumHeight(0, 200); // 设置第0行的最小高度为50像素
// 设置列和行的伸缩因子
layout.main->setColumnStretch(0, 0); // 设置第0列的伸缩因子为0不伸缩
layout.main->setColumnStretch(1, 2); // 设置第1列的伸缩因子为2使其更宽
//gridLayout->setRowStretch(0, 1); // 设置第0行的伸缩因子为1
// 设置列和行的伸缩因子
layoutMain->setColumnStretch(0, 0); // 设置第0列的伸缩因子为0不伸缩
layoutMain->setColumnStretch(1, 2); // 设置第1列的伸缩因子为2使其更宽
}
std::shared_ptr<MyWidget> MainApp::getWorkWidget(std::string name)
{
auto iter = ui.mapWorkWidgets.find(name);
if (iter != ui.mapWorkWidgets.end())
{
return iter->second;
}
std::shared_ptr<MyWidget> widget {nullptr};
if (name == "系统总览") { widget = make_shared<QWHome>(nullptr); }
else if(name == "运行监控") { widget = make_shared<QWMonitor>(nullptr); }
else if (name == "统计分析") { widget = make_shared<QWStatistics>(nullptr); }
//else if (name == "预测管理") { widget = make_shared<QWPredict(nullptr); }
else if (name == "系统管理") { widget = make_shared<QWSysmgr>(nullptr); }
if (widget) { ui.mapWorkWidgets[name] = widget; }
return widget;
}
void MainApp::onActiveMenu(std::string name)
{
std::shared_ptr<MyWidget> widget = getWorkWidget(name);
if (widget == ui.curActiveWidget) { return; }
if (ui.curActiveWidget)
{
ui.curActiveWidget->hide();
}
if (widget)
{
widget->setParent(ui.widgetWorkspace.get());
widget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
widget->show();
//layout.main->replaceWidget(ui.curActiveWidget.get(), widget.get());
}
ui.curActiveWidget = widget;
auto iter = mapWorkWidgets.find(name);
if (iter != mapWorkWidgets.end())
{
return iter->second;
}
std::shared_ptr<MyWidget> widget {nullptr};
if (name == "系统总览") { widget = make_shared<QWHome>(nullptr); }
else if(name == "运行监控") { widget = make_shared<QWMonitor>(nullptr); }
else if (name == "统计分析") { widget = make_shared<QWStatistics>(nullptr); }
//else if (name == "预测管理") { widget = make_shared<QWPredict(nullptr); }
else if (name == "系统管理") { widget = make_shared<QWSysmgr>(nullptr); }
if (widget) { mapWorkWidgets[name] = widget; }
return widget;
}
void MainApp::setWorkspaceWidget(std::shared_ptr<MyWidget> widget)
{
}
void MainApp::setLabelDateTime()
{
string curDateTime = Utils::timeStr();
curDateTime[10] = '\n';
labelDT->setText(curDateTime.c_str());
}
void MainApp::onTimer()
{
ui.labelDT->setText(Utils::timeStr().c_str());
if (ui.curActiveWidget && ui.curActiveWidget->isVisible())
{
ui.curActiveWidget->onTimer();
}
this->setLabelDateTime();
if (curActiveWidget && curActiveWidget->isVisible())
{
curActiveWidget->onTimer();
}
}

View File

@@ -23,34 +23,44 @@ class MainApp : public QWidget
Q_OBJECT
public:
MainApp();
~MainApp();
void initMenu();
QPushButton* addMenuItem(int index, string itemName);
void setActiveMenu(string menuName);
void setMyLayout();
std::shared_ptr<MyWidget> getWorkWidget(std::string name);
void onActiveMenu(std::string name);
void setWorkspaceWidget(std::shared_ptr<MyWidget> widget);
void setLabelDateTime();
private slots:
void onTimer();
public:
struct {
std::shared_ptr<LabelPair> weburl {};
// 主窗口的布局
QGridLayout* layoutMain{};
std::shared_ptr<QLabel> labelDT {};
std::shared_ptr<QWidget> widgetMenu;
std::vector<std::shared_ptr<QPushButton>> vecMenuItems;
std::shared_ptr<QGridLayout> layoutMenu;
std::shared_ptr<QPushButton> curActiveMenuBtn;
// 菜单窗口
std::shared_ptr<QWidget> widgetMenu;
// 菜单窗口的布局
QGridLayout* layoutMenu{ 0 };
// 菜单按钮
map<string, QPushButton*> mapMenuBtn;
// 当前处于激活状态的菜单按钮
QPushButton* curActiveMenuBtn{};
std::shared_ptr<QWidget> widgetWorkspace;
std::shared_ptr<MyWidget> curActiveWidget = nullptr;
std::map<std::string, std::shared_ptr<MyWidget>> mapWorkWidgets;
} ui;
// 工作区窗口
std::shared_ptr<QWidget> widgetWorkspace;
// 工作区已经创建的所有窗口
std::map<std::string, std::shared_ptr<MyWidget>> mapWorkWidgets;
// 工作区当前显示的窗口
std::shared_ptr<MyWidget> curActiveWidget = nullptr;
// 时间标签控件
QLabel* labelDT{};
struct {
std::shared_ptr<QGridLayout> main;
} layout;
std::shared_ptr<QTimer> timer;
};

View File

@@ -4,8 +4,8 @@
#include <QCoreApplication>
#include <QLabel>
#include <QThread>
#include <QWebEngineSettings>
#include <QWebEngineProfile>
//#include <QWebEngineSettings>
//#include <QWebEngineProfile>
#include <QAction>
#include <QToolBar>
#include <QMouseEvent>
@@ -90,41 +90,41 @@ void MainWeb::initWebview()
labelWebErr.hide();
this->setCentralWidget(&webView);
webView.setParent(this);
webView.setGeometry(0, 0, 1920, 1080);
//this->setCentralWidget(&webView);
//webView.setParent(this);
//webView.setGeometry(0, 0, 1920, 1080);
// 在加载页面之前清除缓存
//QWebEngineProfile::defaultProfile()->clearHttpCache();
//QWebEngineSettings* settings = webView.settings();
//settings->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
//settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
//settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); // 解决http资源加载问题
//settings->setAttribute(QWebEngineSettings::PluginsEnabled, true);
// 默认设置透明, 解决加载时的白屏闪烁
//webView.page()->setBackgroundColor(Qt::transparent);
//webView.setContextMenuPolicy(Qt::NoContextMenu);
webView.load(QUrl(Config::option.webSrvUrl.c_str()));
webView.hide();
//// 在加载页面之前清除缓存
////QWebEngineProfile::defaultProfile()->clearHttpCache();
////QWebEngineSettings* settings = webView.settings();
////settings->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
////settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
////settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); // 解决http资源加载问题
////settings->setAttribute(QWebEngineSettings::PluginsEnabled, true);
//// 默认设置透明, 解决加载时的白屏闪烁
////webView.page()->setBackgroundColor(Qt::transparent);
////webView.setContextMenuPolicy(Qt::NoContextMenu);
//webView.load(QUrl(Config::option.webSrvUrl.c_str()));
//webView.hide();
// 将主 Web 页面的开发者工具页面设置为 devToolsView 的页面
//qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "9222"); // 即使内置视图,有时也需要开启调试端口
//webView.page()->setDevToolsPage(devTools.page());
//// 将主 Web 页面的开发者工具页面设置为 devToolsView 的页面
////qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "9222"); // 即使内置视图,有时也需要开启调试端口
////webView.page()->setDevToolsPage(devTools.page());
QObject::connect(&webView, &QWebEngineView::loadFinished, [=](bool ok)
{
if (ok)
{
webView.show();
labelWebErr.hide();
}
else
{
spdlog::error("[web] webview load failed, url={}", Config::option.webSrvUrl);
webView.hide();
labelWebErr.show();
}
});
//QObject::connect(&webView, &QWebEngineView::loadFinished, [=](bool ok)
// {
// if (ok)
// {
// webView.show();
// labelWebErr.hide();
// }
// else
// {
// spdlog::error("[web] webview load failed, url={}", Config::option.webSrvUrl);
// webView.hide();
// labelWebErr.show();
// }
// });
}
void MainWeb::mySplash()
{
@@ -175,21 +175,21 @@ void MainWeb::showDevTools()
else
{
qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "9222"); // 即使内置视图,有时也需要开启调试端口
webView.page()->setDevToolsPage(devTools.page());
//webView.page()->setDevToolsPage(devTools.page());
QWidget* w = new QWidget;
w->resize(800, 900);
devTools.setParent(w);
devTools.resize(800, 900);
w->show();
//QWidget* w = new QWidget;
//w->resize(800, 900);
//devTools.setParent(w);
//devTools.resize(800, 900);
//w->show();
// 如果你需要先导航主页面,然后在某个事件(如按钮点击)后显示开发者工具,可以将这行代码放在事件处理函数中。
layout = new QHBoxLayout(this);
// 将两个视图添加到布局中
layout->addWidget(&webView);
layout->addWidget(&devTools);
layout->setStretch(0, 2); // 主视图占2份
layout->setStretch(1, 1); // 开发者工具视图占1份
//// 如果你需要先导航主页面,然后在某个事件(如按钮点击)后显示开发者工具,可以将这行代码放在事件处理函数中。
//layout = new QHBoxLayout(this);
//// 将两个视图添加到布局中
//layout->addWidget(&webView);
//layout->addWidget(&devTools);
//layout->setStretch(0, 2); // 主视图占2份
//layout->setStretch(1, 1); // 开发者工具视图占1份
}
}
@@ -216,7 +216,7 @@ void MainWeb::keyPressEvent(QKeyEvent* e)
}
else if (key == Qt::Key_F5)
{
webView.update();
//webView.update();
//webView.load(QUrl(Config::option.webSrvUrl.c_str()));
}
}

View File

@@ -1,5 +1,5 @@
#include <QMainWindow>
#include <QtWebEngineWidgets/QWebEngineView>
#include <QtWebEngineWidgets>
#include <QSplashScreen>
#include <QLabel>
#include <QPushButton>
@@ -20,8 +20,8 @@ public:
public:
QLabel labelWebErr;
QWebEngineView webView;
QWebEngineView devTools;
//QWebEngineView webView;
//QWebEngineView devTools;

View File

@@ -10,30 +10,33 @@ static const std::string QSS_BTN =
"QPushButton:pressed {border-width:2px 0 0 2px;border-style:inset;}";
static const std::string QSS_BTN_ACTIVE =
"QPushButton {background:rgba(80, 80, 80,80);border-radius:5px;border:1px solid green;color:green;font:bold 15px;}";
"QPushButton {background:rgba(180,180,180,50);border-radius:2px;border:1px solid rgb(50,200,50);color:rgb(50,200,50);font:bold 15px;}";
static const std::string QSS_BTN_MENU =
"QPushButton {background:rgba(19, 35, 71,200);color:white;border-radius:5px;border:2px solid rgb(10,120,215);font:bold 18px;}"
"QPushButton {background:rgba(180,180,180,50);color:white;border-radius:5px;border:1px solid gray;font:bold 18px;}"
"QPushButton:hover {background-color:rgb(32,164,128);}"
"QPushButton:pressed {border-width:3px 0 0 3px;border-style:inset;}"
"QPushButton:disabled {color:rgb(150,150,150);}";
static const std::string QSS_BTN_MENU_ACTIVE =
"QPushButton {background:rgba(32,164,128, 200);color:white;border-radius:5px;border:2px solid rgb(10,120,215);font:bold 18px;}"
"QPushButton {background:rgba(32,164,128, 200);color:white;border-radius:5px;border:1px solid gray;font:bold 18px;}"
"QPushButton:hover {background-color:rgb(32,164,128);}"
"QPushButton:pressed {border-width:3px 0 0 3px;border-style:inset;}"
"QPushButton:disabled {color:rgb(150,150,150);}";
static const std::string QSS_BTN_TAB =
"QPushButton {background:rgba(80,80,80,100);color:white;border-radius:3px;border:1px solid rgb(10,120,215);}"
"QPushButton {background:rgba(180,180,180,100);color:white;border-radius:3px;border:1px solid rgb(10,120,215);}"
"QPushButton:hover {background-color:rgba(80,80,80,200);}";
//"QPushButton:pressed {border-width:3px 0 0 3px;border-style:inset;}"
//"QPushButton:disabled {color:rgb(150,150,150);}";
static const std::string QSS_LINE =
"QLineEdit { background-color:rgba(180,180,180,36); color:#ffffff; border:1px solid gray; border-radius:3px; font:bold 13px; }"; //14, 49, 66
"QLineEdit { background-color:rgba(180,180,180,10); color:#ffffff; border:1px solid gray; border-radius:3px; font:bold 13px; }"
"QLineEdit:read-only{ background-color:rgba(180,180,180,80); color:rgb(180,180,180); }";
static const std::string QSS_TABLE = // 表格整体样式
static const std::string QSS_TABLE =
// 表格整体样式
"QTableWidget {"
" background-color: transparent;" // 背景色
" gridline-color: #C0C0C0;" // 网格线颜色
@@ -41,12 +44,12 @@ static const std::string QSS_TABLE = // 表格整体样式
" color: white;" // 文字颜色
"}"
// 表头样式
"QHeaderView { background-color: rgba(150,150,150,50); }"
"QHeaderView { background-color: rgba(150,150,150,50);}"
"QHeaderView::section {"
" background-color: rgba(120,120,120,0);" // 表头背景
" padding: 4px;" // 内边距
" border: 1px solid #505050;" // 边框
" min-height: 25px;" // 最小高度
" padding: 4px;" // 内边距
" border: 1px solid gray;" // 边框
" min-height: 25px;" // 最小高度
"}"
// 单元格样式
"QTableWidget::item {"
@@ -55,13 +58,17 @@ static const std::string QSS_TABLE = // 表格整体样式
"}"
// 选中状态
"QTableWidget::item:selected {"
" background-color: rgba(184, 214, 255, 50);" // 选中背景色
" color: rgb(220,220,220);" // 选中文字颜色
" background-color: rgba(184, 214, 255, 50);" // 选中背景色
" color: rgb(220,220,220);" // 选中文字颜色
" outline: none; "
"}";
static const std::string QSS_BTN_COMBOX =
"QComboBox { background-color: transparent; border: 1px solid rgb(18, 251, 255)}"
"QListView::item { background-color: rgba(80,80,80,200); color: white; padding-left: 10px; }";
"QComboBox { background-color: transparent; border: 1px solid rgb(180,180,180); padding-left: 5px; }"
"QComboBox QAbstractItemView { background-color: rgb(60, 80, 120); border: 2px solid #ff0000; padding: 2px; outline: none; }"
"QComboBox QAbstractItemView::item { min-height: 20px; padding: 5px 10px; margin:1px 1px 1px 1px; }"
"QComboBox QAbstractItemView::item:hover { background-color: rgb(220, 220, 220); color: rgb(31, 139, 117); }";
MyWidget::MyWidget(QWidget* parent) : QWidget(parent)
{
@@ -72,6 +79,15 @@ MyWidget::MyWidget(QWidget* parent) : QWidget(parent)
setAutoFillBackground(true);
}
shared_ptr<QWidget> MyQUI::Widget(QWidget* parent, string objectName, string qss)
{
auto widget = std::make_shared<QWidget>(parent);
widget->setObjectName(objectName.c_str());
widget->setStyleSheet(("#" + objectName + " {"+ qss + "}").c_str());
return widget;
}
shared_ptr<QPushButton> MyQUI::Button(QWidget* parent, int x, int y, int w, int h, std::string title)
{
auto btn = std::make_shared<QPushButton>(title.c_str(), parent);
@@ -116,7 +132,7 @@ std::shared_ptr<QTableWidget> MyQUI::TableWidget(QWidget* parent, int x, int y,
return table;
}
void MyQUI::setTableCell(std::shared_ptr<QTableWidget> table, int row, int col, std::string text, std::string style /*= ""*/)
void MyQUI::setTableCellText(std::shared_ptr<QTableWidget> table, int row, int col, std::string text, std::string style /*= ""*/)
{
if (row >= table->rowCount())
{
@@ -132,4 +148,20 @@ void MyQUI::setTableCell(std::shared_ptr<QTableWidget> table, int row, int col,
if (style == "OK") { item->setForeground(QBrush(Qt::green)); }
else if (style == "ERR") { item->setForeground(QBrush(Qt::red)); }
else if (style == "WARN") { item->setForeground(QBrush(Qt::cyan)); }
}
void MyQUI::setTableCellButton(std::shared_ptr<QTableWidget> table, int row, int col, const vector<string>& items, QObject* obj, std::function<void(string name)> cb)
{
if (row >= table->rowCount()) { table->insertRow(row); }
QWidget* cellWidget = new QWidget();
for (int i=0; i<items.size(); ++i)
{
string itemName = items[i];
QPushButton* btn = new QPushButton(itemName.c_str(), cellWidget);
btn->setGeometry(i*60, 3, 50, 24);
btn->setStyleSheet(QSS_BTN_TAB.c_str());
QObject::connect(btn, &QPushButton::clicked, obj, [=]() { if (cb) cb(itemName); });
}
table->setCellWidget(row, col, cellWidget);
}

View File

@@ -2,7 +2,6 @@
#include <QGroupBox>
#include <QMainWindow>
#include <QtWebEngineWidgets/QWebEngineView>
#include <QSplashScreen>
#include <QLabel>
#include <QPushButton>
@@ -10,18 +9,14 @@
#include <QTextEdit>
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>
#include <QComboBox>
#include <QGridLayout>
#include <QLineEdit>
#include <QWidget>
#include <QPalette>
#include <QGroupBox>
#include <QTableWidget>
#include <QHeaderView>
#include <QHBoxLayout>
#include <QTableWidget>
#include <QDialog>
#include <memory>
#include <string>
@@ -29,17 +24,17 @@
#include <map>
using namespace std;
extern const std::string QSS_GROUP;
extern const string QSS_GROUP;
extern const std::string QSS_BTN;
extern const std::string QSS_BTN_ACTIVE;
extern const std::string QSS_BTN_MENU;
extern const std::string QSS_BTN_MENU_ACTIVE;
extern const std::string QSS_BTN_TAB;
extern const std::string QSS_LINE;
extern const string QSS_BTN;
extern const string QSS_BTN_ACTIVE;
extern const string QSS_BTN_MENU;
extern const string QSS_BTN_MENU_ACTIVE;
extern const string QSS_BTN_TAB;
extern const string QSS_LINE;
extern const std::string QSS_TABLE;
extern const std::string QSS_BTN_COMBOX;
extern const string QSS_TABLE;
extern const string QSS_BTN_COMBOX;
class LabelPair
{
@@ -54,12 +49,12 @@ public:
value.show();
}
void setTitle(std::string text)
void setTitle(string text)
{
title.setText(text.c_str());
}
void setValue(std::string text)
void setValue(string text)
{
value.setText(text.c_str());
}
@@ -81,15 +76,18 @@ using MyPairLabelLine = pair<shared_ptr<QLabel>, shared_ptr<QLineEdit>>;
class MyQUI
{
public:
static shared_ptr<QPushButton> Button(QWidget* parent, int x, int y, int w, int h, std::string title);
static shared_ptr<QWidget> Widget(QWidget* parent, string objectName, string qss);
static shared_ptr<QPushButton> Button(QWidget* parent, int x, int y, int w, int h, string title);
static shared_ptr<QGroupBox> GroupBox(QWidget* parent, int x, int y, int w, int h, std::string title);
static shared_ptr<QGroupBox> GroupBox(QWidget* parent, int x, int y, int w, int h, string title);
static MyPairLabelLine PairLine(QWidget* parent, int x, int y, string k, string v, bool readonly=true);
static std::shared_ptr<QTableWidget> TableWidget(QWidget* parent, int x, int y, int w, int h);
static shared_ptr<QTableWidget> TableWidget(QWidget* parent, int x, int y, int w, int h);
static void setTableCell(std::shared_ptr<QTableWidget> table, int row, int col, std::string text, std::string style = "");
static void setTableCellText(shared_ptr<QTableWidget> table, int row, int col, string text, string style = "");
static void setTableCellButton(shared_ptr<QTableWidget> table, int row, int col, const vector<string>& items, QObject* obj, function<void(string)> cb);
};

View File

@@ -59,7 +59,7 @@ private:
bool mHover {0};
QColor mButtonColor {Qt::white}; //开关(圆形按钮)颜色
QColor mBackColor {Qt::red};
QColor mBackColor {Qt::darkRed};
QColor mEdgeColor {Qt::transparent}; //边缘颜色
QRectF mButtonRect; //开关按钮rect
int mRadius {8}; // 开关外观边缘圆角
@@ -67,7 +67,7 @@ private:
int mAnimationPeriod {200}; //动画周期
QPointF mRightPos; // 动画位置-开
QPointF mLeftPos; // 动画位置-关
QColor mBackOnColor {Qt::green}; //背景颜色-开
QColor mBackOnColor {Qt::darkGreen}; //背景颜色-开
QColor mBackOffColor {Qt::darkGray}; //背景颜色-关
};

View File

@@ -0,0 +1,100 @@
#include "DialogPop.h"
DialogPop::DialogPop(QWidget* parent, const Fields& rowdata, string oper)
: QDialog(parent), originData(rowdata), oper(oper)
{
// 设置背景色
QPalette palette(this->palette());
palette.setColor(QPalette::Window, QColor(36, 56, 90));
this->setAutoFillBackground(true);
this->setPalette(palette);
this->setStyleSheet("color: white;");
vecWidgetParams.reserve(20);
btnOk.setParent(this);
btnOk.setText("确 定");
btnOk.setStyleSheet(QSS_BTN.c_str());
btnCancel.setParent(this);
btnCancel.setText("取 消");
btnCancel.setStyleSheet(QSS_BTN.c_str());
QObject::connect(&btnOk, &QPushButton::clicked, this, &DialogPop::slotBtnAccept);
QObject::connect(&btnCancel, &QPushButton::clicked, this, &DialogPop::reject);
this->setFixedSize(500, 500);
}
void DialogPop::addParam(string key, string title, shared_ptr<QWidget> widget)
{
auto label = make_shared<QLabel>(title.c_str(), this);
int n = vecWidgetParams.size();
vecWidgetParams.push_back({ label, widget });
int y = 60 + 40 * n;
label->setGeometry(60, y, 80, 30);
widget->setGeometry(140, y, 280, 30);
widget->setObjectName(key.c_str());
}
void DialogPop::addParamLine(string key, string title, bool readlonly /*= false*/)
{
auto lineedit = make_shared<QLineEdit>(this);
lineedit->setStyleSheet(QSS_LINE.c_str());
lineedit->setText(originData.value(key).c_str());
if (readlonly) { lineedit->setReadOnly(true); }
this->addParam(key, title, lineedit);
QObject::connect(lineedit.get(), &QLineEdit::textChanged, this, &DialogPop::slotLineTextChanged);
}
void DialogPop::addParamCombox(string key, string title, const vector<pair<string, string>>& mapping)
{
auto combox = make_shared<QComboBox>(this);
combox->setStyleSheet(QSS_BTN_COMBOX.c_str());
this->addParam(key, title, combox);
string val = originData.value(key);
for (int i = 0; i < mapping.size(); ++i)
{
auto& item = mapping[i];
combox->insertItem(i, item.second.c_str());
combox->setItemData(i, item.first.c_str());
if (val == item.first) combox->setCurrentText(item.second.c_str());
}
QObject::connect(combox.get(), &QComboBox::currentIndexChanged, this, &DialogPop::slotComboxIndexChanged);
}
void DialogPop::slotLineTextChanged(const QString& s)
{
auto lineedit = dynamic_cast<QLineEdit*>(sender());
string key = lineedit->objectName().toStdString();
curData.set(key, s.toStdString());
}
void DialogPop::slotComboxIndexChanged(int index)
{
auto combox = dynamic_cast<QComboBox*>(sender());
string key = combox->objectName().toStdString();
string val = combox->itemData(index).toString().toStdString();
curData.set(key, val);
}
void DialogPop::slotBtnAccept()
{
this->onAccept();
this->accept();
}
void DialogPop::slotBtnReject()
{
}
void DialogPop::resizeEvent(QResizeEvent* e)
{
int w = 100, offset = 30;
int x = e->size().width() * 0.5 - w - offset;
int y = e->size().height() - 80;
btnOk.setGeometry(x, y, w, 40);
btnCancel.setGeometry(x + w + offset*2, y, w, 40);
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "qt/MyQUI.h"
#include <QResizeEvent>
#include "common/Fields.h"
class DialogPop : public QDialog
{
public:
DialogPop(QWidget* parent, const Fields& rowdata, string oper);
virtual void initBody() {};
void addParamLine(string key, string title, bool readlonly = false);
void addParamCombox(string key, string title, const vector<pair<string, string>>& mapping);
virtual void onAccept() {};
public:
string oper;
Fields originData;
Fields curData;
std::vector<pair<shared_ptr<QLabel>, shared_ptr<QWidget>>> vecWidgetParams;
QPushButton btnOk;
QPushButton btnCancel;
std::map<string, vector<pair<string, string>>> mapMapping;
private:
void addParam(string key, string title, shared_ptr<QWidget> widget);
void slotLineTextChanged(const QString&);
void slotComboxIndexChanged(int index);
void slotBtnAccept();
void slotBtnReject();
void resizeEvent(QResizeEvent*) override;
};

View File

@@ -11,159 +11,158 @@
QWHome::QWHome(QWidget* parent) : MyWidget(parent)
{
this->setObjectName("home");
this->setStyleSheet("#home { background-color:rgba(100,100,100,50); }");
this->setObjectName("home");
this->setStyleSheet("#home { background-color:rgba(100,100,100,50); }");
int x = 10, y = 0;
{
//this->groupSys = MyQUI::GroupBox(this, x, y, 1190, 120, "系统");
//auto pw = groupSys.get();
}
{
x = 10;
this->groupHttp = MyQUI::GroupBox(this, x, y, 390, 200, "HTTP");
auto pw = groupHttp.get();
this->addPair("http-t", pw, 20, 20, "服务类型: ", "服务端");
this->addPair("http-p", pw, 20, 50, "服务端口: ", Utils::toStr(Config::option.http.port));
this->addPair("http-s", pw, 20, 80, "服务状态: ", "运行");
int x = 10, y = 0;
{
//this->groupSys = MyQUI::GroupBox(this, x, y, 1190, 120, "系统");
//auto pw = groupSys.get();
}
{
x = 10;
this->groupHttp = MyQUI::GroupBox(this, x, y, 390, 200, "HTTP");
auto pw = groupHttp.get();
this->addPair("http-t", pw, 20, 20, "服务类型: ", "服务端");
this->addPair("http-p", pw, 20, 50, "服务端口: ", Utils::toStr(Config::option.http.port));
this->addPair("http-s", pw, 20, 80, "服务状态: ", "运行");
QWSwitch* switchBtn = new QWSwitch(this);
switchBtn->setGeometry(30, 110, 50, 20);
}
{
x += 400;
this->groupMqtt = MyQUI::GroupBox(this, x, y, 390, 200, "MQTT");
auto pw = groupMqtt.get();
this->addPair("mqtt-t", pw, 20, 20, "服务类型: ", "客户端");
this->addPair("mqtt-h", pw, 20, 50, "服务地址: ", Config::option.mqtt.host);
this->addPair("mqtt-s", pw, 20, 80, "服务状态: ", "---");
}
{
x += 400;
this->groupDB = MyQUI::GroupBox(this, x, y, 390, 200, "数据库");
auto pw = groupDB.get();
this->addPair("db-n", pw, 20, 20, "数据库名: ", Config::option.database.dbname);
this->addPair("db-h", pw, 20, 50, "主机地址: ", Config::option.database.host);
this->addPair("db-u", pw, 20, 80, "用 户 名: ", Config::option.database.user);
QWSwitch* switchBtn = new QWSwitch(this);
switchBtn->setGeometry(30, 110, 50, 20);
}
{
x += 400;
this->groupMqtt = MyQUI::GroupBox(this, x, y, 390, 200, "MQTT");
auto pw = groupMqtt.get();
this->addPair("mqtt-t", pw, 20, 20, "服务类型: ", "客户端");
this->addPair("mqtt-h", pw, 20, 50, "服务地址: ", Config::option.mqtt.host);
this->addPair("mqtt-s", pw, 20, 80, "服务状态: ", "---");
}
{
x += 400;
this->groupDB = MyQUI::GroupBox(this, x, y, 390, 200, "数据库");
auto pw = groupDB.get();
this->addPair("db-n", pw, 20, 20, "数据库名: ", Config::option.database.dbname);
this->addPair("db-h", pw, 20, 50, "主机地址: ", Config::option.database.host);
this->addPair("db-u", pw, 20, 80, "用 户 名: ", Config::option.database.user);
QStringList headerTextList;
headerTextList << "ID" << "站名" << "编号" << "状态" << "MQTT状态" << "召测(秒)"
<< "日充电\n电量" << "日放电\n电量" << "总充电\n电量" << "总放电\n电量"
<< "日充电\n费用" << "日放电\n费用" << "总充电\n费用" << "总放电\n费用"
<< "日收益" << "总收益" << "--";
QStringList headerTextList;
headerTextList << "ID" << "站名" << "编号" << "状态" << "MQTT状态" << "召测(秒)"
<< "日充电\n电量" << "日放电\n电量" << "总充电\n电量" << "总放电\n电量"
<< "日充电\n费用" << "日放电\n费用" << "总充电\n费用" << "总放电\n费用"
<< "日收益" << "总收益" << "--";
table = MyQUI::TableWidget(this, 10, y += 210, 1190, 265);
// 设置为水平表头
table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList);
table->setColumnWidth(0, 50);
table->setColumnWidth(1, 120);
table->setColumnWidth(2, 50);
table->setColumnWidth(4, 80);
}
table = MyQUI::TableWidget(this, 10, y += 210, 1190, 265);
// 设置为水平表头
table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList);
table->setColumnWidth(0, 50);
table->setColumnWidth(1, 120);
table->setColumnWidth(2, 50);
table->setColumnWidth(4, 80);
}
logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false);
btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除");
connect(btnLogClean.get(), &QPushButton::clicked, this, [=]() { texteditLog->clear(); });
logFilter = MyQUI::PairLine(this, 10, y += 280, "日志过滤: ", "", false);
btnLogClean = MyQUI::Button(this, 400, y-1, 80, 28, "清除");
QObject::connect(btnLogClean.get(), &QPushButton::clicked, this, &QWHome::slotBtnClearLog);
texteditLog = std::make_shared<QTextEdit>(this);
texteditLog->setGeometry(10, y += 35, 1190, 280);
texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;");
texteditLog->setReadOnly(true);
texteditLog->document()->setMaximumBlockCount(1000);
texteditLog = std::make_shared<QTextEdit>(this);
texteditLog->setGeometry(10, y += 35, 1190, 280);
texteditLog->setStyleSheet("background-color: transparent; border: 1px solid gray; font-weight: 400;");
texteditLog->setReadOnly(true);
texteditLog->document()->setMaximumBlockCount(1000);
{
////////////////////////////////////////////////////////////////////////////////////////
// QT显示spdlog: 方法一
// 第二个参数是方法函数名称,即调用 QTextEdit的appeng函数
//auto qtSink = std::make_shared<spdlog::sinks::qt_sink_mt>(textLog.get(), "append");
//spdlog::default_logger()->sinks().push_back(qtSink);
{
////////////////////////////////////////////////////////////////////////////////////////
// QT显示spdlog: 方法一
// 第二个参数是方法函数名称,即调用 QTextEdit的appeng函数
//auto qtSink = std::make_shared<spdlog::sinks::qt_sink_mt>(textLog.get(), "append");
//spdlog::default_logger()->sinks().push_back(qtSink);
////////////////////////////////////////////////////////////////////////////////////////
// QT显示spdlog: 方法二, 自定义实现 QtLogSink
myqtSink = std::make_shared<QtLogSink>(this);
spdlog::default_logger()->sinks().push_back(myqtSink);
//auto logger = std::make_shared<spdlog::logger>("custom_logger", myqtSink);
//spdlog::register_logger(logger);
////////////////////////////////////////////////////////////////////////////////////////
// QT显示spdlog: 方法二, 自定义实现 QtLogSink
auto myqtSink = std::make_shared<QtLogSink>();
spdlog::default_logger()->sinks().push_back(myqtSink);
// 连接信号和槽使用Qt::QueuedConnection确保线程安全
connect(myqtSink.get(), &QtLogSink::logMessageReceived, this, &QWHome::onLogMessageReceived, Qt::QueuedConnection);
}
// 连接信号和槽使用Qt::QueuedConnection确保线程安全
QObject::connect(myqtSink.get(), &QtLogSink::logMessageReceived, this, &QWHome::onLogMessageReceived, Qt::QueuedConnection);
}
}
QWHome::~QWHome()
{
table->clear();
mapPairs.clear();
table->clear();
mapPairs.clear();
}
void QWHome::addPair(string name, QWidget* parent, int x, int y, string k, string v, bool readonly /*= true*/)
{
if (name.empty()) name = k;
mapPairs[name] = MyQUI::PairLine(parent, x, y, k, v);
if (name.empty()) name = k;
mapPairs[name] = MyQUI::PairLine(parent, x, y, k, v);
}
void QWHome::onTimer()
{
if (!this->isVisible()) { return; }
if (!this->isVisible()) { return; }
auto& appdata = Application().data();
int rowNo = 0;
int tsNow = Utils::time();
for (auto& item : appdata.mapStation)
{
auto& station = item.second;
if (rowNo >= table->rowCount())
{
table->insertRow(rowNo);
}
bool isOpen = station->status > 0;
bool isConnected = station->mqttCli->isConnected;
auto& appdata = Application().data();
int rowNo = 0;
int tsNow = Utils::time();
for (auto& item : appdata.mapStation)
{
auto& station = item.second;
if (rowNo >= table->rowCount())
{
table->insertRow(rowNo);
}
bool isOpen = station->status > 0;
bool isConnected = station->mqttCli->isConnected;
MyQUI::setTableCell(table, rowNo, 0, std::to_string(station->stationId));
MyQUI::setTableCell(table, rowNo, 1, station->name);
MyQUI::setTableCell(table, rowNo, 2, station->code);
MyQUI::setTableCell(table, rowNo, 3, isOpen ? "启用" : "未启用", isOpen ? "OK" : "ERR");
MyQUI::setTableCell(table, rowNo, 4, isConnected ? "连接成功" : "未连接", isConnected ? "OK" : "ERR");
MyQUI::setTableCellText(table, rowNo, 0, std::to_string(station->stationId));
MyQUI::setTableCellText(table, rowNo, 1, station->name);
MyQUI::setTableCellText(table, rowNo, 2, station->code);
MyQUI::setTableCellText(table, rowNo, 3, isOpen ? "启用" : "未启用", isOpen ? "OK" : "ERR");
MyQUI::setTableCellText(table, rowNo, 4, isConnected ? "连接成功" : "未连接", isConnected ? "OK" : "ERR");
int tsPolling = station->getPollingTS();
MyQUI::setTableCell(table, rowNo, 5, tsPolling > 0 ? std::to_string(tsNow - tsPolling) + "/" + std::to_string(Config::option.mqtt.interval) : "--");
MyQUI::setTableCell(table, rowNo, 6, Utils::toStr(station->statData.dayElectIn, 0));
MyQUI::setTableCell(table, rowNo, 7, Utils::toStr(station->statData.dayElectOut, 0));
MyQUI::setTableCell(table, rowNo, 8, Utils::toStr(station->statData.totalElectIn, 0));
MyQUI::setTableCell(table, rowNo, 9, Utils::toStr(station->statData.totalElectOut, 0));
MyQUI::setTableCell(table, rowNo, 10, Utils::toStr(station->statData.dayFeeIn, 0));
MyQUI::setTableCell(table, rowNo, 11, Utils::toStr(station->statData.dayFeeOut, 0));
MyQUI::setTableCell(table, rowNo, 12, Utils::toStr(station->statData.totalFeeIn, 0));
MyQUI::setTableCell(table, rowNo, 13, Utils::toStr(station->statData.totalFeeOut, 0));
MyQUI::setTableCell(table, rowNo, 14, Utils::toStr(station->statData.dayIncome, 0));
MyQUI::setTableCell(table, rowNo, 15, Utils::toStr(station->statData.totalIncome, 0));
MyQUI::setTableCell(table, rowNo, 16, station->statData.ts > 0 ? Utils::timeStr(station->statData.ts) : "--");
rowNo++;
}
int tsPolling = station->getPollingTS();
MyQUI::setTableCellText(table, rowNo, 5, tsPolling > 0 ? std::to_string(tsNow - tsPolling) + "/" + std::to_string(Config::option.mqtt.interval) : "--");
MyQUI::setTableCellText(table, rowNo, 6, Utils::toStr(station->statData.dayElectIn, 0));
MyQUI::setTableCellText(table, rowNo, 7, Utils::toStr(station->statData.dayElectOut, 0));
MyQUI::setTableCellText(table, rowNo, 8, Utils::toStr(station->statData.totalElectIn, 0));
MyQUI::setTableCellText(table, rowNo, 9, Utils::toStr(station->statData.totalElectOut, 0));
MyQUI::setTableCellText(table, rowNo, 10, Utils::toStr(station->statData.dayFeeIn, 0));
MyQUI::setTableCellText(table, rowNo, 11, Utils::toStr(station->statData.dayFeeOut, 0));
MyQUI::setTableCellText(table, rowNo, 12, Utils::toStr(station->statData.totalFeeIn, 0));
MyQUI::setTableCellText(table, rowNo, 13, Utils::toStr(station->statData.totalFeeOut, 0));
MyQUI::setTableCellText(table, rowNo, 14, Utils::toStr(station->statData.dayIncome, 0));
MyQUI::setTableCellText(table, rowNo, 15, Utils::toStr(station->statData.totalIncome, 0));
MyQUI::setTableCellText(table, rowNo, 16, station->statData.ts > 0 ? Utils::timeStr(station->statData.ts) : "--");
rowNo++;
}
}
void QWHome::onLogMessageReceived(const QString& message)
{
if (!this->isVisible()) { return; }
if (!this->isVisible()) { return; }
bool show = true;
if (logFilter.second)
{
auto filter = logFilter.second->text();
if (!filter.isEmpty() && !message.contains(filter))
{
show = false;
}
}
if (show)
{
texteditLog->append(message.trimmed());
}
bool show = true;
if (logFilter.second)
{
auto filter = logFilter.second->text();
if (!filter.isEmpty() && !message.contains(filter))
{
show = false;
}
}
if (show)
{
texteditLog->append(message.trimmed());
}
}
void QWHome::slotBtnClearLog()
{
texteditLog->clear();
}

View File

@@ -51,8 +51,10 @@ public:
std::shared_ptr<QTextEdit> texteditLog;
MyPairLabelLine logFilter {};
std::shared_ptr<QPushButton> btnLogClean;
std::shared_ptr<QtLogSink> myqtSink;
//std::shared_ptr<QtLogSink> myqtSink;
void onTimer() override;
void onLogMessageReceived(const QString& message);
void slotBtnClearLog();
};

View File

@@ -110,15 +110,15 @@ void QWMonitor::updateStation(shared_ptr<Station> station)
for (auto& iter : station->mapDevice)
{
auto& device = iter.second;
MyQUI::setTableCell(table, row, 0, Utils::toStr(device->deviceId));
MyQUI::setTableCell(table, row, 1, Utils::toStr(device->type));
MyQUI::setTableCell(table, row, 2, appdata.getDeviceNameById(device->type));
MyQUI::setTableCell(table, row, 3, device->name);
MyQUI::setTableCell(table, row, 4, device->code);
MyQUI::setTableCell(table, row, 5, device->isOpen ? "启用" : "未启用", device->isOpen ? "OK" : "ERR");
MyQUI::setTableCell(table, row, 6, device->online ? "在线" : "离线", device->online ? "OK" : "ERR");
MyQUI::setTableCell(table, row, 7, device->running ? "工作" : "空闲", device->running ? "OK" : "WARN");
MyQUI::setTableCell(table, row, 8, device->err ? "故障" : "正常", device->err ? "ERR" : "OK");
MyQUI::setTableCellText(table, row, 0, Utils::toStr(device->deviceId));
MyQUI::setTableCellText(table, row, 1, Utils::toStr(device->type));
MyQUI::setTableCellText(table, row, 2, appdata.getDeviceNameById(device->type));
MyQUI::setTableCellText(table, row, 3, device->name);
MyQUI::setTableCellText(table, row, 4, device->code);
MyQUI::setTableCellText(table, row, 5, device->isOpen ? "启用" : "未启用", device->isOpen ? "OK" : "ERR");
MyQUI::setTableCellText(table, row, 6, device->online ? "在线" : "离线", device->online ? "OK" : "ERR");
MyQUI::setTableCellText(table, row, 7, device->running ? "工作" : "空闲", device->running ? "OK" : "WARN");
MyQUI::setTableCellText(table, row, 8, device->err ? "故障" : "正常", device->err ? "ERR" : "OK");
++row;
}

View File

@@ -71,20 +71,20 @@ void QWStatistics::onCurrentIndexChanged(int index)
for (int i = 0; i<result.size(); ++i)
{
auto& fields = result[i];
MyQUI::setTableCell(table, i, 0, fields.value("dt"));
MyQUI::setTableCell(table, i, 1, fields.value("E_in"));
MyQUI::setTableCell(table, i, 2, fields.value("E_in_J"));
MyQUI::setTableCell(table, i, 3, fields.value("E_in_F"));
MyQUI::setTableCell(table, i, 4, fields.value("E_in_P"));
MyQUI::setTableCell(table, i, 5, fields.value("E_in_G"));
MyQUI::setTableCell(table, i, 6, fields.value("E_out"));
MyQUI::setTableCell(table, i, 7, fields.value("E_out_J"));
MyQUI::setTableCell(table, i, 8, fields.value("E_out_F"));
MyQUI::setTableCell(table, i, 9, fields.value("E_out_P"));
MyQUI::setTableCell(table, i, 10, fields.value("E_out_G"));
MyQUI::setTableCell(table, i, 11, fields.value("fee_in"));
MyQUI::setTableCell(table, i, 12, fields.value("fee_out"));
MyQUI::setTableCell(table, i, 13, fields.value("income"));
MyQUI::setTableCellText(table, i, 0, fields.value("dt"));
MyQUI::setTableCellText(table, i, 1, fields.value("E_in"));
MyQUI::setTableCellText(table, i, 2, fields.value("E_in_J"));
MyQUI::setTableCellText(table, i, 3, fields.value("E_in_F"));
MyQUI::setTableCellText(table, i, 4, fields.value("E_in_P"));
MyQUI::setTableCellText(table, i, 5, fields.value("E_in_G"));
MyQUI::setTableCellText(table, i, 6, fields.value("E_out"));
MyQUI::setTableCellText(table, i, 7, fields.value("E_out_J"));
MyQUI::setTableCellText(table, i, 8, fields.value("E_out_F"));
MyQUI::setTableCellText(table, i, 9, fields.value("E_out_P"));
MyQUI::setTableCellText(table, i, 10, fields.value("E_out_G"));
MyQUI::setTableCellText(table, i, 11, fields.value("fee_in"));
MyQUI::setTableCellText(table, i, 12, fields.value("fee_out"));
MyQUI::setTableCellText(table, i, 13, fields.value("income"));
}
}
}

View File

@@ -1,241 +1,388 @@
#include "QWSysmgr.h"
#include "common/Fields.h"
#include "DialogPop.h"
#include "database/DAO.h"
class TableInfo;
static map<string, TableInfo> s_mapInfo;
class TableInfo
{
public:
static void initialize()
{
{
auto& info = s_mapInfo["用户管理"];
info.addHead("user_id", "ID", 160);
info.addHead("account", "用户名", 0);
info.addHead("name", "姓名", 200);
info.addHead("gender", "性别", 0);
info.addHead("age", "年龄", 0);
info.addHead("phone", "联系方式", 0);
info.addHead("role_name", "角色", 200);
info.addHead("", "操作", 0);
info.sqlQuery = "SELECT u.*, ur.role_id, r.name role_name FROM USER u LEFT JOIN user_role ur ON u.user_id=ur.user_id LEFT JOIN ROLE r ON r.role_id=ur.role_id;";
}
{
auto& info = s_mapInfo["权限管理"];
info.addHead("permission_id", "ID", 60);
info.addHead("route", "路由", 160);
info.addHead("name", "权限名称", 0);
info.addHead("describe", "描述", 540);
info.addHead("is_open", "是否启用", 0);
info.addHead("", "操作", 0);
info.sqlQuery = "SELECT * FROM permission;";
}
{
auto& info = s_mapInfo["角色管理"];
info.addHead("role_id", "ID", 60);
info.addHead("name", "角色名称", 200);
info.addHead("describe", "描述", 600);
info.addHead("is_open", "是否启用", 0);
info.addHead("", "操作", 0);
info.sqlQuery = "SELECT * FROM role;";
}
{
auto& info = s_mapInfo["场站管理"];
info.addHead("station_id", "ID", 60);
info.addHead("name", "场站名称", 160);
info.addHead("code", "编号", 60);
info.addHead("address", "地址", 280);
info.addHead("lon", "经度", 0);
info.addHead("lat", "维度", 0);
info.addHead("attr", "参数", 200);
info.addHead("", "操作", 0);
info.sqlQuery = "SELECT * FROM station;";
}
{
auto& info = s_mapInfo["设备管理"];
info.addHead("device_id", "ID", 60);
info.addHead("station_name", "所属场站", 200);
info.addHead("type_name", "设备类型", 200);
info.addHead("name", "设备名称", 340);
info.addHead("code", "编号", 60);
info.addHead("is_open", "是否启用", 0);
info.addHead("", "操作", 0);
info.sqlQuery = "SELECT d.*, s.name station_name, ddt.name type_name FROM"
" device d LEFT JOIN station s ON d.station_id=s.station_id"
" LEFT JOIN def_device_type ddt ON ddt.device_type_id = d.`type`;";
}
{
auto& info = s_mapInfo["策略管理"];
info.addHead("policy_id", "ID", 0);
info.addHead("type_name", "策略类型", 160);
info.addHead("name", "策略名称", 0);
info.addHead("describe", "描述", 200);
info.addHead("value", "参数", 400);
info.addHead("", "操作", 0);
info.sqlQuery = "SELECT p.*, dpt.name type_name FROM policy p LEFT JOIN def_policy_type dpt ON dpt.policy_type_id=p.`type`;";
}
{
auto& info = s_mapInfo["日志管理"];
info.addHead("", "ID", 0);
info.addHead("", "日志类型", 0);
info.addHead("", "内容", 0);
info.addHead("", "状态", 0);
info.addHead("", "操作", 0);
}
{
auto& info = s_mapInfo["告警管理"];
info.addHead("", "ID", 0);
info.addHead("", "告警类型", 0);
info.addHead("", "内容", 0);
info.addHead("", "状态", 0);
info.addHead("", "操作", 0);
}
};
static TableInfo* getInfo(string name)
{
auto iter = s_mapInfo.find(name);
return iter != s_mapInfo.end() ? &(iter->second) : nullptr;
}
struct HEAD
{
string key;
string title;
int width{ 0 };
};
TableInfo() {}
void addHead(string k, string t, int w)
{
HEAD head;
head.key = k;
head.title = t;
head.width = w;
vecHead.push_back(head);
}
string name;
string sqlQuery;
vector<HEAD> vecHead;
};
class DialogPopUser : public DialogPop
{
public:
DialogPopUser(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
this->setFixedSize(500, 60 + 140 + 40 * 6);
this->setWindowTitle(("用户管理: " + oper).c_str());
this->addParamLine("user_id", "ID", true);
this->addParamLine("account", "用户名");
this->addParamLine("name", "姓名");
this->addParamCombox("gender", "性别", { {"1", ""}, {"0", ""} });
this->addParamLine("age", "年龄");
this->addParamLine("phone", "联系方式");
}
void onAccept()
{
if (oper == "修改")
{
curData.set("user_id", originData.value("user_id"));
DAO::updateUserById(curData);
}
};
};
class DialogPopPermission : public DialogPop
{
public:
DialogPopPermission(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
this->setFixedSize(500, 60 + 140 + 40 * 5);
this->setWindowTitle(("权限管理: " + oper).c_str());
this->addParamLine("permission_id", "ID", true);
this->addParamLine("route", "路由");
this->addParamLine("name", "权限名称");
this->addParamLine("describe", "描述");
this->addParamCombox("is_open", "是否启用", { {"1","启用"},{"0","不启用"} });
}
void onAccept()
{
if (oper == "修改")
{
curData.set("permission_id", originData.value("permission_id"));
DAO::updatePermissionById(curData);
}
};
};
class DialogPopRole : public DialogPop
{
public:
DialogPopRole(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
this->setFixedSize(500, 60 + 140 + 40 * 4);
this->setWindowTitle(("角色管理: " + oper).c_str());
this->addParamLine("role_id", "ID", true);
this->addParamLine("name", "角色名称");
this->addParamLine("describe", "描述");
this->addParamCombox("is_open", "是否启用", { {"1","启用"},{"0","不启用"} });
}
void onAccept()
{
if (oper == "修改")
{
curData.set("role_id", originData.value("role_id"));
DAO::updateRoleById(nullptr, curData);
}
};
};
class DialogPopStation : public DialogPop
{
public:
DialogPopStation(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
this->setFixedSize(500, 60 + 140 + 40 * 7);
this->setWindowTitle(("场站管理: " + oper).c_str());
this->addParamLine("station_id", "ID", true);
this->addParamLine("name", "名称");
this->addParamLine("code", "编号");
this->addParamLine("address", "地址");
this->addParamLine("lon", "经度");
this->addParamLine("lat", "维度");
this->addParamCombox("is_open", "是否启用", { {"1","启用"},{"0","不启用"} });
}
void onAccept()
{
if (oper == "修改")
{
curData.set("station_id", originData.value("station_id"));
DAO::updateStationById(curData);
}
};
};
class DialogPopDevice : public DialogPop
{
public:
DialogPopDevice(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
this->setFixedSize(500, 60 + 140 + 40 * 6);
this->setWindowTitle(("设备管理: " + oper).c_str());
this->addParamLine("device_id", "ID", true);
this->addParamLine("station_name", "所属场站");
this->addParamLine("type_name", "类型");
this->addParamLine("name", "名称");
this->addParamLine("code", "编号");
this->addParamCombox("is_open", "是否启用", { {"1","启用"},{"0","不启用"} });
}
void onAccept()
{
if (oper == "修改")
{
curData.set("station_id", originData.value("station_id"));
DAO::updateDeviceById(curData);
}
};
};
class DialogPopPolicy : public DialogPop
{
public:
DialogPopPolicy(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
}
};
class DialogPopLog : public DialogPop
{
public:
DialogPopLog(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
}
};
class DialogPopAlarm : public DialogPop
{
public:
DialogPopAlarm(QWidget* parent, const Fields& rowdata, string oper = "") : DialogPop(parent, rowdata, oper)
{
}
};
QWSysmgr::QWSysmgr(QWidget* parent) : MyWidget(parent)
{
std::vector<std::string > vecItems = {"用户管理", "权限管理", "角色管理", "场站管理", "设备管理", "策略管理", "日志管理", "告警管理"};
vecBtnFunc.reserve(vecItems.size());
int x = 10, y = 10;
for (auto& itemName: vecItems)
{
auto btn = make_shared<QPushButton>(itemName.c_str(), this);
btn->setGeometry(x, y, 120, 36);
btn->setStyleSheet(QSS_BTN.c_str());
vecBtnFunc.push_back(btn);
x += 130;
connect(btn.get(), &QPushButton::clicked, this, [=]()
{
if (btn != curActiveBtn)
{
if (curActiveBtn) { curActiveBtn->setStyleSheet(QSS_BTN.c_str()); }
if (btn) { btn->setStyleSheet(QSS_BTN_ACTIVE.c_str()); }
curActiveBtn = btn;
this->initTable(itemName);
}
});
}
TableInfo::initialize();
QStringList headerTextList;
//headerTextList << "ID" << "类型ID" << "类型名称" << "设备名称" << "编号" << "状态" << "通讯\n状态" << "工作\n状态" << "故障\n状态";
std::vector<std::string > vecItems = {"用户管理", "权限管理", "角色管理", "场站管理", "设备管理", "策略管理", "日志管理", "告警管理"};
vecBtnFunc.reserve(vecItems.size());
int x = 10, y = 10;
for (auto& itemName: vecItems)
{
auto btn = make_shared<QPushButton>(itemName.c_str(), this);
btn->setObjectName(itemName);
btn->setGeometry(x, y, 120, 36);
btn->setStyleSheet(QSS_BTN.c_str());
vecBtnFunc.push_back(btn);
x += 130;
connect(btn.get(), &QPushButton::clicked, this, &QWSysmgr::slotBtnModuleChanged);
}
table = MyQUI::TableWidget(this, 10, y += 100, 1190, 740);
// 设置为水平表头
table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList);
table->horizontalHeader()->setDefaultSectionSize(80);
QStringList headerTextList;
//headerTextList << "ID" << "类型ID" << "类型名称" << "设备名称" << "编号" << "状态" << "通讯\n状态" << "工作\n状态" << "故障\n状态";
if (vecBtnFunc.size() > 0)
{
curActiveBtn = vecBtnFunc[0];
curActiveBtn->setStyleSheet(QSS_BTN_ACTIVE.c_str());
this->initTable(curActiveBtn->text().toStdString());
}
table = MyQUI::TableWidget(this, 10, y += 100, 1190, 740);
// 设置为水平表头
table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList);
table->horizontalHeader()->setDefaultSectionSize(80);
if (vecBtnFunc.size() > 0)
{
curActiveBtn = vecBtnFunc[0].get();
curActiveBtn->setStyleSheet(QSS_BTN_ACTIVE.c_str());
this->initTable(curActiveBtn->text().toStdString());
}
}
QWSysmgr::~QWSysmgr()
{
}
class TableOper
{
public:
TableOper()
{
widget = make_shared<QWidget>();
//auto btn = make_shared<QPushButton>(widget.get());
//btn->setGeometry(10+mapBtn.size()*60, 10, 60, 30);
//mapBtn["查看"] = btn;
}
shared_ptr<QWidget> widget;
map<string, shared_ptr<QPushButton>> mapBtn;
};
struct VH
{
string key;
string title;
int width {0};
VH(string k, string t, int w) : key(k), title(t), width(w)
{
}
};
vector<VH> vecHeaderUser =
{
VH("user_id", "ID", 160),
VH("account", "用户名", 0),
VH("name", "姓名", 200),
VH("gender", "性别", 0),
VH("age", "年龄", 0),
VH("phone", "联系方式", 0),
VH("role_name", "角色", 200),
VH("", "操作", 0)
};
vector<VH> vecHeaderPermission =
{
VH("permission_id", "ID", 60),
VH("route", "路由", 160),
VH("name", "权限名称", 0),
VH("describe", "描述", 540),
VH("is_open", "是否启用", 0),
VH("", "操作", 0)
};
vector<VH> vecHeaderRole =
{
VH("role_id", "ID", 60), VH("name", "权限名称", 200), VH("describe", "描述", 600), VH("is_open", "是否启用", 0), VH("", "操作", 0)
};
vector<VH> vecHeaderStation =
{
VH("station_id", "ID", 60), VH("name", "场站名称", 160), VH("code", "编号", 60), VH("address", "地址", 280), VH("lon", "经度", 0), VH("lat", "维度", 0), VH("attr", "参数", 200), VH("", "操作", 0)
};
vector<VH> vecHeaderDevice =
{
VH("device_id", "ID", 60),
VH("station_name", "所属场站", 200),
VH("type_name", "设备类型", 200),
VH("name", "设备名称", 340),
VH("code", "编号", 60),
VH("is_open", "是否启用", 0),
VH("", "操作", 0)
};
vector<VH> vecHeaderPolicy =
{
VH("policy_id", "ID", 0),
VH("type_name", "策略类型", 160),
VH("name", "策略名称", 0),
VH("describe", "描述", 200),
VH("value", "参数", 400),
VH("", "操作", 0)
};
vector<VH> vecHeaderLogSys =
{
VH("", "ID", 0), VH("", "日志类型", 0), VH("", "内容", 0), VH("", "状态", 0), VH("", "操作", 0)
};
vector<VH> vecHeaderLogAlert =
{
VH("", "ID", 0), VH("", "告警类型", 0), VH("", "内容", 0), VH("", "状态", 0), VH("", "操作", 0)
};
map<string, vector<VH>> mapTableHeaderDef =
{
{"用户管理", vecHeaderUser},
{"权限管理", vecHeaderPermission},
{"角色管理", vecHeaderRole},
{"场站管理", vecHeaderStation},
{"设备管理", vecHeaderDevice},
{"策略管理", vecHeaderPolicy},
{"日志管理", vecHeaderLogSys},
{"告警管理", vecHeaderLogAlert},
} ;
#include "database/DAO.h"
void QueryDB(const string& name, std::vector<Fields>& result)
{
string sql;
if (name == "用户管理")
{
sql = "SELECT u.*, ur.role_id, r.name role_name FROM USER u LEFT JOIN user_role ur ON u.user_id=ur.user_id LEFT JOIN ROLE r ON r.role_id=ur.role_id;";
}
else if (name == "权限管理")
{
sql = "SELECT * FROM permission;";
}
else if (name == "角色管理")
{
sql = "SELECT * FROM role;";
}
else if (name == "场站管理")
{
sql = "SELECT * FROM station;";
}
else if (name == "设备管理")
{
sql = "SELECT d.*, s.name station_name, ddt.name type_name FROM"
" device d LEFT JOIN station s ON d.station_id=s.station_id"
" LEFT JOIN def_device_type ddt ON ddt.device_type_id = d.`type`;";
}
else if (name == "策略管理")
{
sql = "SELECT p.*, dpt.name type_name FROM policy p LEFT JOIN def_policy_type dpt ON dpt.policy_type_id=p.`type`;";
}
else if (name == "日志管理")
{
}
else if (name == "告警管理")
{
}
DAO::exec(NULL, sql, result);
}
vector<VH>& GetHeaderVec(const string& name)
{
static vector<VH> vecTmp;
auto iter = mapTableHeaderDef.find(name);
return (iter != mapTableHeaderDef.end()) ? iter->second : vecTmp;
}
void QWSysmgr::initTable(const string& name)
{
auto& vecHeader = GetHeaderVec(name);
QStringList headerTextList;
for (auto& item: vecHeader) { headerTextList << item.title.c_str(); }
table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList);
QStringList headerTextList;
auto tableInfo = TableInfo::getInfo(name);
if (tableInfo)
{
for (auto& item : tableInfo->vecHead) { headerTextList << item.title.c_str(); }
}
table->setColumnCount(headerTextList.size());
table->setHorizontalHeaderLabels(headerTextList);
for (int i = 0; i<vecHeader.size(); ++i)
{
auto& item = vecHeader[i];
table->setColumnWidth(i, item.width > 0 ? item.width : 100);
}
this->initTableData(name);
if (tableInfo)
{
for (int i = 0; i < tableInfo->vecHead.size(); ++i)
{
auto& item = tableInfo->vecHead[i];
table->setColumnWidth(i, item.width > 0 ? item.width : 100);
}
}
this->initTableData(name);
}
void QWSysmgr::initTableData(std::string name)
{
table->clearContents();
table->setRowCount(0);
table->clearContents(); // 会自动释放在setCellWidget时创建的对象
table->setRowCount(0);
QueryDB(name, rowFields);
auto tableInfo = TableInfo::getInfo(name);
if (tableInfo)
{
DAO::exec(NULL, tableInfo->sqlQuery, rowFields);
auto& vecHeader = GetHeaderVec(name);
for (int row = 0; row<rowFields.size(); ++row)
{
auto& fields = rowFields[row];
int col = 0;
for (auto& item : vecHeader)
{
string key = item.key;
if (item.title == "操作")
{
if (row >= table->rowCount()) { table->insertRow(row); }
QWidget* cellWidget = new QWidget();
QPushButton* btn1 = new QPushButton("查看", cellWidget);
btn1->setGeometry(5, 3, 50, 24);
btn1->setStyleSheet(QSS_BTN_TAB.c_str());
QPushButton* btn2 = new QPushButton("修改", cellWidget);
btn2->setGeometry(60, 3, 50, 24);
btn2->setStyleSheet(QSS_BTN_TAB.c_str());
table->setCellWidget(row, col, cellWidget);
}
else
{
string val = fields.value(key);
if (key == "is_open") { val = (val == "1" ? "启用" : "未启用"); }
MyQUI::setTableCell(table, row, col, val);
}
++col;
}
}
for (int row = 0; row < rowFields.size(); ++row)
{
auto& fields = rowFields[row];
int col = 0;
for (auto& item : tableInfo->vecHead)
{
string key = item.key;
if (item.title == "操作")
{
vector<string> items{ "修改" };
MyQUI::setTableCellButton(table, row, col, items, this, [=](string oper) {this->showDialogPop(name, fields, oper); });
}
else
{
string val = fields.value(key);
if (key == "is_open") { val = (val == "1" ? "启用" : "未启用"); }
else if (key == "gender") { val = (val == "1" ? "" : ""); }
MyQUI::setTableCellText(table, row, col, val);
}
++col;
}
}
}
}
void QWSysmgr::showDialogPop(std::string name, const Fields& rowdata, std::string oper)
{
shared_ptr<DialogPop> dlg;
if (name == "用户管理") { dlg = make_shared<DialogPopUser>(this, rowdata, oper); }
else if (name == "权限管理") { dlg = make_shared<DialogPopPermission>(this, rowdata, oper); }
else if (name == "角色管理") { dlg = make_shared<DialogPopRole>(this, rowdata, oper); }
else if (name == "场站管理") { dlg = make_shared<DialogPopStation>(this, rowdata, oper); }
else if (name == "设备管理") { dlg = make_shared<DialogPopDevice>(this, rowdata, oper); }
else if (name == "策略管理") { dlg = make_shared<DialogPopPolicy>(this, rowdata, oper); }
else if (name == "日志管理") { dlg = make_shared<DialogPopLog>(this, rowdata, oper); }
else if (name == "告警管理") { dlg = make_shared<DialogPopAlarm>(this, rowdata, oper); }
if (!dlg) return;
int ret = dlg->exec();
if (ret) { this->initTableData(name); }
}
void QWSysmgr::slotBtnModuleChanged()
{
auto btn = dynamic_cast<QPushButton*>(sender());
string name = btn->objectName().toStdString();
if (btn != curActiveBtn)
{
if (curActiveBtn) { curActiveBtn->setStyleSheet(QSS_BTN.c_str()); }
if (btn) { btn->setStyleSheet(QSS_BTN_ACTIVE.c_str()); }
curActiveBtn = btn;
this->initTable(name);
}
}

View File

@@ -13,9 +13,14 @@ public:
void initTable(const string& name);
void initTableData(std::string name);
void showDialogPop(std::string name, const Fields& rowdata, std::string oper);
public:
void slotBtnModuleChanged();
public:
std::vector<shared_ptr<QPushButton>> vecBtnFunc;
shared_ptr<QPushButton> curActiveBtn;
QPushButton* curActiveBtn {NULL};
shared_ptr<QTableWidget> table;

View File

@@ -1,5 +1,5 @@
#include <QMainWindow>
#include <QtWebEngineWidgets/QWebEngineView>
#include <vector>
#include <QTimer>
#include <fstream>
@@ -53,5 +53,5 @@ public:
std::shared_ptr<Menu> menu_ = nullptr;
std::shared_ptr<QWebEngineView> webView_;
//std::shared_ptr<QWebEngineView> webView_;
};

View File

@@ -1,4 +1,4 @@
cd %~dp0
cd ../bin/Release
@REM D:\Programs\Qt5\5.15.2\msvc2019_64\bin\windeployqt.exe
D:\Programs\Qt6\6.7.3\msvc2019_64\bin\windeployqt.exe ESS.exe
D:\Programs\Qt6\6.10.0\msvc2022_64\bin\windeployqt.exe ESS.exe