LAPTOP-T815PCOQ\25526
2024-11-20 8dbd14952aa622587a92866dc01943869ea4f9dc
1. 添加系统运行记录表 2. 完善用户管理的部分细节
已添加4个文件
已修改6个文件
383 ■■■■■ 文件已修改
SourceCode/Bond/BondEq/BondEq.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEqDlg.cpp 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/DBManager/SystemLogManager.h 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/DBManager/UserManager.cpp 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/DBManager/UserManager.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/InputDialog.cpp 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/InputDialog.h 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/UserManagerDlg.cpp 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Config/BondEq.db 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -217,6 +217,7 @@
    <ClInclude Include="Common.h" />
    <ClInclude Include="Configuration.h" />
    <ClInclude Include="CPanelProject.h" />
    <ClInclude Include="DBManager\SystemLogManager.h" />
    <ClInclude Include="DBManager\UserManager.h" />
    <ClInclude Include="EQState.h" />
    <ClInclude Include="EQStateMonitor.h" />
@@ -274,6 +275,7 @@
    <ClCompile Include="CProjectPageRemoteEqs.cpp" />
    <ClCompile Include="Configuration.cpp" />
    <ClCompile Include="CPanelProject.cpp" />
    <ClCompile Include="DBManager\SystemLogManager.cpp" />
    <ClCompile Include="DBManager\UserManager.cpp" />
    <ClCompile Include="EQState.cpp" />
    <ClCompile Include="EQStateMonitor.cpp" />
SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -10,12 +10,10 @@
#include "CBonder.h"
#include "SettingsDlg.h"
#include "UserManager.h"
#include "SystemLogManager.h"
#include "LoginDlg.h"
#include "ChangePasswordDlg.h"
#include "InputDialog.h"
// test
#include "AxisSettingsDlg.h"
#include "UserManagerDlg.h"
@@ -184,6 +182,23 @@
    SetTimer(1, 60000, nullptr);
#endif
    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);
    // èœå•
@@ -352,6 +367,12 @@
    UserManager::getInstance().terminateIdleDetection();
    KillTimer(1);
#endif
    std::string strUsername = UserManager::getInstance().getCurrentUser();
    if (strUsername.empty()) {
        strUsername = "SYSTEM";
    }
    SystemLogManager::getInstance().log(SystemLogManager::LogType::Info, _T("BondEq关闭..."), strUsername);
}
void CBondEqDlg::OnSize(UINT nType, int cx, int cy)
@@ -546,12 +567,10 @@
        if (menuId == 0) {
            CLoginDlg loginDlg;
            loginDlg.DoModal();
            UpdateLoginStatus();
        }
        else if (1 == menuId) {
            CChangePasswordDlg changePasswordDlg;
            if (changePasswordDlg.DoModal() == IDOK) {
            }
            changePasswordDlg.DoModal();
        }
        else if (2 == menuId) {
            CUserManagerDlg dlg;
@@ -569,12 +588,19 @@
            CLoginDlg loginDlg;
            loginDlg.DoModal();
            UpdateLoginStatus();
        }
        else {
            userManager.logout();
            UpdateLoginStatus();
            CString cstrMessage;
            cstrMessage.Format(_T("是否退出用户 [%s]?"), userManager.getCurrentUser().c_str());
            int ret = AfxMessageBox(_T(cstrMessage), MB_OK | MB_ICONEXCLAMATION);
            if (ret != MB_OK) {
                return 0;
        }
            userManager.logout();
        }
        UpdateLoginStatus();
    }
    return 0;
