| SourceCode/Bond/BondEq/BondEqDlg.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/BondEq/DBManager/SystemLogManager.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| SourceCode/Bond/x64/Debug/Config/BondEq.db | 补丁 | 查看 | 原始文档 | blame | 历史 |
SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -186,11 +186,19 @@ // 设置运行日志模块的数据库连接 SystemLogManager& logManager = SystemLogManager::getInstance(); logManager.setDatabase(db); logManager.setDatabase(db.get()); // 初始化运行日志表 if (!logManager.initializeLogTable()) { AfxMessageBox("初始化系统日志表失败!"); try { if (!logManager.initializeLogTable()) { AfxMessageBox("初始化系统日志表失败!"); return FALSE; } } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("初始化系统日志表失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); return FALSE; } SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp
@@ -1,37 +1,36 @@ #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"( @@ -43,81 +42,67 @@ 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()); } // 获取筛选后的日志数据 @@ -130,30 +115,22 @@ 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 << "'"; } @@ -161,13 +138,10 @@ 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()); } // 获取符合条件的日志总数 @@ -178,31 +152,22 @@ 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 << "'"; } @@ -210,52 +175,31 @@ 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 "δ֪"; } } } SourceCode/Bond/BondEq/DBManager/SystemLogManager.h
@@ -2,13 +2,14 @@ #define SYSTEM_LOG_MANAGER_H #include <string> #include <memory> #include <vector> #include <mutex> #include <chrono> #include "Database.h" // 系统日志管理类 class SystemLogManager { public: // 日志类型定义 enum class LogType { Info, Error, @@ -20,7 +21,7 @@ static SystemLogManager& getInstance(); // 设置数据库连接 void setDatabase(std::unique_ptr<BL::Database>& db); void setDatabase(BL::Database* db); // 初始化日志表 bool initializeLogTable(); @@ -29,8 +30,8 @@ bool log(LogType logType, const std::string& event); bool log(LogType logType, const std::string& event, const std::string& username); // 获取日志 std::vector<std::vector<std::string>> SystemLogManager::getLogs(int startPosition = -1, int count = -1); // 获取日志内容 std::vector<std::vector<std::string>> getLogs(int startPosition = -1, int count = -1); // 获取筛选后的日志数据 std::vector<std::vector<std::string>> getFilteredLogs( @@ -53,22 +54,20 @@ // 清理超过指定天数的旧日志 void cleanOldLogs(int daysToKeep = 30); // 转换日志类型为字符串 static std::string logTypeToString(LogType logType); private: // 构造函数(私有化) // 构造函数和析构函数 SystemLogManager(); ~SystemLogManager(); // 禁止拷贝和赋值 SystemLogManager(const SystemLogManager&) = delete; SystemLogManager& operator=(const SystemLogManager&) = delete; // 转换日志类型为字符串 std::string logTypeToString(LogType logType) const; // 数据库连接 std::unique_ptr<BL::Database>* m_pDB; // 单例实例 static std::unique_ptr<SystemLogManager> m_instance; BL::Database* m_pDB = nullptr; // 线程安全锁 static std::mutex m_mutex; SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp
@@ -162,11 +162,129 @@ m_staticPageNum.SetWindowText(pageInfo); } void CSystemLogManagerDlg::SetDefaultFont() { CFont* pFont = new CFont(); LOGFONT logFont = { 0 }; // 设置字体属性 _tcscpy_s(logFont.lfFaceName, _T("Segoe UI")); // 使用清晰字体 logFont.lfHeight = -12; // 字体高度 logFont.lfWeight = FW_NORMAL; logFont.lfQuality = CLEARTYPE_QUALITY; // 启用 ClearType 抗锯齿 pFont->CreateFontIndirect(&logFont); // 遍历所有控件,应用字体 CWnd* pWnd = GetWindow(GW_CHILD); while (pWnd) { TCHAR szClassName[256]; GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0 || _tcsicmp(szClassName, _T("ComboBoxs")) == 0) { pWnd = pWnd->GetNextWindow(); continue; } pWnd->SetFont(pFont, TRUE); pWnd = pWnd->GetNextWindow(); } } void CSystemLogManagerDlg::AdjustControls(int nWidth, int nHeight) { CWnd* pWnd = GetWindow(GW_CHILD); while (pWnd) { UINT nCtrlID = pWnd->GetDlgCtrlID(); CRect ctrlRect; pWnd->GetWindowRect(&ctrlRect); ScreenToClient(&ctrlRect); // 计算控件的新位置和大小,按比例调整 int newX = (int)(ctrlRect.left * (nWidth / (float)m_nInitialWidth)); int newY = (int)(ctrlRect.top * (nHeight / (float)m_nInitialHeight)); int newWidth = (int)(ctrlRect.Width() * (nWidth / (float)m_nInitialWidth)); int newHeight = (int)(ctrlRect.Height() * (nHeight / (float)m_nInitialHeight)); TCHAR szClassName[256]; GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd; pGridCtrl->SetDefCellHeight(newHeight / 21); pGridCtrl->ExpandColumnsToFit(TRUE); pGridCtrl->Invalidate(); } pWnd->MoveWindow(newX, newY, newWidth, newHeight); AdjustControlFont(pWnd, newWidth, newHeight); // 获取下一个控件 pWnd = pWnd->GetNextWindow(); } } void CSystemLogManagerDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight) { TCHAR szClassName[256]; GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); if (_tcsicmp(szClassName, _T("Static")) == 0) { CStatic* pStatic = (CStatic*)pWnd; pStatic->ModifyStyle(SS_CENTER | SS_RIGHT | SS_CENTERIMAGE, SS_LEFT | SS_CENTERIMAGE); return; } if (_tcsicmp(szClassName, _T("ComboBox")) == 0) { CComboBox* pComboBox = (CComboBox*)pWnd; pComboBox->SetItemHeight(-1, nHeight); // -1 表示所有项的高度 } if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { return; } int fontSize = nHeight - 10; CFont* pCurrentFont = pWnd->GetFont(); LOGFONT logFont; pCurrentFont->GetLogFont(&logFont); logFont.lfHeight = -fontSize; CFont newFont; newFont.CreateFontIndirect(&logFont); pWnd->SetFont(&newFont); pWnd->Invalidate(); } void CSystemLogManagerDlg::AdjustComboBoxStyle(CComboBox& comboBox) { DWORD dwStyle = comboBox.GetStyle(); comboBox.ModifyStyle(0, CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED); comboBox.Invalidate(); comboBox.UpdateWindow(); } void CSystemLogManagerDlg::AdjustDateTimeCtrlStyle(CDateTimeCtrl& dateTimeCtrl) { dateTimeCtrl.ModifyStyle(0, DTS_RIGHTALIGN); dateTimeCtrl.Invalidate(); dateTimeCtrl.UpdateWindow(); } BEGIN_MESSAGE_MAP(CSystemLogManagerDlg, CDialogEx) ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CSystemLogManagerDlg::OnBnClickedButtonSearch) ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CSystemLogManagerDlg::OnBnClickedButtonPrevPage) ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CSystemLogManagerDlg::OnBnClickedButtonNextPage) ON_CBN_SELCHANGE(IDC_COMBO_TYPE, &CSystemLogManagerDlg::OnSelchangeComboType) ON_CBN_SELCHANGE(IDC_COMBO_USER, &CSystemLogManagerDlg::OnSelchangeComboUser) ON_WM_SIZE() END_MESSAGE_MAP() @@ -178,6 +296,8 @@ CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 SetWindowText(_T("系统运行日志")); m_nCurrentPage = 1; // 从第一页开始 m_nTotalPages = 1; // 默认总页数为 1 @@ -202,12 +322,46 @@ COleDateTime defaultStartTime = currentTime - COleDateTimeSpan(30, 0, 0, 0); m_dateTimeStart.SetTime(defaultStartTime); CRect screenRect, dlgRect, clientRect; GetClientRect(&clientRect); m_nInitialWidth = clientRect.Width(); m_nInitialHeight = clientRect.Height(); GetWindowRect(&dlgRect); int dlgWidth = dlgRect.Width() * 2; int dlgHeight = dlgRect.Height() * 2; SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0); if (dlgWidth > screenRect.Width()) { dlgWidth = screenRect.Width(); } if (dlgHeight > screenRect.Height()) { dlgHeight = screenRect.Height(); } int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2; int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2; MoveWindow(centerX, centerY, dlgWidth, dlgHeight); InitSystemLogManager(); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CSystemLogManagerDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 CRect rect; GetClientRect(&rect); // 遍历对话框中的所有控件 AdjustControls(rect.Width(), rect.Height()); //SetDefaultFont(); } void CSystemLogManagerDlg::OnBnClickedButtonSearch() @@ -264,3 +418,32 @@ } } void CSystemLogManagerDlg::OnSelchangeComboType() { // TODO: 在此添加控件通知处理程序代码 try { m_nCurrentPage = 1; FillSystemLogManager(); } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("切换类型失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } void CSystemLogManagerDlg::OnSelchangeComboUser() { // TODO: 在此添加控件通知处理程序代码 try { m_nCurrentPage = 1; FillSystemLogManager(); } catch (const std::exception& ex) { CString errorMsg; errorMsg.Format(_T("切换角色失败:%s"), CString(ex.what())); AfxMessageBox(errorMsg, MB_ICONERROR); } } SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h
@@ -22,8 +22,15 @@ void InitSystemLogManager(); void FillSystemLogManager(); void UpdatePageInfo(); void SetDefaultFont(); void AdjustControls(int nWidth, int nHeight); void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight); void AdjustComboBoxStyle(CComboBox& comboBox); void AdjustDateTimeCtrlStyle(CDateTimeCtrl& dateTimeCtrl); private: int m_nInitialWidth; // 初始宽度 int m_nInitialHeight; // 初始高度 int m_nCurrentPage; // 当前页码 int m_nTotalPages; // 总页数 @@ -42,7 +49,10 @@ DECLARE_MESSAGE_MAP() public: virtual BOOL OnInitDialog(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnBnClickedButtonSearch(); afx_msg void OnBnClickedButtonPrevPage(); afx_msg void OnBnClickedButtonNextPage(); afx_msg void OnSelchangeComboType(); afx_msg void OnSelchangeComboUser(); }; SourceCode/Bond/x64/Debug/Config/BondEq.dbBinary files differ