完成系统管理web端功能,实现系统管理服务端接口,实现登录功能

This commit is contained in:
lixiaoyuan
2025-07-18 09:08:09 +08:00
parent 4a198a7271
commit 7b3f32f334
31 changed files with 1384 additions and 325 deletions

18
src/app/Admin.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include "Admin.h"
#include "app/Dao.h"
#include "common/Logger.h"
Errcode Admin::longin(std::string username, std::string passwd)
{
std::string err;
Errcode ecode = DAO::login(nullptr, username, passwd, err);
if (ecode != Errcode::OK)
{
XLOGE() << "login error, username=" << username << ", err=" << err;
}
else
{
XLOGE() << "login success, username=" << username;
}
return ecode;
}

16
src/app/Admin.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
#include "app/errcode.h"
class Admin
{
public:
static Admin& instance()
{
static Admin admin;
return admin;
}
Errcode longin(std::string username, std::string pwd);
};

View File

@@ -2,20 +2,68 @@
#include "common/Utils.h"
#include "Config.h"
#include "app/Dao.h"
#include "app/Device.h"
void Application::init()
{
std::thread([=]()
{
while (!isQuit()) { runThreadMain(); }
}).detach();
Config::init("assets/config/app.json");
// 设置数据库配置
DaoEntity::setOption(Config::option.database.host,
Config::option.database.port,
Config::option.database.user,
Config::option.database.passwd,
Config::option.database.dbname);
XLOGI() << "[APP] set database option: host=" << Config::option.database.host
<< ", port=" << Config::option.database.port
<< ", user=" << Config::option.database.user
<< ", dbname=" << Config::option.database.dbname;
// 连接数据库,读取基础信息
// 读取设备信息,连接设备
this->initDevice();
std::thread([=]() { runThreadDevice(); }).detach();
// 创建主业务循环线程
std::thread([=]() { runThreadMain(); }).detach();
}
void Application::initDevice()
{
DaoEntity dao("");
std::string sql = "select * from device;";
vector<DataFields> result;
dao.exec(sql, result);
for (auto& fields: result)
{
Device::add(fields);
}
}
void Application::runThreadMain()
{
static TimeTick tt;
tt.elapse(1000);
while (!isQuit())
{
//XLOGD() << "HelloWorld";
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void Application::runThreadDevice()
{
while (!isQuit())
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}

View File

@@ -15,11 +15,16 @@ public:
}
void init();
void initDevice();
bool isQuit() { return isQuit_; }
Operator& getOperator() { return op_; }
void runThreadMain();
void runThreadDevice();
private:
bool isQuit_ = false;

38
src/app/Config.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "Config.h"
#include <fstream>
#include "common/JsonN.h"
#include "Logger.h"
AppOption Config::option;
bool Config::init(std::string filename)
{
NJson jsonroot;
bool ret = NJsonLoad(filename, jsonroot);
if (!ret)
{
XLOGE() << "[APP] load config failed, filename=" << filename;
return false;
}
XLOGI() << "[APP] load config success, filename=" << filename;
if (jsonroot.contains("database"))
{
NJson 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") : "";
option.database.passwd = json.contains("passwd") ? json.at("passwd") : "";
option.database.dbname = json.contains("dbname") ? json.at("dbname") : "";
XLOGI() << "[APP] load database config end. host=" << option.database.host;
}
else
{
XLOGI() << "[APP] load database config error: not found. host=" << option.database.host;
}
return true;
}

26
src/app/Config.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <string>
struct DatabaseOption
{
std::string host;
int port;
std::string user;
std::string passwd;
std::string dbname;
};
struct AppOption
{
DatabaseOption database;
};
class Config
{
public:
static bool init(std::string filename);
static AppOption option;
};

View File

@@ -3,6 +3,8 @@
#include "common/Utils.h"
#include "common/Snowflake.h"
enum class EnDatabaseErr
{
SUCCESS = 0,
@@ -13,7 +15,7 @@ std::shared_ptr<DaoEntity> DAO::get(std::string tableName)
return std::make_shared<DaoEntity>(tableName);
}
bool DAO::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, std::string& err)
Errcode DAO::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, std::string& err)
{
std::string t = Utils::timeNowStr();
if (!dao)
@@ -24,7 +26,7 @@ bool DAO::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string
{
err = "数据库连接错误";
DAO::writeSystemLog(dao, 2, "", account, "用户登录失败:" + err);
return false;
return Errcode::ERR_DB_CONN;
}
std::string sql = "SELECT * FROM user WHERE account='" + account + "';";
@@ -35,24 +37,24 @@ bool DAO::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string
{
err = "数据库操作错误";
DAO::writeSystemLog(dao, 2, "", account, "用户登录失败:" + err);
return false;
return Errcode::ERR_DB_CONN;
}
if (res.size() <=0)
{
err = "用户不存在";
DAO::writeSystemLog(dao, 2, "", account, "用户登录失败:" + err);
return false;
return Errcode::ERR_LOGIN_USER_NOTEXIST;
}
DataFields& fields = res[0];
std::string userId = fields.get_str("user_id");
int loginCount = fields.get_int("login_count");
std::string userId = fields.getStr("user_id");
int loginCount = fields.getInt("login_count");
// 判断密码
if (passwd != fields.get_str("passwd"))
if (passwd != fields.getStr("passwd"))
{
err = "密码错误";
DAO::writeSystemLog(dao, 2, userId, account, "用户登录失败:" + err);
return false;
return Errcode::ERR_LOGIN_PASSWD;
}
err = "登录成功";
@@ -66,7 +68,7 @@ bool DAO::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string
}
DAO::writeSystemLog(dao, 2, userId, account, "用户登录成功");
return true;
return Errcode::OK;
}
bool DAO::writeSystemLog(std::shared_ptr<DaoEntity> dao, int type, std::string userId, std::string account, std::string text)
@@ -83,12 +85,12 @@ bool DAO::writeSystemLog(std::shared_ptr<DaoEntity> dao, int type, std::string u
// 数据库写入登录日志
dao->setTableName("system_log");
DataFields fieldsLog;
fieldsLog.set("id", Snowflake::instance().nextIdStr());
fieldsLog.set("log_id", Snowflake::instance().getIdStr());
fieldsLog.set("type", 2);
fieldsLog.set("user_id", userId);
fieldsLog.set("user_account", account);
fieldsLog.set("content", text);
fieldsLog.set("log_time", Utils::timeNowStr());
fieldsLog.set("create_time", Utils::timeNowStr());
bool ret = dao->insertFields({fieldsLog});
return ret;
}
@@ -114,7 +116,7 @@ int DAO::insertUser(DataFields& fields)
return 1;
}
std::string account = fields.get_str("account");
std::string account = fields.getStr("account");
// step1: 查询
std::vector<DataFields> res;
@@ -128,7 +130,7 @@ int DAO::insertUser(DataFields& fields)
return 1;
}
fields.set("user_id", Snowflake::instance().nextIdStr());
fields.set("user_id", Snowflake::instance().getIdStr());
fields.set("create_time", Utils::timeNowStr());
ret = dao->insertFields(fields);
return (ret) ? 0 : 1;