SourceCode/Bond/BondEq/DBManager/SystemLogManager.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,105 @@
#include "stdafx.h"
#include "SystemLogManager.h"
#include <iostream>
#include <sstream>
#include <stdexcept>
// é™æ€æˆå‘˜å˜é‡åˆå§‹åŒ–
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;
}
// æž„造函数
SystemLogManager::SystemLogManager() : m_pDB(nullptr) {}
// è®¾ç½®æ•°æ®åº“连接
void SystemLogManager::setDatabase(std::unique_ptr<BL::Database>& db) {
    std::lock_guard<std::mutex> lock(m_mutex);
    m_pDB = &db;
}
// åˆå§‹åŒ–日志表
bool SystemLogManager::initializeLogTable() {
    if (!m_pDB || !(*m_pDB)) {
        std::cerr << "Database connection is not set." << std::endl;
        return false;
    }
    const std::string createTableQuery = R"(
        CREATE TABLE IF NOT EXISTS system_logs (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            log_type TEXT NOT NULL,
            event TEXT NOT NULL,
            username TEXT NOT NULL,
            timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
        )
    )";
    return (*m_pDB)->executeQuery(createTableQuery);
}
// æ·»åŠ æ—¥å¿—
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::ostringstream query;
    query << "INSERT INTO system_logs (log_type, event, username) VALUES ("
        << "'" << logTypeToString(logType) << "', "
        << "'" << event << "', "
        << "'" << username << "')";
    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;
    }
    std::ostringstream query;
    // å¦‚æžœ startPosition å’Œ count éƒ½æ˜¯ -1,获取全部数据
    if (startPosition == -1 && count == -1) {
        query << "SELECT id, log_type, event, username, timestamp FROM system_logs";
    }
    else {
        query << "SELECT id, log_type, event, username, timestamp 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;
}
// è½¬æ¢æ—¥å¿—类型为字符串
std::string SystemLogManager::logTypeToString(LogType logType) const {
    switch (logType) {
    case LogType::Info:
        return _T("信息");
    case LogType::Error:
        return _T("错误");
    case LogType::Operation:
        return _T("操作");
    default:
        return _T("δ֪");
    }
}
SourceCode/Bond/BondEq/DBManager/SystemLogManager.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
#ifndef SYSTEM_LOG_MANAGER_H
#define SYSTEM_LOG_MANAGER_H
#include <string>
#include <memory>
#include <mutex>
#include <chrono>
#include "Database.h"
class SystemLogManager {
public:
    enum class LogType {
        Info,     // ä¿¡æ¯æ—¥å¿—
        Error,    // é”™è¯¯æ—¥å¿—
        Operation // æ“ä½œæ—¥å¿—
    };
    // èŽ·å–å•ä¾‹å®žä¾‹
    static SystemLogManager& getInstance();
    // è®¾ç½®æ•°æ®åº“连接
    void setDatabase(std::unique_ptr<BL::Database>& db);
    // æ·»åŠ æ—¥å¿—
    bool log(LogType logType, const std::string& event, const std::string& username = "SYSTEM");
    // èŽ·å–æ—¥å¿—
    std::vector<std::vector<std::string>> SystemLogManager::getLogs(int startPosition = -1, int count = -1);
    // åˆå§‹åŒ–日志表
    bool initializeLogTable();
private:
    // æž„造函数(私有化)
    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;
    // çº¿ç¨‹å®‰å…¨é”
    static std::mutex m_mutex;
};
#endif // SYSTEM_LOG_MANAGER_H
SourceCode/Bond/BondEq/DBManager/UserManager.cpp
@@ -29,6 +29,11 @@
    terminateIdleDetection();
}
// æä¾›æ•°æ®åº“连接
std::unique_ptr<BL::Database>& UserManager::getDatabaseInstance() {
    return m_pDB;
}
// åˆå§‹åŒ–数据库,创建用户表并插入初始管理员用户
bool UserManager::initializeDatabase() {
    std::string dbFilePath = getDatabaseFilePath();
@@ -450,16 +455,31 @@
    return m_strCurrentUser;
}
// ä¿®æ”¹å½“前登录用户名
void UserManager::setCurrentUser(const std::string& strName) {
    m_strCurrentUser = strName;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å¯†ç 
std::string UserManager::getCurrentPass() const {
    return m_strCurrentPass;
}
// ä¿®æ”¹å½“前登录用户密码
void UserManager::setCurrentPass(const std::string& strPass) {
    m_strCurrentPass = strPass;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·è§’è‰²
UserRole UserManager::getCurrentUserRole() const {
    return m_enCurrentUserRole;
}
// ä¿®æ”¹å½“前登录用户角色
void UserManager::setCurrentUserRole(UserRole emRole) {
    m_enCurrentUserRole = emRole;
}
// èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·çš„æ— æ“ä½œè¶…æ—¶æ—¶é—´
std::chrono::minutes UserManager::getSessionTimeout() const {
    return m_tmSessionTimeout;
SourceCode/Bond/BondEq/DBManager/UserManager.h
@@ -22,6 +22,9 @@
    UserManager(const UserManager&) = delete;
    UserManager& operator=(const UserManager&) = delete;
    // æä¾›æ•°æ®åº“连接
    std::unique_ptr<BL::Database>& getDatabaseInstance();
    // ç”¨æˆ·æ“ä½œ
    bool login(const std::string& username, const std::string& password, bool rememberMe = false);
    void logout();
@@ -67,12 +70,21 @@
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å
    std::string getCurrentUser() const;
    // ä¿®æ”¹å½“前登录用户名
    void setCurrentUser(const std::string& strName);
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·å¯†ç 
    std::string getCurrentPass() const;
    // ä¿®æ”¹å½“前登录用户密码
    void setCurrentPass(const std::string& strPass);
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·è§’è‰²
    UserRole getCurrentUserRole() const;
    // ä¿®æ”¹å½“前登录用户角色
    void setCurrentUserRole(UserRole emRole);
    // èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·çš„æ— æ“ä½œè¶…æ—¶æ—¶é—´
    std::chrono::minutes getSessionTimeout() const;
SourceCode/Bond/BondEq/InputDialog.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
// InputDialog.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BondEq.h"
#include "afxdialogex.h"
#include "InputDialog.h"
// CInputDialog å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CInputDialog, CDialogEx)
CInputDialog::CInputDialog(const CString& strTitle, const CString& strPrompt, CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_INPUT, pParent), m_strTitle(strTitle), m_strPrompt(strPrompt), m_strInput(_T(""))
{
}
CInputDialog::~CInputDialog()
{
}
CString CInputDialog::GetInputText() const
{
    return m_strInput;
}
void CInputDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT_INPUT, m_editInput);
    DDX_Control(pDX, IDC_STATIC_PROMPT, m_staticPrompt);
}
BEGIN_MESSAGE_MAP(CInputDialog, CDialogEx)
    ON_BN_CLICKED(IDOK, &CInputDialog::OnBnClickedOk)
END_MESSAGE_MAP()
// CInputDialog æ¶ˆæ¯å¤„理程序
BOOL CInputDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    SetWindowText(m_strTitle);
    m_staticPrompt.SetWindowText(m_strPrompt);
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CInputDialog::OnBnClickedOk()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    m_editInput.GetWindowText(m_strInput);
    if (m_strInput.IsEmpty()) {
        AfxMessageBox(_T("输入不能为空!"));
        return;
    }
    CDialogEx::OnOK();
}
SourceCode/Bond/BondEq/InputDialog.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
#pragma once
#include "afxdialogex.h"
// CInputDialog å¯¹è¯æ¡†
class CInputDialog : public CDialogEx
{
    DECLARE_DYNAMIC(CInputDialog)
public:
    CInputDialog(const CString& strTitle, const CString& strPrompt, CWnd* pParent = nullptr);
    virtual ~CInputDialog();
    CString GetInputText() const; // èŽ·å–è¾“å…¥å†…å®¹
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_INPUT };
#endif
private:
    CEdit m_editInput;
    CStatic m_staticPrompt;
    CString m_strTitle;   // å¯¹è¯æ¡†æ ‡é¢˜
    CString m_strPrompt;  // æç¤ºæ–‡æœ¬
    CString m_strInput;   // è¾“入的文本
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnBnClickedOk();
};
SourceCode/Bond/BondEq/UserManagerDlg.cpp
@@ -12,6 +12,7 @@
#include <set>
const COLORREF CURR_USER_BK_COLOR = RGB(0, 255, 0);
// CUserManagerDlg å¯¹è¯æ¡†
@@ -113,12 +114,12 @@
    if (!usersData.empty()) {
        m_gridUserManager.SetRowCount(usersData.size() + 1);
        for (size_t i = 0; i < usersData.size(); i++) {
        for (int i = 0; i < usersData.size(); i++) {
            int nRowIdx = i + 1;
            int nColIdx = 0;
            m_gridUserManager.SetItemText(nRowIdx, nColIdx++, std::to_string(i + 1).c_str());
            for (size_t j = 0; j < usersData[i].size(); j++) {
            for (int j = 0; j < usersData[i].size(); j++) {
                if (usersData[i][1].empty()) {
                    continue;
                }
@@ -177,8 +178,9 @@
    }
    for (int i = 0; i < nCols; i++) {
        bool ret = m_gridUserManager.SetItemBkColour(nCurrNameRow, i, RGB(0, 255, 0));
        m_gridUserManager.SetItemBkColour(nCurrNameRow, i, CURR_USER_BK_COLOR);
    }
    m_gridUserManager.SetItemState(nCurrNameRow, 3, GVIS_READONLY);
    m_gridUserManager.Invalidate();
    m_gridUserManager.UpdateWindow();
@@ -463,8 +465,11 @@
    // ç¬¬4列为权限列, ç¬¬8列为角色描述列, ä»Žæ˜ å°„中查找对应描述
    if (nCol == 3) {
        if (m_gridUserManager.GetItemBkColour(nRow, nCol) == CURR_USER_BK_COLOR) {
            AfxMessageBox(_T("当前登录用户权限不能修改!"));
        }
        else {
        CString selectedRole = m_gridUserManager.GetItemText(nRow, nCol);
        auto it = m_mapRoleDescriptions.find(selectedRole);
        if (it != m_mapRoleDescriptions.end()) {
            m_gridUserManager.SetItemText(nRow, 7, it->second);
@@ -473,6 +478,7 @@
        else {
            m_gridUserManager.SetItemText(nRow, 7, _T(""));
            m_gridUserManager.RedrawCell(nRow, 7);
            }
        }
    }
@@ -560,10 +566,20 @@
    std::vector<std::vector<std::string>> vecData;
    std::set<std::string> usernameSet; // ç”¨äºŽå­˜å‚¨ç”¨æˆ·åï¼Œæ£€æŸ¥æ˜¯å¦é‡å¤
    int nCurrUserRow = -1;
    UserManager& userManager = UserManager::getInstance();
    for (int i = 1; i < m_gridUserManager.GetRowCount(); ++i) {
        std::vector<std::string> rowData;
        CString cellText = m_gridUserManager.GetItemText(i, 1);
        std::string username = CT2A(cellText.GetString());
        cellText = m_gridUserManager.GetItemText(i, 2);
        std::string userpass = CT2A(cellText.GetString());
        if (username.empty() || userpass.empty()) {
            AfxMessageBox(_T("用户名和密码不能为空!"));
            return;
        }
        if (usernameSet.find(username) != usernameSet.end()) {
            CString message;
@@ -571,8 +587,21 @@
            AfxMessageBox(message, MB_ICONEXCLAMATION);
            return;
        }
        usernameSet.insert(username);
        if (nCurrUserRow == -1 && m_gridUserManager.GetItemBkColour(i, 0) == CURR_USER_BK_COLOR){
            nCurrUserRow = i;
            if (username.compare(userManager.getCurrentUser()) != 0) {
                userManager.setCurrentUser(username);
            }
            if (userpass.compare(userManager.getCurrentPass()) != 0) {
                userManager.setCurrentPass(userpass);
            }
            userManager.clearSession();
            userManager.saveSession();
        }
        for (int j = 1; j < m_gridUserManager.GetColumnCount() - 1; ++j) {
            CString cellText = m_gridUserManager.GetItemText(i, j);
@@ -596,6 +625,6 @@
        vecData.push_back(rowData);
    }
    UserManager::getInstance().setUsers(vecData);
    userManager.setUsers(vecData);
    CDialogEx::OnOK();
}
SourceCode/Bond/x64/Debug/Config/BondEq.db
Binary files differ