From f56f083a7e59e58dd44913b11ce4e959fb0475cc Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期三, 20 十一月 2024 19:16:44 +0800
Subject: [PATCH] 1. 添加运行日志界面2.运行日志基本功能已经完成

---
 SourceCode/Bond/BondEq/Resource.h                     |    0 
 SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp     |    4 
 SourceCode/Bond/BondEq/View/UserManagerDlg.h          |    0 
 SourceCode/Bond/BondEq/BondEq.rc                      |    0 
 SourceCode/Bond/BondEq/stdafx.h                       |    4 
 SourceCode/Bond/BondEq/BondEqDlg.cpp                  |   44 ++-
 SourceCode/Bond/x64/Debug/Config/BondEq.db            |    0 
 SourceCode/Bond/BondEq/View/LoginDlg.cpp              |    3 
 SourceCode/Bond/BondEq/BondEq.vcxproj                 |    6 
 SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h     |   48 ++++
 SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp   |  266 ++++++++++++++++++++++++
 SourceCode/Bond/BondEq/DBManager/UserManager.cpp      |   35 +++
 SourceCode/Bond/BondEq/DBManager/UserManager.h        |    2 
 SourceCode/Bond/BondEq/View/UserManagerDlg.cpp        |   25 +
 SourceCode/Bond/BondEq/DBManager/SystemLogManager.h   |   35 ++
 SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp |  162 ++++++++++++++
 16 files changed, 592 insertions(+), 42 deletions(-)

diff --git a/SourceCode/Bond/BondEq/BondEq.rc b/SourceCode/Bond/BondEq/BondEq.rc
index 28c39e3..4c7a132 100644
--- a/SourceCode/Bond/BondEq/BondEq.rc
+++ b/SourceCode/Bond/BondEq/BondEq.rc
Binary files differ
diff --git a/SourceCode/Bond/BondEq/BondEq.vcxproj b/SourceCode/Bond/BondEq/BondEq.vcxproj
index 55b39dd..926d220 100644
--- a/SourceCode/Bond/BondEq/BondEq.vcxproj
+++ b/SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -244,10 +244,11 @@
     <ClInclude Include="targetver.h" />
     <ClInclude Include="ToolUnits.h" />
     <ClInclude Include="TopToolbar.h" />
-    <ClInclude Include="UserManagerDlg.h" />
     <ClInclude Include="VerticalLine.h" />
     <ClInclude Include="View\ChangePasswordDlg.h" />
     <ClInclude Include="View\LoginDlg.h" />
+    <ClInclude Include="View\SystemLogManagerDlg.h" />
+    <ClInclude Include="View\UserManagerDlg.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="CPLC.cpp" />
@@ -305,10 +306,11 @@
     </ClCompile>
     <ClCompile Include="ToolUnits.cpp" />
     <ClCompile Include="TopToolbar.cpp" />
-    <ClCompile Include="UserManagerDlg.cpp" />
     <ClCompile Include="VerticalLine.cpp" />
     <ClCompile Include="View\ChangePasswordDlg.cpp" />
     <ClCompile Include="View\LoginDlg.cpp" />
+    <ClCompile Include="View\SystemLogManagerDlg.cpp" />
+    <ClCompile Include="View\UserManagerDlg.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="BondEq.rc" />
diff --git a/SourceCode/Bond/BondEq/BondEqDlg.cpp b/SourceCode/Bond/BondEq/BondEqDlg.cpp
index 1a8a2ec..9668aa4 100644
--- a/SourceCode/Bond/BondEq/BondEqDlg.cpp
+++ b/SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -9,13 +9,13 @@
 #include "Common.h"
 #include "CBonder.h"
 #include "SettingsDlg.h"
-#include "UserManager.h"
-#include "SystemLogManager.h"
 #include "LoginDlg.h"
 #include "ChangePasswordDlg.h"
 #include "InputDialog.h"
 #include "UserManagerDlg.h"
 
+// test
+#include "SystemLogManagerDlg.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -184,21 +184,15 @@
 	userManager.loadSession();
 	std::unique_ptr<BL::Database>& db = userManager.getDatabaseInstance();
 
-	// 设置日志模块的数据库连接
+	// 设置运行日志模块的数据库连接
 	SystemLogManager& logManager = SystemLogManager::getInstance();
 	logManager.setDatabase(db);
 
-	// 初始化日志表
+	// 初始化运行日志表
 	if (!logManager.initializeLogTable()) {
 		AfxMessageBox("初始化系统日志表失败!");
 		return FALSE;
 	}
-
-	std::string strUsername = userManager.getCurrentUser();
-	if (strUsername.empty()) {
-		strUsername = "SYSTEM";
-	}
-	logManager.log(SystemLogManager::LogType::Info, _T("BondEq启动..."), strUsername);
 
 
 	// 菜单
