搭建PVB架构,实现前端的基础布局、菜单、表格、图示等功能

This commit is contained in:
lixiaoyuan
2025-08-20 19:00:22 +08:00
parent 5de7687bcc
commit 7e965b6fb4
142 changed files with 28270 additions and 411 deletions

View File

@@ -1,5 +1,4 @@
#include "Admin.h"
#include "app/Dao.h"
#include "common/Logger.h"
Errcode Admin::longin(std::string username, std::string passwd)

49
src/app/AppData.cpp Normal file
View File

@@ -0,0 +1,49 @@
#include "AppData.h"
#include "app/Station.h"
std::shared_ptr<Station> AppData::getStation(int stationId)
{
auto iter = mapStation.find(stationId);
if (iter!=mapStation.end())
{
return iter->second;
}
return nullptr;
}
std::shared_ptr<Station> AppData::getStationByName(std::string name)
{
for (auto iter = mapStation.begin(); iter!=mapStation.end(); ++iter)
{
if (iter->second->name == name)
{
return iter->second;
}
}
return nullptr;
}
void AppData::getStationNames(std::vector<std::string>& vecNames)
{
vecNames.resize(mapStation.size());
int i = 0;
for (auto iter = mapStation.begin(); iter!=mapStation.end(); ++iter)
{
vecNames[i] = iter->second->name;
}
}
std::shared_ptr<Device> AppData::getDevice(int stationId, int deviceId)
{
auto station = getStation(stationId);
if (station)
{
return station->getDevice(deviceId);
}
return nullptr;
}
void AppData::loadStatData()
{
}

48
src/app/AppData.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include <map>
#include <unordered_map>
class Station;
class Device;
class AppData
{
public:
std::shared_ptr<Station> getStation(int stationId);
std::shared_ptr<Station> getStationByName(std::string name);
void getStationNames(std::vector<std::string>& vecNames);
std::shared_ptr<Device> getDevice(int stationId, int deviceId);
// 读取统计数据: 今日统计数据,累计统计数据
void loadStatData();
public:
///////////////////////////////////////////////////////////////////////////////////////////////
// === 系统 ===
int64_t sysActivationTime {};
///////////////////////////////////////////////////////////////////////////////////////////////
// === 数据库 ===
struct {
std::string host;
int port;
std::string user;
std::string passwd;
} db;
///////////////////////////////////////////////////////////////////////////////////////////////
// === 场站信息 ===
std::unordered_map<int, std::shared_ptr<Station>> mapStation;
///////////////////////////////////////////////////////////////////////////////////////////////
// === 角色定义 ===
};

View File

View File

@@ -1,12 +0,0 @@
#pragma once
class AppSetting
{
public:
static AppSetting& instance() {
static AppSetting inst;
return inst;
}
};

View File

