| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CBaseDlg.h" |
| | | #include "GridCtrl.h" |
| | | |
| | | // å
¨å±ä¸»é¢å¯¹è±¡ |
| | | Theme g_lightTheme = { RGB(255, 255, 255), RGB(0, 0, 0), RGB(240, 240, 240), RGB(200, 200, 200) }; |
| | | Theme g_darkTheme = { RGB(40, 40, 40), RGB(255, 255, 255), RGB(60, 60, 60), RGB(80, 80, 80) }; |
| | | |
| | | CFont g_defaultFont; |
| | | Theme* g_currentTheme = &g_lightTheme; |
| | | |
| | | // å
¨å±èµæºå¥æ |
| | | HINSTANCE g_hCurrentResource = NULL; |
| | | |
| | | IMPLEMENT_DYNAMIC(CBaseDlg, CDialogEx) |
| | | |
| | | CBaseDlg::CBaseDlg(UINT nID, CWnd* pPage) : CDialogEx(nID, pPage), m_bResizing(false) |
| | | { |
| | | m_nID = nID; |
| | | m_pParent = pPage; |
| | | m_nInitialWidth = 0; |
| | | m_nInitialHeight = 0; |
| | | } |
| | | |
| | | CBaseDlg::~CBaseDlg() |
| | | { |
| | | // shared_pträ¼èªå¨æ¸
çå
åï¼ä¸éè¦æå¨å é¤ |
| | | m_mapFonts.clear(); |
| | | m_mapCtrlLayouts.clear(); |
| | | m_mapControls.clear(); |
| | | } |
| | | |
| | | void CBaseDlg::SwitchTheme(ThemeType enThemeType) |
| | | { |
| | | // ä½¿ç¨ map æ¥æ ¹æ® themeType æ¥æ¾ä¸»é¢ |
| | | static const std::unordered_map<ThemeType, Theme*> themeMap = { |
| | | { ThemeType::Light, &g_lightTheme }, |
| | | { ThemeType::Dark, &g_darkTheme } |
| | | }; |
| | | |
| | | // 设置å½åä¸»é¢ |
| | | auto it = themeMap.find(enThemeType); |
| | | if (it != themeMap.end()) { |
| | | g_currentTheme = it->second; |
| | | } |
| | | else { |
| | | g_currentTheme = &g_lightTheme; |
| | | } |
| | | |
| | | // æ´æ°æ§ä»¶çå¤è§ |
| | | CWnd* pWnd = GetWindow(GW_CHILD); |
| | | while (pWnd) { |
| | | pWnd->Invalidate(); |
| | | pWnd = pWnd->GetNextWindow(); |
| | | } |
| | | |
| | | // æ´æ°å¯¹è¯æ¡èæ¯é¢è² |
| | | SetBackgroundColor(g_currentTheme->backgroundColor); |
| | | } |
| | | |
| | | void CBaseDlg::LoadResourceLibrary(const CString& strLanguage) |
| | | { |
| | | // å¸è½½ä¹åå è½½çèµæºåº |
| | | UnloadResourceLibrary(); |
| | | |
| | | // å è½½æ°çèµæºåº |
| | | g_hCurrentResource = AfxLoadLibrary(strLanguage); |
| | | |
| | | // 设置æ°çèµæºå¥æ |
| | | if (g_hCurrentResource != NULL) { |
| | | AfxSetResourceHandle(g_hCurrentResource); |
| | | } |
| | | } |
| | | |
| | | void CBaseDlg::UnloadResourceLibrary() |
| | | { |
| | | // å¸è½½ä¹åå è½½çèµæºåº |
| | | if (g_hCurrentResource != NULL) { |
| | | FreeLibrary(g_hCurrentResource); // éæ¾å½åèµæºåº |
| | | g_hCurrentResource = NULL; // æ¸
ç©ºèµæºå¥æ |
| | | } |
| | | } |
| | | |
| | | CFont* CBaseDlg::GetOrCreateFont(int nFontSize) |
| | | { |
| | | auto it = m_mapFonts.find(nFontSize); |
| | | if (it != m_mapFonts.end()) { |
| | | return it->second.get(); |
| | | } |
| | | |
| | | // ä½¿ç¨ shared_ptr æ¥ç®¡çåä½å¯¹è±¡ |
| | | auto font = std::make_shared<CFont>(); |
| | | LOGFONT logFont = { 0 }; |
| | | _tcscpy_s(logFont.lfFaceName, _T("Segoe UI")); |
| | | logFont.lfHeight = -nFontSize; |
| | | logFont.lfQuality = CLEARTYPE_QUALITY; |
| | | font->CreateFontIndirect(&logFont); |
| | | m_mapFonts[nFontSize] = font; |
| | | |
| | | return font.get(); |
| | | } |
| | | |
| | | void CBaseDlg::SetDefaultFont() |
| | | { |
| | | CFont* defaultFont = GetOrCreateFont(12); |
| | | |
| | | CWnd* pWnd = GetWindow(GW_CHILD); |
| | | while (pWnd) { |
| | | TCHAR szClassName[256]; |
| | | GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); |
| | | if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { |
| | | pWnd = pWnd->GetNextWindow(); |
| | | continue; |
| | | } |
| | | |
| | | pWnd->SetFont(defaultFont, TRUE); |
| | | pWnd = pWnd->GetNextWindow(); |
| | | } |
| | | } |
| | | |
| | | BOOL CBaseDlg::AddControl(UINT nCtrlID, CWnd* pControl) |
| | | { |
| | | // ç¡®ä¿æ§ä»¶ä¸é夿·»å |
| | | if (m_mapControls.find(nCtrlID) != m_mapControls.end()) { |
| | | return FALSE; // æ§ä»¶å·²ç»åå¨ |
| | | } |
| | | |
| | | m_mapControls[nCtrlID] = std::unique_ptr<CWnd>(pControl); |
| | | return TRUE; |
| | | } |
| | | |
| | | BOOL CBaseDlg::RemoveControl(UINT nCtrlID) |
| | | { |
| | | auto it = m_mapControls.find(nCtrlID); |
| | | if (it != m_mapControls.end()) { |
| | | m_mapControls.erase(it); |
| | | return TRUE; |
| | | } |
| | | return FALSE; |
| | | } |
| | | |
| | | BOOL CBaseDlg::UpdateControlText(UINT nCtrlID, const CString& strText) |
| | | { |
| | | auto it = m_mapControls.find(nCtrlID); |
| | | if (it != m_mapControls.end()) { |
| | | CWnd* pWnd = it->second.get(); |
| | | if (pWnd->GetSafeHwnd() != nullptr) |
| | | { |
| | | pWnd->SetWindowText(strText); |
| | | return TRUE; |
| | | } |
| | | } |
| | | return FALSE; |
| | | } |
| | | |
| | | CWnd* CBaseDlg::GetControl(UINT nCtrlID) |
| | | { |
| | | auto it = m_mapControls.find(nCtrlID); |
| | | if (it != m_mapControls.end()) { |
| | | return it->second.get(); |
| | | } |
| | | return nullptr; |
| | | } |
| | | |
| | | void CBaseDlg::AdjustControls(float dScaleX, float dScaleY) |
| | | { |
| | | if (m_bResizing) return; // 鲿¢å¨è°æ´è¿ç¨ä¸éå¤è°æ´ |
| | | |
| | | m_bResizing = true; |
| | | CWnd* pWnd = GetWindow(GW_CHILD); |
| | | while (pWnd) { |
| | | int nCtrlID = pWnd->GetDlgCtrlID(); |
| | | if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end()) { |
| | | CRect originalRect = m_mapCtrlLayouts[nCtrlID]; |
| | | CRect newRect( |
| | | static_cast<int>(originalRect.left * dScaleX), |
| | | static_cast<int>(originalRect.top * dScaleY), |
| | | static_cast<int>(originalRect.right * dScaleX), |
| | | static_cast<int>(originalRect.bottom * dScaleY)); |
| | | |
| | | TCHAR szClassName[256]; |
| | | GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); |
| | | |
| | | if (_tcsicmp(szClassName, _T("ComboBox")) == 0) { |
| | | CComboBox* pComboBox = (CComboBox*)pWnd; |
| | | pComboBox->SetItemHeight(-1, newRect.Height()); // -1 表示ææé¡¹çé«åº¦ |
| | | } |
| | | |
| | | if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { |
| | | CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd; |
| | | pGridCtrl->SetDefCellHeight(newRect.Height() / 21); |
| | | pGridCtrl->ExpandColumnsToFit(TRUE); |
| | | pGridCtrl->ExpandLastColumn(); |
| | | pGridCtrl->Invalidate(); |
| | | pGridCtrl->UpdateWindow(); |
| | | } |
| | | |
| | | pWnd->MoveWindow(&newRect); |
| | | AdjustControlFont(pWnd, newRect.Width(), newRect.Height()); |
| | | } |
| | | pWnd = pWnd->GetNextWindow(); |
| | | } |
| | | m_bResizing = false; |
| | | } |
| | | |
| | | void CBaseDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight) |
| | | { |
| | | TCHAR szClassName[256]; |
| | | GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); |
| | | |
| | | if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { |
| | | return; |
| | | } |
| | | |
| | | int fontSize = nHeight / 2; |
| | | if (fontSize < 8) fontSize = 8; |
| | | if (fontSize > 32) fontSize = 32; |
| | | |
| | | CFont* pFont = GetOrCreateFont(fontSize); |
| | | |
| | | pWnd->SetFont(pFont); |
| | | pWnd->Invalidate(); // å·æ°æ§ä»¶æ¾ç¤º |
| | | } |
| | | |
| | | BEGIN_MESSAGE_MAP(CBaseDlg, CDialogEx) |
| | | ON_WM_SIZE() |
| | | ON_WM_GETMINMAXINFO() |
| | | ON_WM_CTLCOLOR() |
| | | END_MESSAGE_MAP() |
| | | |
| | | BOOL CBaseDlg::OnInitDialog() |
| | | { |
| | | CDialogEx::OnInitDialog(); |
| | | |
| | | // è·åå½åè¯è¨ |
| | | LANGID langId = GetUserDefaultLangID(); |
| | | if (langId == LANG_CHINESE) { |
| | | // å è½½ä¸æèµæº |
| | | } |
| | | else { |
| | | // å è½½è±æèµæº |
| | | } |
| | | |
| | | // è·åå¯¹è¯æ¡çå·¥ä½åºï¼å±å¹å¯ç¨åºåï¼ |
| | | CRect screenRect, dlgRect, clientRect; |
| | | SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0); |
| | | GetClientRect(&clientRect); |
| | | m_nInitialWidth = clientRect.Width(); |
| | | m_nInitialHeight = clientRect.Height(); |
| | | |
| | | // 设置é»è®¤åä½ |
| | | CFont* pDefaultFont = GetOrCreateFont(12); |
| | | |
| | | // éååçªå£ï¼æ§ä»¶ï¼ |
| | | CWnd* pWnd = GetWindow(GW_CHILD); |
| | | while (pWnd) { |
| | | int nCtrlID = pWnd->GetDlgCtrlID(); |
| | | if (nCtrlID != -1) { |
| | | // ä¿åæ§ä»¶çåå§å¸å± |
| | | CRect ctrlRect; |
| | | pWnd->GetWindowRect(&ctrlRect); |
| | | ScreenToClient(&ctrlRect); |
| | | m_mapCtrlLayouts[nCtrlID] = ctrlRect; |
| | | |
| | | // æé¤ä¸éè¦æä½çæ§ä»¶ï¼å¦èªå®ä¹æ§ä»¶ GridCtrlï¼ |
| | | TCHAR szClassName[256]; |
| | | GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName)); |
| | | if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) { |
| | | pWnd = pWnd->GetNextWindow(); |
| | | continue; |
| | | } |
| | | |
| | | // 设置æ§ä»¶çé»è®¤åä½ |
| | | pWnd->SetFont(pDefaultFont); |
| | | } |
| | | pWnd = pWnd->GetNextWindow(); |
| | | } |
| | | |
| | | // å°å¯¹è¯æ¡å±
ä¸ |
| | | GetWindowRect(&dlgRect); |
| | | int dlgWidth = dlgRect.Width() * 2; |
| | | int dlgHeight = dlgRect.Height() * 2; |
| | | |
| | | 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); |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | void CBaseDlg::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | | |
| | | if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) { |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥å°ºå¯¸å忝å¦è¶³å¤å¤§ï¼é¿å
é¢ç¹è°æ´ |
| | | //static int lastWidth = 0, lastHeight = 0; |
| | | //if (abs(cx - lastWidth) < 10 && abs(cy - lastHeight) < 10) { |
| | | // return; |
| | | //} |
| | | |
| | | //lastWidth = cx; |
| | | //lastHeight = cy; |
| | | |
| | | // è®¡ç®æ¯ä¾å¹¶è°æ´å¸å± |
| | | float dScaleX = static_cast<float>(cx) / m_nInitialWidth; |
| | | float dScaleY = static_cast<float>(cy) / m_nInitialHeight; |
| | | |
| | | AdjustControls(dScaleX, dScaleY); |
| | | } |
| | | |
| | | void CBaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) |
| | | { |
| | | lpMMI->ptMinTrackSize.x = 400; |
| | | lpMMI->ptMinTrackSize.y = 300; |
| | | |
| | | CDialogEx::OnGetMinMaxInfo(lpMMI); |
| | | } |
| | | |
| | | HBRUSH CBaseDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) |
| | | { |
| | | if (g_currentTheme) { |
| | | pDC->SetBkColor(g_currentTheme->backgroundColor); |
| | | pDC->SetTextColor(g_currentTheme->textColor); |
| | | |
| | | // è¿åèæ¯ç»å· |
| | | return CreateSolidBrush(g_currentTheme->backgroundColor); |
| | | } |
| | | |
| | | return CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <map> |
| | | #include <memory> |
| | | #include <unordered_map> |
| | | |
| | | enum class ThemeType { |
| | | Light, // æµ
è²ä¸»é¢ |
| | | Dark // æ·±è²ä¸»é¢ |
| | | }; |
| | | |
| | | struct Theme { |
| | | COLORREF backgroundColor; |
| | | COLORREF textColor; |
| | | COLORREF buttonColor; |
| | | COLORREF borderColor; |
| | | }; |
| | | |
| | | class CBaseDlg : public CDialogEx |
| | | { |
| | | DECLARE_DYNAMIC(CBaseDlg) |
| | | |
| | | public: |
| | | CBaseDlg(UINT nID, CWnd* pPage); // æ åæé 彿° |
| | | virtual ~CBaseDlg(); // ææå½æ° |
| | | |
| | | // 主é¢ç®¡ç |
| | | void SwitchTheme(ThemeType enThemeType); // åæ¢ä¸»é¢ |
| | | |
| | | // èµæºç®¡ç |
| | | void LoadResourceLibrary(const CString& strLanguage); // å è½½èµæºåº |
| | | void UnloadResourceLibrary(); // å¸è½½èµæºåº |
| | | |
| | | // åä½ç®¡ç |
| | | CFont* GetOrCreateFont(int nFontSize); // è·åæå建åä½ |
| | | void SetDefaultFont(); // 设置é»è®¤åä½ |
| | | |
| | | // 卿æ§ä»¶ç®¡ç |
| | | BOOL AddControl(UINT nCtrlID, CWnd* pControl); // æ·»å æ§ä»¶ |
| | | BOOL RemoveControl(UINT nCtrlID); // ç§»é¤æ§ä»¶ |
| | | BOOL UpdateControlText(UINT nCtrlID, const CString& strText); // æ´æ°æ§ä»¶ææ¬ |
| | | CWnd* GetControl(UINT nCtrlID); // è·åæ§ä»¶ |
| | | |
| | | private: |
| | | void AdjustControls(float dScaleX, float dScaleY); // è°æ´æ§ä»¶å¤§å° |
| | | void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight); // è°æ´æ§ä»¶åä½ |
| | | |
| | | private: |
| | | UINT m_nID; // å¯¹è¯æ¡ID |
| | | CWnd* m_pParent; // ç¶çªå£ |
| | | bool m_bResizing; // æ§ä»¶æ¯å¦æ£å¨è°æ´å¤§å° |
| | | int m_nInitialWidth; // å¯¹è¯æ¡åå§å®½åº¦ |
| | | int m_nInitialHeight; // å¯¹è¯æ¡åå§é«åº¦ |
| | | std::unordered_map<int, CRect> m_mapCtrlLayouts; // æ§ä»¶å¸å± |
| | | std::map<UINT, std::unique_ptr<CWnd>> m_mapControls; // æ§ä»¶éå |
| | | std::unordered_map<int, std::shared_ptr<CFont>> m_mapFonts; // æ§ä»¶åä½ |
| | | |
| | | DECLARE_MESSAGE_MAP() |
| | | public: |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnSize(UINT nType, int cx, int cy); |
| | | afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); |
| | | afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // CChangePasswordDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "Servo.h" |
| | | #include "afxdialogex.h" |
| | | #include "ChangePasswordDlg.h" |
| | | #include "UserManager.h" |
| | | #include "SystemLogManager.h" |
| | | |
| | | |
| | | // CChangePasswordDlg å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CChangePasswordDlg, CDialogEx) |
| | | |
| | | CChangePasswordDlg::CChangePasswordDlg(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_DIALOG_CHANGE_PASSWORD, pParent) |
| | | { |
| | | } |
| | | |
| | | CChangePasswordDlg::~CChangePasswordDlg() |
| | | { |
| | | } |
| | | |
| | | bool CChangePasswordDlg::changeUserPassword(UserManager& userManager, const std::string& username, const std::string& newPassword) |
| | | { |
| | | if (!userManager.changePassword(username, newPassword)) { |
| | | AfxMessageBox(_T("ä¿®æ¹ç¨æ·å¯ç 失败ã")); |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | void CChangePasswordDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_EDIT_CHANGE_USERNAME, m_editUsername); |
| | | DDX_Control(pDX, IDC_EDIT_CHANGE_CURRENT_PASSWORD, m_editCurrentPassword); |
| | | DDX_Control(pDX, IDC_EDIT_CHANGE_NEW_PASSWORD, m_editNewPassword); |
| | | DDX_Control(pDX, IDC_EDIT_CHANGE_CONFIRM_PASSWORD, m_editConfirmPassword); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CChangePasswordDlg, CDialogEx) |
| | | ON_BN_CLICKED(IDOK, &CChangePasswordDlg::OnBnClickedOk) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | // CChangePasswordDlg æ¶æ¯å¤çç¨åº |
| | | |
| | | |
| | | BOOL CChangePasswordDlg::OnInitDialog() |
| | | { |
| | | CDialogEx::OnInitDialog(); |
| | | |
| | | // 设置çªå£æ é¢ååå§å¼ |
| | | SetWindowText(_T("ä¿®æ¹å¯ç ")); |
| | | |
| | | UserManager& userManager = UserManager::getInstance(); |
| | | if (userManager.isLoggedIn()) { |
| | | m_editUsername.SetWindowText(userManager.getCurrentUser().c_str()); |
| | | } |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | void CChangePasswordDlg::OnBnClickedOk() |
| | | { |
| | | CString username, currentPassword, newPassword, confirmPassword; |
| | | m_editUsername.GetWindowText(username); |
| | | m_editCurrentPassword.GetWindowText(currentPassword); |
| | | m_editNewPassword.GetWindowText(newPassword); |
| | | m_editConfirmPassword.GetWindowText(confirmPassword); |
| | | |
| | | if (username.IsEmpty() || currentPassword.IsEmpty() || newPassword.IsEmpty() || confirmPassword.IsEmpty()) { |
| | | AfxMessageBox(_T("ææå段å为å¿
填项ã")); |
| | | return; |
| | | } |
| | | |
| | | if (newPassword.Compare(confirmPassword) != 0) { |
| | | AfxMessageBox(_T("æ°å¯ç ä¸ç¡®è®¤å¯ç ä¸å¹é
ã")); |
| | | return; |
| | | } |
| | | |
| | | SystemLogManager& logManager = SystemLogManager::getInstance(); |
| | | if (newPassword.Compare(currentPassword) == 0) { |
| | | EndDialog(IDCANCEL); |
| | | return; |
| | | } |
| | | |
| | | #ifdef UNICODE |
| | | std::string strUsername = CStringA(username); |
| | | std::string strCurrentPassword = CStringA(currentPassword); |
| | | std::string strNewPassword = CStringA(newPassword); |
| | | #else |
| | | std::string strUsername = username; |
| | | std::string strCurrentPassword = currentPassword; |
| | | std::string strNewPassword = newPassword; |
| | | #endif |
| | | |
| | | UserManager& userManager = UserManager::getInstance(); |
| | | 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(); |
| | | } |
| | | } |
| | | else { |
| | | AfxMessageBox(_T("å½åç¨æ·åæå¯ç è¾å
¥é误ã")); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "afxdialogex.h" |
| | | #include <string> |
| | | |
| | | class UserManager; |
| | | |
| | | // CChangePasswordDlg å¯¹è¯æ¡ |
| | | |
| | | class CChangePasswordDlg : public CDialogEx |
| | | { |
| | | DECLARE_DYNAMIC(CChangePasswordDlg) |
| | | |
| | | public: |
| | | CChangePasswordDlg(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CChangePasswordDlg(); |
| | | |
| | | private: |
| | | bool changeUserPassword(UserManager& userManager, const std::string& username, const std::string& newPassword); |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_CHANGE_PASSWORD }; |
| | | #endif |
| | | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnBnClickedOk(); |
| | | afx_msg void OnBnClickedCancel(); |
| | | DECLARE_MESSAGE_MAP() |
| | | |
| | | private: |
| | | CEdit m_editUsername; // ç¨æ·åè¾å
¥æ¡ |
| | | CEdit m_editCurrentPassword; // å½åå¯ç è¾å
¥æ¡ |
| | | CEdit m_editNewPassword; // æ°å¯ç è¾å
¥æ¡ |
| | | CEdit m_editConfirmPassword; // 确认æ°å¯ç è¾å
¥æ¡ |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // InputDialog.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "Servo.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); |
| | | m_editInput.SetFocus(); |
| | | m_editInput.SetWindowText("1"); |
| | | |
| | | 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(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #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(); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // LoginDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "Servo.h" |
| | | #include "afxdialogex.h" |
| | | #include "LoginDlg.h" |
| | | #include "ChangePasswordDlg.h" |
| | | #include "UserManager.h" |
| | | #include "SystemLogManager.h" |
| | | |
| | | |
| | | // CLoginDlg å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CLoginDlg, CDialogEx) |
| | | |
| | | CLoginDlg::CLoginDlg(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_DIALOG_LOGIN, pParent) |
| | | { |
| | | } |
| | | |
| | | CLoginDlg::~CLoginDlg() |
| | | { |
| | | } |
| | | |
| | | void CLoginDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_STATIC_IMAGE, m_staticImage); |
| | | DDX_Control(pDX, IDC_EDIT_USERNAME, m_editUsername); |
| | | DDX_Control(pDX, IDC_EDIT_PASSWORD, m_editPassword); |
| | | DDX_Control(pDX, IDC_CHECK_REMEMBER_PASSWORD, m_checkRememberPassword); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CLoginDlg, CDialogEx) |
| | | ON_BN_CLICKED(IDC_BUTTON_LOGIN, &CLoginDlg::OnBnClickedLogin) |
| | | ON_STN_CLICKED(IDC_STATIC_CHANGE_PASSWORD, &CLoginDlg::OnBnClickedChangePassword) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | // CLoginDlg æ¶æ¯å¤çç¨åº |
| | | |
| | | |
| | | BOOL CLoginDlg::OnInitDialog() |
| | | { |
| | | CDialog::OnInitDialog(); |
| | | |
| | | // 设置çªå£æ é¢ååå§å¼ |
| | | SetWindowText(_T("ç»å½")); |
| | | |
| | | CString strIconPath; |
| | | strIconPath.Format(_T("%s\\Res\\Operator_High_32.ico"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | |
| | | // å è½½å¾æ |
| | | HICON hIcon = (HICON)::LoadImage( |
| | | nullptr, |
| | | strIconPath, |
| | | IMAGE_ICON, |
| | | 32, // 徿 宽度 |
| | | 32, // 徿 é«åº¦ |
| | | LR_LOADFROMFILE); |
| | | |
| | | if (hIcon) { |
| | | // 设置 CStatic æ§ä»¶ä¸ºå¾æ æ ·å¼ |
| | | m_staticImage.ModifyStyle(0xF, SS_ICON); |
| | | m_staticImage.SetIcon(hIcon); |
| | | } |
| | | |
| | | // æ·»å SS_NOTIFYæ ·å¼ |
| | | CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATIC_CHANGE_PASSWORD); |
| | | if (pStatic != nullptr) { |
| | | pStatic->ModifyStyle(0, SS_NOTIFY); |
| | | } |
| | | |
| | | UserManager& userManager = UserManager::getInstance(); |
| | | if (userManager.isLoggedIn()) { |
| | | if (userManager.isRememberMe()) { |
| | | m_checkRememberPassword.SetCheck(BST_CHECKED); |
| | | } |
| | | |
| | | userManager.getCurrentUserRole(); |
| | | m_editUsername.SetWindowText(userManager.getCurrentUser().c_str()); |
| | | m_editPassword.SetWindowText(userManager.getCurrentPass().c_str()); |
| | | } |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | void CLoginDlg::OnBnClickedLogin() |
| | | { |
| | | CString username, password, role; |
| | | m_editUsername.GetWindowText(username); |
| | | m_editPassword.GetWindowText(password); |
| | | |
| | | if (username.IsEmpty() || password.IsEmpty()) { |
| | | AfxMessageBox(_T("请è¾å
¥ç¨æ·ååå¯ç ã")); |
| | | return; |
| | | } |
| | | |
| | | #ifdef UNICODE |
| | | std::string strUsername = CStringA(username); |
| | | std::string strPassword = CStringA(password); |
| | | #else |
| | | std::string strUsername = username; |
| | | std::string strPassword = password; |
| | | #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() |
| | | { |
| | | CChangePasswordDlg changePasswordDlg; |
| | | if (changePasswordDlg.DoModal() == IDOK) { |
| | | m_editPassword.SetWindowText(""); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "afxdialogex.h" |
| | | |
| | | |
| | | // CLoginDlg å¯¹è¯æ¡ |
| | | |
| | | class CLoginDlg : public CDialogEx |
| | | { |
| | | DECLARE_DYNAMIC(CLoginDlg) |
| | | |
| | | public: |
| | | CLoginDlg(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CLoginDlg(); |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_LOGIN }; |
| | | #endif |
| | | |
| | | private: |
| | | CStatic m_staticImage; |
| | | CEdit m_editUsername; |
| | | CEdit m_editPassword; |
| | | CButton m_checkRememberPassword; |
| | | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnBnClickedLogin(); |
| | | afx_msg void OnBnClickedChangePassword(); |
| | | DECLARE_MESSAGE_MAP() |
| | | }; |
| | |
| | | <Text Include="ReadMe.txt" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="CBaseDlg.h" /> |
| | | <ClInclude Include="CEquipmentPage3.h" /> |
| | | <ClInclude Include="CGlassPool.h" /> |
| | | <ClInclude Include="ChangePasswordDlg.h" /> |
| | | <ClInclude Include="CMyStatusbar.h" /> |
| | | <ClInclude Include="CRobotCmdContainerDlg.h" /> |
| | | <ClInclude Include="CRobotCmdTestDlg.h" /> |
| | |
| | | <ClInclude Include="CRobotTask.h" /> |
| | | <ClInclude Include="CSlot.h" /> |
| | | <ClInclude Include="HorizontalLine.h" /> |
| | | <ClInclude Include="InputDialog.h" /> |
| | | <ClInclude Include="JobSlotGrid.h" /> |
| | | <ClInclude Include="LoginDlg.h" /> |
| | | <ClInclude Include="MsgDlg.h" /> |
| | | <ClInclude Include="PageRecipe.h" /> |
| | | <ClInclude Include="CDoubleGlass.h" /> |
| | |
| | | <ClInclude Include="ServoGraph.h" /> |
| | | <ClInclude Include="ServoMemDC.h" /> |
| | | <ClInclude Include="stdafx.h" /> |
| | | <ClInclude Include="SystemLogManager.h" /> |
| | | <ClInclude Include="SystemLogManagerDlg.h" /> |
| | | <ClInclude Include="targetver.h" /> |
| | | <ClInclude Include="TerminalDisplayDlg.h" /> |
| | | <ClInclude Include="ToolUnits.h" /> |
| | | <ClInclude Include="TransferManager.h" /> |
| | | <ClInclude Include="TopToolbar.h" /> |
| | | <ClInclude Include="UserManager.h" /> |
| | | <ClInclude Include="UserManagerDlg.h" /> |
| | | <ClInclude Include="VerticalLine.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="CBaseDlg.cpp" /> |
| | | <ClCompile Include="CEquipmentPage3.cpp" /> |
| | | <ClCompile Include="CGlassPool.cpp" /> |
| | | <ClCompile Include="ChangePasswordDlg.cpp" /> |
| | | <ClCompile Include="CMyStatusbar.cpp" /> |
| | | <ClCompile Include="CRobotCmdContainerDlg.cpp" /> |
| | | <ClCompile Include="CRobotCmdTestDlg.cpp" /> |
| | |
| | | <ClCompile Include="CRobotTask.cpp" /> |
| | | <ClCompile Include="CSlot.cpp" /> |
| | | <ClCompile Include="HorizontalLine.cpp" /> |
| | | <ClCompile Include="InputDialog.cpp" /> |
| | | <ClCompile Include="JobSlotGrid.cpp" /> |
| | | <ClCompile Include="LoginDlg.cpp" /> |
| | | <ClCompile Include="MsgDlg.cpp" /> |
| | | <ClCompile Include="PageRecipe.cpp" /> |
| | | <ClCompile Include="CDoubleGlass.cpp" /> |
| | |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> |
| | | </ClCompile> |
| | | <ClCompile Include="SystemLogManager.cpp" /> |
| | | <ClCompile Include="SystemLogManagerDlg.cpp" /> |
| | | <ClCompile Include="TerminalDisplayDlg.cpp" /> |
| | | <ClCompile Include="ToolUnits.cpp" /> |
| | | <ClCompile Include="TransferManager.cpp" /> |
| | | <ClCompile Include="TopToolbar.cpp" /> |
| | | <ClCompile Include="UserManager.cpp" /> |
| | | <ClCompile Include="UserManagerDlg.cpp" /> |
| | | <ClCompile Include="VerticalLine.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | |
| | | <ClCompile Include="CRobotTaskDlg.cpp" /> |
| | | <ClCompile Include="PageTransferLog.cpp" /> |
| | | <ClCompile Include="ServoMemDC.cpp" /> |
| | | <ClCompile Include="ChangePasswordDlg.cpp" /> |
| | | <ClCompile Include="LoginDlg.cpp" /> |
| | | <ClCompile Include="SystemLogManagerDlg.cpp" /> |
| | | <ClCompile Include="UserManagerDlg.cpp" /> |
| | | <ClCompile Include="CBaseDlg.cpp" /> |
| | | <ClCompile Include="SystemLogManager.cpp" /> |
| | | <ClCompile Include="UserManager.cpp" /> |
| | | <ClCompile Include="InputDialog.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | |
| | | <ClInclude Include="CRobotTaskDlg.h" /> |
| | | <ClInclude Include="PageTransferLog.h" /> |
| | | <ClInclude Include="ServoMemDC.h" /> |
| | | <ClInclude Include="ChangePasswordDlg.h" /> |
| | | <ClInclude Include="LoginDlg.h" /> |
| | | <ClInclude Include="SystemLogManagerDlg.h" /> |
| | | <ClInclude Include="UserManagerDlg.h" /> |
| | | <ClInclude Include="CBaseDlg.h" /> |
| | | <ClInclude Include="UserManager.h" /> |
| | | <ClInclude Include="SystemLogManager.h" /> |
| | | <ClInclude Include="InputDialog.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "SystemLogManager.h" |
| | | #include "UserManager.h" |
| | | #include <sstream> |
| | | #include <iostream> |
| | | #include <stdexcept> |
| | | #include <ctime> |
| | | |
| | | // éææååå§å |
| | | std::mutex SystemLogManager::m_mutex; |
| | | |
| | | // è·ååä¾å®ä¾ |
| | | SystemLogManager& SystemLogManager::getInstance() { |
| | | static SystemLogManager instance; |
| | | return instance; |
| | | } |
| | | |
| | | // æé 彿° |
| | | SystemLogManager::SystemLogManager() : m_pDB(nullptr) {} |
| | | |
| | | // ææå½æ° |
| | | SystemLogManager::~SystemLogManager() { |
| | | m_pDB = nullptr; // æ¸
餿éå¼ç¨ |
| | | } |
| | | |
| | | // è®¾ç½®æ°æ®åºè¿æ¥ |
| | | void SystemLogManager::setDatabase(BL::Database* db) { |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | m_pDB = db; |
| | | } |
| | | |
| | | // åå§åæ¥å¿è¡¨ |
| | | bool SystemLogManager::initializeLogTable() { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | 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 (datetime('now', 'localtime')) |
| | | ) |
| | | )"; |
| | | |
| | | return m_pDB->executeQuery(createTableQuery); |
| | | } |
| | | |
| | | // æ·»å æ¥å¿ï¼ä½¿ç¨å½åç¨æ·ï¼ |
| | | bool SystemLogManager::log(LogType logType, const std::string& event) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | cleanOldLogs(); |
| | | |
| | | 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 << "', " |
| | | << "'" << username << "')"; |
| | | |
| | | 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) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | if (startPosition == -1 && count == -1) { |
| | | query << "SELECT id, log_type, event, username, datetime(timestamp, 'localtime') FROM system_logs"; |
| | | } |
| | | else { |
| | | query << "SELECT id, log_type, event, username, datetime(timestamp, 'localtime') FROM system_logs " |
| | | << "LIMIT " << count << " OFFSET " << startPosition; |
| | | } |
| | | |
| | | return m_pDB->fetchResults(query.str()); |
| | | } |
| | | |
| | | // è·åçéåçæ¥å¿æ°æ® |
| | | 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) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | 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 << "'"; |
| | | } |
| | | if (!endTime.empty()) { |
| | | query << " AND timestamp <= '" << endTime << "'"; |
| | | } |
| | | |
| | | int offset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY timestamp DESC 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) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | 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()); |
| | | return (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0; |
| | | } |
| | | |
| | | // æ¸
çè¶
è¿æå®å¤©æ°çæ§æ¥å¿ |
| | | void SystemLogManager::cleanOldLogs(int daysToKeep) { |
| | | if (!m_pDB) { |
| | | throw std::runtime_error("Database connection is not set."); |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "DELETE FROM system_logs WHERE timestamp < datetime('now', '-" << daysToKeep << " days')"; |
| | | m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | // è½¬æ¢æ¥å¿ç±»å为å符串 |
| | | std::string SystemLogManager::logTypeToString(LogType logType) { |
| | | switch (logType) { |
| | | case LogType::Info: |
| | | return "ä¿¡æ¯"; |
| | | case LogType::Error: |
| | | return "é误"; |
| | | case LogType::Operation: |
| | | return "æä½"; |
| | | default: |
| | | return "δ֪"; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #ifndef SYSTEM_LOG_MANAGER_H |
| | | #define SYSTEM_LOG_MANAGER_H |
| | | |
| | | #include <string> |
| | | #include <vector> |
| | | #include <mutex> |
| | | #include "Database.h" |
| | | |
| | | // ç³»ç»æ¥å¿ç®¡çç±» |
| | | class SystemLogManager { |
| | | public: |
| | | // æ¥å¿ç±»åå®ä¹ |
| | | enum class LogType { |
| | | Info, |
| | | Error, |
| | | Operation, |
| | | Unknown |
| | | }; |
| | | |
| | | // è·ååä¾å®ä¾ |
| | | static SystemLogManager& getInstance(); |
| | | |
| | | // è®¾ç½®æ°æ®åºè¿æ¥ |
| | | void setDatabase(BL::Database* db); |
| | | |
| | | // åå§åæ¥å¿è¡¨ |
| | | bool initializeLogTable(); |
| | | |
| | | // æ·»å æ¥å¿ |
| | | 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>> getLogs(int startPosition = -1, int count = -1); |
| | | |
| | | // è·åçéåçæ¥å¿æ°æ® |
| | | 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); |
| | | |
| | | // è½¬æ¢æ¥å¿ç±»å为å符串 |
| | | static std::string logTypeToString(LogType logType); |
| | | |
| | | private: |
| | | // æé 彿°åææå½æ° |
| | | SystemLogManager(); |
| | | ~SystemLogManager(); |
| | | |
| | | // ç¦æ¢æ·è´åèµå¼ |
| | | SystemLogManager(const SystemLogManager&) = delete; |
| | | SystemLogManager& operator=(const SystemLogManager&) = delete; |
| | | |
| | | // æ°æ®åºè¿æ¥ |
| | | BL::Database* m_pDB = nullptr; |
| | | |
| | | // 线ç¨å®å
¨é |
| | | static std::mutex m_mutex; |
| | | }; |
| | | |
| | | #endif // SYSTEM_LOG_MANAGER_H |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // SystemLogManagerDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "Servo.h" |
| | | #include "afxdialogex.h" |
| | | #include "SystemLogManagerDlg.h" |
| | | #include "UserManager.h" |
| | | #include "SystemLogManager.h" |
| | | |
| | | |
| | | // CSystemLogManagerDlg å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CSystemLogManagerDlg, CBaseDlg) |
| | | |
| | | CSystemLogManagerDlg::CSystemLogManagerDlg(CWnd* pParent /*=nullptr*/) |
| | | : CBaseDlg(IDD_DIALOG_SYSTEM_LOG_MANAGER, pParent) |
| | | { |
| | | } |
| | | |
| | | CSystemLogManagerDlg::~CSystemLogManagerDlg() |
| | | { |
| | | } |
| | | |
| | | void CSystemLogManagerDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CBaseDlg::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, 10); |
| | | m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("No.")); |
| | | m_listLogs.SetColumnWidth(nColIdx, 10); |
| | | m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("ç±»å")); |
| | | m_listLogs.SetColumnWidth(nColIdx, 100); |
| | | m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("äºä»¶")); |
| | | m_listLogs.SetColumnWidth(nColIdx, 30); |
| | | m_listLogs.SetItemText(nRowIdx, nColIdx++, _T("ç¨æ·")); |
| | | m_listLogs.SetColumnWidth(nColIdx, 50); |
| | | 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.ExpandColumnsToFit(FALSE); |
| | | m_listLogs.ExpandLastColumn(); |
| | | m_listLogs.Invalidate(); |
| | | m_listLogs.UpdateWindow(); |
| | | |
| | | UpdatePageInfo(); |
| | | } |
| | | |
| | | void CSystemLogManagerDlg::UpdatePageInfo() |
| | | { |
| | | // æ ¼å¼å页ç ä¿¡æ¯ä¸º "å½å页/æ»é¡µæ°" |
| | | CString pageInfo; |
| | | pageInfo.Format(_T("%d/%d 页"), m_nCurrentPage, m_nTotalPages); |
| | | m_staticPageNum.SetWindowText(pageInfo); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CSystemLogManagerDlg, CBaseDlg) |
| | | 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) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | // CSystemLogManagerDlg æ¶æ¯å¤çç¨åº |
| | | |
| | | |
| | | BOOL CSystemLogManagerDlg::OnInitDialog() |
| | | { |
| | | CBaseDlg::OnInitDialog(); |
| | | |
| | | // TODO: 卿¤æ·»å é¢å¤çåå§å |
| | | SetWindowText(_T("ç³»ç»è¿è¡æ¥å¿")); |
| | | |
| | | 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: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | 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: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | 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: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "afxdialogex.h" |
| | | #include "GridCtrl.h" |
| | | #include "CBaseDlg.h" |
| | | |
| | | // CSystemLogManagerDlg å¯¹è¯æ¡ |
| | | |
| | | class CSystemLogManagerDlg : public CBaseDlg |
| | | { |
| | | 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 æ¯æ |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnBnClickedButtonSearch(); |
| | | afx_msg void OnBnClickedButtonPrevPage(); |
| | | afx_msg void OnBnClickedButtonNextPage(); |
| | | afx_msg void OnSelchangeComboType(); |
| | | afx_msg void OnSelchangeComboUser(); |
| | | DECLARE_MESSAGE_MAP() |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "UserManager.h" |
| | | #include <chrono> |
| | | #include <iostream> |
| | | #include <fstream> |
| | | #include <ctime> |
| | | #include <sstream> |
| | | |
| | | const std::string SESSION_FILE = R"(session.dat)"; |
| | | const std::string DATABASE_FILE = R"(BondEq.db)"; |
| | | |
| | | const std::string INITIAL_ADMIN_USERNAME = "admin"; |
| | | const std::string INITIAL_ADMIN_PASSWORD = "admin"; |
| | | |
| | | // è·ååä¾å®ä¾ |
| | | UserManager& UserManager::getInstance() { |
| | | static UserManager instance; |
| | | return instance; |
| | | } |
| | | |
| | | UserManager::UserManager() |
| | | : m_isLoggedIn(false), m_isRememberMe(false), m_tmSessionTimeout(std::chrono::minutes(30)), |
| | | m_tmSessionExpiration(std::chrono::hours(72)), m_hMouseHook(nullptr), m_hKeyboardHook(nullptr), |
| | | m_pDB(std::make_unique<BL::SQLiteDatabase>()) { |
| | | initializeDatabase(); |
| | | } |
| | | |
| | | UserManager::~UserManager() { |
| | | terminateIdleDetection(); |
| | | } |
| | | |
| | | // æä¾æ°æ®åºè¿æ¥ |
| | | std::unique_ptr<BL::Database>& UserManager::getDatabaseInstance() { |
| | | return m_pDB; |
| | | } |
| | | |
| | | // åå§åæ°æ®åºï¼åå»ºç¨æ·è¡¨å¹¶æå
¥åå§ç®¡çåç¨æ· |
| | | bool UserManager::initializeDatabase() { |
| | | std::string dbFilePath = getDatabaseFilePath(); |
| | | if (!m_pDB->connect(dbFilePath, true)) { |
| | | throw std::runtime_error("Failed to connect to database."); |
| | | } |
| | | |
| | | std::string createTableQuery = R"( |
| | | CREATE TABLE IF NOT EXISTS users ( |
| | | username VARCHAR(50) PRIMARY KEY, |
| | | password VARCHAR(255) NOT NULL, |
| | | role INT NOT NULL, |
| | | session_timeout INT DEFAULT 30, |
| | | session_expiration INT DEFAULT 72, |
| | | last_login DATETIME DEFAULT (datetime('now', 'localtime')) |
| | | ) |
| | | )"; |
| | | m_pDB->executeQuery(createTableQuery); |
| | | |
| | | std::string checkAdminQuery = "SELECT COUNT(*) FROM users WHERE role = 0"; |
| | | auto result = m_pDB->fetchResults(checkAdminQuery); |
| | | |
| | | if (result.empty() || result[0][0] == "0") { |
| | | std::string insertAdminQuery = "INSERT INTO users (username, password, role, session_timeout, session_expiration) VALUES ('" + |
| | | INITIAL_ADMIN_USERNAME + "', '" + simpleEncryptDecrypt(INITIAL_ADMIN_PASSWORD, "BandKey") + "', 0, 30, 72)"; |
| | | m_pDB->executeQuery(insertAdminQuery); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | // 对å¯ç è¿è¡åå¸å¤ç |
| | | std::string UserManager::hashPassword(const std::string& password) { |
| | | return std::to_string(std::hash<std::string>{}(password)); |
| | | } |
| | | |
| | | // ç®åçå å¯åè§£å¯å½æ° |
| | | std::string UserManager::simpleEncryptDecrypt(const std::string& data, const std::string& key) { |
| | | std::string result = data; |
| | | for (size_t i = 0; i < data.size(); ++i) { |
| | | result[i] ^= key[i % key.size()]; // ç®å弿å å¯ |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | // ä»ä¼è¯æä»¶å è½½ä¼è¯ä¿¡æ¯ |
| | | bool UserManager::loadSession() { |
| | | std::ifstream sessionFile(getSessionFilePath(), std::ios::binary); |
| | | if (!sessionFile.is_open()) { |
| | | return false; |
| | | } |
| | | |
| | | // ä»æä»¶è¯»åå 坿°æ® |
| | | std::string encryptedData((std::istreambuf_iterator<char>(sessionFile)), std::istreambuf_iterator<char>()); |
| | | sessionFile.close(); |
| | | |
| | | // è§£å¯æ°æ® |
| | | std::string decryptedData = simpleEncryptDecrypt(encryptedData, "my_secret_key"); |
| | | |
| | | // è§£æè§£å¯çæ°æ® |
| | | std::istringstream sessionData(decryptedData); |
| | | std::string username; |
| | | std::string password; |
| | | std::time_t lastLoginTime; |
| | | int timeoutMinutes; |
| | | int expirationHours; |
| | | |
| | | sessionData >> username >> password >> lastLoginTime >> timeoutMinutes >> expirationHours; |
| | | |
| | | // éªè¯æ¶é´æ³æææ§ |
| | | auto now = std::chrono::system_clock::now(); |
| | | auto lastLogin = std::chrono::system_clock::from_time_t(lastLoginTime); |
| | | auto sessionDuration = std::chrono::duration_cast<std::chrono::hours>(now - lastLogin); |
| | | |
| | | if (sessionDuration > std::chrono::hours(expirationHours)) { |
| | | clearSession(); |
| | | return false; |
| | | } |
| | | |
| | | // æ¢å¤ä¼è¯æ°æ® |
| | | m_strCurrentUser = username; |
| | | m_strCurrentPass = password; |
| | | m_tpLastLogin = lastLogin; |
| | | m_tmSessionTimeout = std::chrono::minutes(timeoutMinutes); |
| | | m_tmSessionExpiration = std::chrono::hours(expirationHours); |
| | | m_isLoggedIn = true; |
| | | m_isRememberMe = true; |
| | | updateActivityTime(); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | // ä¿åä¼è¯ä¿¡æ¯å°æä»¶ |
| | | void UserManager::saveSession() { |
| | | if (!m_isRememberMe) { |
| | | clearSession(); |
| | | return; |
| | | } |
| | | |
| | | // åå§ä¼è¯æ°æ® |
| | | std::stringstream sessionData; |
| | | std::time_t lastLoginTime = std::chrono::system_clock::to_time_t(m_tpLastLogin); |
| | | sessionData << m_strCurrentUser << " " << m_strCurrentPass << " " << lastLoginTime << " " |
| | | << m_tmSessionTimeout.count() << " " << m_tmSessionExpiration.count(); |
| | | |
| | | // å 坿°æ® |
| | | std::string encryptedData = simpleEncryptDecrypt(sessionData.str(), "my_secret_key"); |
| | | |
| | | // åå
¥å 坿°æ®å°æä»¶ |
| | | std::ofstream sessionFile(getSessionFilePath(), std::ios::binary); |
| | | if (sessionFile.is_open()) { |
| | | sessionFile << encryptedData; |
| | | sessionFile.close(); |
| | | } |
| | | } |
| | | |
| | | // æ¸
é¤ä¼è¯æä»¶ |
| | | void UserManager::clearSession() { |
| | | std::remove(getSessionFilePath().c_str()); |
| | | } |
| | | |
| | | // è·åç¨åºè·¯å¾ä¸çconfigæä»¶å¤¹è·¯å¾ |
| | | std::string UserManager::getConfigFolderPath() { |
| | | char path[MAX_PATH]; |
| | | GetModuleFileName(NULL, path, MAX_PATH); |
| | | std::string exePath = std::string(path).substr(0, std::string(path).find_last_of("\\/")); |
| | | std::string configPath = exePath + "\\Config\\"; |
| | | |
| | | // æ£æ¥å¹¶å建configæä»¶å¤¹ |
| | | DWORD fileAttr = GetFileAttributes(configPath.c_str()); |
| | | if (fileAttr == INVALID_FILE_ATTRIBUTES) { |
| | | CreateDirectory(configPath.c_str(), NULL); |
| | | } |
| | | |
| | | return configPath; |
| | | } |
| | | |
| | | // è·åsession.datæä»¶è·¯å¾ |
| | | std::string UserManager::getSessionFilePath() { |
| | | return getConfigFolderPath() + SESSION_FILE; |
| | | } |
| | | |
| | | // è·åæ°æ®åºæä»¶è·¯å¾ |
| | | std::string UserManager::getDatabaseFilePath() { |
| | | return getConfigFolderPath() + DATABASE_FILE; |
| | | } |
| | | |
| | | // ç»å½æ¹æ³ |
| | | bool UserManager::login(const std::string& username, const std::string& password, bool rememberMeFlag) { |
| | | std::string query = "SELECT username, password, role, session_timeout, session_expiration FROM users WHERE username = '" + username + "'"; |
| | | auto result = m_pDB->fetchResults(query); |
| | | |
| | | if (result.empty() || result[0][1] != simpleEncryptDecrypt(password, "BandKey")) { |
| | | std::cerr << "Login failed: Invalid username or password." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | m_strCurrentUser = username; |
| | | m_strCurrentPass = password; |
| | | m_enCurrentUserRole = static_cast<UserRole>(std::stoi(result[0][2])); |
| | | m_tmSessionTimeout = std::chrono::minutes(std::stoi(result[0][3])); |
| | | m_tmSessionExpiration = std::chrono::hours(std::stoi(result[0][4])); |
| | | m_isLoggedIn = true; |
| | | m_isRememberMe = rememberMeFlag; |
| | | updateActivityTime(); |
| | | m_tpLastLogin = std::chrono::system_clock::now(); |
| | | |
| | | std::string updateLoginTime = "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE username = '" + username + "'"; |
| | | m_pDB->executeQuery(updateLoginTime); |
| | | |
| | | saveSession(); |
| | | return true; |
| | | } |
| | | |
| | | // ç»åºæ¹æ³ |
| | | void UserManager::logout() { |
| | | if (m_isLoggedIn) { |
| | | std::cout << "User logged out: " << m_strCurrentUser << std::endl; |
| | | m_strCurrentUser.clear(); |
| | | m_strCurrentPass.clear(); |
| | | m_isLoggedIn = false; |
| | | m_isRememberMe = false; |
| | | clearSession(); |
| | | } |
| | | } |
| | | |
| | | // è¿åå½åç¨æ·çç»å½ç¶æ |
| | | bool UserManager::isLoggedIn() const { |
| | | return m_isLoggedIn; |
| | | } |
| | | |
| | | // è¿åå½åç¨æ·çè®°ä½ç»å½ç¶æ |
| | | bool UserManager::isRememberMe() const { |
| | | return m_isRememberMe; |
| | | } |
| | | |
| | | // å建æ°ç¨æ·ï¼ä»
è¶
级管çåææé |
| | | bool UserManager::createUser(const std::string& username, const std::string& password, UserRole role, |
| | | std::chrono::minutes timeout, std::chrono::hours expiration) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can create new users." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "INSERT INTO users (username, password, role, session_timeout, session_expiration) VALUES ('" + |
| | | username + "', '" + simpleEncryptDecrypt(password, "BandKey") + "', " + std::to_string(static_cast<int>(role)) + ", " + |
| | | std::to_string(timeout.count()) + ", " + std::to_string(expiration.count()) + ")"; |
| | | return m_pDB->executeQuery(query); |
| | | } |
| | | |
| | | // å é¤ç¨æ·ï¼ä»
è¶
级管çåææéï¼ä¸ä¸è½å é¤èªå·± |
| | | bool UserManager::deleteUser(const std::string& username) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can delete users." << std::endl; |
| | | return false; |
| | | } |
| | | if (username == m_strCurrentUser) { |
| | | std::cerr << "SuperAdmin cannot delete their own account." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "DELETE FROM users WHERE username = '" + username + "'"; |
| | | return m_pDB->executeQuery(query); |
| | | } |
| | | |
| | | // è·åææç¨æ·ä¿¡æ¯ï¼ä»
è¶
级管çåææé |
| | | std::vector<std::vector<std::string>> UserManager::getUsers() { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can retrieve user data." << std::endl; |
| | | return {}; |
| | | } |
| | | |
| | | // æ¥è¯¢æ´ä¸ªç¨æ·è¡¨ |
| | | std::string query = "SELECT username, password, role, session_timeout, session_expiration, last_login FROM users"; |
| | | std::vector<std::vector<std::string>> results = m_pDB->fetchResults(query); |
| | | for (auto& row : results) { |
| | | row[1] = simpleEncryptDecrypt(row[1], "BandKey"); |
| | | } |
| | | |
| | | return results; |
| | | } |
| | | |
| | | // 设置æ´ä¸ªç¨æ·è¡¨çæ°æ®ï¼ä»
è¶
级管çåææé |
| | | bool UserManager::setUsers(const std::vector<std::vector<std::string>>& usersData) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can set user data." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // æ¸
ç©ºç¨æ·è¡¨ |
| | | std::string deleteQuery = "DELETE FROM users"; |
| | | if (!m_pDB->executeQuery(deleteQuery)) { |
| | | std::cerr << "Failed to clear the users table." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // æå
¥æ°çç¨æ·æ°æ® |
| | | for (const auto& user : usersData) { |
| | | if (user.size() != 6) { |
| | | std::cerr << "Invalid data format for user. Each user must have 6 fields." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string insertQuery = "INSERT INTO users (username, password, role, session_timeout, session_expiration, last_login) VALUES ('" + |
| | | user[0] + "', '" + simpleEncryptDecrypt(user[1], "BandKey") + "', " + user[2] + ", " + user[3] + ", " + user[4] + ", '" + user[5] + "')"; |
| | | |
| | | if (!m_pDB->executeQuery(insertQuery)) { |
| | | std::cerr << "Failed to insert user: " << user[0] << std::endl; |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·åï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUsername(const std::string& username, const std::string& newUsername) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change usernames." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET username = '" + newUsername + "' WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çç¨æ·åï¼æ´æ°æååéå¹¶ä¿åä¼è¯æä»¶ |
| | | if (success && m_strCurrentUser == username) { |
| | | m_strCurrentUser = newUsername; |
| | | |
| | | // 妿âè®°ä½å¯ç âå·²å¯ç¨ï¼æ´æ°ä¼è¯æä»¶ |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·å¯ç ï¼ä»
å
许å½åç¨æ·æè¶
级管çåï¼ |
| | | bool UserManager::changePassword(const std::string& username, const std::string& newPassword) { |
| | | if (username != m_strCurrentUser && m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Permission denied: Only the user or SuperAdmin can change passwords." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET password = '" + simpleEncryptDecrypt(newPassword, "BandKey") + |
| | | "' WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | |
| | | // 妿æ¯å½åç¨æ·ä¿®æ¹èªå·±çå¯ç ï¼éåºç»å½å¹¶æ¸
é¤ä¼è¯æä»¶ |
| | | if (success && m_strCurrentUser == username) { |
| | | logout(); |
| | | std::cout << "Password changed successfully. Please log in again." << std::endl; |
| | | } |
| | | |
| | | return success; |
| | | } |
| | | |
| | | // æ´æ¹ç¨æ·è§è²ï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUserRole(const std::string& username, UserRole newRole) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change user roles." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // 鲿¢ç®¡çåæ´æ¹èªå·±çè§è² |
| | | if (m_strCurrentUser == username) { |
| | | std::cerr << "SuperAdmin cannot change their own role." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET role = " + std::to_string(static_cast<int>(newRole)) + |
| | | " WHERE username = '" + username + "'"; |
| | | return m_pDB->executeQuery(query); |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·ç session_timeoutï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change session timeout." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET session_timeout = " + std::to_string(newTimeoutMinutes) + |
| | | " WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çè¶
æ¶è®¾ç½®ï¼æ´æ°æååé |
| | | if (success && m_strCurrentUser == username) { |
| | | m_tmSessionTimeout = std::chrono::minutes(newTimeoutMinutes); |
| | | |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·ç session_expirationï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUserSessionExpiration(const std::string& username, int newExpirationHours) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change session expiration." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET session_expiration = " + std::to_string(newExpirationHours) + |
| | | " WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çè¿æè®¾ç½®ï¼æ´æ°æååé |
| | | if (success && m_strCurrentUser == username) { |
| | | m_tmSessionExpiration = std::chrono::hours(newExpirationHours); |
| | | |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | 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(); |
| | | std::cout << "Activity updated at: " << std::chrono::system_clock::to_time_t(m_tpLastActivity) << std::endl; |
| | | } |
| | | |
| | | // è®¾ç½®æ æä½è¶
æ¶æ¶é´ |
| | | void UserManager::setSessionTimeout(std::chrono::minutes timeout) { |
| | | m_tmSessionTimeout = timeout; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦è¶
è¿æ æä½è¶
æ¶æ¶é´ |
| | | bool UserManager::isInactiveTimeout() const { |
| | | auto now = std::chrono::system_clock::now(); |
| | | auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>(now - m_tpLastActivity).count(); |
| | | return elapsedSeconds > m_tmSessionTimeout.count() * 60; |
| | | } |
| | | |
| | | // åå§åæ æä½æ£æµï¼å
æ¬è®¾ç½®å
¨å±é¼ æ åé®çé©å |
| | | void UserManager::initializeIdleDetection(HWND hwnd) { |
| | | updateActivityTime(); |
| | | m_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, (HINSTANCE) nullptr, 0); |
| | | m_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, (HINSTANCE) nullptr, 0); |
| | | ::SetTimer(hwnd, 1, 60000, nullptr); |
| | | } |
| | | |
| | | // ç»æ¢æ æä½æ£æµï¼æ¸
é¤é¼ æ åé®çé©å |
| | | void UserManager::terminateIdleDetection() { |
| | | if (m_hMouseHook) { |
| | | UnhookWindowsHookEx(m_hMouseHook); |
| | | m_hMouseHook = nullptr; |
| | | } |
| | | if (m_hKeyboardHook) { |
| | | UnhookWindowsHookEx(m_hKeyboardHook); |
| | | m_hKeyboardHook = nullptr; |
| | | } |
| | | ::KillTimer(nullptr, 1); |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·å |
| | | std::string UserManager::getCurrentUser() const { |
| | | 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; |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·çä¼è¯è¿ææ¶é´ |
| | | std::chrono::hours UserManager::getSessionExpiration() const { |
| | | return m_tmSessionExpiration; |
| | | } |
| | | |
| | | // å
¨å±é¼ æ é©ååè°ï¼è®°å½æ´»å¨æ¶é´ |
| | | LRESULT CALLBACK UserManager::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { |
| | | if (nCode == HC_ACTION) { |
| | | UserManager::getInstance().updateActivityTime(); |
| | | std::cout << "Mouse event detected. Activity time updated." << std::endl; |
| | | } |
| | | return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| | | } |
| | | |
| | | // å
¨å±é®çé©ååè°ï¼è®°å½æ´»å¨æ¶é´ |
| | | LRESULT CALLBACK UserManager::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { |
| | | if (nCode == HC_ACTION) { |
| | | UserManager::getInstance().updateActivityTime(); |
| | | std::cout << "Keyboard event detected. Activity time updated." << std::endl; |
| | | } |
| | | return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #ifndef USER_MANAGER_H |
| | | #define USER_MANAGER_H |
| | | |
| | | #include <string> |
| | | #include <memory> |
| | | #include <chrono> |
| | | #include <windows.h> |
| | | #include "Database.h" |
| | | |
| | | // ç¨æ·è§è²å®ä¹ |
| | | enum class UserRole { |
| | | SuperAdmin = 0, // è¶
级管çå |
| | | Engineer, // å·¥ç¨å¸ |
| | | Operator // æä½å |
| | | }; |
| | | |
| | | // ç¨æ·ç®¡çç±»ï¼éç¨å便¨¡å¼ |
| | | class UserManager { |
| | | public: |
| | | static UserManager& getInstance(); |
| | | |
| | | 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(); |
| | | bool isLoggedIn() const; |
| | | bool isRememberMe() const; |
| | | bool createUser(const std::string& username, const std::string& password, UserRole role, |
| | | std::chrono::minutes timeout = std::chrono::minutes(30), |
| | | std::chrono::hours expiration = std::chrono::hours(72)); |
| | | bool deleteUser(const std::string& username); |
| | | std::vector<std::vector<std::string>> getUsers(); |
| | | bool setUsers(const std::vector<std::vector<std::string>>& usersData); |
| | | bool changeUsername(const std::string& username, const std::string& newUsername); |
| | | bool changePassword(const std::string& username, const std::string& newPassword); |
| | | 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(); // ä»ä¼è¯æä»¶å è½½ä¼è¯ä¿¡æ¯ |
| | | void saveSession(); // ä¿åä¼è¯ä¿¡æ¯å°æä»¶ |
| | | void clearSession(); // æ¸
é¤ä¼è¯æä»¶ |
| | | |
| | | // é
ç½®æä»¶å¤¹è·¯å¾ç®¡ç |
| | | static std::string getConfigFolderPath(); |
| | | static std::string getSessionFilePath(); |
| | | static std::string getDatabaseFilePath(); |
| | | |
| | | // æ´æ°æåæ´»å¨æ¶é´ï¼ç¨äºæ æä½è¶
æ¶æ£æµï¼ |
| | | void updateActivityTime(); |
| | | |
| | | // è®¾ç½®ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | void setSessionTimeout(std::chrono::minutes timeout); |
| | | |
| | | // æ£æ¥æ¯å¦æ æä½è¶
æ¶ |
| | | bool isInactiveTimeout() const; |
| | | |
| | | // åå§åæ æä½æ£æµï¼è®¾ç½®å
¨å±é©åå宿¶å¨ï¼ |
| | | void initializeIdleDetection(HWND hwnd); |
| | | |
| | | // ç»æ¢æ æä½æ£æµï¼æ¸
é¤é©åå宿¶å¨ï¼ |
| | | void terminateIdleDetection(); |
| | | |
| | | // è·åå½åç»å½ç¨æ·å |
| | | 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; |
| | | |
| | | // è·åå½åç»å½ç¨æ·çä¼è¯è¿ææ¶é´ |
| | | std::chrono::hours getSessionExpiration() const; |
| | | |
| | | private: |
| | | UserManager(); |
| | | ~UserManager(); |
| | | |
| | | // åå§åæ°æ®åºè¿æ¥åç¨æ·è¡¨ |
| | | bool initializeDatabase(); |
| | | |
| | | // åå¸å¯ç ï¼ç¨äºå å¯ç¨æ·å¯ç |
| | | std::string hashPassword(const std::string& password); |
| | | |
| | | // å å¯åè§£å¯å½æ° |
| | | std::string simpleEncryptDecrypt(const std::string& data, const std::string& key); |
| | | |
| | | // é®çåé¼ æ é©å彿° |
| | | static LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam); |
| | | static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); |
| | | |
| | | // 屿§å®ä¹ |
| | | std::string m_strCurrentUser; // å½åç»å½ç¨æ·å |
| | | std::string m_strCurrentPass; // å½åç»å½å¯ç |
| | | UserRole m_enCurrentUserRole; // å½åç»å½ç¨æ·è§è² |
| | | bool m_isLoggedIn; // æ¯å¦å·²ç»å½ |
| | | bool m_isRememberMe; // æ¯å¦è®°ä½ç»å½ç¶æ |
| | | |
| | | std::chrono::time_point<std::chrono::system_clock> m_tpLastLogin; // 䏿¬¡ç»å½æ¶é´ |
| | | std::chrono::time_point<std::chrono::system_clock> m_tpLastActivity; // æåæ´»å¨æ¶é´ |
| | | std::chrono::minutes m_tmSessionTimeout; // æ æä½è¶
æ¶æ¶é´ |
| | | std::chrono::hours m_tmSessionExpiration; // ä¼è¯è¿ææ¶é´ |
| | | HHOOK m_hMouseHook; // é¼ æ é©å奿 |
| | | HHOOK m_hKeyboardHook; // é®çé©å奿 |
| | | |
| | | std::unique_ptr<BL::Database> m_pDB; // æ°æ®åºæ¥å£ |
| | | }; |
| | | |
| | | #endif // USER_MANAGER_H |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // UserManagerDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | | #include "stdafx.h" |
| | | #include "Servo.h" |
| | | #include "afxdialogex.h" |
| | | #include "UserManagerDlg.h" |
| | | #include "InputDialog.h" |
| | | #include "UserManager.h" |
| | | #include "SystemLogManager.h" |
| | | #include "NewCellTypes/GridCellCombo.h" |
| | | #include "NewCellTypes/GridCellNumeric.h" |
| | | #include <set> |
| | | |
| | | const COLORREF CURR_USER_BK_COLOR = RGB(0, 255, 0); |
| | | |
| | | // CUserManagerDlg å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CUserManagerDlg, CBaseDlg) |
| | | |
| | | CUserManagerDlg::CUserManagerDlg(CWnd* pParent /*=nullptr*/) |
| | | : CBaseDlg(IDD_DIALOG_USER_MANAGER, pParent) |
| | | { |
| | | } |
| | | |
| | | CUserManagerDlg::~CUserManagerDlg() |
| | | { |
| | | } |
| | | |
| | | void CUserManagerDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | DDX_Control(pDX, IDC_CUSTOM_USER, m_gridUserManager); |
| | | CBaseDlg::DoDataExchange(pDX); |
| | | } |
| | | |
| | | void CUserManagerDlg::InitUserManager() |
| | | { |
| | | if (m_gridUserManager.GetSafeHwnd() == NULL) |
| | | return; |
| | | |
| | | int nRows = 1; |
| | | int nCols = 8; |
| | | |
| | | int nFixRows = 1; |
| | | int nFixCols = 0; |
| | | int nRowIdx = 0; |
| | | int nColIdx = 0; |
| | | |
| | | m_gridUserManager.DeleteAllItems(); |
| | | m_gridUserManager.SetVirtualMode(FALSE); |
| | | m_gridUserManager.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor); // 设置åºå®è¡èæ¯è² |
| | | m_gridUserManager.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor); // 设置åºå®åèæ¯è² |
| | | m_gridUserManager.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor); // 设置åå
æ ¼èæ¯è² |
| | | m_gridUserManager.SetFixedTextColor(g_nGridFixFontColor); // 设置åºå®è¡ååä½é¢è² |
| | | |
| | | m_gridUserManager.SetRowCount(nRows); |
| | | m_gridUserManager.SetColumnCount(nCols); |
| | | m_gridUserManager.SetFixedRowCount(nFixRows); |
| | | m_gridUserManager.SetFixedColumnCount(nFixCols); |
| | | |
| | | // Col |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 20); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("No.")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 70); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("ç¨æ·å")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 70); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("å¯ç ")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 70); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("æé")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 70); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("ä¼è¯è¶
æ¶ï¼åéï¼")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 70); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("ä¼è¯è¿æï¼å°æ¶ï¼")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 70); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("æå䏿¬¡ç»å½æ¶é´")); |
| | | m_gridUserManager.SetColumnWidth(nColIdx, 100); |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, _T("è§è²æè¿°")); |
| | | |
| | | m_gridUserManager.SetFixedRowSelection(FALSE); |
| | | m_gridUserManager.SetFixedColumnSelection(FALSE); |
| | | m_gridUserManager.SetEditable(TRUE); |
| | | m_gridUserManager.SetRowResize(FALSE); |
| | | m_gridUserManager.SetColumnResize(TRUE); |
| | | m_gridUserManager.ExpandColumnsToFit(TRUE); |
| | | m_gridUserManager.SetListMode(TRUE); // å¯ç¨åè¡¨æ¨¡å¼ |
| | | m_gridUserManager.EnableSelection(TRUE); // å¯ç¨éæ© |
| | | m_gridUserManager.SetSingleRowSelection(TRUE); // èªå¨æ´è¡é«äº®ï¼éå¶ä¸ºåè¡éæ©ï¼ |
| | | m_gridUserManager.ExpandLastColumn(); // æåä¸åå¡«å
ç½æ ¼ |
| | | |
| | | m_mapRoleDescriptions.clear(); |
| | | m_mapRoleDescriptions.emplace(_T("管çå"), _T("ç®¡çææç¨æ·ï¼åé
æé")); |
| | | m_mapRoleDescriptions.emplace(_T("å·¥ç¨å¸"), _T("ç»´æ¤ç³»ç»ï¼è§£å³ææ¯é®é¢")); |
| | | m_mapRoleDescriptions.emplace(_T("æä½å"), _T("æ§è¡æ¥å¸¸æä½ä»»å¡")); |
| | | |
| | | FillUserManager(); |
| | | } |
| | | |
| | | void CUserManagerDlg::FillUserManager() |
| | | { |
| | | UserManager& userManager = UserManager::getInstance(); |
| | | if (!userManager.isLoggedIn()) { |
| | | AfxMessageBox(_T("æªç»å½")); |
| | | return; |
| | | } |
| | | |
| | | if (userManager.getCurrentUserRole() != UserRole::SuperAdmin) { |
| | | AfxMessageBox(_T("é管çåç¨æ·")); |
| | | return; |
| | | } |
| | | |
| | | int nCurrNameRow = -1; |
| | | std::vector<std::vector<std::string>> usersData = userManager.getUsers(); |
| | | if (!usersData.empty()) { |
| | | m_gridUserManager.SetRowCount((int)usersData.size() + 1); |
| | | |
| | | 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 (int j = 0; j < usersData[i].size(); j++) { |
| | | if (usersData[i][1].empty()) { |
| | | continue; |
| | | } |
| | | m_gridUserManager.SetItemText(nRowIdx, nColIdx++, usersData[i][j].c_str()); |
| | | } |
| | | |
| | | // å½åç»å½ç¨æ·é«äº® |
| | | if (nCurrNameRow == -1 && usersData[i][0] == userManager.getCurrentUser()) { |
| | | nCurrNameRow = nRowIdx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | CStringArray permissions; |
| | | permissions.Add(_T("管çå")); |
| | | permissions.Add(_T("å·¥ç¨å¸")); |
| | | permissions.Add(_T("æä½å")); |
| | | |
| | | int nCols = m_gridUserManager.GetColumnCount(); |
| | | for (int i = 1; i < m_gridUserManager.GetRowCount(); ++i) { |
| | | m_gridUserManager.SetItemState(i, 0, GVIS_READONLY); // 第ä¸ååªè¯» |
| | | m_gridUserManager.SetItemState(i, nCols - 2, GVIS_READONLY); // åæ°ç¬¬äºååªè¯» |
| | | m_gridUserManager.SetItemState(i, nCols - 1, GVIS_READONLY); // æåä¸ååªè¯» |
| | | |
| | | // 第åå设置æéåä¸ºä¸ææ¡ |
| | | if (m_gridUserManager.SetCellType(i, 3, RUNTIME_CLASS(CGridCellCombo))) { |
| | | CGridCellCombo* pCell = static_cast<CGridCellCombo*>(m_gridUserManager.GetCell(i, 3)); |
| | | pCell->SetOptions(permissions); |
| | | pCell->SetStyle(CBS_DROPDOWNLIST); |
| | | |
| | | CString cstrRole = m_gridUserManager.GetItemText(i, 3); |
| | | int nRole = _ttoi(cstrRole); |
| | | if (nRole < 0 || nRole > 2) { |
| | | CString cstrMessage; |
| | | cstrMessage.Format(_T("ç¨æ· [%s]ï¼æéå¼å¸¸ï¼å°è®¾ç½®ææä½åï¼"), m_gridUserManager.GetItemText(i, 1)); |
| | | AfxMessageBox(cstrMessage); |
| | | nRole = 2; |
| | | } |
| | | |
| | | m_gridUserManager.SetItemText(i, 3, permissions.GetAt(nRole)); |
| | | |
| | | auto it = m_mapRoleDescriptions.find(permissions.GetAt(nRole)); |
| | | if (it != m_mapRoleDescriptions.end()) { |
| | | m_gridUserManager.SetItemText(i, 7, it->second); |
| | | } |
| | | } |
| | | |
| | | // 第äºãå
åï¼ä¼è¯è¶
æ¶ï¼è®¾ç½®ä¸ºNumeric |
| | | //m_gridUserManager.SetCellType(i, 4, RUNTIME_CLASS(CGridCellNumeric)); |
| | | //m_gridUserManager.SetCellType(i, 5, RUNTIME_CLASS(CGridCellNumeric)); |
| | | m_gridUserManager.SetItemState(i, 4, GVIS_READONLY); // 第äºååªè¯» |
| | | m_gridUserManager.SetItemState(i, 5, GVIS_READONLY); // 第å
ååªè¯» |
| | | |
| | | m_gridUserManager.ExpandColumnsToFit(FALSE); |
| | | m_gridUserManager.ExpandLastColumn(); |
| | | } |
| | | |
| | | for (int i = 0; i < nCols; i++) { |
| | | m_gridUserManager.SetItemBkColour(nCurrNameRow, i, CURR_USER_BK_COLOR); |
| | | } |
| | | m_gridUserManager.SetItemState(nCurrNameRow, 3, GVIS_READONLY); |
| | | |
| | | m_gridUserManager.Invalidate(); |
| | | m_gridUserManager.UpdateWindow(); |
| | | } |
| | | |
| | | void CUserManagerDlg::AddRow(CGridCtrl* pGridCtrl) |
| | | { |
| | | if (!pGridCtrl) return; |
| | | |
| | | if (pGridCtrl->GetRowCount() <= 0 || pGridCtrl->GetColumnCount() <= 0) { |
| | | AfxMessageBox(_T("ç½æ ¼æ§ä»¶æªæ£ç¡®åå§åï¼è¯·æ£æ¥åå§åé»è¾ï¼")); |
| | | return; |
| | | } |
| | | |
| | | CInputDialog inputDialog(_T("æ·»å ç¨æ·"), _T("请è¾å
¥ç¨æ·åï¼")); |
| | | if (inputDialog.DoModal() != IDOK) { |
| | | return; |
| | | } |
| | | |
| | | CString inputText = inputDialog.GetInputText(); |
| | | if (inputText.IsEmpty()) { |
| | | AfxMessageBox(_T("ç¨æ·åä¸è½ä¸ºç©ºï¼")); |
| | | return; |
| | | } |
| | | |
| | | if (IsUsernameDuplicate(inputText)) { |
| | | AfxMessageBox(_T("ç¨æ·åéå¤ï¼")); |
| | | return; |
| | | } |
| | | |
| | | int nRowCount = pGridCtrl->GetRowCount(); |
| | | pGridCtrl->SetRowCount(nRowCount + 1); |
| | | int newRowIndex = nRowCount; |
| | | |
| | | CString strText; |
| | | strText.Format(_T("%d"), newRowIndex); |
| | | pGridCtrl->SetItemText(newRowIndex, 0, strText); |
| | | pGridCtrl->SetItemText(newRowIndex, 1, inputText); |
| | | pGridCtrl->SetItemText(newRowIndex, 2, _T("123456")); |
| | | pGridCtrl->SetItemText(newRowIndex, 3, _T("æä½å")); |
| | | pGridCtrl->SetItemText(newRowIndex, 4, _T("30")); |
| | | pGridCtrl->SetItemText(newRowIndex, 5, _T("72")); |
| | | pGridCtrl->SetItemText(newRowIndex, 6, _T("2024-01-01 00:00:00")); |
| | | |
| | | auto it = m_mapRoleDescriptions.find(_T("æä½å")); |
| | | if (it != m_mapRoleDescriptions.end()) { |
| | | pGridCtrl->SetItemText(newRowIndex, 7, it->second); |
| | | } |
| | | |
| | | int nCols = pGridCtrl->GetColumnCount(); |
| | | pGridCtrl->SetItemState(newRowIndex, 0, GVIS_READONLY); // 第ä¸ååªè¯» |
| | | pGridCtrl->SetItemState(newRowIndex, nCols - 2, GVIS_READONLY); // åæ°ç¬¬äºååªè¯» |
| | | pGridCtrl->SetItemState(newRowIndex, nCols - 1, GVIS_READONLY); // æåä¸ååªè¯» |
| | | |
| | | // 第ååè®¾ç½®ï¼æéåï¼ä¸ºä¸ææ¡ |
| | | CStringArray permissions; |
| | | permissions.Add(_T("管çå")); |
| | | permissions.Add(_T("å·¥ç¨å¸")); |
| | | permissions.Add(_T("æä½å")); |
| | | |
| | | if (pGridCtrl->SetCellType(newRowIndex, 3, RUNTIME_CLASS(CGridCellCombo))) { |
| | | CGridCellCombo* pCell = static_cast<CGridCellCombo*>(pGridCtrl->GetCell(newRowIndex, 3)); |
| | | pCell->SetOptions(permissions); |
| | | pCell->SetStyle(CBS_DROPDOWNLIST); |
| | | |
| | | pGridCtrl->SetItemText(newRowIndex, 3, permissions.GetAt(2)); |
| | | } |
| | | |
| | | // 第äºãå
åï¼ä¼è¯è¶
æ¶ï¼è®¾ç½®ä¸ºNumeric |
| | | //pGridCtrl->SetCellType(newRowIndex, 4, RUNTIME_CLASS(CGridCellNumeric)); |
| | | //pGridCtrl->SetCellType(newRowIndex, 5, RUNTIME_CLASS(CGridCellNumeric)); |
| | | pGridCtrl->SetItemState(newRowIndex, 4, GVIS_READONLY); // 第äºååªè¯» |
| | | pGridCtrl->SetItemState(newRowIndex, 5, GVIS_READONLY); // 第å
ååªè¯» |
| | | |
| | | pGridCtrl->ExpandColumnsToFit(FALSE); |
| | | 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) |
| | | { |
| | | if (!pGridCtrl) return; |
| | | CCellRange selectedRange = pGridCtrl->GetSelectedCellRange(); |
| | | if (selectedRange.IsValid()) { |
| | | CString currentUser = UserManager::getInstance().getCurrentUser().c_str(); |
| | | std::vector<int> rowsToDelete; |
| | | |
| | | for (int row = selectedRange.GetMinRow(); row <= selectedRange.GetMaxRow(); ++row) { |
| | | BOOL isRowSelected = FALSE; |
| | | for (int col = selectedRange.GetMinCol(); col <= selectedRange.GetMaxCol(); ++col) { |
| | | if (pGridCtrl->IsCellSelected(row, col)) { |
| | | isRowSelected = TRUE; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (!isRowSelected) { |
| | | continue; |
| | | } |
| | | |
| | | CString selectedUser = pGridCtrl->GetItemText(row, 1); |
| | | if (selectedUser == currentUser) { |
| | | CString message; |
| | | message.Format(_T("ç¨æ· [%s] æ¯å½åç»å½ç¨æ·ï¼ä¸è½å é¤ï¼"), currentUser); |
| | | AfxMessageBox(message); |
| | | return; |
| | | } |
| | | |
| | | rowsToDelete.push_back(row); |
| | | } |
| | | |
| | | if (rowsToDelete.empty()) { |
| | | AfxMessageBox(_T("请å
éæ©è¦å é¤çè¡ï¼")); |
| | | return; |
| | | } |
| | | |
| | | CString message; |
| | | 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()); |
| | | } |
| | | |
| | | if (AfxMessageBox(message, MB_YESNO | MB_ICONQUESTION) == IDYES) { |
| | | for (auto it = rowsToDelete.rbegin(); it != rowsToDelete.rend(); ++it) { |
| | | pGridCtrl->DeleteRow(*it); |
| | | } |
| | | |
| | | pGridCtrl->ExpandColumnsToFit(FALSE); |
| | | pGridCtrl->ExpandLastColumn(); |
| | | pGridCtrl->Invalidate(); |
| | | pGridCtrl->UpdateWindow(); |
| | | } |
| | | } |
| | | else { |
| | | AfxMessageBox(_T("请å
éæ©è¦å é¤çç¨æ·ï¼")); |
| | | } |
| | | } |
| | | |
| | | bool CUserManagerDlg::IsUsernameDuplicate(const CString& username) |
| | | { |
| | | for (int row = 1; row < m_gridUserManager.GetRowCount(); ++row) { |
| | | if (m_gridUserManager.GetItemText(row, 1) == username) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | BEGIN_MESSAGE_MAP(CUserManagerDlg, CBaseDlg) |
| | | ON_NOTIFY(GVN_COMBOSELCHANGE, IDC_CUSTOM_USER, &CUserManagerDlg::OnGridComboSelChange) |
| | | ON_BN_CLICKED(IDC_BUTTON_ADD, &CUserManagerDlg::OnBnClickedButtonAdd) |
| | | ON_BN_CLICKED(IDC_BUTTON_DEL, &CUserManagerDlg::OnBnClickedButtonDel) |
| | | ON_BN_CLICKED(IDOK, &CUserManagerDlg::OnBnClickedOk) |
| | | ON_BN_CLICKED(IDC_BUTTON_INSERT, &CUserManagerDlg::OnBnClickedButtonInsert) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | | // CUserManagerDlg æ¶æ¯å¤çç¨åº |
| | | |
| | | |
| | | BOOL CUserManagerDlg::OnInitDialog() |
| | | { |
| | | CBaseDlg::OnInitDialog(); |
| | | |
| | | // TODO: 卿¤æ·»å é¢å¤çåå§å |
| | | SetWindowText(_T("ç¨æ·ç®¡ç")); |
| | | |
| | | // åå§åç¨æ·ç®¡çè¡¨æ ¼ |
| | | InitUserManager(); |
| | | |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | // å¼å¸¸: OCX 屿§é¡µåºè¿å FALSE |
| | | } |
| | | |
| | | void CUserManagerDlg::OnGridComboSelChange(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | NM_GRIDVIEW* pItem = (NM_GRIDVIEW*)pNMHDR; |
| | | |
| | | int nRow = pItem->iRow; |
| | | int nCol = pItem->iColumn; |
| | | |
| | | // 第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); |
| | | m_gridUserManager.RedrawCell(nRow, 7); |
| | | } |
| | | else { |
| | | m_gridUserManager.SetItemText(nRow, 7, _T("")); |
| | | m_gridUserManager.RedrawCell(nRow, 7); |
| | | } |
| | | } |
| | | } |
| | | |
| | | *pResult = 0; |
| | | } |
| | | |
| | | |
| | | void CUserManagerDlg::OnBnClickedButtonAdd() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | AddRow(&m_gridUserManager); |
| | | } |
| | | |
| | | |
| | | void CUserManagerDlg::OnBnClickedButtonInsert() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | if (!m_gridUserManager.GetSafeHwnd()) return; |
| | | |
| | | CCellRange selectedRange = m_gridUserManager.GetSelectedCellRange(); |
| | | if (!selectedRange.IsValid()) { |
| | | AfxMessageBox(_T("请å
éæ©è¦æå
¥çä½ç½®ï¼")); |
| | | return; |
| | | } |
| | | |
| | | int minRow = selectedRange.GetMinRow(); |
| | | int maxRow = selectedRange.GetMaxRow(); |
| | | if (minRow < 1) { |
| | | AfxMessageBox(_T("è¯·éæ©ææçè¡ï¼")); |
| | | return; |
| | | } |
| | | |
| | | for (int row = maxRow; row >= minRow; --row) { |
| | | std::vector<CString> rowData; |
| | | for (int col = 0; col < m_gridUserManager.GetColumnCount(); ++col) { |
| | | rowData.push_back(m_gridUserManager.GetItemText(row, col)); |
| | | } |
| | | |
| | | m_gridUserManager.InsertRow(_T("æ°ç¨æ·"), row); |
| | | CString newUsername = rowData[1]; |
| | | int suffix = 1; |
| | | while (IsUsernameDuplicate(newUsername)) { |
| | | newUsername.Format(_T("%s_%d"), rowData[1], suffix++); |
| | | } |
| | | rowData[1] = newUsername; |
| | | |
| | | for (int col = 0; col < m_gridUserManager.GetColumnCount(); ++col) { |
| | | m_gridUserManager.SetItemText(row, col, rowData[col]); |
| | | } |
| | | |
| | | CStringArray permissions; |
| | | permissions.Add(_T("管çå")); |
| | | permissions.Add(_T("å·¥ç¨å¸")); |
| | | permissions.Add(_T("æä½å")); |
| | | |
| | | if (m_gridUserManager.SetCellType(row, 3, RUNTIME_CLASS(CGridCellCombo))) { |
| | | CGridCellCombo* pCell = static_cast<CGridCellCombo*>(m_gridUserManager.GetCell(row, 3)); |
| | | pCell->SetOptions(permissions); |
| | | pCell->SetStyle(CBS_DROPDOWNLIST); |
| | | |
| | | m_gridUserManager.SetItemText(row, 3, rowData[3]); |
| | | } |
| | | |
| | | m_gridUserManager.SetCellType(row, 4, RUNTIME_CLASS(CGridCellNumeric)); |
| | | m_gridUserManager.SetCellType(row, 5, RUNTIME_CLASS(CGridCellNumeric)); |
| | | } |
| | | |
| | | for (int row = 1; row < m_gridUserManager.GetRowCount(); ++row) { |
| | | CString strIndex; |
| | | strIndex.Format(_T("%d"), row); |
| | | m_gridUserManager.SetItemText(row, 0, strIndex); |
| | | } |
| | | |
| | | m_gridUserManager.Invalidate(); |
| | | m_gridUserManager.UpdateWindow(); |
| | | } |
| | | |
| | | |
| | | void CUserManagerDlg::OnBnClickedButtonDel() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | DeleteSelectedRow(&m_gridUserManager); |
| | | } |
| | | |
| | | |
| | | void CUserManagerDlg::OnBnClickedOk() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | 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; |
| | | message.Format(_T("ç¨æ·å [%s] éå¤ï¼è¯·ä¿®æ¹åä¿åï¼"), cellText); |
| | | 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); |
| | | std::string cellString = CT2A(cellText.GetString()); |
| | | |
| | | // 第4忝æéï¼è½¬æ¢ä¸ºæ°åå符串 |
| | | if (j == 3) { |
| | | if (cellText == _T("管çå")) |
| | | cellString = "0"; |
| | | else if (cellText == _T("å·¥ç¨å¸")) |
| | | cellString = "1"; |
| | | else if (cellText == _T("æä½å")) |
| | | cellString = "2"; |
| | | else |
| | | cellString = "2"; |
| | | } |
| | | |
| | | rowData.push_back(cellString); |
| | | } |
| | | |
| | | vecData.push_back(rowData); |
| | | } |
| | | |
| | | userManager.setUsers(vecData); |
| | | CBaseDlg::OnOK(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "afxdialogex.h" |
| | | #include "GridCtrl.h" |
| | | #include "CBaseDlg.h" |
| | | |
| | | // CUserManagerDlg å¯¹è¯æ¡ |
| | | |
| | | class CUserManagerDlg : public CBaseDlg |
| | | { |
| | | DECLARE_DYNAMIC(CUserManagerDlg) |
| | | |
| | | public: |
| | | CUserManagerDlg(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CUserManagerDlg(); |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_USER_MANAGER }; |
| | | #endif |
| | | |
| | | private: |
| | | void InitUserManager(); |
| | | void FillUserManager(); |
| | | void AddRow(CGridCtrl* pGridCtrl); |
| | | void DeleteSelectedRow(CGridCtrl* pGridCtrl); |
| | | bool IsUsernameDuplicate(const CString& username); |
| | | |
| | | private: |
| | | std::map<CString, CString> m_mapRoleDescriptions; |
| | | |
| | | // æ§ä»¶ |
| | | CGridCtrl m_gridUserManager; |
| | | |
| | | protected: |
| | | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV æ¯æ |
| | | |
| | | DECLARE_MESSAGE_MAP() |
| | | public: |
| | | virtual BOOL OnInitDialog(); |
| | | afx_msg void OnGridComboSelChange(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnBnClickedButtonAdd(); |
| | | afx_msg void OnBnClickedButtonInsert(); |
| | | afx_msg void OnBnClickedButtonDel(); |
| | | afx_msg void OnBnClickedOk(); |
| | | }; |