@@ -243,6 +237,7 @@
 
 	// 更新登录状态
 	UpdateLoginStatus();
+	logManager.log(SystemLogManager::LogType::Info, _T("BondEq启动..."));
 
 
 	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
@@ -368,11 +363,7 @@
 	KillTimer(1);
 #endif
 
-	std::string strUsername = UserManager::getInstance().getCurrentUser();
-	if (strUsername.empty()) {
-		strUsername = "SYSTEM";
-	}
-	SystemLogManager::getInstance().log(SystemLogManager::LogType::Info, _T("BondEq关闭..."), strUsername);
+	SystemLogManager::getInstance().log(SystemLogManager::LogType::Info, _T("BondEq关闭..."));
 }
 
 void CBondEqDlg::OnSize(UINT nType, int cx, int cy)
@@ -533,6 +524,7 @@
 LRESULT CBondEqDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
 {
 	int id = (int)lParam;
+	SystemLogManager& logManager = SystemLogManager::getInstance();
 	if (id == IDC_BUTTON_RUN || id == IDC_BUTTON_STOP || id == IDC_BUTTON_SETTINGS)
 	{
 		CInputDialog inputDialog(_T("验证用户"), _T("请输入用户密码:"));
@@ -545,6 +537,7 @@
 		std::string strPass = UserManager::getInstance().getCurrentPass();
 		if (inputText.Compare(strPass.c_str()) != 0) {
 			AfxMessageBox(_T("密码错误!"));
+			logManager.log(SystemLogManager::LogType::Info, _T("验证时,密码错误!"));
 			return 0;
 		}
 	}
@@ -552,10 +545,12 @@
 	if (id == IDC_BUTTON_RUN) {
 		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
 		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
+		logManager.log(SystemLogManager::LogType::Operation, _T("运行..."));
 	}
 	else if (id == IDC_BUTTON_STOP) {
 		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
 		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+		logManager.log(SystemLogManager::LogType::Operation, _T("停止..."));
 	}
 	else if (id == IDC_BUTTON_SETTINGS) {
 		CSettingsDlg dlg;
@@ -569,20 +564,28 @@
 			loginDlg.DoModal();
 		}
 		else if (1 == menuId) {
+			// test 
+			CSystemLogManagerDlg dlg;
+			dlg.DoModal();
+
 			CChangePasswordDlg changePasswordDlg;
 			changePasswordDlg.DoModal();
 		}
 		else if (2 == menuId) {
 			CUserManagerDlg dlg;
-			dlg.DoModal();
+			if (dlg.DoModal()!= IDOK) {
+				logManager.log(SystemLogManager::LogType::Operation, _T("用户管理的预操作被取消!"));
+			}
 		}
 		else if (3 == menuId) {
-			int ret = AfxMessageBox(_T("是否切换用户?切换用户会退出当前账号!"), MB_OK | MB_ICONEXCLAMATION);
-			if (ret != MB_OK) {
+			int ret = AfxMessageBox(_T("是否切换用户?切换用户会退出当前账号!"), MB_OKCANCEL | MB_ICONEXCLAMATION);
+			if (ret != IDOK) {
 				return 0;
 			}
 
+			logManager.log(SystemLogManager::LogType::Operation, _T("确认切换角色!"));
 			if (userManager.isLoggedIn()) {
+				logManager.log(SystemLogManager::LogType::Info, _T("退出登录!"));
 				userManager.logout();
 			}
 
@@ -592,11 +595,12 @@
 		else {
 			CString cstrMessage;
 			cstrMessage.Format(_T("是否退出用户 [%s]?"), userManager.getCurrentUser().c_str());
-			int ret = AfxMessageBox(_T(cstrMessage), MB_OK | MB_ICONEXCLAMATION);
-			if (ret != MB_OK) {
+			int ret = AfxMessageBox(_T(cstrMessage), MB_OKCANCEL | MB_ICONEXCLAMATION);
+			if (ret != IDOK) {
 				return 0;
 			}
 
+			logManager.log(SystemLogManager::LogType::Info, _T("退出登录!"));
 			userManager.logout();
 		}
 
diff --git a/SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp b/SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp
index 92a6502..d4efa64 100644
--- a/SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp
+++ b/SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp
@@ -1,5 +1,4 @@
 #include "stdafx.h"
-#include "SystemLogManager.h"
 #include <iostream>
 #include <sstream>
 #include <stdexcept>
@@ -41,18 +40,49 @@
             log_type TEXT NOT NULL,
             event TEXT NOT NULL,
             username TEXT NOT NULL,
-            timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
+            timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
         )
     )";
     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;
+    }
+
+    // 清理旧日志
+    cleanOldLogs(30);
+
+    std::string strUsername = UserManager::getInstance().getCurrentUser();
+    if (strUsername.empty()) {
+        strUsername = "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 ("
@@ -90,6 +120,132 @@
     return logs;
 }
 
+// 获取筛选后的日志数据
+std::vector<std::vector<std::string>> SystemLogManager::getFilteredLogs(
+    const std::string& logType,
+    const std::string& username,
+    const std::string& description,
+    const std::string& startTime,
+    const std::string& endTime,
+    int pageNumber,
+    int pageSize)
+{
+    if (!m_pDB || !(*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";
+
+    // 按日志类型筛选
+    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 << "'";
+    }
+    if (!endTime.empty()) {
+        query << " AND timestamp <= '" << endTime << "'";
+    }
+
+    // 分页逻辑:设置 LIMIT 和 OFFSET
+    int offset = (pageNumber - 1) * pageSize;
+    query << " ORDER BY timestamp DESC"; // 按时间降序排列
+    query << " LIMIT " << pageSize << " OFFSET " << offset;
+
+    // 执行查询
+    return (*m_pDB)->fetchResults(query.str());
+}
+
+// 获取符合条件的日志总数
+int SystemLogManager::getTotalLogCount(
+    const std::string& logType,
+    const std::string& username,
+    const std::string& description,
+    const std::string& startTime,
+    const std::string& endTime)
+{
+    // 检查数据库连接是否可用
+    if (!m_pDB || !(*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 << "'";
+    }
+    if (!endTime.empty()) {
+        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
+}
+
+void SystemLogManager::cleanOldLogs(int daysToKeep)
+{
+    if (!m_pDB || !(*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.");
+    }
+}
+
 // 转换日志类型为字符串
 std::string SystemLogManager::logTypeToString(LogType logType) const {
     switch (logType) {
@@ -102,4 +258,4 @@
     default:
         return _T("未知");
     }
-}
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/DBManager/SystemLogManager.h b/SourceCode/Bond/BondEq/DBManager/SystemLogManager.h
index 290e046..075fdec 100644
--- a/SourceCode/Bond/BondEq/DBManager/SystemLogManager.h
+++ b/SourceCode/Bond/BondEq/DBManager/SystemLogManager.h
@@ -10,9 +10,10 @@
 class SystemLogManager {
 public:
     enum class LogType {
-        Info,     // 信息日志
-        Error,    // 错误日志
-        Operation // 操作日志
+        Info,
+        Error,
+        Operation,
+        Unknown
     };
 
     // 获取单例实例
@@ -21,14 +22,36 @@
     // 设置数据库连接
     void setDatabase(std::unique_ptr<BL::Database>& db);
 
+    // 初始化日志表
+    bool initializeLogTable();
+
     // 添加日志
-    bool log(LogType logType, const std::string& event, const std::string& username = "SYSTEM");
+    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);
 
-    // 初始化日志表
-    bool initializeLogTable();
+    // 获取筛选后的日志数据
+    std::vector<std::vector<std::string>> getFilteredLogs(
+        const std::string& logType,
+        const std::string& username,
+        const std::string& description,
+        const std::string& startTime,
+        const std::string& endTime,
+        int pageNumber,
+        int pageSize);
+
+    // 获取符合条件的日志总数
+    int getTotalLogCount(
+        const std::string& logType,
+        const std::string& username,
+        const std::string& description,
+        const std::string& startTime,
+        const std::string& endTime);
+
+    // 清理超过指定天数的旧日志
+    void cleanOldLogs(int daysToKeep = 30);
 
 private:
     // 构造函数(私有化)
diff --git a/SourceCode/Bond/BondEq/DBManager/UserManager.cpp b/SourceCode/Bond/BondEq/DBManager/UserManager.cpp
index bd3f4df..db9f1e5 100644
--- a/SourceCode/Bond/BondEq/DBManager/UserManager.cpp
+++ b/SourceCode/Bond/BondEq/DBManager/UserManager.cpp
@@ -48,7 +48,7 @@
             role INT NOT NULL,
             session_timeout INT DEFAULT 30,
             session_expiration INT DEFAULT 72,
-            last_login TIMESTAMP
+            last_login DATETIME DEFAULT (datetime('now', 'localtime'))
         )
     )";
     m_pDB->executeQuery(createTableQuery);
@@ -411,6 +411,39 @@
     return success;
 }
 
+// 获取所有用户名称
+std::vector<std::string> UserManager::getUsernames() {
+    std::vector<std::string> usernames;
+    std::string query = "SELECT username FROM users";
+    auto results = m_pDB->fetchResults(query);
+
+    for (const auto& row : results) {
+        if (!row.empty()) {
+            usernames.push_back(row[0]); // 获取用户名列的值
+        }
+    }
+
+    return usernames;
+}
+
+// 获取指定用户名的用户信息
+std::vector<std::string> UserManager::getUserInfo(const std::string& username)
+{
+    // 构建查询语句
+    std::ostringstream query;
+    query << "SELECT username, password, role, session_timeout, session_expiration, last_login "
+        << "FROM users WHERE username = '" << username << "'";
+
+    // 执行查询并获取结果
+    auto results = m_pDB->fetchResults(query.str());
+    if (results.empty()) {
+        return {};
+    }
+
+    // 返回查询到的第一行数据
+    return results[0];
+}
+
 // 更新最后活动时间,用于无操作超时检测
 void UserManager::updateActivityTime() {
     m_tpLastActivity = std::chrono::system_clock::now();
diff --git a/SourceCode/Bond/BondEq/DBManager/UserManager.h b/SourceCode/Bond/BondEq/DBManager/UserManager.h
index 44bb5cc..590b2e1 100644
--- a/SourceCode/Bond/BondEq/DBManager/UserManager.h
+++ b/SourceCode/Bond/BondEq/DBManager/UserManager.h
@@ -41,6 +41,8 @@
     bool changeUserRole(const std::string& username, UserRole newRole);
     bool changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes);
     bool changeUserSessionExpiration(const std::string& username, int newExpirationHours);
+    std::vector<std::string> getUsernames();
+    std::vector<std::string> getUserInfo(const std::string& username);
 
     // 会话文件操作
     bool loadSession();     // 从会话文件加载会话信息
diff --git a/SourceCode/Bond/BondEq/Resource.h b/SourceCode/Bond/BondEq/Resource.h
index bd8fa27..4f930a8 100644
--- a/SourceCode/Bond/BondEq/Resource.h
+++ b/SourceCode/Bond/BondEq/Resource.h
Binary files differ
diff --git a/SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp b/SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp
index 7fe322e..3ac5196 100644
--- a/SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp
+++ b/SourceCode/Bond/BondEq/View/ChangePasswordDlg.cpp
@@ -5,7 +5,6 @@
 #include "BondEq.h"
 #include "afxdialogex.h"
 #include "ChangePasswordDlg.h"
-#include "UserManager.h"
 
 
 // CChangePasswordDlg 瀵硅瘽妗�
@@ -82,6 +81,7 @@
         return;
     }
 
+    SystemLogManager& logManager = SystemLogManager::getInstance();
     if (newPassword.Compare(currentPassword) == 0) {
         EndDialog(IDCANCEL);
         return;
@@ -101,12 +101,14 @@
     if (userManager.isLoggedIn() && strCurrentPassword.compare(userManager.getCurrentPass()) == 0) {
         if (changeUserPassword(userManager, strUsername, strNewPassword)) {
             EndDialog(IDOK);
+			logManager.log(SystemLogManager::LogType::Info, "淇敼瀵嗙爜鎴愬姛锛�", strUsername);
         }
     }
     else {
         if (userManager.login(strUsername, strCurrentPassword)) {
             if (changeUserPassword(userManager, strUsername, strNewPassword)) {
                 EndDialog(IDOK);
+                logManager.log(SystemLogManager::LogType::Info, "淇敼瀵嗙爜鎴愬姛锛�", strUsername);
             }
             else {
                 userManager.logout();
diff --git a/SourceCode/Bond/BondEq/View/LoginDlg.cpp b/SourceCode/Bond/BondEq/View/LoginDlg.cpp
index 9dae4f8..b78c28d 100644
--- a/SourceCode/Bond/BondEq/View/LoginDlg.cpp
+++ b/SourceCode/Bond/BondEq/View/LoginDlg.cpp
@@ -5,7 +5,6 @@
 #include "BondEq.h"
 #include "afxdialogex.h"
 #include "LoginDlg.h"
-#include "UserManager.h"
 #include "ChangePasswordDlg.h"
 
 
@@ -98,12 +97,14 @@
 #endif
 
     UserManager& userManager = UserManager::getInstance();
+    SystemLogManager& logManager = SystemLogManager::getInstance();
     if (!userManager.login(strUsername, strPassword, (m_checkRememberPassword.GetCheck() == BST_CHECKED))) {
         AfxMessageBox(_T("鐧诲綍澶辫触銆�"));
         return;
     }
 
     EndDialog(IDOK);
+    logManager.log(SystemLogManager::LogType::Info, _T("鐧诲綍鎴愬姛..."));
 }
 
 void CLoginDlg::OnBnClickedChangePassword()
diff --git a/SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp b/SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp
new file mode 100644
index 0000000..40e4492
--- /dev/null
+++ b/SourceCode/Bond/BondEq/View/SystemLogManagerDlg.cpp
@@ -0,0 +1,266 @@
+锘�// SystemLogManagerDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "BondEq.h"
+#include "afxdialogex.h"
+#include "SystemLogManagerDlg.h"
+#include "UserManager.h"
+#include "SystemLogManager.h"
+
+
+// CSystemLogManagerDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CSystemLogManagerDlg, CDialogEx)
+
+CSystemLogManagerDlg::CSystemLogManagerDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_SYSTEM_LOG_MANAGER, pParent)
+{
+
+}
+
+CSystemLogManagerDlg::~CSystemLogManagerDlg()
+{
+}
+
+void CSystemLogManagerDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_COMBO_TYPE, m_comboType);
+	DDX_Control(pDX, IDC_COMBO_USER, m_comboUser);
+	DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
+	DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd);
+	DDX_Control(pDX, IDC_EDIT_DESCRIPTION, m_editDescription);
+	DDX_Control(pDX, IDC_CUSTOM_LIST_LOGS, m_listLogs);
+	DDX_Control(pDX, IDC_STATIC_PAGE_NUMBER, m_staticPageNum);
+}
+
+void CSystemLogManagerDlg::InitSystemLogManager()
+{
+	if (m_listLogs.GetSafeHwnd() == NULL)
+		return;
+
+	int nRows = 21; // 鍖呮嫭琛ㄥご锛�1 琛岋級鍜屾暟鎹紙20 琛岋級
+	int nCols = 5;
+
+	int nFixRows = 1;
+	int nFixCols = 0;
+	int nRowIdx = 0;
+	int nColIdx = 0;
+
+	m_listLogs.DeleteAllItems();
+	m_listLogs.SetVirtualMode(FALSE);
+	m_listLogs.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor); // 璁剧疆鍥哄畾琛岃儗鏅壊
+	m_listLogs.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor); // 璁剧疆鍥哄畾鍒楄儗鏅壊
+	m_listLogs.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor);	// 璁剧疆鍗曞厓鏍艰儗鏅壊
+	m_listLogs.SetFixedTextColor(g_nGridFixFontColor); // 璁剧疆鍥哄畾琛屽垪瀛椾綋棰滆壊
+
+	m_listLogs.SetRowCount(nRows);
+	m_listLogs.SetColumnCount(nCols);
+	m_listLogs.SetFixedRowCount(nFixRows);
+	m_listLogs.SetFixedColumnCount(nFixCols);
+
+	// Col
+	m_listLogs.SetColumnWidth(nColIdx, 20);
+	m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("No."));
+	m_listLogs.SetColumnWidth(nColIdx, 70);
+	m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("绫诲瀷"));
+	m_listLogs.SetColumnWidth(nColIdx, 150);
+	m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("浜嬩欢"));
+	m_listLogs.SetColumnWidth(nColIdx, 70);
+	m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("鐢ㄦ埛"));
+	m_listLogs.SetColumnWidth(nColIdx, 70);
+	m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("鏃堕棿"));
+
+	// 鍒涘缓 20 琛岀┖鐧芥暟鎹
+	for (int i = 1; i < nRows; ++i) {
+		for (int j = 0; j < nCols; ++j) {
+			m_listLogs.SetItemText(i, j, _T("")); // 鍒濆鍖栦负绌哄瓧绗︿覆
+		}
+	}
+
+	m_listLogs.SetFixedRowSelection(FALSE);
+	m_listLogs.SetFixedColumnSelection(FALSE);
+	m_listLogs.SetEditable(FALSE);
+	m_listLogs.SetRowResize(FALSE);
+	m_listLogs.SetColumnResize(TRUE);
+	m_listLogs.ExpandColumnsToFit(TRUE);
+	m_listLogs.SetListMode(TRUE);				// 鍚敤鍒楄〃妯″紡
+	m_listLogs.EnableSelection(TRUE);			// 鍚敤閫夋嫨
+	m_listLogs.SetSingleRowSelection(TRUE);		// 鑷姩鏁磋楂樹寒锛堥檺鍒朵负鍗曡閫夋嫨锛�
+	m_listLogs.ExpandLastColumn();				// 鏈�鍚庝竴鍒楀~鍏呯綉鏍�
+
+	try {
+		FillSystemLogManager();
+	}
+	catch (const std::exception& ex) {
+		CString errorMsg;
+		errorMsg.Format(_T("鍒濆鍖栬繍琛屾棩蹇楀け璐ワ細%s"), CString(ex.what()));
+		AfxMessageBox(errorMsg, MB_ICONERROR);
+	}
+}
+
+void CSystemLogManagerDlg::FillSystemLogManager()
+{
+	// 鑾峰彇绛涢�夋潯浠�
+	CString selectedType, selectedUser, description;
+	m_comboType.GetLBText(m_comboType.GetCurSel(), selectedType);
+	m_comboUser.GetLBText(m_comboUser.GetCurSel(), selectedUser);
+	m_editDescription.GetWindowText(description);
+
+	COleDateTime startTime, endTime;
+	m_dateTimeStart.GetTime(startTime);
+	m_dateTimeEnd.GetTime(endTime);
+	CString strStartTime = startTime.Format(_T("%Y-%m-%d %H:%M:%S"));
+	CString strEndTime = endTime.Format(_T("%Y-%m-%d %H:%M:%S"));
+
+	std::string type = CT2A(selectedType);
+	std::string user = CT2A(selectedUser);
+	std::string desc = CT2A(description);
+	std::string start = CT2A(strStartTime);
+	std::string end = CT2A(strEndTime);
+
+	// 鑾峰彇鏃ュ織绠$悊瀹炰緥
+	SystemLogManager& logManager = SystemLogManager::getInstance();
+
+	int pageSize = 20; // 姣忛〉鏄剧ず 20 鏉¤褰�
+	int totalRecords = logManager.getTotalLogCount(type, user, desc, start, end);
+	m_nTotalPages = (totalRecords + pageSize - 1) / pageSize;
+	auto logs = logManager.getFilteredLogs(type, user, desc, start, end, m_nCurrentPage, pageSize);
+
+	// 鏇存柊琛ㄦ牸鏁版嵁
+	int rowIdx = 1;
+	for (const auto& log : logs) {
+		m_listLogs.SetItemText(rowIdx, 0, CString(std::to_string(rowIdx).c_str())); // 搴忓彿
+		m_listLogs.SetItemText(rowIdx, 1, CString(log[1].c_str()));                 // 绫诲瀷
+		m_listLogs.SetItemText(rowIdx, 2, CString(log[2].c_str()));                 // 浜嬩欢
+		m_listLogs.SetItemText(rowIdx, 3, CString(log[3].c_str()));                 // 鐢ㄦ埛
+		m_listLogs.SetItemText(rowIdx, 4, CString(log[4].c_str()));                 // 鏃堕棿
+		++rowIdx;
+	}
+
+	// 娓呯┖澶氫綑琛�
+	for (; rowIdx <= 20; ++rowIdx) {
+		m_listLogs.SetItemText(rowIdx, 0, CString(std::to_string(rowIdx).c_str())); // 搴忓彿鍒�
+		for (int colIdx = 1; colIdx < m_listLogs.GetColumnCount(); ++colIdx) {
+			m_listLogs.SetItemText(rowIdx, colIdx, _T(""));
+		}
+	}
+
+	m_listLogs.Invalidate();
+	m_listLogs.UpdateWindow();
+	m_listLogs.ExpandColumnsToFit(FALSE);
+	m_listLogs.ExpandLastColumn();
+	UpdatePageInfo();
+}
+
+void CSystemLogManagerDlg::UpdatePageInfo()
+{
+	// 鏍煎紡鍖栭〉鐮佷俊鎭负 "褰撳墠椤�/鎬婚〉鏁�"
+	CString pageInfo;
+	pageInfo.Format(_T("%d/%d 椤�"), m_nCurrentPage, m_nTotalPages);
+	m_staticPageNum.SetWindowText(pageInfo);
+}
+
+
+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)
+END_MESSAGE_MAP()
+
+
+// CSystemLogManagerDlg 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CSystemLogManagerDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// TODO:  鍦ㄦ娣诲姞棰濆鐨勫垵濮嬪寲
+	m_nCurrentPage = 1;  // 浠庣涓�椤靛紑濮�
+	m_nTotalPages = 1;   // 榛樿鎬婚〉鏁颁负 1
+
+	m_comboType.AddString(_T("ALL"));
+	m_comboType.AddString(_T("淇℃伅"));
+	m_comboType.AddString(_T("鎿嶄綔"));
+	m_comboType.AddString(_T("閿欒"));
+	m_comboType.AddString(_T("鏈煡"));
+	m_comboType.SetCurSel(0);
+
+	m_comboUser.AddString(_T("ALL"));
+	m_comboUser.AddString(_T("SYSTEM"));
+	auto usernames = UserManager::getInstance().getUsernames();
+	for (const auto& username : usernames) {
+		CString cstrUsername(username.c_str());
+		m_comboUser.AddString(cstrUsername);
+	}
+	m_comboUser.SetCurSel(0);
+	
+	// 璁剧疆涓� 30 澶╁墠
+	COleDateTime currentTime = COleDateTime::GetCurrentTime();
+	COleDateTime defaultStartTime = currentTime - COleDateTimeSpan(30, 0, 0, 0);
+	m_dateTimeStart.SetTime(defaultStartTime);
+
+	InitSystemLogManager();
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+	// 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+
+
+void CSystemLogManagerDlg::OnBnClickedButtonSearch()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	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::OnBnClickedButtonPrevPage()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	try {
+		if (m_nCurrentPage > 1) {
+			m_nCurrentPage--;
+			FillSystemLogManager();
+		}
+		else {
+			AfxMessageBox(_T("宸茬粡鏄涓�椤碉紒"));
+		}
+	}
+	catch (const std::exception& ex) {
+		CString errorMsg;
+		errorMsg.Format(_T("鍒囨崲鍒颁笂涓�椤靛け璐ワ細%s"), CString(ex.what()));
+		AfxMessageBox(errorMsg, MB_ICONERROR);
+	}
+}
+
+
+void CSystemLogManagerDlg::OnBnClickedButtonNextPage()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	try {
+		if (m_nCurrentPage < m_nTotalPages) {
+			m_nCurrentPage++;
+			FillSystemLogManager();
+		}
+		else {
+			AfxMessageBox(_T("宸茬粡鏄渶鍚庝竴椤碉紒"));
+		}
+	}
+	catch (const std::exception& ex) {
+		CString errorMsg;
+		errorMsg.Format(_T("鍒囨崲鍒颁笅涓�椤靛け璐ワ細%s"), CString(ex.what()));
+		AfxMessageBox(errorMsg, MB_ICONERROR);
+	}
+}
+
diff --git a/SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h b/SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h
new file mode 100644
index 0000000..c7a0601
--- /dev/null
+++ b/SourceCode/Bond/BondEq/View/SystemLogManagerDlg.h
@@ -0,0 +1,48 @@
+锘�#pragma once
+#include "afxdialogex.h"
+#include "GridCtrl.h"
+
+
+// CSystemLogManagerDlg 瀵硅瘽妗�
+
+class CSystemLogManagerDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CSystemLogManagerDlg)
+
+public:
+	CSystemLogManagerDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CSystemLogManagerDlg();
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_SYSTEM_LOG_MANAGER };
+#endif
+
+private:
+	void InitSystemLogManager();
+	void FillSystemLogManager();
+	void UpdatePageInfo();
+
+private:
+	int m_nCurrentPage;    // 褰撳墠椤电爜
+	int m_nTotalPages;     // 鎬婚〉鏁�
+
+private:
+	CComboBox m_comboType;
+	CComboBox m_comboUser;
+	CDateTimeCtrl m_dateTimeStart;
+	CDateTimeCtrl m_dateTimeEnd;
+	CEdit m_editDescription;
+	CGridCtrl m_listLogs;
+	CStatic m_staticPageNum;
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBnClickedButtonSearch();
+	afx_msg void OnBnClickedButtonPrevPage();
+	afx_msg void OnBnClickedButtonNextPage();
+};
diff --git a/SourceCode/Bond/BondEq/UserManagerDlg.cpp b/SourceCode/Bond/BondEq/View/UserManagerDlg.cpp
similarity index 95%
rename from SourceCode/Bond/BondEq/UserManagerDlg.cpp
rename to SourceCode/Bond/BondEq/View/UserManagerDlg.cpp
index f58d1e6..512eb5e 100644
--- a/SourceCode/Bond/BondEq/UserManagerDlg.cpp
+++ b/SourceCode/Bond/BondEq/View/UserManagerDlg.cpp
@@ -6,7 +6,6 @@
 #include "afxdialogex.h"
 #include "UserManagerDlg.h"
 #include "InputDialog.h"