View File

@@ -1,11 +1,13 @@
#include "database/DaoEntity.h"
#include "app/errcode.h"
class DAO
{
public:
static std::shared_ptr<DaoEntity> get(std::string tableName="");
static bool login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, std::string& err);
static Errcode login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, std::string& err);
static bool writeSystemLog(std::shared_ptr<DaoEntity> dao, int type, std::string userId, std::string account, std::string text);

View File

@@ -0,0 +1,126 @@
#include "Device.h"
#include "common/Logger.h"
#include "common/Utils.h"
#include "protocol/Communicator.h"
#include "common/JsonN.h"
//int DeviceEntity::getAttrInt(std::string key)
//{
// auto iter = mapAttrs.find(key);
// if (iter == mapAttrs.end()) { return 0; }
// return Utils::toInt(iter->second);
//}
//
//float DeviceEntity::getAttrFloat(std::string key)
//{
// auto iter = mapAttrs.find(key);
// if (iter == mapAttrs.end()) { return 0.0f; }
// return Utils::toFloat(iter->second);
//}
//
//double DeviceEntity::getAttrDouble(std::string key)
//{
// auto iter = mapAttrs.find(key);
// if (iter == mapAttrs.end()) { return 0.0; }
// return Utils::toDouble(iter->second);
//}
//
//std::string DeviceEntity::getAttrStr(std::string key)
//{
// auto iter = mapAttrs.find(key);
// if (iter == mapAttrs.end()) { return ""; }
// return iter->second;
//}
int DeviceEntity::startComm()
{
if (!isOpen)
{
if (commEntity && commEntity->isAlive())
{
commEntity->close();
}
return 0;
}
// 从属性列表中获取通讯方式和通讯地址、端口
std::string commType = attrs.getStr("commType");
// 如果entity的通讯协议类型当前配置不一致需要关闭连接删除通讯后创建新的通讯
if (commEntity && commEntity->type != commType)
{
commEntity->close();
commEntity = nullptr;
}
// 创建新的通讯
if (!commEntity)
{
commEntity = Communicator::createEntity(attrs);
if (!commEntity) { return -1; }
}
commEntity->start();
return 0;
}
// ================================================================================================
// $$Device
std::map<int, std::shared_ptr<DeviceEntity>> Device::mapDevices;
void Device::add(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");
// 解析属性的JSON字符串转换成键值对
NJson jsonroot;
bool ret = NJsonParse(entity->attrsJson, jsonroot);
if (!ret) // 解析错误
{
XLOGE() << "device attr json parse error, device_id=" << entity->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>());
}
else if (valType == "number") {
entity->attrs.set(key, val.get<int>());
}
else {
XLOGE() << key << ": [" << valType << "]";
}
}
}
// 保存设备 entity 到 map
if (entity->deviceId != -1)
{
mapDevices[entity->deviceId] = entity;
}
// 启动通讯该函数中会自动判断isOpen状态选择是否进行通讯连接
entity->startComm();
}
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