@@ -1,13 +1,92 @@
#include "Application.h"
#include "common/Utils.h"
#include "Config.h"
#include "app/Dao.h"
#include "app/Device.h"
#include "database/DaoEntity.h"
#include "database/Dao.h"
#include "app/Station.h"
#include "app/Device.h"
void InitStation()
{
AppData& appdata = Application::instance().getAppData();
// 读取数据库
std::vector<DataFields> result;
DAO::queryStationList(result);
for (auto& fields: result)
{
int stationId = fields.getInt(DMStation::STATION_ID);
auto station = std::make_shared<Station>(stationId);
station->name = fields.getStr(DMStation::NAME);
station->energyCapacity = fields.getDouble(DMStation::CAPACITY);
appdata.mapStation[stationId] = station;
}
}
void InitDevice()
{
AppData& appdata = Application::instance().getAppData();
vector<DataFields> result;
DAO::queryDeviceList(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)
{
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 = Application::instance().getAppData();
std::string curDate = Utils::dateStr();
vector<DataFields> result;
DAO::queryStatDataList(curDate, curDate, result);
for (auto& fields: result)
{
std::string dt = fields.getStr(DMStatStation::DT);
int stationId = fields.getInt(DMStatStation::STATION_ID);
auto station = appdata.getStation(stationId);
if (station)
{
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;
}
}
}
void Application::init()
{
// 初始化系统配置,读取配置文件
Config::init("assets/config/app.json");
// 设置数据库配置
@@ -23,79 +102,23 @@ void Application::init()
// 连接数据库,读取基础信息
// 初始化场站信息
InitStation();
// 读取设备信息,连接设备
this->initDevice();
InitDevice();
// 读取基础统计信息,在系统总览中需要展示
InitStatData();
// 创建设备处理线程
std::thread([=]() { runThreadDevice(); }).detach();
// 创建主业务循环线程
std::thread([=]() { runThreadMain(); }).detach();
}
static void addDeviceTest(vector<DataFields>& v, int device_id, int type, std::string name, std::string code, int is_open, std::string attrs = "{}")
AppData& Application::getAppData()
{
DataFields fields;
fields.set("device_id", device_id);
fields.set("type", type);
fields.set("name", name);
fields.set("code", code);
fields.set("is_open", is_open);
fields.set("attrs", attrs);
v.push_back(fields);
}
void Application::initDevice()
{
DaoEntity dao("");
std::string sql = "select * from device;";
vector<DataFields> result;
//dao.exec(sql, result);
addDeviceTest(result, 1, 1, "变压器", "", 1);
addDeviceTest(result, 2, 2, "配电柜1", "", 1);
addDeviceTest(result, 3, 3, "电表", "", 1);
addDeviceTest(result, 4, 4, "门禁", "", 1);
addDeviceTest(result, 5, 5, "空调", "", 1);
addDeviceTest(result, 6, 6, "照明", "", 1);
addDeviceTest(result, 7, 7, "消防", "", 1);
addDeviceTest(result, 8, 8, "光照监测设备", "", 1);
addDeviceTest(result, 9, 9, "风速监测设备", "", 1);
addDeviceTest(result, 10, 10, "温湿度监测设备", "", 1);
addDeviceTest(result, 11, 11, "烟感监测设备", "", 1);
addDeviceTest(result, 12, 12, "水浸传感器", "", 1);
addDeviceTest(result, 13, 13, "视频监控", "", 1);
addDeviceTest(result, 14, 101, "逆变器", "", 1);
addDeviceTest(result, 15, 102, "汇流箱", "", 1);
addDeviceTest(result, 16, 103, "光伏板", "", 1);
addDeviceTest(result, 17, 104, "风力发电机", "", 1);
addDeviceTest(result, 18, 105, "储能变流器", "", 1);
addDeviceTest(result, 19, 106, "储能电池", "", 1);
addDeviceTest(result, 20, 107, "BMS", "", 1);
addDeviceTest(result, 21, 108, "充电桩", "", 1);
addDeviceTest(result, 22, 103, "光伏板-1000", "", 1);
addDeviceTest(result, 23, 108, "充电桩-000001", "", 1);
addDeviceTest(result, 24, 103, "光伏板-1001", "", 1);
addDeviceTest(result, 25, 103, "光伏板-1002", "", 1);
addDeviceTest(result, 26, 103, "光伏板-1003", "", 1);
addDeviceTest(result, 27, 103, "光伏板-1004", "", 1);
addDeviceTest(result, 28, 103, "光伏板-1005", "", 1);
addDeviceTest(result, 29, 103, "光伏板-1006", "", 1);
addDeviceTest(result, 30, 103, "光伏板-1007", "", 1);
addDeviceTest(result, 31, 103, "光伏板-1008", "", 1);
addDeviceTest(result, 32, 103, "光伏板-1009", "", 1);
addDeviceTest(result, 33, 103, "光伏板-1010", "", 1);
addDeviceTest(result, 34, 103, "光伏板-1011", "", 1);
addDeviceTest(result, 35, 103, "光伏板-1012", "", 1);
addDeviceTest(result, 36, 106, "储能电池-001", "", 1);
addDeviceTest(result, 37, 106, "储能电池-005", "", 1);
addDeviceTest(result, 38, 106, "储能电池-002", "", 1);
addDeviceTest(result, 39, 106, "储能电池-003", "", 1);
addDeviceTest(result, 40, 106, "储能电池-004", "", 1);
for (auto& fields: result)
{
Device::add(fields);
}
return appdata_;
}
void Application::runThreadMain()
@@ -110,7 +133,6 @@ void Application::runThreadMain()
}
void Application::runThreadDevice()
{
while (!isQuit())

View File

@@ -1,85 +1,10 @@
#pragma once
#include <thread>
#include "common/Logger.h"
#include "Operator.h"
struct AppData
{
/////////////////////////////////////////////
/// === 系统 ===
int64_t sysActivationTime {};
/////////////////////////////////////////////
/// === 数据库 ===
struct {
std::string host;
int port;
std::string user;
std::string passwd;
} db;
/////////////////////////////////////////////
/// === 系统统计 ===
// 累计发电量单位kWh
double electGenTatal {};
// 累计入网电量单位kWh
double electInTotal {};
// 累计收益,单位:元
double incomeTotal {};
// 碳减排量, 单位:吨
double ccers {};
/////////////////////////////////////////////
/// === 环境 ===
// 光照度
double illuminance {};
// 辐照度
double irradiance {};
// 风速
double windspeed {};
// 温度
double temperature {};
// 湿度
double humidity {};
/////////////////////////////////////////////
/// === 日统计 ===
struct {
// 发电量
double electGen {};
// 入网电量
double electIn {};
// 发电收益金额
double incomeElect {};
// 储能电量
double electStorage {};
// 储能次数
int numStore {};
// 放电电量
double electDischarge {};
// 放电次数
int numDischarge {};
// 用电电量
double electLoad {};
// 充电电量
double electCharge {};
// 充电次数
int numCharge {};
// 充电收益
double incomeCharge {};
// 故障次数
int numFault {};
// 故障次数:光伏设备
int numFaultSolar {};
// 故障次数:储能设备
int numFaultStorage {};
// 故障次数:负荷设备
int numFaultLoad {};
} statDay;
};
#include "app/AppData.h"
class Application
{
@@ -91,8 +16,9 @@ public:
}
void init();
void initDevice();
AppData& getAppData();
bool isQuit() { return isQuit_; }
Operator& getOperator() { return op_; }
@@ -100,9 +26,12 @@ public:
void runThreadDevice();
private:
public:
bool isQuit_ = false;
// 登录的管理员信息
Operator op_;
// 应用数据
AppData appdata_;
};