-#include "UserManager.h"
 #include "NewCellTypes/GridCellCombo.h"
 #include "NewCellTypes/GridCellNumeric.h"
 
@@ -202,12 +201,12 @@
 
 	CString inputText = inputDialog.GetInputText();
 	if (inputText.IsEmpty()) {
-		AfxMessageBox(_T("鐢ㄦ埛鍚嶄笉鑳戒负绌猴紒"), MB_OK | MB_ICONEXCLAMATION);
+		AfxMessageBox(_T("鐢ㄦ埛鍚嶄笉鑳戒负绌猴紒"));
 		return;
 	}
 
 	if (IsUsernameDuplicate(inputText)) {
-		AfxMessageBox(_T("鐢ㄦ埛鍚嶉噸澶嶏紒"), MB_OK | MB_ICONEXCLAMATION);
+		AfxMessageBox(_T("鐢ㄦ埛鍚嶉噸澶嶏紒"));
 		return;
 	}
 
@@ -259,6 +258,11 @@
 	pGridCtrl->ExpandLastColumn();
 	pGridCtrl->Invalidate();
 	pGridCtrl->UpdateWindow();
+
+	CString cstrMessage;
+	cstrMessage.Format(_T("棰勬坊鍔犵敤鎴� [%s]锛�"), inputText);
+	std::string strMessage = CT2A(cstrMessage);
+	SystemLogManager::getInstance().log(SystemLogManager::LogType::Operation, strMessage);
 }
 
 void CUserManagerDlg::DeleteSelectedRow(CGridCtrl* pGridCtrl)
