| | |
| | | #include "stdafx.h" |
| | | #include <iostream> |
| | | #include <sstream> |
| | | #include <iostream> |
| | | #include <stdexcept> |
| | | #include <ctime> |
| | | |
| | | // 静态成员变量初始化 |
| | | std::unique_ptr<SystemLogManager> SystemLogManager::m_instance = nullptr; |
| | | // 静态成员初始化 |
| | | std::mutex SystemLogManager::m_mutex; |
| | | |
| | | // 获取单例实例 |
| | | SystemLogManager& SystemLogManager::getInstance() { |
| | | if (m_instance == nullptr) { |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | if (m_instance == nullptr) { |
| | | m_instance = std::unique_ptr<SystemLogManager>(new SystemLogManager()); |
| | | } |
| | | } |
| | | return *m_instance; |
| | | static SystemLogManager instance; |
| | | return instance; |
| | | } |
| | | |
| | | // 构造函数 |
| | | SystemLogManager::SystemLogManager() : m_pDB(nullptr) {} |
| | | |
| | | // 析构函数 |
| | | SystemLogManager::~SystemLogManager() { |
| | | m_pDB = nullptr; // 清除指针引用 |
| | | } |
| | | |
| | | // 设置数据库连接 |
| | | void SystemLogManager::setDatabase(std::unique_ptr<BL::Database>& db) { |
| | | void SystemLogManager::setDatabase(BL::Database* db) { |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | m_pDB = &db; |
| | | m_pDB = db; |
| | | } |
| | | |
| | | // 初始化日志表 |
| | | bool SystemLogManager::initializeLogTable() { |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | std::cerr << "Database connection is not set." << std::endl; |
| | | return false; |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | const std::string createTableQuery = R"( |
| | |
| | | timestamp DATETIME DEFAULT (datetime('now', 'localtime')) |
| | | ) |
| | | )"; |
| | | return (*m_pDB)->executeQuery(createTableQuery); |
| | | |
| | | return m_pDB->executeQuery(createTableQuery); |
| | | } |
| | | |
| | | // 添加日志 |
| | | // 添加日志(使用当前用户) |
| | | bool SystemLogManager::log(LogType logType, const std::string& event) { |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | std::cerr << "Database connection is not set." << std::endl; |
| | | return false; |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | // 清理旧日志 |
| | | cleanOldLogs(30); |
| | | cleanOldLogs(); |
| | | |
| | | std::string strUsername = UserManager::getInstance().getCurrentUser(); |
| | | if (strUsername.empty()) { |
| | | strUsername = "SYSTEM"; |
| | | std::string username = UserManager::getInstance().getCurrentUser(); |
| | | if (username.empty()) { |
| | | username = "SYSTEM"; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "INSERT INTO system_logs (log_type, event, username) VALUES (" |
| | | << "'" << logTypeToString(logType) << "', " |
| | | << "'" << event << "', " |
| | | << "'" << strUsername << "')"; |
| | | return (*m_pDB)->executeQuery(query.str()); |
| | | } |
| | | |
| | | bool SystemLogManager::log(LogType logType, const std::string& event, const std::string& username) { |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | std::cerr << "Database connection is not set." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::vector<std::string> vecUserInfo = UserManager::getInstance().getUserInfo(username); |
| | | if (username.empty() || vecUserInfo.empty()) { |
| | | std::cerr << "Username empty." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // 清理旧日志 |
| | | cleanOldLogs(30); |
| | | |
| | | std::ostringstream query; |
| | | query << "INSERT INTO system_logs (log_type, event, username) VALUES (" |
| | | << "'" << logTypeToString(logType) << "', " |
| | | << "'" << event << "', " |
| | | << "'" << username << "')"; |
| | | return (*m_pDB)->executeQuery(query.str()); |
| | | |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | // 添加日志(指定用户) |
| | | bool SystemLogManager::log(LogType logType, const std::string& event, const std::string& username) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | cleanOldLogs(); |
| | | |
| | | std::ostringstream query; |
| | | query << "INSERT INTO system_logs (log_type, event, username) VALUES (" |
| | | << "'" << logTypeToString(logType) << "', " |
| | | << "'" << event << "', " |
| | | << "'" << username << "')"; |
| | | |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | // 获取日志内容 |
| | | std::vector<std::vector<std::string>> SystemLogManager::getLogs(int startPosition, int count) { |
| | | std::vector<std::vector<std::string>> logs; |
| | | |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | std::cerr << "Database connection is not set." << std::endl; |
| | | return logs; |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | |
| | | // 如果 startPosition 和 count 都是 -1,获取全部数据 |
| | | if (startPosition == -1 && count == -1) { |
| | | query << "SELECT id, log_type, event, username, timestamp FROM system_logs"; |
| | | query << "SELECT id, log_type, event, username, datetime(timestamp, 'localtime') FROM system_logs"; |
| | | } |
| | | else { |
| | | query << "SELECT id, log_type, event, username, timestamp FROM system_logs " |
| | | query << "SELECT id, log_type, event, username, datetime(timestamp, 'localtime') FROM system_logs " |
| | | << "LIMIT " << count << " OFFSET " << startPosition; |
| | | } |
| | | |
| | | auto results = (*m_pDB)->fetchResults(query.str()); |
| | | for (const auto& row : results) { |
| | | logs.push_back(row); |
| | | } |
| | | |
| | | return logs; |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // 获取筛选后的日志数据 |
| | |
| | | int pageNumber, |
| | | int pageSize) |
| | | { |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | // 构建基础 SQL 查询 |
| | | std::ostringstream query; |
| | | query << "SELECT id, log_type, event, username, timestamp FROM system_logs WHERE 1=1"; |
| | | query << "SELECT id, log_type, event, username, datetime(timestamp, 'localtime') FROM system_logs WHERE 1=1"; |
| | | |
| | | // 按日志类型筛选 |
| | | if (logType != "ALL") { |
| | | query << " AND log_type = '" << logType << "'"; |
| | | } |
| | | |
| | | // 按用户名筛选 |
| | | if (username != "ALL") { |
| | | query << " AND username = '" << username << "'"; |
| | | } |
| | | |
| | | // 按描述关键词筛选 |
| | | if (!description.empty()) { |
| | | query << " AND event LIKE '%" << description << "%'"; |
| | | } |
| | | |
| | | // 按时间范围筛选 |
| | | if (!startTime.empty()) { |
| | | query << " AND timestamp >= '" << startTime << "'"; |
| | | } |
| | |
| | | query << " AND timestamp <= '" << endTime << "'"; |
| | | } |
| | | |
| | | // 分页逻辑:设置 LIMIT 和 OFFSET |
| | | int offset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY timestamp DESC"; // 按时间降序排列 |
| | | query << " LIMIT " << pageSize << " OFFSET " << offset; |
| | | query << " ORDER BY timestamp DESC LIMIT " << pageSize << " OFFSET " << offset; |
| | | |
| | | // 执行查询 |
| | | return (*m_pDB)->fetchResults(query.str()); |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // 获取符合条件的日志总数 |
| | |
| | | const std::string& startTime, |
| | | const std::string& endTime) |
| | | { |
| | | // 检查数据库连接是否可用 |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | // 构建基础 SQL 查询 |
| | | std::ostringstream query; |
| | | query << "SELECT COUNT(*) FROM system_logs WHERE 1=1"; |
| | | |
| | | // 按日志类型筛选 |
| | | if (logType != "ALL") { |
| | | query << " AND log_type = '" << logType << "'"; |
| | | } |
| | | |
| | | // 按用户名筛选 |
| | | if (username != "ALL") { |
| | | query << " AND username = '" << username << "'"; |
| | | } |
| | | |
| | | // 按描述关键词筛选 |
| | | if (!description.empty()) { |
| | | query << " AND event LIKE '%" << description << "%'"; |
| | | } |
| | | |
| | | // 按时间范围筛选 |
| | | if (!startTime.empty()) { |
| | | query << " AND timestamp >= '" << startTime << "'"; |
| | | } |
| | |
| | | query << " AND timestamp <= '" << endTime << "'"; |
| | | } |
| | | |
| | | // 执行查询 |
| | | auto results = (*m_pDB)->fetchResults(query.str()); |
| | | |
| | | // 返回记录总数 |
| | | if (!results.empty() && !results[0].empty()) { |
| | | return std::stoi(results[0][0]); // 第一行第一列是计数值 |
| | | } |
| | | |
| | | return 0; // 如果没有结果,返回 0 |
| | | auto results = m_pDB->fetchResults(query.str()); |
| | | return (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0; |
| | | } |
| | | |
| | | void SystemLogManager::cleanOldLogs(int daysToKeep) |
| | | { |
| | | if (!m_pDB || !(*m_pDB)) { |
| | | // 清理超过指定天数的旧日志 |
| | | void SystemLogManager::cleanOldLogs(int daysToKeep) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | // 获取当前日期并计算截断日期 |
| | | time_t now = time(nullptr); |
| | | tm timeInfo; |
| | | localtime_s(&timeInfo, &now); |
| | | timeInfo.tm_mday -= daysToKeep; // 计算指定天数之前的日期 |
| | | mktime(&timeInfo); // 规范化日期 |
| | | |
| | | char buffer[20]; |
| | | strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &timeInfo); |
| | | std::string cutoffDate(buffer); |
| | | |
| | | std::ostringstream query; |
| | | query << "DELETE FROM system_logs WHERE timestamp < '" << cutoffDate << "'"; |
| | | bool ret = (*m_pDB)->executeQuery(query.str()); |
| | | if (!ret) { |
| | | throw std::runtime_error("System Log cleanup operation failed."); |
| | | } |
| | | query << "DELETE FROM system_logs WHERE timestamp < datetime('now', '-" << daysToKeep << " days')"; |
| | | m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | // 转换日志类型为字符串 |
| | | std::string SystemLogManager::logTypeToString(LogType logType) const { |
| | | std::string SystemLogManager::logTypeToString(LogType logType) { |
| | | switch (logType) { |
| | | case LogType::Info: |
| | | return _T("信息"); |
| | | return "信息"; |
| | | case LogType::Error: |
| | | return _T("错误"); |
| | | return "错误"; |
| | | case LogType::Operation: |
| | | return _T("操作"); |
| | | return "操作"; |
| | | default: |
| | | return _T("δ֪"); |
| | | return "δ֪"; |
| | | } |
| | | } |
| | | } |