View File

@@ -1,4 +1,4 @@
#include "Dao.h"
#include "Dao1.h"
#include "common/Logger.h"
#include "common/Utils.h"
#include "common/Snowflake.h"
@@ -17,7 +17,7 @@ std::shared_ptr<DaoEntity> DAO::get(std::string tableName)
Errcode DAO::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, std::string& err)
{
std::string t = Utils::timeNowStr();
std::string t = Utils::timeStr();
if (!dao)
{
dao = std::make_shared<DaoEntity>("");
@@ -90,7 +90,7 @@ bool DAO::writeSystemLog(std::shared_ptr<DaoEntity> dao, int type, std::string u
fieldsLog.set("user_id", userId);
fieldsLog.set("user_account", account);
fieldsLog.set("content", text);
fieldsLog.set("create_time", Utils::timeNowStr());
fieldsLog.set("create_time", Utils::timeStr());
bool ret = dao->insertFields({fieldsLog});
return ret;
}
@@ -131,7 +131,7 @@ int DAO::insertUser(DataFields& fields)
}
fields.set("user_id", Snowflake::instance().getIdStr());
fields.set("create_time", Utils::timeNowStr());
fields.set("create_time", Utils::timeStr());
ret = dao->insertFields(fields);
return (ret) ? 0 : 1;
}

View File