@@ -286,7 +290,7 @@
 			if (selectedUser == currentUser) {
 				CString message;
 				message.Format(_T("鐢ㄦ埛 [%s] 鏄綋鍓嶇櫥褰曠敤鎴凤紝涓嶈兘鍒犻櫎锛�"), currentUser);
-				AfxMessageBox(message, MB_OK | MB_ICONEXCLAMATION);
+				AfxMessageBox(message);
 				return;
 			}
 
@@ -294,7 +298,7 @@
 		}
 
 		if (rowsToDelete.empty()) {
-			AfxMessageBox(_T("璇峰厛閫夋嫨瑕佸垹闄ょ殑琛岋紒"), MB_OK | MB_ICONINFORMATION);
+			AfxMessageBox(_T("璇峰厛閫夋嫨瑕佸垹闄ょ殑琛岋紒"));
 			return;
 		}
 
@@ -302,6 +306,11 @@
 		if (rowsToDelete.size() == 1) {
 			CString selectedUser = pGridCtrl->GetItemText(rowsToDelete[0], 1);
 			message.Format(_T("纭畾瑕佸垹闄ら�変腑鐢ㄦ埛 [%s] 鍚楋紵"), selectedUser);
+
+			CString cstrMessage;
+			cstrMessage.Format(_T("棰勫垹闄ょ敤鎴� [%s]锛�"), selectedUser);
+			std::string strMessage = CT2A(cstrMessage);
+			SystemLogManager::getInstance().log(SystemLogManager::LogType::Operation, strMessage);
 		}
 		else {
 			message.Format(_T("纭畾瑕佸垹闄ら�変腑鐨� %d 涓敤鎴峰悧锛�"), rowsToDelete.size());
@@ -319,7 +328,7 @@
 		}
 	}
 	else {
-		AfxMessageBox(_T("璇峰厛閫夋嫨瑕佸垹闄ょ殑鐢ㄦ埛锛�"), MB_OK | MB_ICONINFORMATION);
+		AfxMessageBox(_T("璇峰厛閫夋嫨瑕佸垹闄ょ殑鐢ㄦ埛锛�"));
 	}
 }
 
