From 8f6c83147b1b0b26aed9c448e0196607b093569d Mon Sep 17 00:00:00 2001 From: lixiaoyuan Date: Tue, 26 Aug 2025 18:36:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=89=8A=E5=B3=B0=E5=A5=97?= =?UTF-8?q?=E5=88=A9=E7=AD=96=E7=95=A5=E7=9A=84=E7=BC=96=E8=BE=91=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/Release/assets/pv/downFill.png | Bin 327 -> 264 bytes src/app/AppData.cpp | 336 +++++++++++----- src/app/AppData.h | 78 +++- src/app/Config.cpp | 6 +- src/app/Dao1.cpp | 2 +- src/app/Device.cpp | 10 +- src/app/Policy.cpp | 0 src/app/Policy.h | 15 + src/app/Station.cpp | 27 +- src/app/Station.h | 7 + src/common/Fields.cpp | 223 +++++------ src/common/Fields.h | 141 +++---- src/common/JsonN.h | 77 ++-- src/common/Utils.cpp | 2 +- src/database/Dao.cpp | 100 +++-- src/database/Dao.h | 71 ++-- src/database/DaoEntity.cpp | 45 +-- src/database/DataModelDef.h | 28 +- src/database/MysqlClient.cpp | 32 +- src/database/SQL.cpp | 64 +++ src/database/SQL.h | 70 +--- src/main.cpp | 40 +- src/protocol/Communicator.cpp | 4 +- src/pv/PvApp.cpp | 36 +- src/pv/PvApp.h | 6 +- src/pv/PvPopWidget.cpp | 4 +- src/pv/PvStyle.cpp | 8 +- src/pv/PvTable.cpp | 100 ++++- src/pv/PvTable.h | 30 +- src/pv/pages/MaskPageHome.cpp | 20 +- src/pv/pages/MaskPageRunning.cpp | 6 +- src/pv/pages/MaskPageSysmgr.cpp | 2 +- .../{PageSysmgrPop.cpp => PageSysmgr.cpp} | 126 ++---- .../pages/{PageSysmgrPop.h => PageSysmgr.h} | 30 +- src/pv/pages/PanelPolicy.cpp | 366 ++++++++++++++++++ src/pv/pages/PanelPolicy.h | 75 ++++ src/pv/pvmain.cpp | 48 +-- 37 files changed, 1506 insertions(+), 729 deletions(-) create mode 100644 src/app/Policy.cpp create mode 100644 src/app/Policy.h create mode 100644 src/database/SQL.cpp rename src/pv/pages/{PageSysmgrPop.cpp => PageSysmgr.cpp} (83%) rename src/pv/pages/{PageSysmgrPop.h => PageSysmgr.h} (81%) create mode 100644 src/pv/pages/PanelPolicy.cpp create mode 100644 src/pv/pages/PanelPolicy.h diff --git a/bin/Release/assets/pv/downFill.png b/bin/Release/assets/pv/downFill.png index f4fb0ab3311cf6269812eda89f939dccdf21d51d..e2bbf787e5fb1528b0dc2edd088e72e97cb5dafb 100644 GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^d_c^}!3HFmd}T9%6k~CayA#8@b22Z19F}xPUq=Rp zjs4tz5?Mhi3p^r=ftn73Fyrz36)8Z$xt=bLAsWGJ`*-sm3gBVTpWnX8m5Xg*gJs5y z7F&;lGAWa%7#tLK?CQ-~#S+I7#I#}w-)7+I6Q})+4i5vcm>2!LQe-7wS22WQ%mvv4F FO#s%ST;~7) literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3e>`0rLn;{GTnglCGT>o*(5KP4 z{lel3VcX8nDse|=ztHswF#dj6Wn<#fXroF=&&Jkm@>5K=TnK!)pLbv1uD)G2Se~4H zDtB8aGElrdwp=0V?uk;ndFo%eHC{_COgzA|@7AQ?2ew&y&i+>{|9?8%HJ|myoybk1 zALUEd?CC3ic;t0U)LesIQ~BZ*7SKb)x%b=ts4 zWzIfn&d!dyJ&&dra=iwXaun_f9j9%ef*C^#1?priceSuperPeak); + NJson::read(jsonroot, "price_peak", this->pricePeak); + NJson::read(jsonroot, "price_shoulder", this->priceShoulder); + NJson::read(jsonroot, "price_off_peak", this->priceOffPeak); + NJson::read>>(jsonroot, "periods", this->vecPeriods); +} + +std::string ElectPeriod::dump() +{ + NJsonNode jsonroot; + jsonroot["price_super_peak"] = this->priceSuperPeak; + jsonroot["price_peak"] = this->pricePeak; + jsonroot["price_shoulder"] = this->priceShoulder; + jsonroot["price_off_peak"] = this->priceOffPeak; + jsonroot["periods"] = this->vecPeriods; + return jsonroot.dump(); +} + + + + +void AppData::initFromDB() +{ + auto dao = DaoEntity::create(""); + if (!dao->isConnected()) + { + XLOGE() << "Database connected error."; + return; + } + + std::string str; std::vector result; - DAO::queryStationList(NULL, result); - for (auto& fields: result) - { - int stationId = fields.getInt(DMStation::STATION_ID); - auto station = std::make_shared(stationId); - station->name = fields.value(DMStation::NAME); - station->energyCapacity = fields.getDouble(DMStation::CAPACITY); - appdata->mapStation[stationId] = station; - } -} -void InitDevice(AppData* appdata) -{ - vector result; - DAO::queryDeviceList(NULL, result); - for (auto& fields: result) - { - int deviceId = fields.getInt(DMDevice::DEVICE_ID); - int stationId = fields.getInt(DMDevice::STATION_ID); - auto station = appdata->getStation(stationId); - if (station) + { // 数据库读取工作模式定义 + str = "", result.clear(); + DAO::queryWorkModeDef(dao, result); + for (auto& fields: result) { - auto device = Device::create(fields); - station->addDevice(deviceId, device); + std::string workModeId = fields.value(DMDefWorkMode::WORK_MODE_ID); + std::string name = fields.value(DMDefWorkMode::NAME); + this->mapping.workMode.push_back({workModeId, name}); + str += ("工作模式: {" + workModeId + ":" + name + "},"); } - else + XLOGD() << str; + } + { // 数据库读取策略类型定义 + str = "", result.clear(); + DAO::queryPolicyTypeDef(dao, result); + for (auto& fields: result) { - XLOGE() << "init device error: unknown station_id:[" << stationId << "] device_id=" << deviceId; + std::string policyTypeId = fields.value(DMDefPolicyType::POLICY_TYPE_ID); + std::string name = fields.value(DMDefWorkMode::NAME); + this->mapping.workMode.push_back({policyTypeId, name}); + str += ("策略类型: {" + policyTypeId + ":" + name + "},"); + } + XLOGD() << str; + } + { // 数据库读取设备类型定义 + str = "", result.clear(); + DAO::queryDeviceTypeDef(dao, result); + for (auto& fields: result) + { + auto item = std::make_shared(); + item->typeId = fields.get(DMDefDeviceType::DEVICE_TYPE_ID); + item->name = fields.value(DMDefDeviceType::NAME); + item->attrs = fields.value(DMDefDeviceType::ATTRS); + mapDeviceType[item->typeId] = item; + mapping.deviceType.push_back({std::to_string(item->typeId), item->name}); + str += ("设备类型: {" + std::to_string(item->typeId) + ":" + item->name + "},"); + } + XLOGD() << str; + } + { // 数据库读取角色定义 + str = "", result.clear(); + this->mapping.role.clear(); + DAO::queryRoleList(dao, result); + for (auto& fields : result) + { + auto item = std::make_shared(); + item->roleId = fields.get(DMRole::ROLE_ID); + item->name = fields.value(DMRole::NAME); + item->isOpen = fields.get(DMRole::IS_OPEN); + mapRole[item->roleId] = item; + mapping.role.push_back({std::to_string(item->roleId), item->name}); + str += ("角色: {" + std::to_string(item->roleId) + ":" + item->name + "},"); + } + XLOGD() << str; + } + { // 数据库读取场站信息 + str = "", result.clear(); + DAO::queryStationList(dao, result); + for (auto& fields: result) + { + int stationId = fields.get(DMStation::STATION_ID); + auto station = std::make_shared(stationId); + station->name = fields.value(DMStation::NAME); + station->energyCapacity = fields.get(DMStation::CAPACITY); + this->mapStation[stationId] = station; + str += ("场站: {" + std::to_string(stationId) + ":" + station->name + "},"); + } + XLOGD() << str; + } + { // 数据库读取设备信息 + str = "", result.clear(); + DAO::queryDeviceList(dao, result); + for (auto& fields: result) + { + int deviceId = fields.get(DMDevice::DEVICE_ID); + int stationId = fields.get(DMDevice::STATION_ID); + auto station = this->getStation(stationId); + if (station) + { + auto device = Device::create(fields); + station->addDevice(deviceId, device); + } + else + { + XLOGE() << "init device error: unknown station_id:[" << stationId << "] device_id=" << deviceId; + } } } -} - -void InitStatData(AppData* appdata) -{ - std::string curDate = Utils::dateStr(); - vector result; - DAO::queryStatDataList(curDate, curDate, result); - for (auto& fields: result) - { - std::string dt = fields.value(DMStatStation::DT); - int stationId = fields.getInt(DMStatStation::STATION_ID); - auto station = appdata->getStation(stationId); - if (station) + { // 数据库读取策略信息 + str = "", result.clear(); + DAO::queryPolicyList(dao, result); + for (auto& fields: result) { - station->storageIn = fields.getFloat(DMStatStation::STORAGE_ELECT_IN); - station->storageOut = fields.getFloat(DMStatStation::STORAGE_ELECT_OUT); - //station->storageNumIn = fields.getFloat(DMStatStation::STORAGE_NUM); - //station->storageNumOut = fields.getFloat(DMStatStation::STORAGE_NUM); - station->storageNumErr = fields.getFloat(DMStatStation::STORAGE_NUM_ERR); - - station->solarGen = fields.getFloat(DMStatStation::SOLAR_ELECT_GEN); - station->solarGrid = fields.getFloat(DMStatStation::SOLAR_ELECT_GRID); - station->solarNumErr = fields.getFloat(DMStatStation::SOLAR_NUM_ERR); - - station->chargeElect = fields.getFloat(DMStatStation::CHARGE_ELECT); - station->chargeNum = fields.getFloat(DMStatStation::CHARGE_NUM); - station->chargeNumErr = fields.getFloat(DMStatStation::CHARGE_NUM_ERR); - } - else - { - XLOGE() << "init staticis data error: unknown station_id:[" << stationId << "] dt=" << dt; + auto policy = std::make_shared(); + policy->policyId = fields.get(DMPolicy::POLICY_ID); + policy->type = fields.get(DMPolicy::TYPE); + policy->name = fields.value(DMPolicy::NAME); + policy->value = fields.value(DMPolicy::VALUE); + this->mapPolicy[policy->policyId] = policy; } } + { // 数据库读取电价分段信息 + result.clear(); + vecElectPeriods.resize(12); + DAO::exec(dao, "SELECT * FROM configure;", result); + + Fields info; + for (auto& fields: result) + { + auto k = fields.value("key"); + auto v = fields.value("val"); + info.set(k, v); + } + for (int month = 1; month<=12; month++) + { + if (month-1 < vecElectPeriods.size()) + { + auto& vecItems = vecElectPeriods[month-1]; + std::string str = info.value("period_" + std::to_string(month)); + std::vector vec; + Utils::split(str, ",", vecItems); + } + } + electPriceSuperPeak = info.get("price_super_peak"); + electPricePeak = info.get("price_peak"); + electPriceShoulder = info.get("price_shoulder"); + electPriceOffPeak = info.get("price_off_peak"); + } + { // 数据库读取统计数据 + vector result; + std::string curDate = Utils::dateStr(); + DAO::queryStatDataList(dao, curDate, curDate, result); + for (auto& fields: result) + { + std::string dt = fields.value(DMStatStation::DT); + int stationId = fields.get(DMStatStation::STATION_ID); + auto station = this->getStation(stationId); + if (station) + { + station->storageIn = fields.get(DMStatStation::STORAGE_ELECT_IN); + station->storageOut = fields.get(DMStatStation::STORAGE_ELECT_OUT); + //station->storageNumIn = fields.getFloat(DMStatStation::STORAGE_NUM); + //station->storageNumOut = fields.getFloat(DMStatStation::STORAGE_NUM); + station->storageNumErr = fields.get(DMStatStation::STORAGE_NUM_ERR); + + station->solarGen = fields.get(DMStatStation::SOLAR_ELECT_GEN); + station->solarGrid = fields.get(DMStatStation::SOLAR_ELECT_GRID); + station->solarNumErr = fields.get(DMStatStation::SOLAR_NUM_ERR); + + station->chargeElect = fields.get(DMStatStation::CHARGE_ELECT); + station->chargeNum = fields.get(DMStatStation::CHARGE_NUM); + station->chargeNumErr = fields.get(DMStatStation::CHARGE_NUM_ERR); + } + else + { + XLOGE() << "init staticis data error: unknown station_id:[" << stationId << "] dt=" << dt; + } + } + } } void AppData::init() { - // 初始化场站信息 - InitStation(this); - // 读取设备信息,连接设备 - InitDevice(this); - // 读取基础统计信息,在系统总览中需要展示 - InitStatData(this); - + this->initFromDB(); this->initUser(); } @@ -135,31 +262,7 @@ void AppData::initUser() auto dao = DaoEntity::create(""); std::vector result; - // 数据库读取角色定义 - mapping.role.clear(); - DAO::queryRoleList(dao, result); - for (auto& fields : result) - { - auto item = std::make_shared(); - item->roleId = fields.getInt(DMRole::ROLE_ID); - item->name = fields.value(DMRole::NAME); - item->isOpen = fields.getInt(DMRole::IS_OPEN); - mapRole[item->roleId] = item; - mapping.role.push_back({std::to_string(item->roleId), item->name}); - } - // 数据库读取设备类型定义 - result.clear(); - DAO::queryDeviceTypeDef(dao, result); - for (auto& fields : result) - { - auto item = std::make_shared() ; - item->typeId = fields.getInt(DMDeviceTypeDef::TYPE_ID); - item->name = fields.value(DMDeviceTypeDef::NAME); - item->attrs = fields.value(DMDeviceTypeDef::ATTRS); - mapDeviceType[item->typeId] = item; - mapping.deviceType.push_back({std::to_string(item->typeId), item->name}); - } } std::vector AppData::getRoleNames() @@ -186,7 +289,7 @@ std::vector AppData::getStationNames() return vec; } -std::vector AppData::getDeviceTypes() +std::vector AppData::getDeviceTypeNames() { std::vector vec(mapping.deviceType.size()); int i = 0; @@ -196,4 +299,61 @@ std::vector AppData::getDeviceTypes() ++i; } return vec; +} + +std::vector AppData::getWorkModes() +{ + std::vector vec(mapWorkMode.size()); + int i = 0; + for (auto iter = mapWorkMode.begin(); iter!=mapWorkMode.end(); ++iter) + { + vec[i] = iter->second; + ++i; + } + return vec; +} + +std::vector AppData::getPolicyTypeNames() +{ + std::vector vec(mapPolicyType.size()); + int i = 0; + for (auto iter = mapPolicyType.begin(); iter!=mapPolicyType.end(); ++iter) + { + vec[i] = iter->second; + ++i; + } + return vec; +} + +std::vector AppData::getPolicyNames() +{ + std::vector vec; + return vec; +} + +std::vector AppData::getElectPreiodVals(int month) +{ + if (month > 0 && month-1 < vecElectPeriods.size()) + { + return vecElectPeriods[month-1]; + } + return {}; +} + +std::string AppData::getElectPreiodVal(int month, int hour) +{ + if (month > 0 && month-1 < vecElectPeriods.size()) + { + auto& vec = vecElectPeriods[month-1]; + if (hour > 0 && hour-1 < vec.size()) + { + auto& val = vec[hour-1]; + if (val == "尖") return "尖峰"; + if (val == "峰") return "高峰"; + if (val == "平") return "平段"; + if (val == "谷") return "低谷"; + return val; + } + } + return ""; } \ No newline at end of file diff --git a/src/app/AppData.h b/src/app/AppData.h index cae0f82..163bf98 100644 --- a/src/app/AppData.h +++ b/src/app/AppData.h @@ -8,6 +8,7 @@ class Station; class Device; +class MyPolicy; using VecPairSS = std::vector>; @@ -25,27 +26,32 @@ struct Role bool isOpen {false}; }; +class ElectPeriod +{ +public: + double priceSuperPeak {}; + double pricePeak {}; + double priceShoulder {}; + double priceOffPeak {}; + + std::vector> vecPeriods; + + void parse(std::string jsonstr); + + std::string dump(); +}; + class AppData { public: void init(); - + void initFromDB(); std::shared_ptr getStation(int stationId); std::shared_ptr getStationByName(std::string name); - - - - std::shared_ptr getDevice(int stationId, int deviceId); - /////////////////////////////////////////////////////////////////////////////////////////////// - // 获取角色名称列表 - std::vector getRoleNames(); - // 获取场站名称列表 - std::vector getStationNames(); - // 获取设备类型 - std::vector getDeviceTypes(); + std::shared_ptr getDevice(int stationId, int deviceId); // 获取设备类型定义 std::unordered_map>& getDeviceTypeDef(); @@ -55,6 +61,25 @@ public: void initUser(); + /////////////////////////////////////////////////////////////////////////////////////////////// + // 获取角色名称列表 + std::vector getRoleNames(); + // 获取场站名称列表 + std::vector getStationNames(); + // 获取设备类型 + std::vector getDeviceTypeNames(); + // 获取工作模式 + std::vector getWorkModes(); + // 获取策略类型定义 + std::vector getPolicyTypeNames(); + // 获取策略名称 + std::vector getPolicyNames(); + + std::vector getElectPreiodVals(int month); + + std::string getElectPreiodVal(int month, int hour); + + public: /////////////////////////////////////////////////////////////////////////////////////////////// // === 系统 === @@ -77,18 +102,33 @@ public: VecPairSS deviceType; + VecPairSS workMode; } mapping; - - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 场站信息 === + double electPriceSuperPeak {}; + double electPricePeak {}; + double electPriceShoulder {}; + double electPriceOffPeak {}; + + // 场站信息 std::unordered_map> mapStation; - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 角色定义 === + // 角色信息 std::unordered_map> mapRole; - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 设备类型定义 === + // 设备类型定义 std::unordered_map> mapDeviceType; + + // 工作模式定义 + std::unordered_map mapWorkMode; + + // 策略类型定义 + std::unordered_map mapPolicyType; + + // 策略信息 + std::unordered_map> mapPolicy; + + // 电力峰谷分段 (12个月,每个月按小时分成24个时段) + std::vector> vecElectPeriods; + }; diff --git a/src/app/Config.cpp b/src/app/Config.cpp index df2cd9b..b7d02ab 100644 --- a/src/app/Config.cpp +++ b/src/app/Config.cpp @@ -9,8 +9,8 @@ AppOption Config::option; bool Config::init(std::string filename) { - NJson jsonroot; - bool ret = NJsonLoad(filename, jsonroot); + NJsonNode jsonroot; + bool ret = NJson::load(filename, jsonroot); if (!ret) { XLOGE() << "[APP] load config failed, filename=" << filename; @@ -20,7 +20,7 @@ bool Config::init(std::string filename) if (jsonroot.contains("database")) { - NJson json = jsonroot.at("database"); + NJsonNode json = jsonroot.at("database"); option.database.host = json.contains("host") ? json.at("host") : ""; option.database.port = json.contains("port") ? json.at("port") : 0; option.database.user = json.contains("user") ? json.at("user") : ""; diff --git a/src/app/Dao1.cpp b/src/app/Dao1.cpp index 09ffaab..b7b6bb7 100644 --- a/src/app/Dao1.cpp +++ b/src/app/Dao1.cpp @@ -47,7 +47,7 @@ Errcode DAO1::login(std::shared_ptr dao, std::string account, std::st } Fields& fields = res[0]; std::string userId = fields.value("user_id"); - int loginCount = fields.getInt("login_count"); + int loginCount = fields.get("login_count"); // 判断密码 if (passwd != fields.value("passwd")) diff --git a/src/app/Device.cpp b/src/app/Device.cpp index 8732e9a..6535184 100644 --- a/src/app/Device.cpp +++ b/src/app/Device.cpp @@ -67,16 +67,16 @@ int Device::startComm() std::shared_ptr Device::create(Fields& fields) { auto device = std::make_shared(); - device->deviceId = fields.getInt("device_id"); - device->type = fields.getInt("type"); + device->deviceId = fields.get("device_id"); + device->type = fields.get("type"); device->name = fields.value("name"); device->code = fields.value("code"); - device->isOpen = fields.getInt("is_open"); + device->isOpen = fields.get("is_open"); device->attrsJson = fields.value("attrs"); // 解析属性的JSON字符串,转换成键值对 - NJson jsonroot; - bool ret = NJsonParse(device->attrsJson, jsonroot); + NJsonNode jsonroot; + bool ret = NJson::parse(device->attrsJson, jsonroot); if (!ret) // 解析错误 { XLOGE() << "device attr json parse error, device_id=" << device->deviceId; diff --git a/src/app/Policy.cpp b/src/app/Policy.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/app/Policy.h b/src/app/Policy.h new file mode 100644 index 0000000..172e238 --- /dev/null +++ b/src/app/Policy.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include "common/Fields.h" + +class MyPolicy +{ +public: + int policyId {0}; + int type {0}; + std::string name; + std::string value; + int isOpen {0}; + + Fields fields; +}; \ No newline at end of file diff --git a/src/app/Station.cpp b/src/app/Station.cpp index 89675f2..e9a97b6 100644 --- a/src/app/Station.cpp +++ b/src/app/Station.cpp @@ -1,5 +1,6 @@ #include "Station.h" - +#include "database/DAO.h" +#include "database/SQL.h" Station::Station(int id) : id(id) { @@ -18,4 +19,28 @@ std::shared_ptr Station::getDevice(int deviceId) return iter->second; } return nullptr; +} + +void Station::setWorkMode(int modeId) +{ + std::string sql = SQL(SQL::TYPE::update).table(DMStation::TABLENAME) + .update(DMStation::WORK_MODE_ID, std::to_string(modeId)) + .where(DMStation::STATION_ID + "=" + std::to_string(id)).str(); + Errcode err = DAO::exec(NULL, sql); + if (err != Errcode::OK) + { + XLOGE() << "set station work mode failed."; + } +} + +void Station::setPolicy(int policyId) +{ + std::string sql = SQL(SQL::TYPE::update).table(DMStation::TABLENAME) + .update(DMStation::POLICY_ID, std::to_string(policyId)) + .where(DMStation::STATION_ID + "=" + std::to_string(id)).str(); + Errcode err = DAO::exec(NULL, sql); + if (err != Errcode::OK) + { + XLOGE() << "set station policy failed."; + } } \ No newline at end of file diff --git a/src/app/Station.h b/src/app/Station.h index 1974a2e..c9bebb7 100644 --- a/src/app/Station.h +++ b/src/app/Station.h @@ -13,10 +13,17 @@ public: void addDevice(int deviceId, std::shared_ptr device); std::shared_ptr getDevice(int deviceId); + void setWorkMode(int modeId); + void setPolicy(int policyId); + + public: int id {}; std::string name; + int workModeId; // 运行模式 + int runPolicyId; // 运行策略 + // 储能容量 double energyCapacity {}; diff --git a/src/common/Fields.cpp b/src/common/Fields.cpp index 2c3680c..f76961a 100644 --- a/src/common/Fields.cpp +++ b/src/common/Fields.cpp @@ -1,22 +1,7 @@ #include "Fields.h" #include "common/Utils.h" -void Fields::set(string key, string val) -{ - mapFields[key] = val; -} -void Fields::set(string key, float val) -{ - mapFields[key] = std::to_string(val); -} -void Fields::set(string key, int val) -{ - mapFields[key] = std::to_string(val); -} -void Fields::set(string key, int64_t val) -{ - mapFields[key] = std::to_string(val); -} + std::string& Fields::value(std::string key) { static std::string tmp; @@ -24,27 +9,12 @@ std::string& Fields::value(std::string key) return (it != mapFields.end()) ? it->second : (tmp = ""); } -//string Fields::getStr(string key) -//{ -// return (mapFields.count(key) > 0) ? mapFields[key] : ""; -//} - -int Fields::getInt(string key) +bool Fields::contains(std::string key) { - return mapFields.count(key) > 0 ? Utils::toInt(mapFields[key]) : 0; + return (mapFields.find(key) != mapFields.end()); } -float Fields::getFloat(string key) -{ - return mapFields.count(key) > 0 ? Utils::toFloat(mapFields[key]) : 0.0f; -} - -double Fields::getDouble(string key) -{ - return mapFields.count(key) > 0 ? Utils::toDouble(mapFields[key]) : 0.0; -} - -std::map::iterator Fields::remove(string key) +std::unordered_map::iterator Fields::remove(string key) { auto it = mapFields.find(key); if (it != mapFields.end()) @@ -53,19 +23,36 @@ std::map::iterator Fields::remove(string key) } return it; } + void Fields::append(Fields& datafield) { - auto& map_f = datafield.fields(); - for (auto it = map_f.begin(); it != map_f.end(); it++) + auto& mapVal = datafield.map(); + for (auto it = mapVal.begin(); it != mapVal.end(); it++) { mapFields[it->first] = it->second; } } -map& Fields::fields() + +std::unordered_map& Fields::map() { return mapFields; } +int Fields::size() +{ + return mapFields.size(); +} + +bool Fields::isEmpty() +{ + return mapFields.empty(); +} + +void Fields::clear() +{ + mapFields.clear(); +} + void Fields::check(string key, string val, string d) { if (mapFields.count(key) > 0 && mapFields[key] == val) @@ -74,84 +61,6 @@ void Fields::check(string key, string val, string d) } } -string Fields::get_insert_sql(string tbname) -{ - string key; - string val; - for (auto it = mapFields.begin(); it != mapFields.end(); it++) - { - if (!key.empty()) - { - key += ","; - val += ","; - } - key += ("`" + it->first + "`"); - if (it->second == "null" || it->second == "NULL") - { - val += "NULL"; - } - else - { - val += ("'" + it->second + "'"); - } - } - return "INSERT INTO `" + tbname + "` (" + key + ") VALUES(" + val + ");"; -} - -string Fields::get_update_sql(string tbname, string sql_c) -{ - ostringstream oss; - oss << "update " << tbname << " set "; - for (auto iter = mapFields.begin(); iter != mapFields.end(); iter++) - { - if (iter != mapFields.begin()) - { - oss << ","; - }; - oss << "`" << iter->first << "`="; - if (iter->second == "null" || iter->second == "NULL") - { - oss << "NULL"; - } - else - { - oss << "'" << iter->second << "'"; - } - } - oss << " " << sql_c << ";"; - return oss.str(); -} - -string Fields::get_update_sql(string tbname, std::vector vec_keys, string sql_c) -{ - std::map map_keys; - for (auto& k : vec_keys) { map_keys[k] = true; } - - ostringstream oss; - oss << "update " << tbname << " set "; - for (auto iter = mapFields.begin(); iter != mapFields.end(); iter++) - { - auto& k = iter->first; - auto& v = iter->second; - if (!map_keys[k]) { continue; } - if (iter != mapFields.begin()) - { - oss << ","; - }; - oss << "`" << k << "`="; - if (v == "null" || v == "NULL") - { - oss << "NULL"; - } - else - { - oss << "'" << v << "'"; - } - } - oss << " " << sql_c << ";"; - return oss.str(); -} - void Fields::foreachItem(function onForaach) { for (auto it = mapFields.begin(); it != mapFields.end(); it++) @@ -162,11 +71,6 @@ void Fields::foreachItem(function onForaach) } } } -bool Fields::isEmpty(string key) -{ - auto& s = mapFields[key]; - return s.empty(); -} bool Fields::is_float_number(string key) { @@ -195,19 +99,84 @@ string Fields::toStr() return s; } -int Fields::size() +string Fields::toSqlInsert(string tableName) { - return mapFields.size(); + string key; + string val; + for (auto it = mapFields.begin(); it != mapFields.end(); it++) + { + if (!key.empty()) + { + key += ","; + val += ","; + } + key += ("`" + it->first + "`"); + if (it->second == "null" || it->second == "NULL") + { + val += "NULL"; + } + else + { + val += ("'" + it->second + "'"); + } + } + return "INSERT INTO `" + tableName + "` (" + key + ") VALUES(" + val + ");"; } -void Fields::clear() +string Fields::toSqlUpdate(string tableName, string sql_c) { - mapFields.clear(); + ostringstream oss; + oss << "update " << tableName << " set "; + for (auto iter = mapFields.begin(); iter != mapFields.end(); iter++) + { + if (iter != mapFields.begin()) + { + oss << ","; + }; + oss << "`" << iter->first << "`="; + if (iter->second == "null" || iter->second == "NULL") + { + oss << "NULL"; + } + else + { + oss << "'" << iter->second << "'"; + } + } + oss << " " << sql_c << ";"; + return oss.str(); } -bool Fields::hasKey(std::string key) +string Fields::toSqlUpdate(string tableName, std::vector vecKeys, string condition) { - auto iter = mapFields.find(key); - return (iter != mapFields.end()); + std::map map_keys; + for (auto& k : vecKeys) { map_keys[k] = true; } + + ostringstream oss; + oss << "update " << tableName << " set "; + for (auto iter = mapFields.begin(); iter != mapFields.end(); iter++) + { + auto& k = iter->first; + auto& v = iter->second; + if (!map_keys[k]) { continue; } + if (iter != mapFields.begin()) + { + oss << ","; + }; + oss << "`" << k << "`="; + if (v == "null" || v == "NULL") + { + oss << "NULL"; + } + else + { + oss << "'" << v << "'"; + } + } + oss << " " << condition << ";"; + return oss.str(); } + + + diff --git a/src/common/Fields.h b/src/common/Fields.h index f3280b5..bc9e569 100644 --- a/src/common/Fields.h +++ b/src/common/Fields.h @@ -1,9 +1,10 @@ #ifndef _Fields_H_ #define _Fields_H_ +#include #include #include -#include +#include #include #include using namespace std; @@ -18,33 +19,29 @@ struct PageInfo class Fields { public: - /** - * 设置索引名称和值 - * @param: [string key] 索引名称 - * @param: [string val] 值 - */ - void set(string key, string val); + template + void set(string key, T val, int precision=6) + { + stringstream ss; + ss.precision(precision); + ss << val; + mapFields[key] = ss.str(); + } - /** - * 设置索引名称和值 - * @param: [string key] 索引名称 - * @param: [float val] 值 - */ - void set(string key, float val); + template + T get(string key, int precision = 6) + { + T val {}; + auto iter = mapFields.find(key); + if (iter != mapFields.end()) + { + stringstream ss(iter->second); + ss.precision(precision); + ss >> val; + } + return val; + } - /** - * 设置索引名称和值 - * @param: [string key] 索引名称 - * @param: [int val] 值 - */ - void set(string key, int val); - - /** - * 设置索引名称和值 - * @param: [string key] 索引名称 - * @param: [int64_t val] 值 - */ - void set(string key, int64_t val); /** * 获取值 @@ -53,28 +50,17 @@ public: std::string& value(std::string key); /** - * 获取 int 值 + * 是否包含 key * @param: [string key] 索引名称 + * @return: true: 包含; false:不包含 */ - int getInt(string key); + bool contains(std::string key); - /** - * 获取 float 值 - * @param: [string key] 索引名称 - */ - float getFloat(string key); - - /** - * 获取 double 值 - * @param: [string key] 索引名称 - */ - double getDouble(string key); - /** * 删除指定索引的值 * @param: [string key] 索引名称 */ - std::map::iterator remove(string key); + std::unordered_map::iterator remove(string key); /** * 追加合并 @@ -83,9 +69,25 @@ public: void append(Fields& fields); /** - * 获取数据项map + * 获取数据项 map */ - map& fields(); + std::unordered_map& map(); + + /** + * 获取数据项的大小 + */ + int size(); + + /** + * 判断是否含有数据项 + * @param: [string key] 索引名称 + */ + bool isEmpty(); + + /** + * 清空数据项 + */ + void clear(); /** * 检查某一数据项的值进行替换,如果该项的值是val,则替换成成d @@ -95,39 +97,12 @@ public: */ void check(string key, string val, string d); - /** - * 转换成插入数据的 sql 语句 - * @param: [string tableName] 数据表名称 - */ - string get_insert_sql(string tableName); - - /** - * 转换成更新数据的 sql 语句 - * @param: [string tableName] 数据表名称 - * @param: [string condition] sql的更新条件,例如: where id='1' - */ - string get_update_sql(string tableName, string condition); - - - /** - * 转换成更新数据的 sql 语句 - * @param: [string tableName] 数据表名称 - * @param: [string vecKeys] 需要更新的字段名称 - * @param: [string condition] sql的更新条件,例如: where id='1' - */ - string get_update_sql(string tableName, std::vector vecKeys, string condition); - /** * 遍历数据项 * @param: [function... onForaach] 回调函数 */ void foreachItem(function onForaach); - /** - * 判断是否含有数据项 - * @param: [string key] 索引名称 - */ - bool isEmpty(string key); /** * 判断数据项是否是float数值类型 @@ -141,20 +116,28 @@ public: string toStr(); /** - * 获取数据项的大小 + * 转换成插入数据的 sql 语句 + * @param: [string tableName] 数据表名称 */ - int size(); + string toSqlInsert(string tableName); - void clear(); + /** + * 转换成更新数据的 sql 语句 + * @param: [string tableName] 数据表名称 + * @param: [string condition] sql的更新条件,例如: where id='1' + */ + string toSqlUpdate(string tableName, string condition); - bool hasKey(std::string key); - - - - std::map& map() { return mapFields; } + /** + * 转换成更新数据的 sql 语句 + * @param: [string tableName] 数据表名称 + * @param: [string vecKeys] 需要更新的字段名称 + * @param: [string condition] sql的更新条件,例如: where id='1' + */ + string toSqlUpdate(string tableName, std::vector vecKeys, string condition); private: - std::map mapFields; + std::unordered_map mapFields; }; #endif \ No newline at end of file diff --git a/src/common/JsonN.h b/src/common/JsonN.h index 821447e..54eb1cb 100644 --- a/src/common/JsonN.h +++ b/src/common/JsonN.h @@ -1,8 +1,9 @@ #include #include #include +#include -using NJson = nlohmann::json; +using NJsonNode = nlohmann::json; /// ============================================================================================= /// 使用说明: @@ -36,32 +37,60 @@ using NJson = nlohmann::json; /// 序列化为字符串 ------------- // std::string json_str = j.dump(4); // 4 表示缩进,美化输出 -static bool NJsonLoad(std::string jsonfile, NJson& json) -{ - std::ifstream ifs(jsonfile); - if (ifs.is_open()) - { - ifs >> json; - return true; - } - return false; -} +/// 数组解析 ------------- +// json jArray = json::array() +// jArray.push_back(1); +// jArray.push_back(2); +// json j; +// j["data"] = {1,2,3,4,5}; +// std::vector v1; +// v1 = j.at["data"].get>() -static bool NJsonParse(std::string jsonstr, NJson& json) +class NJson { - try - { - json = NJson::parse(jsonstr); - } - catch (nlohmann::json::parse_error& e) +public: + static bool load(std::string jsonfile, NJsonNode& json) { - //std::cerr << "JSON 解析错误: " << e.what() << std::endl; + std::ifstream ifs(jsonfile); + if (ifs.is_open()) + { + ifs >> json; + return true; + } return false; } - return true; -} -static bool NJsonLHas(NJson& json, std::string key) -{ - return json.contains("database"); -} + static bool parse(std::string jsonstr, NJsonNode& json) + { + try + { + json = NJsonNode::parse(jsonstr); + } + catch (nlohmann::json::parse_error& e) + { + std::cout << "JSON parse error: " << e.what() << std::endl; + return false; + } + return true; + } + + static bool contains(NJsonNode& json, std::string key) + { + return json.contains("database"); + } + + template + static void read(NJsonNode& json, std::string k, T& v) + { + try + { + if (json.contains(k)) { v = json.at(k).get(); } + } + catch (const nlohmann::detail::exception& e) + { + std::cout << "JSON read error: " << e.what() << std::endl; + } + } +}; + + diff --git a/src/common/Utils.cpp b/src/common/Utils.cpp index 2522e16..788d760 100644 --- a/src/common/Utils.cpp +++ b/src/common/Utils.cpp @@ -435,7 +435,7 @@ void Utils::split(string buf, string c, vector& res) string tmp = buf; while (true) { - auto pos = tmp.find(c); + auto pos = tmp.find_first_of(c); if (pos == string::npos) { res.push_back(tmp); diff --git a/src/database/Dao.cpp b/src/database/Dao.cpp index 4017693..2e79d3a 100644 --- a/src/database/Dao.cpp +++ b/src/database/Dao.cpp @@ -18,18 +18,40 @@ bool DAO::count(DaoEntity& dao, std::string tableName, std::string condition, in bool ret = dao.exec(sql, result); if (ret) { - count = (result.size() > 0) ? result[0].getInt("count") : 0; + count = (result.size() > 0) ? result[0].get("count") : 0; } return ret; } +Errcode DAO::exec(std::shared_ptr dao, std::string sql) +{ + if (!dao) { dao = DaoEntity::create(""); } + if (!dao->isConnected()) + { + return Errcode::ERR_DB_CONN; + } + auto ret = dao->exec(sql); + return ret ? Errcode::OK : Errcode::ERR_DB_SQL; +} + +Errcode DAO::exec(std::shared_ptr dao, std::string sql, vector& result) +{ + if (!dao) { dao = DaoEntity::create(""); } + if (!dao->isConnected()) + { + return Errcode::ERR_DB_CONN; + } + auto ret = dao->exec(sql, result); + return ret ? Errcode::OK : Errcode::ERR_DB_SQL; +} + static bool QueryCount(DaoEntity& dao, std::string sqlFrom, int& count) { std::vector result; bool ret = dao.exec("SELECT COUNT(*) count " + sqlFrom, result); if (ret) { - count = (result.size() > 0) ? result[0].getInt("count") : 0; + count = (result.size() > 0) ? result[0].get("count") : 0; } return ret; } @@ -108,7 +130,7 @@ Errcode DAO::updateUserById(Fields& params) std::string createTime = Utils::timeStr(); std::string userId = params.value(DMUser::USER_ID); std::string roleId = ""; - if (params.hasKey(DMRole::ROLE_ID)) + if (params.contains(DMRole::ROLE_ID)) { roleId = params.value(DMRole::ROLE_ID); params.remove(DMUser::USER_ID); @@ -137,11 +159,10 @@ Errcode DAO::updateUserById(Fields& params) return Errcode::OK; } -bool DAO::queryRoleList(std::shared_ptr dao, vector& result) +Errcode DAO::queryRoleList(std::shared_ptr dao, vector& result) { - if (!dao) { dao = DaoEntity::create(""); } std::string sql = "SELECT * FROM " + DMRole::TABLENAME + ";"; - return dao->exec(sql, result); + return DAO::exec(dao, sql, result); } bool DAO::queryRoleList(PageInfo& pageInfo, vector& result) @@ -174,20 +195,16 @@ Errcode DAO::insertStation(Fields& params) params.remove(DMStation::STATION_ID); params.check(DMStation::LATITUDE, "", "NULL"); params.check(DMStation::LONGITUDE, "", "NULL"); - bool ret = dao->insertFields(params); - if (!ret) - { - return Errcode::ERR_DB_SQL; - } - return Errcode::OK; + + std::string sql = params.toSqlInsert(DMStation::TABLENAME); + return DAO::exec(dao, sql); } // 查询场站信息列表 -bool DAO::queryStationList(std::shared_ptr dao, vector& result) +Errcode DAO::queryStationList(std::shared_ptr dao, vector& result) { - if (!dao) { dao = DaoEntity::create(""); } std::string sql = "SELECT * FROM " + DMStation::TABLENAME; - return DaoEntity::execOnce(sql, result); + return DAO::exec(dao, sql, result); } // 分页查询场站信息列表 @@ -221,11 +238,10 @@ Errcode DAO::updateStationById(Fields& params) } // 查询设备信息列表 -bool DAO::queryDeviceList(std::shared_ptr dao, vector& result) +Errcode DAO::queryDeviceList(std::shared_ptr dao, vector& result) { - if (!dao) { dao = DaoEntity::create(""); } std::string sql = "SELECT * FROM " + DMDevice::TABLENAME; - return DaoEntity::execOnce(sql, result); + return DAO::exec(dao, sql, result); } // 分页查询设备信息列表 @@ -242,23 +258,17 @@ bool DAO::queryDeviceList(PageInfo& pageInfo, vector& result) } // 查询设备类型定义 -bool DAO::queryDeviceTypeDef(std::shared_ptr dao, vector& result) +Errcode DAO::queryDeviceTypeDef(std::shared_ptr dao, vector& result) { - if (!dao) { dao = DaoEntity::create(""); } - std::string sql = "SELECT * FROM " + DMDeviceTypeDef::TABLENAME + ";"; - return DaoEntity::execOnce(sql, result); + std::string sql = "SELECT * FROM " + DMDefDeviceType::TABLENAME + ";"; + return DAO::exec(dao, sql, result); } Errcode DAO::insertDevice(Fields& params) { - auto dao = DaoEntity::create(DMDevice::TABLENAME); - bool ret = dao->insertFields(params); - if (!ret) - { - return Errcode::ERR_DB_SQL; - } - return Errcode::OK; + return DAO::exec(NULL, params.toSqlInsert(DMDevice::TABLENAME)); } + Errcode DAO::updateDeviceById(Fields& params) { std::string deviceId = params.value(DMDevice::DEVICE_ID); @@ -266,13 +276,8 @@ Errcode DAO::updateDeviceById(Fields& params) { return Errcode::ERR_DB_SQL; } - auto dao = DaoEntity::create(DMDevice::TABLENAME); - bool ret = dao->updateFields(params, "WHERE " + DMDevice::DEVICE_ID + "='" + deviceId + "'"); - if (!ret) - { - return Errcode::ERR_DB_SQL; - } - return Errcode::OK; + std::string sql = params.toSqlUpdate(DMDevice::TABLENAME, "WHERE " + DMDevice::DEVICE_ID + "='" + deviceId + "'"); + return DAO::exec(NULL, sql); } // 策略管理 @@ -288,6 +293,12 @@ bool DAO::queryPolicyList(PageInfo& pageInfo, vector& result) return ret; } +Errcode DAO::queryPolicyList(std::shared_ptr dao, vector& result) +{ + std::string sql = "SELECT * FROM " + DMPolicy::TABLENAME; + return DAO::exec(dao, sql, result); +} + // 系统日志管理 bool DAO::querySystemLogList(PageInfo& pageInfo, vector& result) { @@ -301,8 +312,21 @@ bool DAO::querySystemLogList(PageInfo& pageInfo, vector& result) return ret; } -bool DAO::queryStatDataList(std::string startDate, std::string endDate, vector& result) +Errcode DAO::queryStatDataList(std::shared_ptr dao, std::string startDate, std::string endDate, vector& result) { std::string sql = "SELECT * FROM " + DMStatStation::TABLENAME + " WHERE dt BETWEEN '" + startDate + "' AND '" + endDate + "';"; - return DaoEntity::execOnce(sql, result); + return DAO::exec(dao, sql, result); +} + +Errcode DAO::queryWorkModeDef(std::shared_ptr dao, vector& result) +{ + std::string sql = "SELECT * FROM " + DMDefWorkMode::TABLENAME + ";"; + return DAO::exec(dao, sql, result); +} + + +Errcode DAO::queryPolicyTypeDef(std::shared_ptr dao, vector& result) +{ + std::string sql = "SELECT * FROM " + DMDefPolicyType::TABLENAME + ";"; + return DAO::exec(dao, sql, result); } \ No newline at end of file diff --git a/src/database/Dao.h b/src/database/Dao.h index 23dbdc8..a290c18 100644 --- a/src/database/Dao.h +++ b/src/database/Dao.h @@ -11,51 +11,55 @@ public: static bool count(DaoEntity& dao, std::string tableName, std::string condition, int& count); - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 用户管理 - // 新增用户信息 - static Errcode insertUser(Fields& params); - // 分页查询用户信息列表 + static Errcode exec(std::shared_ptr dao, std::string sql); + static Errcode exec(std::shared_ptr dao, std::string sql, vector& result); + + + // 查询用户信息列表(分页) static bool queryUserList(PageInfo& pageInfo, vector& result); + // 新增用户信息 + static Errcode insertUser(Fields& params); + // 更新用户信息 static Errcode updateUserById(Fields& params); - - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 角色管理 === - // 查询角色信息列表 - static bool queryRoleList(std::shared_ptr dao, vector& result); - // 分页查询角色信息列表 + + // 查询角色信息列表(分页) static bool queryRoleList(PageInfo& pageInfo, vector& result); - - - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 权限管理 === + // 查询角色信息列表 + static Errcode queryRoleList(std::shared_ptr dao, vector& result); + + + + // 查询权限信息列表(分页) static bool queryPermissionList(PageInfo& pageInfo, vector& result); - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 场站管理 === - // 新增场站信息 - static Errcode insertStation(Fields& params); - // 查询场站信息列表 - static bool queryStationList(std::shared_ptr dao, vector& result); - // 分页查询场站信息列表 + + + + // 查询场站信息列表(分页) static bool queryStationList(PageInfo& pageInfo, vector& result); + // 查询场站信息列表 + static Errcode queryStationList(std::shared_ptr dao, vector& result); + // 新增场站信息 + static Errcode insertStation(Fields& params); + // 更新场站信息 static Errcode updateStationById(Fields& params); - /////////////////////////////////////////////////////////////////////////////////////////////// - // === 设备管理 === - // 查询设备信息列表 - static bool queryDeviceList(std::shared_ptr dao, vector& result); - // 分页查询设备信息列表 - static bool queryDeviceList(PageInfo& pageInfo, vector& result); - // 查询设备类型定义 - static bool queryDeviceTypeDef(std::shared_ptr dao, vector& result); + + // 查询设备信息列表(分页) + static bool queryDeviceList(PageInfo& pageInfo, vector& result); + // 查询设备信息列表 + static Errcode queryDeviceList(std::shared_ptr dao, vector& result); + // 查询设备类型定义 + static Errcode queryDeviceTypeDef(std::shared_ptr dao, vector& result); + // 新增设备信息 static Errcode insertDevice(Fields& params); + // 更新设备信息 static Errcode updateDeviceById(Fields& params); /////////////////////////////////////////////////////////////////////////////////////////////// @@ -63,6 +67,8 @@ public: // 分页查询策略信息列表 static bool queryPolicyList(PageInfo& pageInfo, vector& result); + static Errcode queryPolicyList(std::shared_ptr dao, vector& result); + /////////////////////////////////////////////////////////////////////////////////////////////// // === 系统日志管理 === // 分页查询系统日志列表 @@ -70,7 +76,10 @@ public: /////////////////////////////////////////////////////////////////////////////////////////////// // === 统计数据管理 === - static bool queryStatDataList(std::string startDate, std::string endDate, vector& result); + static Errcode queryStatDataList(std::shared_ptr dao, std::string startDate, std::string endDate, vector& result); + static Errcode queryWorkModeDef(std::shared_ptr dao, vector& result); + + static Errcode queryPolicyTypeDef(std::shared_ptr dao, vector& result); }; \ No newline at end of file diff --git a/src/database/DaoEntity.cpp b/src/database/DaoEntity.cpp index e66cda8..16b11ac 100644 --- a/src/database/DaoEntity.cpp +++ b/src/database/DaoEntity.cpp @@ -41,8 +41,7 @@ void DaoEntity::setOption(std::string host, int port, std::string user, std::str std::shared_ptr DaoEntity::create(string tb_name) { - std::shared_ptr dao = std::make_shared(tb_name); - return (dao->isConnected() ? dao : nullptr); + return std::make_shared(tb_name); } bool DaoEntity::execOnce(string sql) @@ -79,7 +78,7 @@ bool DaoEntity::exec(string sql, vector& result) bool DaoEntity::insertFields(Fields& fields) { - string sql = fields.get_insert_sql(tableName_); + string sql = fields.toSqlInsert(tableName_); return this->db_->exec(sql); } @@ -95,7 +94,7 @@ bool DaoEntity::insertFields(vector& vec_fields) { keys = ""; values = ""; - for (auto& item : field.fields()) + for (auto& item : field.map()) { const string& k = item.first; const string& v = item.second; @@ -133,7 +132,7 @@ bool DaoEntity::duplicateUpdate(Fields& fields, const vector& keys) //insert into device_attr(device_id, attr_id, attr_val) values('26', 'model', '型号1') on duplicate key update attr_val='型号1'; string s_key; string s_val; - for (auto& item : fields.fields()) + for (auto& item : fields.map()) { if (!s_key.empty()) { @@ -162,18 +161,17 @@ bool DaoEntity::duplicateUpdate(Fields& fields, const vector& keys) // }); //} - -bool DaoEntity::queryFields(string keys, const string& sql_c, vector& result) +bool DaoEntity::queryFields(string keys, const string& condition, vector& result) { ostringstream oss; - oss << "SELECT " + keys + " FROM " << tableName_ << (" " + sql_c) << "; "; + oss << "SELECT " + keys + " FROM " << tableName_ << (" " + condition) << "; "; return this->db_->exec(oss.str(), result); } -bool DaoEntity::queryFields(string keys, const string& sql_c, PageInfo& page, vector& result) +bool DaoEntity::queryFields(string keys, const string& condition, PageInfo& page, vector& result) { ostringstream oss; - oss << "SELECT count(1) total FROM `" << tableName_ << "` " << sql_c << ";"; + oss << "SELECT count(1) total FROM `" << tableName_ << "` " << condition << ";"; vector res_total; if (!this->db_->exec(oss.str().c_str(), res_total)) @@ -186,7 +184,7 @@ bool DaoEntity::queryFields(string keys, const string& sql_c, PageInfo& page, ve page.total = 0; return true; } - page.total = res_total[0].getInt("total"); + page.total = res_total[0].get("total"); if (page.total <= 0) { return true; @@ -198,29 +196,18 @@ bool DaoEntity::queryFields(string keys, const string& sql_c, PageInfo& page, ve page.index = 1; } int start = (page.index - 1) * page.size; - oss << "SELECT " << keys << " FROM `" << tableName_ << "` " << sql_c << " LIMIT " << start << "," << page.size << ";"; + oss << "SELECT " << keys << " FROM `" << tableName_ << "` " << condition << " LIMIT " << start << "," << page.size << ";"; return this->db_->exec(oss.str().c_str(), result); } -bool DaoEntity::updateFields(Fields& fields, const string& sql_c) +bool DaoEntity::updateFields(Fields& fields, const string& condition) { - string sql = fields.get_update_sql(tableName_, sql_c); - std::cout << sql; - if (sql_c.empty()) - { - //Spdlogger::error("[DB] update condition is empty, not exec, sql={}", sql); - return false; - } - return this->db_->exec(sql.c_str()); + string sql = fields.toSqlUpdate(tableName_, condition); + return this->db_->exec(sql); } -bool DaoEntity::updateFields(Fields& fields, vector vec_keys, const string& sql_c) +bool DaoEntity::updateFields(Fields& fields, vector vecKeys, const string& condition) { - string sql = fields.get_update_sql(tableName_, vec_keys, sql_c); - if (sql_c.empty()) - { - //Spdlogger::error("[DB] update condition is empty, not exec, sql={}", sql); - return false; - } - return this->db_->exec(sql.c_str()); + string sql = fields.toSqlUpdate(tableName_, vecKeys, condition); + return this->db_->exec(sql); } \ No newline at end of file diff --git a/src/database/DataModelDef.h b/src/database/DataModelDef.h index 26bc4e6..2d30d87 100644 --- a/src/database/DataModelDef.h +++ b/src/database/DataModelDef.h @@ -3,6 +3,15 @@ #include using namespace std; +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// 工作模式定义 表结构字段 +namespace DMDefWorkMode +{ + const string TABLENAME = "def_work_mode"; + const string WORK_MODE_ID = "work_mode_id"; + const string NAME = "name"; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// /// 用户 表结构字段 namespace DMUser @@ -80,6 +89,16 @@ namespace DMStation const string TEL = "tel"; const string CAPACITY = "capacity"; const string STATUS = "status"; + const string WORK_MODE_ID = "work_mode_id"; + const string POLICY_ID = "policy_id"; +} + +namespace DMDefDeviceType +{ + const string TABLENAME = "def_device_type"; + const string DEVICE_TYPE_ID = "device_type_id"; + const string NAME = "name"; + const string ATTRS = "attrs"; } namespace DMDevice @@ -87,7 +106,7 @@ namespace DMDevice const string TABLENAME = "device"; const string DEVICE_ID = "device_id"; const string STATION_ID = "station_id"; - const string TYPE_ID = "type_id"; + const string TYPE = "type"; const string NAME = "name"; const string CODE = "code"; const string MODEL = "model"; @@ -100,12 +119,11 @@ namespace DMDevice const string UPDATE_TIME = "update_time"; } -namespace DMDeviceTypeDef +namespace DMDefPolicyType { - const string TABLENAME = "def_device_type"; - const string TYPE_ID = "type_id"; + const string TABLENAME = "def_policy_type"; + const string POLICY_TYPE_ID = "policy_type_id"; const string NAME = "name"; - const string ATTRS = "attrs"; } namespace DMPolicy diff --git a/src/database/MysqlClient.cpp b/src/database/MysqlClient.cpp index 4821894..076732f 100644 --- a/src/database/MysqlClient.cpp +++ b/src/database/MysqlClient.cpp @@ -50,12 +50,16 @@ void MysqlClient::close() bool MysqlClient::exec(std::string sql) { - //XLOGD() << "Mysql exec sql=" << sql; if (!mysql_) { XLOGE() << "Mysql exec error, database is not connected."; return false; } + if (sql.empty()) + { + XLOGE() << "Mysql exec error, sql is empty."; + return false; + } int ret = mysql_query(mysql_, sql.c_str()); if (0 != ret) { @@ -68,28 +72,18 @@ bool MysqlClient::exec(std::string sql) bool MysqlClient::exec(std::string sql, vector& result) { result.clear(); - if (!mysql_) + bool ret = MysqlClient::exec(sql); + if (!ret) { return false; } - int ret = mysql_query(mysql_, sql.c_str()); - if (0 != ret) - { - //Spdlogger::error("[mysql] mysql_query failed!! error ret={:d}, sql={}", ret, sql); - XLOGE() << "mysql error: " << sql; - return false; - } - else - { - //Spdlogger::info("[mysql] query success. sql={}", sql); - } MYSQL_RES* res = mysql_store_result(mysql_); if (!res) { return false; } - vector field_names; + vector fieldNames; while (true) { MYSQL_FIELD* field = mysql_fetch_field(res); @@ -97,7 +91,7 @@ bool MysqlClient::exec(std::string sql, vector& result) { break; } - field_names.push_back(field->name); + fieldNames.push_back(field->name); } while (true) @@ -108,13 +102,13 @@ bool MysqlClient::exec(std::string sql, vector& result) break; } - Fields row_data; - for (size_t i = 0; i < field_names.size(); ++i) + Fields rowData; + for (size_t i = 0; i < fieldNames.size(); ++i) { string field_text = (row[i] == NULL) ? "" : row[i]; - row_data.set(field_names[i], field_text); + rowData.set(fieldNames[i], field_text); } - result.push_back(row_data); + result.push_back(rowData); } // 释放结果集 diff --git a/src/database/SQL.cpp b/src/database/SQL.cpp new file mode 100644 index 0000000..83d1c23 --- /dev/null +++ b/src/database/SQL.cpp @@ -0,0 +1,64 @@ +#include "SQL.h" + +std::string SQL::str() +{ + if (type == TYPE::select) + { + // SELECT * from t_tabname WHERE id='1'; + if (sql_k.empty()) {} + std::string s = "SELECT " + (sql_k.empty() ? "*" : sql_k) + " FROM `" + tabname + "`"; + if (!sql_c.empty()) { s += (" WHERE" + sql_c); } + return s + ";"; + } + else if (type == TYPE::update) + { + // UPDATE t_tabname SET a='1', b='2' WHERE id='1'; + std::string s = "UPDATE `" + tabname + "` SET " + sql_k + " WHERE" + sql_c; + return s + ";"; + } + else if (type == TYPE::insert) + { + // INSERT INTO t_tabname (a,b,c) VALUES('1','2','3'); + std::string s = "INSERT INTO `" + tabname + "` (" + sql_k + ") VALUES(" + sql_v + ");"; + return s; + } + else if (type == TYPE::del) + { + return ""; + } + return ""; +} + +SQL& SQL::table(std::string t) +{ + tabname = t; + return *this; +} + +SQL& SQL::select(std::string k) +{ + if (!sql_k.empty()) { sql_k += ","; } + sql_k += k; + return *this; +} +SQL& SQL::where(std::string expr) +{ + sql_c += (" " + expr); + return *this; +} + +SQL& SQL::update(std::string k, std::string v) +{ + if (!sql_k.empty()) { sql_k += ","; } + sql_k += ("`" + k + "`='" + v + "'"); + return *this; +} + +SQL& SQL::insert(std::string k, std::string v) +{ + if (!sql_k.empty()) { sql_k += ","; } + sql_k += ("`" + k + "`"); + if (!sql_v.empty()) { sql_v += ","; } + sql_v += ("'" + v + "'"); + return *this; +} \ No newline at end of file diff --git a/src/database/SQL.h b/src/database/SQL.h index 66d20a2..cc0a564 100644 --- a/src/database/SQL.h +++ b/src/database/SQL.h @@ -13,71 +13,19 @@ public: del, }; - SQL(TYPE t = TYPE::select) : type(t) - { - } + SQL(TYPE t = TYPE::select) : type(t) {} - std::string str() - { - if (type == TYPE::select) - { - // SELECT * from t_tabname WHERE id='1'; - if (sql_k.empty()) {} - std::string s = "SELECT " + (sql_k.empty() ? "*" : sql_k) + " FROM `" + tabname + "`"; - if (!sql_c.empty()) { s += (" WHERE" + sql_c); } - return s + ";"; - } - else if (type == TYPE::update) - { - // UPDATE t_tabname SET a='1', b='2' WHERE id='1'; - std::string s = "UPDATE `" + tabname + "` SET " + sql_k + " WHERE" + sql_c; - return s + ";"; - } - else if (type == TYPE::insert) - { - // INSERT INTO t_tabname (a,b,c) VALUES('1','2','3'); - std::string s = "INSERT INTO `" + tabname + "` (" + sql_k + ") VALUES(" + sql_v + ");"; - return s; - } - else if (type == TYPE::del) - { - return ""; - } - return ""; - } - SQL& table(std::string t) - { - tabname = t; - return *this; - } + std::string str(); - SQL& select(std::string k) - { - if (!sql_k.empty()) { sql_k += ","; } - sql_k += k; - return *this; - } - SQL& where(std::string expr) - { - sql_c += (" " + expr); - return *this; - } + SQL& table(std::string t); - SQL& update(std::string k, std::string v) - { - if (!sql_k.empty()) { sql_k += ","; } - sql_k += ("`" + k + "`='" + v + "'"); - return *this; - } + SQL& select(std::string k); - SQL& insert(std::string k, std::string v) - { - if (!sql_k.empty()) { sql_k += ","; } - sql_k += ("`" + k + "`"); - if (!sql_v.empty()) { sql_v += ","; } - sql_v += ("'" + v + "'"); - return *this; - } + SQL& where(std::string expr); + + SQL& update(std::string k, std::string v); + + SQL& insert(std::string k, std::string v); private: TYPE type = TYPE::select; diff --git a/src/main.cpp b/src/main.cpp index 678798d..1287bc5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,23 +18,41 @@ #include "pv/PvApp.h" #include "pv/PvUser.h" + int main(int argc, char** argv) { - std::string str = "用户编号"; - int a = str.size(); - int b = str.length(); - - int x = 5/10 + int(6%10 != 0); - // 设置控制台输出为 UTF-8 编码 SetConsoleOutputCP(CP_UTF8); // 设置控制台输入为 UTF-8 编码(如果需要输入中文) SetConsoleCP(CP_UTF8); - - NJson jsonroot; - NJsonParse(R"({"name": "Alice", "age": 25, 111,})", jsonroot); - std::cout << (jsonroot.is_null() ? "ERROR" : "OK") << std::endl; + { + + NJsonNode jsonroot; + NJson::parse(R"({"name": "Alice", "age": 25, "data":[["1","1","1"],["1","1","1"],["1","1","1"]]})", jsonroot); + std::cout << (jsonroot.is_null() ? "ERROR" : "OK") << std::endl; + + std::vector> v1; + NJson::read>>(jsonroot, "data", v1); + + std::vector> vec = { + {"1", "1", "1", "1", "1", "1", "1", "1"}, + {"1", "1", "1", "1", "1", "1", "1", "1"}, + {"1", "1", "1", "1", "1", "1", "1", "1"}, + {"1", "1", "1", "1", "1", "1", "1", "1"} + }; + + NJsonNode jsonroot1; + jsonroot1["price_super_peak"] = 0.53; + jsonroot1["price_peak"] = 0.53; + jsonroot1["price_shoulder"] = 0.53; + jsonroot1["price_off_peak"] = 0.53; + jsonroot1["periods"] = vec; + + std::cout << jsonroot1.dump(); + } + + std::cout << "===>>> main start ... " << std::endl; ////std::cout << Snowflake::instance().getId() << std::endl; //for (int i = 0; i<=10; ++i) { @@ -83,7 +101,7 @@ int main(int argc, char** argv) //mainWin.show(); //qapp.exec(); - + // 运行pv主流程 PARAM p; int s; pvInit(argc, argv, &p); diff --git a/src/protocol/Communicator.cpp b/src/protocol/Communicator.cpp index 69ac712..e8fe42d 100644 --- a/src/protocol/Communicator.cpp +++ b/src/protocol/Communicator.cpp @@ -5,8 +5,8 @@ std::shared_ptr Communicator::createEntity(Fields& data) { std::string commType = data.value("commType"); std::string ip = data.value("ip"); - int port = data.getInt("port"); - int isclient = data.getInt("isclient"); + int port = data.get("port"); + int isclient = data.get("isclient"); if (commType == "TCP") { diff --git a/src/pv/PvApp.cpp b/src/pv/PvApp.cpp index 3b07555..1e0b93e 100644 --- a/src/pv/PvApp.cpp +++ b/src/pv/PvApp.cpp @@ -132,7 +132,7 @@ int PvApp::image(PARAM* p, int parent, int x, int y, int w, int h, const char* f return id; } -int PvApp::combox(PARAM* p, int parent, int x, int y, int w, int h, const std::vector& vecItems) +int PvApp::combox(PARAM* p, int parent, int x, int y, int w, int h, const std::vector& vecItems, int index /*= 0*/) { int id = PvApp::pvid(p); pvQComboBox(p, id, parent, 0, 0); @@ -141,8 +141,9 @@ int PvApp::combox(PARAM* p, int parent, int x, int y, int w, int h, const std::v for (int i=0; i& vecItems); + static int combox(PARAM* p, int parent, int x, int y, int w, int h, const std::vector& vecItems, int index=0); static int lineEdit(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string qss = ""); static int textEdit(PARAM* p, int parent, int x, int y, int w, int h, std::string text, std::string qss = ""); + + static int radioButton(PARAM* p, int parent, int x, int y, int w, int h, std::string text); + + static int timeEdit(PARAM* p, int parent, int x, int y, int w, int h); }; /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/pv/PvPopWidget.cpp b/src/pv/PvPopWidget.cpp index c1cf2b4..605ab41 100644 --- a/src/pv/PvPopWidget.cpp +++ b/src/pv/PvPopWidget.cpp @@ -159,7 +159,7 @@ Fields PvPopWidget::getChangedData() { auto& key = it->second->key; auto& val = it->second->val; - if (primaryKeys.hasKey(key) || val != dataOrigin.value(key)) + if (primaryKeys.contains(key) || val != dataOrigin.value(key)) { fields.set(key, val); } @@ -174,7 +174,7 @@ void PvPopWidget::checkChangedData(Fields& fields) { auto& key = it->first; auto& val = it->second; - if (!primaryKeys.hasKey(key) && val == dataOrigin.value(key)) + if (!primaryKeys.contains(key) && val == dataOrigin.value(key)) { mapItems.erase(it); } diff --git a/src/pv/PvStyle.cpp b/src/pv/PvStyle.cpp index 54aae3a..ac26abb 100644 --- a/src/pv/PvStyle.cpp +++ b/src/pv/PvStyle.cpp @@ -111,15 +111,11 @@ namespace qss "QComboBox:disabled { color:rgb(150,150,150);}"; const std::string LINEEDIT = - "QLineEdit { background-color: rgb(12, 39, 58); border: 1px solid rgb(18, 251, 255); border-radius: 5px; color:white; font: bold 15px;}" + "QLineEdit { background-color: rgb(12, 39, 58); border: 1px solid rgb(18, 251, 255); border-radius: 5px; color:white; font: bold 14px;}" "QLineEdit:disabled { border: 1px solid gray; color:rgb(150,150,150);}"; - - - - const std::string STYLE_TITLE_ICON = "padding-top: 0px;" "background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 71, 105, 255),stop:1 rgba(0, 71, 105, 0));" @@ -142,7 +138,7 @@ namespace qss // 表头标签 const std::string QSS_TABLE_HEAD = - qss::label(15, "", "rgb(18, 93, 113)", "1px solid rgb(120, 120, 120); border-style:inset solid"); + qss::label(14, "", "rgb(18, 93, 113)", "1px solid rgb(120, 120, 120); border-style:inset solid"); //"background-color: rgb(18, 93, 113); color:rgb(255, 255, 255); font:bold 16px;" //"border-width:1 1 1 1px; border-style:inset solid; border-color:rgb(120, 120, 120);"; diff --git a/src/pv/PvTable.cpp b/src/pv/PvTable.cpp index 88aa826..b001fa6 100644 --- a/src/pv/PvTable.cpp +++ b/src/pv/PvTable.cpp @@ -1,6 +1,7 @@ #include "PvTable.h" #include "PvStyle.h" #include "pv/PvApp.h" +#include "pv/PvPopWidget.h" static const string STYLE_BKG = "border-width:1 1 1 1px; border-style:outset solid; border-color:rgba(180,180,180,255);" @@ -208,7 +209,7 @@ void PvTable::mappingData(Fields& fields) for (int i=0; i< vecHead_.size(); ++i) { auto& head = vecHead_[i]; - if (fields.hasKey(head.id)) + if (fields.contains(head.id)) { auto& val = fields.value(head.id); val = head.getMapping(val); @@ -417,16 +418,91 @@ void PvPagination::setCallback(std::function func) callback = func; } -PvPageTable::PvPageTable(PARAM* p, int parent, int x, int y, int w, int rows, PvTable::Options& opts) -//: PvWidget(p, parent, PvRect(x, y, w, opts.item_height* rows + (opts.show_header ? (opts.header_height) : 0))) - : PvObject(p) -{ - int h = opts.row_height* rows + (opts.show_header ? (opts.head_height) : 0); - int pvid_ = PvApp::widget(p, parent, x, y, w, h); - table_ = make_shared(p, pvid_, 0, 0, w, rows, opts); -} -shared_ptr PvPageTable::getTable() +/////////////////////////////////////////////////////////////////////////////////////////////////// +// === PageTable === +PageTable::PageTable(PARAM* p) : PvMask(p) { - return table_; -} \ No newline at end of file + table = std::make_shared(p, 0, 20, 210, 1880, pageSize, option); + table->setOperateCallback([=](int row, int col, std::string text) { this->onOperate(row, col, text); }); + + pagination = std::make_shared(p, 0, 20, 780, 20); + pagination->setCallback([=](int index) + { + pageIndex = index; + this->updateDataFromDB(); + }); +} +std::shared_ptr PageTable::addPop(int w, int h, int w0, std::string name, std::vector primaryKeys) +{ + std::shared_ptr pop = std::make_shared(p, w, h, name); + pop->lineValWidth = w0; + pop->setPrimaryKeys(primaryKeys); + pop->setCallbackConfirm([=]() + { + auto fields = pop->getData(); + std::string err = this->onValidation(pop, fields); + pop->setMsg(err); + + if (err.empty()) + { + XLOGD() << "POP get: data=" << fields.toStr(); + if (pop->status == POP_OPER_EDIT) { pop->checkChangedData(fields); } + XLOGD() << "POP get: data=" << fields.toStr(); + table->mappingData(fields); + XLOGD() << "POP get: data=" << fields.toStr(); + err = this->onPopConfirm(pop, fields); + pop->setMsg(err); + if (err.empty()) + { + this->hidePop(0); + this->updateDataFromDB(); + }; + } + }); + pop->show(0); + vecPop.push_back(pop); + return pop; +} +void PageTable::showPop(int index, std::string oper, Fields& fields) +{ + XLOGD() << "POP set: data=" << fields.toStr(); + table->mappingData(fields); + XLOGD() << "POP set: data=" << fields.toStr(); + if (index < vecPop.size()) + { + auto& pop = vecPop[index]; + pop->show(true); + pop->setStatus(oper); + pop->setData(fields); + pop->setMsg(""); + } +} +void PageTable::hidePop(int index) +{ + if (index < vecPop.size()) + { + vecPop[index]->show(false); + } +} +void PageTable::updateDataFromDB() +{ + std::vector result; + PageInfo pageInfo; + pageInfo.size = pageSize; + pageInfo.index = pageIndex; + this->onQueryTable(pageInfo, result); + for (int i = 0; irows(); ++i) + { + if (isetRowData(i, result[i]); + } + else + { + table->setRowVisible(i, false); + } + } + pagination->setPage(pageInfo.index, pageInfo.total/pageInfo.size + int(pageInfo.total%pageInfo.size != 0)); +} diff --git a/src/pv/PvTable.h b/src/pv/PvTable.h index 1222c2e..f8cb866 100644 --- a/src/pv/PvTable.h +++ b/src/pv/PvTable.h @@ -158,16 +158,34 @@ private: }; -class PvPageTable :public PvObject +/////////////////////////////////////////////////////////////////////////////////////////////////// +// === PageTable === +class PvPopWidget; +class PageTable : public PvMask { public: - PvPageTable(PARAM* p, int parent, int x, int y, int w, int rows, PvTable::Options& opts); + PageTable(PARAM* p); - shared_ptr getTable(); + void setPage(int pageIndex, int pageSize, int count) {} -private: - shared_ptr table_ = nullptr; - shared_ptr page_ctrl_ = nullptr; + std::shared_ptr addPop(int w, int h, int w0, std::string name, std::vector primaryKeys); + + void showPop(int index, std::string optr, Fields& fields); + void hidePop(int index); + + void updateDataFromDB(); + + virtual void onQueryTable(PageInfo& pageInfo, std::vector& result) {} + virtual void onOperate(int row, int col, std::string oper) {}; + virtual std::string onValidation(std::shared_ptr pop, Fields& fields) { return ""; }; + virtual std::string onPopConfirm(std::shared_ptr pop, Fields& fields) { return ""; }; + + int pageSize {15}; + int pageIndex {0}; + PvTable::Options option; + std::shared_ptr table; + std::shared_ptr pagination; + std::vector> vecPop; }; #endif // ! _PvTable_H_ \ No newline at end of file diff --git a/src/pv/pages/MaskPageHome.cpp b/src/pv/pages/MaskPageHome.cpp index c73425a..11f988a 100644 --- a/src/pv/pages/MaskPageHome.cpp +++ b/src/pv/pages/MaskPageHome.cpp @@ -5,6 +5,20 @@ #include "pv/PvTable.h" #include "pv/PvChart.h" +#include "pv/PvPopWidget.h" +#include "pv/pages/PanelPolicy.h" + + +void TestPage(PARAM* p) +{ + auto& appdata = Application::data(); + auto pagination = new PvPagination(p, 0, 600, 160, 20); + pagination->setPage(5, 10); + + int id = PvApp::label(p, 0, 0, 0, 1920, 800, "", qss::label(14, "", "rgb(15, 50, 68)")); + new PanelPolicyPeak(p, id, 0, 0, 1920, 1080); +} + static int CreatePanel(PARAM* p, int parent, int x, int y, int w, int h, std::string title) { @@ -304,8 +318,10 @@ int MaskPageHome::initUI(EPvCode pvcode) this->updateUI(); - auto pagination = new PvPagination(p, 0, 600, 160, 20); - pagination->setPage(5, 10); + + TestPage(p); + + return 0; } diff --git a/src/pv/pages/MaskPageRunning.cpp b/src/pv/pages/MaskPageRunning.cpp index a715771..ae7d194 100644 --- a/src/pv/pages/MaskPageRunning.cpp +++ b/src/pv/pages/MaskPageRunning.cpp @@ -1,6 +1,6 @@ #include "MaskPageRunning.h" #include "app/Application.h" - +#include "app/AppData.h" static int CreateParamLabel(PARAM* p, int parent, int x, int y, std::string k, std::string v) { @@ -119,10 +119,10 @@ int MaskPageRunning::initUI(EPvCode pvcode) } PvApp::label(p, 0, 320, 110, 80, 30, "运行模式", "color:white; font: bold 16px;"); - PvApp::combox(p, 0, 400, 110, 200, 30, {"最优经济化运行模式", "最优经济化运行模式", "自定义"}); + PvApp::combox(p, 0, 400, 110, 200, 30, Application::data().getWorkModes()); PvApp::label(p, 0, 670, 110, 80, 30, "策略名称", "color:white; font: bold 16px;"); - PvApp::combox(p, 0, 750, 110, 200, 30, {"峰谷套利策略", "需求响应策略", "自发自用上网策略"}); + PvApp::combox(p, 0, 750, 110, 200, 30, Application::data().getPolicyNames()); int x = 20, y = 160, w = 200, h = 180; // 储能设备 diff --git a/src/pv/pages/MaskPageSysmgr.cpp b/src/pv/pages/MaskPageSysmgr.cpp index 3cff900..0d65a6a 100644 --- a/src/pv/pages/MaskPageSysmgr.cpp +++ b/src/pv/pages/MaskPageSysmgr.cpp @@ -6,7 +6,7 @@ #include "pv/PvPopWidget.h" #include "database/Dao.h" #include "app/Application.h" -#include "PageSysmgrPop.h" +#include "PageSysmgr.h" static void createPvTable(PARAM* p) { diff --git a/src/pv/pages/PageSysmgrPop.cpp b/src/pv/pages/PageSysmgr.cpp similarity index 83% rename from src/pv/pages/PageSysmgrPop.cpp rename to src/pv/pages/PageSysmgr.cpp index 945729d..6eb00f3 100644 --- a/src/pv/pages/PageSysmgrPop.cpp +++ b/src/pv/pages/PageSysmgr.cpp @@ -1,4 +1,4 @@ -#include "PageSysmgrPop.h" +#include "PageSysmgr.h" #include "app/Application.h" @@ -6,94 +6,6 @@ #include "database/DataModelDef.h" #include "common/Snowflake.h" -/////////////////////////////////////////////////////////////////////////////////////////////////// -// === PageTable === -PageTable::PageTable(PARAM* p) : PvMask(p) -{ - table = std::make_shared(p, 0, 20, 210, 1880, pageSize, option); - table->setOperateCallback([=](int row, int col, std::string text) { this->onOperate(row, col, text); }); - - pagination = std::make_shared(p, 0, 20, 780, 20); - pagination->setCallback([=](int index) - { - pageIndex = index; - this->updateDataFromDB(); - }); -} -std::shared_ptr PageTable::addPop(int w, int h, int w0, std::string name, std::vector primaryKeys) -{ - std::shared_ptr pop = std::make_shared(p, w, h, name); - pop->lineValWidth = w0; - pop->setPrimaryKeys(primaryKeys); - pop->setCallbackConfirm([=]() - { - auto fields = pop->getData(); - std::string err = this->onValidation(pop, fields); - pop->setMsg(err); - - if (err.empty()) - { - XLOGD() << "POP get: data=" << fields.toStr(); - if (pop->status == POP_OPER_EDIT) { pop->checkChangedData(fields); } - XLOGD() << "POP get: data=" << fields.toStr(); - table->mappingData(fields); - XLOGD() << "POP get: data=" << fields.toStr(); - err = this->onPopConfirm(pop, fields); - pop->setMsg(err); - if (err.empty()) - { - this->hidePop(0); - this->updateDataFromDB(); - }; - } - }); - pop->show(0); - vecPop.push_back(pop); - return pop; -} -void PageTable::showPop(int index, std::string oper, Fields& fields) -{ - XLOGD() << "POP set: data=" << fields.toStr(); - table->mappingData(fields); - XLOGD() << "POP set: data=" << fields.toStr(); - if (index < vecPop.size()) - { - auto& pop = vecPop[index]; - pop->show(true); - pop->setStatus(oper); - pop->setData(fields); - pop->setMsg(""); - } -} -void PageTable::hidePop(int index) -{ - if (index < vecPop.size()) - { - vecPop[index]->show(false); - } -} -void PageTable::updateDataFromDB() -{ - std::vector result; - PageInfo pageInfo; - pageInfo.size = pageSize; - pageInfo.index = pageIndex; - this->onQueryTable(pageInfo, result); - for (int i = 0; irows(); ++i) - { - if (isetRowData(i, result[i]); - } - else - { - table->setRowVisible(i, false); - } - } - pagination->setPage(pageInfo.index, pageInfo.total/pageInfo.size + int(pageInfo.total%pageInfo.size != 0)); -} - /////////////////////////////////////////////////////////////////////////////////////////////////// // === PageUser === @@ -215,6 +127,7 @@ std::string PageRole::onPopConfirm(std::shared_ptr pop, Fields& fie return ""; } + /////////////////////////////////////////////////////////////////////////////////////////////////// // === PagePermission === PagePermission::PagePermission(PARAM* p, EPvCode pvcode) : PageTable(p) @@ -326,13 +239,14 @@ std::string PageStation::onPopConfirm(std::shared_ptr pop, Fields& } return ""; } + /////////////////////////////////////////////////////////////////////////////////////////////////// // === PageDevice === PageDevice::PageDevice(PARAM* p, EPvCode pvcode) : PageTable(p) { auto& appdata = Application::data(); table->addHead(DMDevice::DEVICE_ID, "设备编号", 120, {}); - table->addHead(DMDevice::TYPE_ID, "设备类型", 120, appdata.mapping.deviceType); + table->addHead(DMDevice::TYPE, "设备类型", 120, appdata.mapping.deviceType); table->addHead(DMDevice::NAME, "设备名称", 180, {}); table->addHead(DMDevice::CODE, "设备编码", 160, {}); table->addHead(DMDevice::MODEL, "设备型号", 160, {}); @@ -348,7 +262,7 @@ PageDevice::PageDevice(PARAM* p, EPvCode pvcode) : PageTable(p) int x = 50, y = 80, w = 350, h = 60; auto pop = this->addPop(700, 520, 180, "设备信息", {DMDevice::DEVICE_ID}); pop->addParamLineEdit(DMDevice::DEVICE_ID, "设备编号", x, y, false); - pop->addParamCombox(DMDevice::TYPE_ID, "类型", x+w, y, appdata.getDeviceTypes()); + pop->addParamCombox(DMDevice::TYPE, "类型", x+w, y, appdata.getDeviceTypeNames()); pop->addParamLineEdit(DMDevice::NAME, "设备名称", x, y += h); pop->addParamLineEdit(DMDevice::CODE, "设备编码", x+w, y); pop->addParamLineEdit(DMDevice::MODEL, "设备型号", x, y += h); @@ -394,8 +308,11 @@ std::string PageDevice::onPopConfirm(std::shared_ptr pop, Fields& f } return ""; } + /////////////////////////////////////////////////////////////////////////////////////////////////// // === PagePolicy === + + PagePolicy::PagePolicy(PARAM* p, EPvCode pvcode) : PageTable(p) { auto& appdata = Application::data(); @@ -410,9 +327,18 @@ PagePolicy::PagePolicy(PARAM* p, EPvCode pvcode) : PageTable(p) int btnNew = PvApp::button(p, PV_ID_MAIN, 20, 160, 80, 35, POP_OPER_NEW); PvApp::bind(p, PvEvent::BUTTON_EVENT, btnNew, [=](std::string) { this->onOperate(-1, -1, POP_OPER_NEW); }); - int x = 80, y = 80, h = 60; - auto pop = this->addPop(500, 600, 180, "策略信息", {DMPolicy::POLICY_ID}); - pop->addParamLineEdit(DMPolicy::POLICY_ID, "编号", x, y, false); + int x = 50, y = 80, w = 280; + auto pop = this->addPop(1620, 800, 180, "策略信息", {DMPolicy::POLICY_ID}); + //pop->addParamLineEdit(DMPolicy::POLICY_ID, "编号", x, y, false); + { + pop->addParamLineEdit("1", "策略名称", x, y); + pop->addParamCombox("2", "策略类型", x+w, y, {"峰谷套利"}); + pop->addParamLineEdit("3", "尖峰电价", x, y += 50); + pop->addParamLineEdit("4", "高峰电价", x+w, y); + pop->addParamLineEdit("5", "平段电价", x+w*2, y); + pop->addParamLineEdit("6", "低谷电价", x+w*3, y); + } + } void PagePolicy::onQueryTable(PageInfo& pageInfo, std::vector& result) { @@ -423,12 +349,18 @@ void PagePolicy::onOperate(int row, int col, std::string oper) if (oper == POP_OPER_NEW) { Fields fields; - fields.set(DMUser::USER_ID, Snowflake::instance().getIdStr()); this->showPop(0, oper, fields); } else if (oper == POP_OPER_EDIT) { - this->showPop(0, oper, table->getRowData(row)); + table->getRowData(row); + auto& appdata = Application::data(); + Fields fields; + fields.set("3", appdata.electPriceSuperPeak); + fields.set("4", appdata.electPricePeak); + fields.set("5", appdata.electPriceShoulder); + fields.set("6", appdata.electPriceOffPeak); + this->showPop(0, oper, fields); } } std::string PagePolicy::onValidation(std::shared_ptr pop, Fields& fields) @@ -438,6 +370,8 @@ std::string PagePolicy::onValidation(std::shared_ptr pop, Fields& f std::string PagePolicy::onPopConfirm(std::shared_ptr pop, Fields& fields) { + + return ""; } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/pv/pages/PageSysmgrPop.h b/src/pv/pages/PageSysmgr.h similarity index 81% rename from src/pv/pages/PageSysmgrPop.h rename to src/pv/pages/PageSysmgr.h index 2879ffd..7c8f8dc 100644 --- a/src/pv/pages/PageSysmgrPop.h +++ b/src/pv/pages/PageSysmgr.h @@ -3,34 +3,6 @@ #include "pv/PvTable.h" #include "pv/PvPopWidget.h" -/////////////////////////////////////////////////////////////////////////////////////////////////// -// === PageTable === -class PageTable : public PvMask -{ -public: - PageTable(PARAM* p); - - void setPage(int pageIndex, int pageSize, int count) {} - - std::shared_ptr addPop(int w, int h, int w0, std::string name, std::vector primaryKeys); - - void showPop(int index, std::string optr, Fields& fields); - void hidePop(int index); - - void updateDataFromDB(); - - virtual void onQueryTable(PageInfo& pageInfo, std::vector& result) {} - virtual void onOperate(int row, int col, std::string oper) {}; - virtual std::string onValidation(std::shared_ptr pop, Fields& fields) { return ""; }; - virtual std::string onPopConfirm(std::shared_ptr pop, Fields& fields) { return ""; }; - - int pageSize {15}; - int pageIndex {0}; - PvTable::Options option; - std::shared_ptr table; - std::shared_ptr pagination; - std::vector> vecPop; -}; /////////////////////////////////////////////////////////////////////////////////////////////////// // === PageUser === @@ -108,6 +80,8 @@ public: virtual void onOperate(int row, int col, std::string oper) override; virtual std::string onValidation(std::shared_ptr pop, Fields& fields) override; virtual std::string onPopConfirm(std::shared_ptr pop, Fields& fields) override; + + }; /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/pv/pages/PanelPolicy.cpp b/src/pv/pages/PanelPolicy.cpp new file mode 100644 index 0000000..bd4a089 --- /dev/null +++ b/src/pv/pages/PanelPolicy.cpp @@ -0,0 +1,366 @@ +#include "PanelPolicy.h" +#include "app/Application.h" +#include "app/AppData.h" +#include "common/JsonN.h" + +const std::string QSS_COMBOX_1 = +"QComboBox {border: 1px solid rgb(18, 251, 255); background-color: rgb(255, 89, 0); border-radius: 3px; color: rgb(30,30,30); font: bold 14px;}" +"QComboBox QAbstractItemView { border: 1px solid gray; background-color: rgba(8, 54, 91); border-radius: 5px; color:white;}" +"QComboBox::drop-down { border-radius: 5px; width: 30px; }" +"QComboBox:disabled { color:rgb(150,150,150);}"; + +const std::string QSS_COMBOX_2 = +"QComboBox {border: 1px solid rgb(18, 251, 255); background-color: rgb(255, 255, 0); border-radius: 3px; color: rgb(30,30,30); font: bold 14px;}" +"QComboBox QAbstractItemView { border: 1px solid gray; background-color: rgba(8, 54, 91); border-radius: 5px; color:white;}" +"QComboBox::drop-down { border-radius: 5px; width: 30px; }" +"QComboBox:disabled { color:rgb(150,150,150);}"; + +const std::string QSS_COMBOX_3 = +"QComboBox {border: 1px solid rgb(18, 251, 255); background-color: rgb(121, 191, 226); border-radius: 3px; color: rgb(30,30,30); font: bold 14px;}" +"QComboBox QAbstractItemView { border: 1px solid gray; background-color: rgba(8, 54, 91); border-radius: 5px; color:white;}" +"QComboBox::drop-down { border-radius: 5px; width: 30px; }" +"QComboBox:disabled { color:rgb(150,150,150);}"; + +const std::string QSS_COMBOX_4 = +"QComboBox {border: 1px solid rgb(18, 251, 255); background-color: rgb(0, 255, 58); border-radius: 3px; color: rgb(30,30,30); font: bold 14px;}" +"QComboBox QAbstractItemView { border: 1px solid gray; background-color: rgba(8, 54, 91); border-radius: 5px; color:white;}" +"QComboBox::drop-down { border-radius: 5px; width: 30px; }" +"QComboBox:disabled { color:rgb(150,150,150);}"; + +static std::string GetPeriodQss(int v) +{ + if (v == 1) { return QSS_COMBOX_1; } + else if (v == 2) { return QSS_COMBOX_2; } + else if (v == 3) { return QSS_COMBOX_3; } + else if (v == 4) { return QSS_COMBOX_4; } + else { return QSS_COMBOX_1; } +} +static std::string GetPeriodQss(std::string text) +{ + if (text == "尖峰") { return QSS_COMBOX_1; } + else if (text == "高峰") { return QSS_COMBOX_2; } + else if (text == "平段") { return QSS_COMBOX_3; } + else if (text == "低谷") { return QSS_COMBOX_4; } + else { return QSS_COMBOX_1; } +} +static int GetPeriod(std::string text) +{ + if (text == "尖峰") { return 1; } + else if (text == "高峰") { return 2; } + else if (text == "平段") { return 3; } + else if (text == "低谷") { return 4; } + else { return 3; } +} +PanelPolicyPeak::PanelPolicyPeak(PARAM* p, int parent, int x, int y, int w, int h) : PvObject(p) +{ + data.vecPeriods.resize(12, std::vector(24, 3)); + ui.parent = parent; + ui.widget = PvApp::widget(p, parent, x, y, w, h); + + auto& appdata = Application::data(); + std::vector vecPeriods = {"尖峰", "高峰", "平段", "低谷"}; + + ui.vecComboxs.resize(12, std::vector(24, PV_ID_NUL)); + { + int parent = ui.widget; + int x = 10, y = 180, w = 64, h = 30; + for (int row = 0; row<=12; row++) + { + for (int col = 0; col<=24; ++col) + { + std::string text; + if (row == 0) + { + text = (col == 0) ? "月份" : std::to_string(col-1) + "-" + std::to_string(col) + "时"; + } + else + { + text = (col == 0) ? std::to_string(row) : ""; + } + if (row == 0 || col == 0) + { + std::string qssLabel = (row==0) ? qss::label(14, "", "rgb(19, 93, 114)") : ""; + int label = PvApp::label(p, parent, x+w*col, y+h*row, w, h, text, qssLabel); + pvSetAlignment(p, label, AlignCenter); + } + else + { + int periodVal = data.vecPeriods[row-1][col-1]; + int combox = PvApp::combox(p, parent, x+w*col, y+h*row+3, w-3, 24, vecPeriods, periodVal); + pvSetStyleSheet(p, combox, GetPeriodQss(periodVal).c_str()); + ui.vecComboxs[row-1][col-1] = combox; + PvApp::bind(p, PvEvent::TEXT_EVENT, combox, [=](std::string text) { + pvSetStyleSheet(p, combox, GetPeriodQss(text).c_str()); + data.vecPeriods[row-1][col-1] = GetPeriod(text); + }); + } + + } + } + + const int H = 24; + int labelPolicy = PvApp::label(p, parent, 20, 600, 300, H, "充电策略"); + ui.radioPolicy1 = PvApp::radioButton(p, labelPolicy, 80, 0, 80, H, "一充一放"); + ui.radioPolicy2 = PvApp::radioButton(p, labelPolicy, 170, 0, 80, H, "两充两放"); + + ui.label1 = PvApp::label(p, parent, 10, 640, 610, 90, "第一次充放电过程", qss::label(14, "", "", "1px solid rgb(49, 130, 141)")); + pvSetAlignment(p, ui.label1, AlignLeft | AlignTop); + { + int y0 = 70; + int labelChargeT = PvApp::label(p, ui.label1, 10, 30, 300, H, "充电时间"); + ui.attr1TimeCharge0 = PvApp::timeEdit(p, labelChargeT, y0, 0, 60, H); + PvApp::label(p, labelChargeT, 150, 0, 10, H, "--"); + ui.attr1TimeCharge1 = PvApp::timeEdit(p, labelChargeT, 170, 0, 60, H); + + int labelDischargeT = PvApp::label(p, ui.label1, 320, 30, 300, H, "放电时间"); + ui.attr1TimeDischarge0 = PvApp::timeEdit(p, labelDischargeT, y0 = 70, 0, 60, H); + PvApp::label(p, labelDischargeT, y0+=70, 0, 10, H, "--"); + ui.attr1TimeDischarge1 = PvApp::timeEdit(p, labelDischargeT, y0+=20, 0, 60, H); + + int labelPowerIn = PvApp::label(p, ui.label1, 10, 60, 300, H, "充电功率"); + ui.attr1RadioPowerInAuto = PvApp::radioButton(p, labelPowerIn, y0 = 70, 0, 60, H, "自动"); + ui.attr1RadioPowerIn = PvApp::radioButton(p, labelPowerIn, y0 += 60, 0, 64, H, "自定义"); + ui.arrt1LabelPowerIn = PvApp::lineEdit(p, labelPowerIn, y0 += 70, 0, 80, H, ""); + + int labelPowerOut = PvApp::label(p, ui.label1, 320, 60, 300, H, "放电功率"); + ui.attr1RadioPowerOutAuto = PvApp::radioButton(p, labelPowerOut, y0 = 70, 0, 60, H, "自动"); + ui.attr1RadioPowerOut = PvApp::radioButton(p, labelPowerOut, y0 += 60, 0, 64, H, "自定义"); + ui.arrt1LabelPowerOut = PvApp::lineEdit(p, labelPowerOut, y0 += 70, 0, 80, H, ""); + } + + ui.label2 = PvApp::label(p, parent, 630, 640, 610, 90, "第二次充放电过程", qss::label(14, "", "", "1px solid rgb(49, 130, 141)")); + pvSetAlignment(p, ui.label2, AlignLeft | AlignTop); + { + int y0 = 70; + int labelChargeT = PvApp::label(p, ui.label2, 10, 30, 300, H, "充电时间"); + XLOGD() << "labelChargeT=" << labelChargeT; + ui.attr2TimeCharge0 = PvApp::timeEdit(p, labelChargeT, y0, 0, 60, H); + PvApp::label(p, labelChargeT, 150, 0, 10, H, "--"); + ui.attr2TimeCharge1 = PvApp::timeEdit(p, labelChargeT, 170, 0, 60, H); + + + + + int labelDischargeT = PvApp::label(p, ui.label2, 320, 30, 300, H, "放电时间"); + ui.attr2TimeDischarge0 = PvApp::timeEdit(p, labelDischargeT, y0 = 70, 0, 60, H); + PvApp::label(p, labelDischargeT, y0 += 70, 0, 10, H, "--"); + ui.attr2TimeDischarge1 = PvApp::timeEdit(p, labelDischargeT, y0 += 20, 0, 60, H); + + int labelPowerIn = PvApp::label(p, ui.label2, 10, 60, 300, H, "充电功率"); + ui.attr2RadioPowerInAuto = PvApp::radioButton(p, labelPowerIn, y0 = 70, 0, 60, H, "自动"); + ui.attr2RadioPowerIn = PvApp::radioButton(p, labelPowerIn, y0 += 60, 0, 64, H, "自定义"); + ui.arrt2LabelPowerIn = PvApp::lineEdit(p, labelPowerIn, y0 += 70, 0, 80, H, ""); + + int labelPowerOut = PvApp::label(p, ui.label2, 320, 60, 300, H, "放电功率"); + ui.attr2RadioPowerOutAuto = PvApp::radioButton(p, labelPowerOut, y0 = 70, 0, 60, H, "自动"); + ui.attr2RadioPowerOut = PvApp::radioButton(p, labelPowerOut, y0 += 60, 0, 64, H, "自定义"); + ui.arrt2LabelPowerOut = PvApp::lineEdit(p, labelPowerOut, y0 += 70, 0, 80, H, ""); + } + + + PvApp::bind(p, PvEvent::RADIOBUTTON_EVENT, ui.radioPolicy1, [=](std::string s) { + this->data.times = 1; + pvHide(p, ui.label2); + //setTimeText(ui.attr2TimeCharge0, ""); + //setTimeText(ui.attr2TimeCharge1, ""); + //setTimeText(ui.attr2TimeDischarge0, ""); + //setTimeText(ui.attr2TimeDischarge1, ""); + //pvSetChecked(p, ui.attr2RadioPowerInAuto, 1); + //pvSetChecked(p, ui.attr2RadioPowerOutAuto, 1); + //pvSetText(p, ui.arrt2LabelPowerOut, ""); + //data.attr2.chargePower = data.attr2.dischargePower = 0.0; + //data.attr2.chargeTimeStart = data.attr2.chargeTimeEnd = data.attr2.dischargeTimeStart = data.attr2.dischargeTimeEnd = ""; + }); + + PvApp::bind(p, PvEvent::RADIOBUTTON_EVENT, ui.radioPolicy2, [=](std::string s) { + this->data.times = 2; + pvShow(p, ui.label2); + }); + + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr1TimeCharge0, [=](std::string s) { + data.attr1.chargeTimeStart = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr1TimeCharge1, [=](std::string s) { + data.attr1.chargeTimeEnd = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr1TimeDischarge0, [=](std::string s) { + data.attr1.dischargeTimeStart = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr1TimeDischarge1, [=](std::string s) { + data.attr1.dischargeTimeEnd = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr2TimeCharge0, [=](std::string s) { + data.attr2.chargeTimeStart = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr2TimeCharge1, [=](std::string s) { + data.attr2.chargeTimeEnd = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr2TimeDischarge0, [=](std::string s) { + data.attr2.dischargeTimeStart = s.substr(0, 8); + }); + PvApp::bind(p, PvEvent::TEXT_EVENT, ui.attr2TimeDischarge1, [=](std::string s) { + data.attr2.dischargeTimeEnd = s.substr(0, 8); + }); + + { + int btn = PvApp::button(p, ui.widget, 10, 750, 100, 30, "DUMP"); + PvApp::bind(p, PvEvent::BUTTON_EVENT, btn, [=](std::string) { + XLOGD() << dumpAttr(); + }); + } + { + int btn = PvApp::button(p, ui.widget, 110, 750, 100, 30, "PARSE1"); + PvApp::bind(p, PvEvent::BUTTON_EVENT, btn, [=](std::string) { + std::string s = R"({"cycle":[{"charge_end":"","charge_power":0.0,"charge_start":"","discharge_end":"","discharge_power":0.0,"discharge_start":""}], +"period":[[1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]], +"times":1})"; + parseAttr(s); + }); + } + { + int btn = PvApp::button(p, ui.widget, 210, 750, 100, 30, "PARSE2"); + PvApp::bind(p, PvEvent::BUTTON_EVENT, btn, [=](std::string) { + std::string s = R"({"cycle":[{"charge_end":"09:00:00","charge_power":0.0,"charge_start":"00:00:00","discharge_end":"","discharge_power":0.0,"discharge_start":""}], +"period":[[1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]], +"times":2})"; + parseAttr(s); + }); + } + } +} + +void PanelPolicyPeak::updateUI() +{ +} + +void PanelPolicyPeak::setTimeText(int id, std::string s) +{ + int hour {0}, minute {0}, second {0}; + sscanf_s(s.c_str(), "%d:%d:%d", &hour, &minute, &second); + pvSetTime(p, id, hour, minute, second); +} + +void PanelPolicyPeak::parseAttr(std::string str) +{ + NJsonNode jsonroot; + bool ret = NJson::parse(str, jsonroot); + if (!ret) + { + return; + } + + NJson::read(jsonroot, "times", data.times); + // 更新UI (充电策略) + if (data.times == 2) + { + pvSetChecked(p, ui.radioPolicy2, 1); + pvShow(p, ui.label2); + } + else + { + pvSetChecked(p, ui.radioPolicy1, 1); + pvHide(p, ui.label2); + } + + std::vector> vecTmp; + NJson::read>>(jsonroot, "period", vecTmp); + for (int row = 0; row < data.vecPeriods.size(); ++row) + { + auto& vecRows = data.vecPeriods[row]; + for (int col = 0; col < vecRows.size(); ++col) + { + auto& periodVal = vecRows[col]; + int tmpVal {}; + if (row < vecTmp.size()) + { + tmpVal = (col < vecTmp[row].size() ? vecTmp[row][col] : 3); + } + else + { + tmpVal = 3; + } + if (periodVal != tmpVal) + { + periodVal = tmpVal; + // 更新UI (时段下拉列表) + auto combox = ui.vecComboxs[row][col]; + pvSetCurrentItem(p, combox, periodVal); + pvSetStyleSheet(p, combox, GetPeriodQss(periodVal).c_str()); + } + } + } + if (jsonroot.contains("cycle")) + { + auto& jsonCycle = jsonroot["cycle"]; + if (jsonCycle.is_array()) + { + auto size = jsonCycle.size(); + if (size >= 1) + { + data.attr1.chargeTimeStart = jsonCycle[0]["charge_start"]; + data.attr1.chargeTimeEnd = jsonCycle[0]["charge_end"]; + data.attr1.chargePower = jsonCycle[0]["charge_power"]; + data.attr1.dischargeTimeStart = jsonCycle[0]["discharge_start"]; + data.attr1.dischargeTimeEnd = jsonCycle[0]["discharge_end"]; + data.attr1.dischargePower = jsonCycle[0]["discharge_power"]; + // 更新UI (一放一充) + setTimeText(ui.attr1TimeCharge0, data.attr1.chargeTimeStart); + setTimeText(ui.attr1TimeCharge1, data.attr1.chargeTimeEnd); + //setTimeText(ui.attr1TimeCharge1, data.attr1.chargeTimeEnd); + setTimeText(ui.attr1TimeDischarge0, data.attr1.dischargeTimeStart); + setTimeText(ui.attr1TimeDischarge1, data.attr1.dischargeTimeEnd); + //setTimeText(ui.attr1TimeCharge1, data.attr1.chargeTimeEnd); + } + if (size >= 2) + { + data.attr2.chargeTimeStart = jsonCycle[1]["charge_start"]; + data.attr2.chargeTimeEnd = jsonCycle[1]["charge_end"]; + data.attr2.chargePower = jsonCycle[1]["charge_power"]; + data.attr2.dischargeTimeStart = jsonCycle[1]["discharge_start"]; + data.attr2.dischargeTimeEnd = jsonCycle[1]["discharge_end"]; + data.attr2.dischargePower = jsonCycle[1]["discharge_power"]; + // 更新UI (两放两充) + setTimeText(ui.attr2TimeCharge0, data.attr2.chargeTimeStart); + setTimeText(ui.attr2TimeCharge1, data.attr2.chargeTimeEnd); + //setTimeText(ui.attr2TimeCharge1, data.attr2.chargeTimeEnd); + setTimeText(ui.attr2TimeDischarge0, data.attr2.dischargeTimeStart); + setTimeText(ui.attr2TimeDischarge1, data.attr2.dischargeTimeEnd); + //setTimeText(ui.attr2TimeCharge1, data.attr2.chargeTimeEnd); + } + } + } + // 更新UI + +} + + +std::string PanelPolicyPeak::dumpAttr() +{ + NJsonNode jsonroot; + jsonroot["period"] = data.vecPeriods; + jsonroot["times"] = data.times; + + NJsonNode nodeCycle = NJsonNode::array(); + + NJsonNode nodeAttr1; + nodeAttr1["charge_start"] = data.attr1.chargeTimeStart; + nodeAttr1["charge_end"] = data.attr1.chargeTimeEnd; + nodeAttr1["charge_power"] = data.attr1.chargePower; + nodeAttr1["discharge_start"] = data.attr1.dischargeTimeStart; + nodeAttr1["discharge_end"] = data.attr1.dischargeTimeEnd; + nodeAttr1["discharge_power"] = data.attr1.dischargePower; + nodeCycle.push_back(nodeAttr1); + if (data.times > 1) + { + NJsonNode nodeAttr2; + nodeAttr2["charge_start"] = data.attr2.chargeTimeStart; + nodeAttr2["charge_end"] = data.attr2.chargeTimeEnd; + nodeAttr2["charge_power"] = data.attr2.chargePower; + nodeAttr2["discharge_start"] = data.attr2.dischargeTimeStart; + nodeAttr2["discharge_end"] = data.attr2.dischargeTimeEnd; + nodeAttr2["discharge_power"] = data.attr2.dischargePower; + nodeCycle.push_back(nodeAttr2); + } + jsonroot["cycle"] = nodeCycle; + return jsonroot.dump(); +} \ No newline at end of file diff --git a/src/pv/pages/PanelPolicy.h b/src/pv/pages/PanelPolicy.h new file mode 100644 index 0000000..dcc083c --- /dev/null +++ b/src/pv/pages/PanelPolicy.h @@ -0,0 +1,75 @@ +#pragma once +#include "pv/PvApp.h" + +// 峰谷套利策、需求响应、自发自用 + +class PanelPolicyPeak : public PvObject +{ +public: + PanelPolicyPeak(PARAM* p, int parent, int x, int y, int w, int h); + + void updateUI(); + + void setTimeText(int id, std::string s); + + void parseAttr(std::string str); + std::string dumpAttr(); + + struct { + int parent {}; + int widget {PV_ID_NUL}; + + int label1 {PV_ID_NUL}; + int label2 {PV_ID_NUL}; + + int radioPolicy1 {PV_ID_NUL}; + int radioPolicy2 {PV_ID_NUL}; + + int attr1TimeCharge0 {PV_ID_NUL}; + int attr1TimeCharge1 {PV_ID_NUL}; + int attr1TimeDischarge0 {PV_ID_NUL}; + int attr1TimeDischarge1 {PV_ID_NUL}; + + int attr1RadioPowerInAuto {PV_ID_NUL}; + int attr1RadioPowerIn {PV_ID_NUL}; + int arrt1LabelPowerIn {PV_ID_NUL}; + + int attr1RadioPowerOutAuto {PV_ID_NUL}; + int attr1RadioPowerOut {PV_ID_NUL}; + int arrt1LabelPowerOut {PV_ID_NUL}; + + int attr2TimeCharge0 {PV_ID_NUL}; + int attr2TimeCharge1 {PV_ID_NUL}; + int attr2TimeDischarge0 {PV_ID_NUL}; + int attr2TimeDischarge1 {PV_ID_NUL}; + + int attr2RadioPowerInAuto {PV_ID_NUL}; + int attr2RadioPowerIn {PV_ID_NUL}; + int arrt2LabelPowerIn {PV_ID_NUL}; + + int attr2RadioPowerOutAuto {PV_ID_NUL}; + int attr2RadioPowerOut {PV_ID_NUL}; + int arrt2LabelPowerOut {PV_ID_NUL}; + + std::vector> vecComboxs {}; + + } ui; + + struct ChargeAttr + { + std::string chargeTimeStart; + std::string chargeTimeEnd; + double chargePower {0.0}; + + std::string dischargeTimeStart; + std::string dischargeTimeEnd; + double dischargePower {0.0}; + }; + + struct { + int times {1}; + ChargeAttr attr1; + ChargeAttr attr2; + std::vector> vecPeriods; + } data; +}; \ No newline at end of file diff --git a/src/pv/pvmain.cpp b/src/pv/pvmain.cpp index b2e9a6e..40f2151 100644 --- a/src/pv/pvmain.cpp +++ b/src/pv/pvmain.cpp @@ -45,7 +45,7 @@ int pvMain(PARAM* p) mask = std::make_shared(p, pvcode); // 超过设定数量值的控件将不会显示 - pvStartDefinition(p, 1024); + pvStartDefinition(p, 2048); if (mask) { pvSetFont(p, PV_ID_MAIN, "微软雅黑", 12, 1, 0, 0, 0); @@ -75,30 +75,30 @@ int pvMain(PARAM* p) pvcode = mask->onEventNull(pvid); } break; case BUTTON_EVENT: { - pvcode = mask->onEventButton(pvid); std::cout << "EVENT: BUTTON\n"; + pvcode = mask->onEventButton(pvid); std::cout << "EVENT: (" << pvid << ")BUTTON\n"; } break; - case TEXT_EVENT: {} break; - case SLIDER_EVENT: {} break; - case CHECKBOX_EVENT: {} break; - case RADIOBUTTON_EVENT: {} break; - case GL_IDLE_EVENT: {} break; - case GL_PAINT_EVENT: {} break; - case GL_INITIALIZE_EVENT: {} break; - case GL_RESIZE_EVENT: {} break; - case TAB_EVENT: {} break; - case TABLE_CLICKED_EVENT: {} break; - case TABLE_TEXT_EVENT: {} break; - case SELECTION_EVENT: {} break; - case CLIPBOARD_EVENT: {} break; - case BUTTON_PRESSED_EVENT: {} break; - case BUTTON_RELEASED_EVENT: {} break; - case RIGHT_MOUSE_EVENT: {} break; - case KEYBOARD_EVENT: {} break; - case PLOT_MOUSE_MOVED_EVENT: {} break; - case PLOT_MOUSE_PRESSED_EVENT: {} break; - case PLOT_MOUSE_RELEASED_EVENT: {} break; - case USER_EVENT: {} break; - case MOUSE_OVER_EVENT: {} break; + case TEXT_EVENT: { std::cout << "EVENT: (" << pvid << ")TEXT_EVENT\n"; } break; + case SLIDER_EVENT: { std::cout << "EVENT: (" << pvid << ")SLIDER_EVENT\n"; } break; + case CHECKBOX_EVENT: { std::cout << "EVENT: (" << pvid << ")CHECKBOX_EVENT\n"; } break; + case RADIOBUTTON_EVENT: { std::cout << "EVENT: (" << pvid << ")RADIOBUTTON_EVENT\n"; } break; + case GL_IDLE_EVENT: { std::cout << "EVENT: (" << pvid << ")GL_IDLE_EVENT\n"; } break; + case GL_PAINT_EVENT: { std::cout << "EVENT: (" << pvid << ")GL_PAINT_EVENT\n"; } break; + case GL_INITIALIZE_EVENT: { std::cout << "EVENT: (" << pvid << ")GL_INITIALIZE_EVENT\n"; } break; + case GL_RESIZE_EVENT: { std::cout << "EVENT: (" << pvid << ")GL_RESIZE_EVENT\n"; } break; + case TAB_EVENT: { std::cout << "EVENT: (" << pvid << ")TAB_EVENT\n"; } break; + case TABLE_CLICKED_EVENT: { std::cout << "EVENT: (" << pvid << ")TABLE_CLICKED_EVENT\n"; } break; + case TABLE_TEXT_EVENT: { std::cout << "EVENT: (" << pvid << ")TABLE_TEXT_EVENT\n"; } break; + case SELECTION_EVENT: { std::cout << "EVENT: (" << pvid << ")SELECTION_EVENT\n"; } break; + case CLIPBOARD_EVENT: { std::cout << "EVENT: (" << pvid << ")CLIPBOARD_EVENT\n"; } break; + case BUTTON_PRESSED_EVENT: { std::cout << "EVENT: (" << pvid << ")BUTTON_PRESSED_EVENT\n"; } break; + case BUTTON_RELEASED_EVENT: { std::cout << "EVENT: (" << pvid << ")BUTTON_RELEASED_EVENT\n"; } break; + case RIGHT_MOUSE_EVENT: { std::cout << "EVENT: (" << pvid << ")RIGHT_MOUSE_EVENT\n"; } break; + case KEYBOARD_EVENT: { std::cout << "EVENT: (" << pvid << ")KEYBOARD_EVENT\n"; } break; + case PLOT_MOUSE_MOVED_EVENT: { std::cout << "EVENT: (" << pvid << ")PLOT_MOUSE_MOVED_EVENT\n"; } break; + case PLOT_MOUSE_PRESSED_EVENT: { std::cout << "EVENT: (" << pvid << ")PLOT_MOUSE_PRESSED_EVENT\n"; } break; + case PLOT_MOUSE_RELEASED_EVENT: { std::cout << "EVENT: (" << pvid << ")PLOT_MOUSE_RELEASED_EVENT\n"; } break; + case USER_EVENT: { std::cout << "EVENT: (" << pvid << ")USER_EVENT\n"; } break; + case MOUSE_OVER_EVENT: { /*std::cout << "EVENT: (" << pvid << ")MOUSE_OVER_EVENT\n";*/ } break; default: {} break; } }