@@ -1,7 +1,54 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <common/DataFields.h>
class CommEntity;
class DeviceEntity
{
public:
int deviceId = -1;
int type = -1;
std::string name;
std::string code;
bool isOpen = false;
std::string attrsJson = "";
int err = 0;
int online = 0;
int status = 0;
//std::map<std::string, std::string> mapAttrs;
DataFields attrs;
// 通讯entity
std::shared_ptr<CommEntity> commEntity;
//int getAttrInt(std::string key);
//float getAttrFloat(std::string key);
//double getAttrDouble(std::string key);
//std::string getAttrStr(std::string key);
// 启动通讯
int startComm();
};
class Device
{
public:
static bool init();
};
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

@@ -4,9 +4,8 @@
bool Operator::login(std::string account, std::string passwd, std::string& err)
{
bool ret = DAO::login(nullptr, account, passwd, err);
if (ret)
auto ecode = DAO::login(nullptr, account, passwd, err);
if (ecode == Errcode::OK)
{
XLOGD() << "用户[" + account + "]登录成功";
}
@@ -14,5 +13,5 @@ bool Operator::login(std::string account, std::string passwd, std::string& err)
{
XLOGD() << "用户[" + account + "]登录失败: " << err;
}
return ret;
return (ecode == Errcode::OK);
}

15
src/app/errcode.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
enum class Errcode
{
OK = 0,
ERR = 100,
ERR_DB_CONN = 101, // 数据库连接错误
ERR_DB_SQL = 102, // 数据库查询SQL错误
ERR_LOGIN_USER_NOTEXIST = 103, // 登入错误,用户不存在
ERR_LOGIN_PASSWD = 104, // 登入错误,密码不正确
};