@@ -33,7 +33,7 @@
// return iter->second;
//}
int DeviceEntity::startComm()
int Device::startComm()
{
if (!isOpen)
{
@@ -64,63 +64,58 @@ int DeviceEntity::startComm()
return 0;
}
// ================================================================================================
// $$Device
std::map<int, std::shared_ptr<DeviceEntity>> Device::mapDevices;
void Device::add(DataFields& fields)
std::shared_ptr<Device> Device::create(DataFields& fields)
{
auto entity = std::make_shared<DeviceEntity>();
entity->deviceId = fields.getInt("device_id");
entity->type = fields.getInt("type");
entity->name = fields.getStr("name");
entity->code = fields.getStr("code");
entity->isOpen = fields.getInt("is_open");
entity->attrsJson = fields.getStr("attrs");
auto device = std::make_shared<Device>();
device->deviceId = fields.getInt("device_id");
device->type = fields.getInt("type");
device->name = fields.getStr("name");
device->code = fields.getStr("code");
device->isOpen = fields.getInt("is_open");
device->attrsJson = fields.getStr("attrs");
// 解析属性的JSON字符串转换成键值对
NJson jsonroot;
bool ret = NJsonParse(entity->attrsJson, jsonroot);
bool ret = NJsonParse(device->attrsJson, jsonroot);
if (!ret) // 解析错误
{
XLOGE() << "device attr json parse error, device_id=" << entity->deviceId;
XLOGE() << "device attr json parse error, device_id=" << device->deviceId;
}
else
{
for (auto& [key, val] : jsonroot.items()) {
std::string valType = val.type_name();
if (valType == "string") {
entity->attrs.set(key, val.get<std::string>());
device->attrs.set(key, val.get<std::string>());
}
else if (valType == "number") {
entity->attrs.set(key, val.get<int>());
device->attrs.set(key, val.get<int>());
}
else {
else {
XLOGE() << key << ": [" << valType << "]";
}
}
}
// 保存设备 entity 到 map
if (entity->deviceId != -1)
{
mapDevices[entity->deviceId] = entity;
}
// 启动通讯该函数中会自动判断isOpen状态选择是否进行通讯连接
entity->startComm();
device->startComm();
return device;
}
std::vector<std::shared_ptr<DeviceEntity>> Device::getDeviceByType(int type)
{
std::vector<std::shared_ptr<DeviceEntity>> vecDevice;
for (auto iter = mapDevices.begin(); iter!=mapDevices.end(); ++iter)
{
auto device = iter->second;
if (device && (type<=0 || device->type == type))
{
vecDevice.push_back(device);
}
}
return vecDevice;
}
//
//std::vector<std::shared_ptr<DeviceEntity>> Device::getDeviceByType(int type)
//{
// std::vector<std::shared_ptr<DeviceEntity>> vecDevice;
// for (auto iter = mapDevices.begin(); iter!=mapDevices.end(); ++iter)
// {
// auto device = iter->second;
// if (device && (type<=0 || device->type == type))
// {
// vecDevice.push_back(device);
// }
// }
// return vecDevice;
//}

View File

@@ -9,7 +9,7 @@
class CommEntity;
class DeviceEntity
class Device
{
public:
int deviceId = -1;
@@ -38,17 +38,19 @@ public:
// 启动通讯
int startComm();
static std::shared_ptr<Device> create(DataFields& fields);
};
class Device
{
public:
static void add(DataFields& fields);
static std::vector<std::shared_ptr<DeviceEntity>> getDeviceByType(int type);
public:
static std::map<int, std::shared_ptr<DeviceEntity>> mapDevices;
};
//class Device
//{
//public:
// static void add(DataFields& fields);
//
// static std::vector<std::shared_ptr<DeviceEntity>> getDeviceByType(int type);
//
//public:
// static std::map<int, std::shared_ptr<DeviceEntity>> mapDevices;
//};

View File

@@ -1,17 +1,17 @@
#include "Operator.h"
#include "DAO.h"
#include "common/Logger.h"
bool Operator::login(std::string account, std::string passwd, std::string& err)
{
auto ecode = DAO::login(nullptr, account, passwd, err);
if (ecode == Errcode::OK)
{
XLOGD() << "用户[" + account + "]登录成功";
}
else
{
XLOGD() << "用户[" + account + "]登录失败: " << err;
}
return (ecode == Errcode::OK);
//auto ecode; = DAO::login(nullptr, account, passwd, err);
//if (ecode == Errcode::OK)
//{
// XLOGD() << "用户[" + account + "]登录成功";
//}
//else
//{
// XLOGD() << "用户[" + account + "]登录失败: " << err;
//}
//return (ecode == Errcode::OK);
return true;
}

21
src/app/Station.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include "Station.h"
Station::Station(int id) : id(id)
{
}
void Station::addDevice(int deviceId, std::shared_ptr<Device> device)
{
mapDevice_[deviceId] = device;
}
std::shared_ptr<Device> Station::getDevice(int deviceId)
{
auto iter = mapDevice_.find(deviceId);
if (iter!=mapDevice_.end())
{
return iter->second;
}
return nullptr;
}

74
src/app/Station.h Normal file
View File

@@ -0,0 +1,74 @@
#pragma once
#include <memory>
#include <unordered_map>
class Device;
class Station
{
public:
Station(int id);
void addDevice(int deviceId, std::shared_ptr<Device> device);
std::shared_ptr<Device> getDevice(int deviceId);
public:
int id {};
std::string name;
// 储能容量
double energyCapacity {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 系统统计 ===
// 累计发电量单位kWh
double electGenTatal {};
// 累计入网电量单位kWh
double electGridTotal {};
// 累计收益,单位:元
double incomeTotal {};
// 碳减排量, 单位:吨
double ccers {};
// 累计储能充电电量
double electStorageIn {};
// 累计储能放电电量
double electStorageOut {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 日统计 ===
double storageIn {}; // 储能充电电量
double storageOut {}; // 储能放电电量
int storageNumIn {}; // 储能充电次数
int storageNumOut {}; // 储能放电次数
int storageNumErr {}; // 储能故障次数
double solarGen {}; // 光伏发电电量
double solarGrid {}; // 光伏入网电量
int solarNumErr {}; // 光伏故障次数
double chargeElect {}; // 充电设备充电电量
int chargeNum {}; // 充电设备充电次数
int chargeNumErr {}; // 充电设备故障次数
double incomeElect {}; // 发电收益金额
double incomeCharge {}; // 充电收益金额
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 环境 ===
// 光照度
double illuminance {};
// 辐照度
double irradiance {};
// 风速
double windspeed {};
// 温度
double temperature {};
// 湿度
double humidity {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 设备信息 ===
std::unordered_map<int, std::shared_ptr<Device>> mapDevice_;
};