@@ -498,14 +507,14 @@
 
 	CCellRange selectedRange = m_gridUserManager.GetSelectedCellRange();
 	if (!selectedRange.IsValid()) {
-		AfxMessageBox(_T("璇峰厛閫夋嫨瑕佹彃鍏ョ殑浣嶇疆锛�"), MB_OK | MB_ICONINFORMATION);
+		AfxMessageBox(_T("璇峰厛閫夋嫨瑕佹彃鍏ョ殑浣嶇疆锛�"));
 		return;
 	}
 
 	int minRow = selectedRange.GetMinRow();
 	int maxRow = selectedRange.GetMaxRow();
 	if (minRow < 1) {
-		AfxMessageBox(_T("璇烽�夋嫨鏈夋晥鐨勮锛�"), MB_OK | MB_ICONEXCLAMATION);
+		AfxMessageBox(_T("璇烽�夋嫨鏈夋晥鐨勮锛�"));
 		return;
 	}
 
diff --git a/SourceCode/Bond/BondEq/UserManagerDlg.h b/SourceCode/Bond/BondEq/View/UserManagerDlg.h
similarity index 100%
rename from SourceCode/Bond/BondEq/UserManagerDlg.h
rename to SourceCode/Bond/BondEq/View/UserManagerDlg.h
diff --git a/SourceCode/Bond/BondEq/stdafx.h b/SourceCode/Bond/BondEq/stdafx.h
index cf4ecaf..c82164e 100644
--- a/SourceCode/Bond/BondEq/stdafx.h
+++ b/SourceCode/Bond/BondEq/stdafx.h
@@ -47,6 +47,10 @@
 #include "..\DatabaseSDK\include\MySQLDatabase.h"
 #include "..\DatabaseSDK\include\SQLiteDatabase.h"
 
+// 单例模式的数据库管理类
+#include "UserManager.h"
+#include "SystemLogManager.h"
+
 // 控件样式
 static UINT g_nGridFixCellColor = RGB(144, 200, 246);
 static UINT g_nGridFixFontColor = RGB(0, 0, 0);
diff --git a/SourceCode/Bond/x64/Debug/Config/BondEq.db b/SourceCode/Bond/x64/Debug/Config/BondEq.db
index 4e066d3..3ce9c51 100644
--- a/SourceCode/Bond/x64/Debug/Config/BondEq.db
+++ b/SourceCode/Bond/x64/Debug/Config/BondEq.db
Binary files differ

--
Gitblit v1.9.3