From fc8d367963a16de61dfbc4a0ff34c78c91ec2cfe Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期五, 05 九月 2025 09:21:28 +0800
Subject: [PATCH] Merge branch 'liuyang' into clh
---
SourceCode/Bond/Servo/PortConfigurationDlg.cpp | 27
SourceCode/Bond/Servo/RecipeManager.cpp | 873 ++++++++++++--------
SourceCode/Bond/Servo/UserManagerDlg.cpp | 33
SourceCode/Bond/Servo/RecipeManager.h | 150 ++-
SourceCode/Bond/Servo/UserManager.h | 164 ++-
SourceCode/Bond/Servo/PageRecipe.h | 5
SourceCode/Bond/Servo/ServoDlg.cpp | 23
SourceCode/Bond/Servo/UserManager.cpp | 688 ++++++++--------
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp | 330 ++++---
SourceCode/Bond/Servo/PageRecipe.cpp | 127 ++
10 files changed, 1,364 insertions(+), 1,056 deletions(-)
diff --git a/SourceCode/Bond/Servo/PageRecipe.cpp b/SourceCode/Bond/Servo/PageRecipe.cpp
index 891f274..f19cae0 100644
--- a/SourceCode/Bond/Servo/PageRecipe.cpp
+++ b/SourceCode/Bond/Servo/PageRecipe.cpp
@@ -5,6 +5,8 @@
#include "Servo.h"
#include "afxdialogex.h"
#include "PageRecipe.h"
+#include "MsgDlg.h"
+#include "InputDialog.h"
#include "RecipeDeviceBindDlg.h"
@@ -55,9 +57,9 @@
CString strIniFile, strItem;
strIniFile.Format(_T("%s\\configuration.ini"), (LPCTSTR)theApp.m_strAppDir);
- int width[] = { 0, 60, 150, 150 };
+ int width[] = { 0, 60, 100, 100, 150 };
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 5; i++) {
strItem.Format(_T("Col_Device_%d_Width"), i);
width[i] = GetPrivateProfileInt(_T("PageRecipeListCtrl"), strItem, width[i], strIniFile);
}
@@ -66,6 +68,7 @@
m_listPPID.InsertColumn(1, _T("No."), LVCFMT_CENTER, width[1]);
m_listPPID.InsertColumn(2, _T("Recipe ID"), LVCFMT_CENTER, width[2]);
m_listPPID.InsertColumn(3, _T("Recipe 鍚嶇О"), LVCFMT_CENTER, width[3]);
+ m_listPPID.InsertColumn(4, _T("Recipe 鍙傛暟"), LVCFMT_CENTER, width[4]);
}
void CPageRecipe::UpdateRecipeByPPID(const CString& strPPID)
@@ -146,8 +149,18 @@
m_listPPID.SetItemText(i, 2, CA2T(recipe.strPPID.c_str()));
for (int j = 0; j < recipe.vecDeviceList.size(); j++){
+ int nRecipeID = recipe.vecDeviceList.at(j).nRecipeID;
+ std::string strDeviceName = recipe.vecDeviceList.at(j).strDeviceName;
+ std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(strDeviceName, nRecipeID);
+
CString str;
- str.Format(_T("%d"), recipe.vecDeviceList.at(j).nRecipeID);
+ if (strRecipeName.empty()) {
+ str.Format(_T("%d"), recipe.vecDeviceList.at(j).nRecipeID);
+ }
+ else {
+ str.Format(_T("%s"), CA2T(strRecipeName.c_str()));
+ }
+
m_listPPID.SetItemText(i, j + 3, str);
}
@@ -175,6 +188,7 @@
}
// 閬嶅巻鏁版嵁骞舵彃鍏ュ埌CListCtrl涓�
+ auto& mgr = RecipeManager::getInstance();
std::map<int, short>& ids = pRecipeList->getIds();
auto rawDatas = pRecipeList->getParamsRawData();
for (auto item : ids) {
@@ -182,10 +196,19 @@
m_listPPID.SetItemText(index, 1, std::to_string(item.first).c_str());
m_listPPID.SetItemText(index, 2, std::to_string(item.second).c_str());
+ std::string strRecipeName = mgr.getDeviceRecipeName(pEq->getName(), item.second);
+ m_listPPID.SetItemText(index, 3, strRecipeName.c_str());
+
+ std::string strDescription;
auto iter = rawDatas.find(item.second);
if (iter != rawDatas.end()) {
- std::string strDescription;
pEq->parsingParams((const char*)iter->second.data(), iter->second.size(), strDescription);
+ m_listPPID.SetItemText(index, 4, strDescription.c_str());
+ }
+
+ if (strRecipeName.empty()) {
+ strRecipeName = std::to_string(item.second);
+ mgr.addDeviceRecipe(pEq->getName(), item.second, strRecipeName, strDescription);
}
}
@@ -211,7 +234,8 @@
ON_BN_CLICKED(IDC_BUTTON_DELETE, &CPageRecipe::OnBnClickedButtonDelete)
ON_BN_CLICKED(IDC_BUTTON_DELETE_ALL, &CPageRecipe::OnBnClickedButtonDeleteAll)
ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CPageRecipe::OnBnClickedButtonRefresh)
- ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PPID, &CPageRecipe::OnLvnItemChangedListPPID)
+ ON_NOTIFY(NM_CLICK, IDC_LIST_PPID, &CPageRecipe::OnClickListPPID)
+ ON_NOTIFY(NM_DBLCLK, IDC_LIST_PPID, &CPageRecipe::OnDblclkListPPID)
ON_CBN_SELCHANGE(IDC_COMBO_EQUIPMENT, &CPageRecipe::OnCbnSelchangeComboEquipment)
END_MESSAGE_MAP()
@@ -428,15 +452,41 @@
void CPageRecipe::OnBnClickedButtonModify()
{
// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
+ if (pComboBox == nullptr || !::IsWindow(pComboBox->m_hWnd)) {
+ return;
+ }
+
POSITION pos = m_listPPID.GetFirstSelectedItemPosition();
if (!pos) {
AfxMessageBox(_T("璇峰厛閫夋嫨涓�鏉¢厤鏂硅褰曡繘琛屼慨鏀癸紒"));
return;
}
- int nSel = m_listPPID.GetNextSelectedItem(pos);
- CString strPPID = m_listPPID.GetItemText(nSel, 2);
- UpdateRecipeByPPID(strPPID);
+ int nLine = m_listPPID.GetNextSelectedItem(pos);
+ CString strID = m_listPPID.GetItemText(nLine, 2);
+
+ int nSel = pComboBox->GetCurSel();
+ SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nSel);
+ if (pEq == nullptr) {
+ UpdateRecipeByPPID(strID);
+ }
+ else {
+ CInputDialog dlg(_T("淇敼閰嶆柟鍚嶇О"), _T("璇疯緭鍏ラ厤鏂瑰悕绉帮細"));
+ if (dlg.DoModal() != IDOK) {
+ return;
+ }
+
+ CString strText = dlg.GetInputText();
+ if (strText.IsEmpty()) {
+ AfxMessageBox(_T("閰嶆柟鍚嶇О涓嶈兘涓虹┖锛�"));
+ return;
+ }
+
+ if (RecipeManager::getInstance().updateDeviceRecipeName(pEq->getName(), _ttoi(strID), std::string(CT2A(strText)))) {
+ m_listPPID.SetItemText(nLine, 3, strText);
+ }
+ }
}
void CPageRecipe::OnBnClickedButtonDelete()
@@ -507,31 +557,60 @@
}
}
-void CPageRecipe::OnLvnItemChangedListPPID(NMHDR* pNMHDR, LRESULT* pResult)
+void CPageRecipe::OnClickListPPID(NMHDR* pNMHDR, LRESULT* pResult)
{
- LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
+ LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
*pResult = 0;
CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
- int nEqSel = pComboBox->GetCurSel();
- int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd());
+ if (pComboBox == nullptr) {
+ return;
+ }
- GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0 && selectedCount > 0);
- GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && selectedCount > 0);
- GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && selectedCount > 0);
- GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && selectedCount > 0);
+ int nItem = pNMItemActivate->iItem;
+ int nEqSel = pComboBox->GetCurSel();
+
+ GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0);
+ GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nItem != -1);
+ GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1);
+ GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1);
+}
+
+void CPageRecipe::OnDblclkListPPID(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ *pResult = 0;
+
+ int nItem = pNMItemActivate->iItem;
+ if (nItem < 0) {
+ return;
+ }
+
+ CString strText = m_listPPID.GetItemText(nItem, 2);
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
+ int nEqSel = pComboBox->GetCurSel();
+ if (nEqSel == CB_ERR) {
+ return;
+ }
+
+ SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nEqSel);
+ if (pEq == nullptr) {
+ return;
+ }
}
void CPageRecipe::OnCbnSelchangeComboEquipment()
{
CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
int nEqSel = pComboBox->GetCurSel();
- int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd());
+ int nItem = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd());
- GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0 && selectedCount > 0);
- GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && selectedCount > 0);
- GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && selectedCount > 0);
- GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && selectedCount > 0);
+ GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0);
+ GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && nItem != -1);
+ GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1);
+ GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1);
GetDlgItem(IDC_EDIT_KEYWORD)->EnableWindow(nEqSel == 0);
GetDlgItem(IDC_BUTTON_SEARCH)->EnableWindow(nEqSel == 0);
@@ -632,7 +711,7 @@
ResetEvent(hEvent);
}
-
+
pEq->saveRecipeList(0, strFilepath);
pMsgDlg->SetIcon(MSG_BOX_SUCCEED);
pMsgDlg->SetTitle(_T("鎿嶄綔瀹屾垚"));
@@ -643,7 +722,6 @@
FillRecipeListToListCtrl(pEq);
CloseHandle(hEvent);
-
// 鍦ㄦ鎵撳嵃閰嶆柟鍙傛暟浠ヤ究鏍稿鏁版嵁
@@ -665,9 +743,6 @@
}
}
-
-
-
return 0;
}
diff --git a/SourceCode/Bond/Servo/PageRecipe.h b/SourceCode/Bond/Servo/PageRecipe.h
index 352daed..0eac2df 100644
--- a/SourceCode/Bond/Servo/PageRecipe.h
+++ b/SourceCode/Bond/Servo/PageRecipe.h
@@ -43,10 +43,11 @@
afx_msg void OnBnClickedButtonDelete();
afx_msg void OnBnClickedButtonDeleteAll();
afx_msg void OnBnClickedButtonRefresh();
- afx_msg void OnLvnItemChangedListPPID(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnClickListPPID(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDblclkListPPID(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnCbnSelchangeComboEquipment();
DECLARE_MESSAGE_MAP()
private:
CListCtrlEx m_listPPID;
-};
+};
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/PortConfigurationDlg.cpp b/SourceCode/Bond/Servo/PortConfigurationDlg.cpp
index fba8bf8..62ad3a0 100644
--- a/SourceCode/Bond/Servo/PortConfigurationDlg.cpp
+++ b/SourceCode/Bond/Servo/PortConfigurationDlg.cpp
@@ -11,8 +11,6 @@
#include "RecipeManager.h"
#include "ServoCommo.h"
-
-
#define CHECKBOX_ALL_ID 0x1234
// CPortConfigurationDlg 瀵硅瘽妗�
@@ -102,11 +100,26 @@
// 鍥炲~ Job 淇℃伅锛堝彧鍙栫涓�涓湁鏁� Glass锛�
if (!bJobInfoSet && pGlass) {
SERVO::CJobDataS* pJS = pGlass->getJobDataS();
- if (pJS) {
+ if (pJS) {
+ int nRecipeID = pJobDataS->getMasterRecipe();
+ std::string strRecipeName = RecipeManager::getInstance().getPPIDById(nRecipeID);
SetDlgItemText(IDC_EDIT_LOTID, CString(pJS->getLotId().c_str()));
SetDlgItemText(IDC_EDIT_PRODUCTID, CString(pJS->getProductId().c_str()));
SetDlgItemText(IDC_EDIT_OPERATIONID, CString(pJS->getOperationId().c_str()));
m_comboMaterialsType.SetCurSel(pJS->getMaterialsType() - 1);
+
+ if (!strRecipeName.empty()) {
+ CString csRecipeName(strRecipeName.c_str());
+ int nIndex = m_comboRecipe.FindStringExact(-1, csRecipeName);
+ if (nIndex != CB_ERR) {
+ m_comboRecipe.SetCurSel(nIndex);
+ }
+ else {
+ AfxMessageBox(_T("褰撳墠閰嶆柟鍦ㄧ郴缁熶腑涓嶅瓨鍦紝璇烽噸鏂伴�夋嫨锛�"), MB_ICONWARNING);
+ m_comboRecipe.SetCurSel(0);
+ }
+ }
+
bJobInfoSet = true;
}
}
@@ -252,7 +265,6 @@
SetWindowText(_T("Port Configuration"));
}
-
// Porcess Start / Process Cancel 鎸夐挳鐘舵��
GetDlgItem(IDC_BUTTON_PROCESS_START)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_PROCESS_CANCEL)->EnableWindow(FALSE);
@@ -299,6 +311,9 @@
m_comboRecipe.GetLBText(selRecipe, str);
config.strRecipe = CT2A(str.GetString());
}
+ int nRecipeID = RecipeManager::getInstance().getIdByPPID(config.strRecipe);
+ RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(config.strRecipe);
+ std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList;
// 鑾峰彇 Material Type 绱㈠紩锛堢储寮曚粠 0 寮�濮嬶紝瀵瑰簲鏋氫妇浠� 1 寮�濮嬶級
//int selMaterial = m_comboMaterialsType.GetCurSel();
@@ -349,9 +364,7 @@
pJobDataS->setProductId(config.strProductID.c_str());
pJobDataS->setOperationId(config.strOperationID.c_str());
pJobDataS->setMaterialsType(nMaterialType);
-
- RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(config.strRecipe);
- std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList;
+ pJobDataS->setMasterRecipe(nRecipeID);
for (const auto& info : vecRecipeInfo) {
const std::string& name = info.strDeviceName;
diff --git a/SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp b/SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
index 549fb19..81059ac 100644
--- a/SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
+++ b/SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
@@ -14,12 +14,12 @@
// 缁戝畾鐣岄潰闇�瑕佹樉绀虹殑璁惧
static const std::vector<DeviceMetaInfo> g_vecBindDevices = {
- { EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE },
- { EQ_ID_Bonder1, EQ_NAME_BONDER1 },
- { EQ_ID_Bonder2, EQ_NAME_BONDER2 },
- { EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING },
- { EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT },
- { EQ_ID_EFEM, EQ_NAME_EFEM }
+ { EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE },
+ { EQ_ID_Bonder1, EQ_NAME_BONDER1 },
+ { EQ_ID_Bonder2, EQ_NAME_BONDER2 },
+ { EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING },
+ { EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT },
+ { EQ_ID_EFEM, EQ_NAME_EFEM }
};
// CRecipeDeviceBindDlg 瀵硅瘽妗�
@@ -28,8 +28,8 @@
CRecipeDeviceBindDlg::CRecipeDeviceBindDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG_RECIPE_DEVICE_BIND, pParent)
- , m_strPPID(_T(""))
- , m_strDesc(_T(""))
+ , m_strPPID(_T(""))
+ , m_strDesc(_T(""))
{
}
@@ -39,116 +39,122 @@
}
const RecipeInfo& CRecipeDeviceBindDlg::GetRecipeInfo() const {
- return m_recipe;
+ return m_recipe;
}
void CRecipeDeviceBindDlg::SetRecipeInfo(const RecipeInfo& info)
{
- m_recipe = info;
+ m_recipe = info;
}
void CRecipeDeviceBindDlg::ReleaseDeviceControls()
{
- for (auto& ctrl : m_vecDevices) {
- delete ctrl.editDeviceID; ctrl.editDeviceID = nullptr;
- delete ctrl.editDeviceName; ctrl.editDeviceName = nullptr;
- delete ctrl.comboRecipeID; ctrl.comboRecipeID = nullptr;
- }
- m_vecDevices.clear();
+ for (auto& ctrl : m_vecDevices) {
+ delete ctrl.editDeviceID; ctrl.editDeviceID = nullptr;
+ delete ctrl.editDeviceName; ctrl.editDeviceName = nullptr;
+ delete ctrl.comboRecipeID; ctrl.comboRecipeID = nullptr;
+ }
+ m_vecDevices.clear();
}
void CRecipeDeviceBindDlg::CreateDeviceControls(int nXStart, int nYStart, int nTotalControlWidth, int nRowHeight)
{
- for (size_t i = 0; i < g_vecBindDevices.size(); ++i) {
- int y = nYStart + static_cast<int>(i) * nRowHeight;
- auto* pEditID = new CEdit;
- pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart, y, nXStart + 100, y + 25), this, (UINT)(IDC_EDIT_DEVICEID_BASE + i));
- pEditID->SetFont(&m_font);
+ for (size_t i = 0; i < g_vecBindDevices.size(); ++i) {
+ int y = nYStart + static_cast<int>(i) * nRowHeight;
+ auto* pEditID = new CEdit;
+ pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart, y, nXStart + 100, y + 25), this, (UINT)(IDC_EDIT_DEVICEID_BASE + i));
+ pEditID->SetFont(&m_font);
- auto* pEditName = new CEdit;
- pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart + 110, y, nXStart + 210, y + 25), this, (UINT)(IDC_EDIT_DEVICENAME_BASE + i));
- pEditName->SetFont(&m_font);
+ auto* pEditName = new CEdit;
+ pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart + 110, y, nXStart + 210, y + 25), this, (UINT)(IDC_EDIT_DEVICENAME_BASE + i));
+ pEditName->SetFont(&m_font);
- auto* pCombo = new CComboBox;
- pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(nXStart + 220, y, nXStart + nTotalControlWidth, y + 25), this, (UINT)(IDC_COMBO_RECIPEID_BASE + i));
- pCombo->SetFont(&m_font);
+ auto* pCombo = new CComboBox;
+ pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(nXStart + 220, y, nXStart + nTotalControlWidth, y + 25), this, (UINT)(IDC_COMBO_RECIPEID_BASE + i));
+ pCombo->SetFont(&m_font);
- m_vecDevices.push_back({ pEditID, pEditName, pCombo });
- }
+ m_vecDevices.push_back({ pEditID, pEditName, pCombo });
+ }
}
bool CRecipeDeviceBindDlg::FillComboRecipeList(CComboBox* pCombo, int nDeviceID, int nSelectedRecipeID)
{
- auto& master = theApp.m_model.getMaster();
- auto* pEq = master.getEquipment(nDeviceID);
- if (!pEq) {
- return false;
- }
+ auto& master = theApp.m_model.getMaster();
+ auto* pEq = master.getEquipment(nDeviceID);
+ if (!pEq) {
+ return false;
+ }
- auto* pRecipeList = pEq->getRecipeList(0);
- if (!pRecipeList) {
- return false;
- }
+ auto* pRecipeList = pEq->getRecipeList(0);
+ if (!pRecipeList) {
+ return false;
+ }
- auto& mapRecipeIds = pRecipeList->getIds();
- bool bFound = false;
- pCombo->ResetContent();
- for (const auto& pair : mapRecipeIds) {
- int nRecipeID = pair.second;
- CString strRecipeName;
- strRecipeName.Format(_T("%d"), nRecipeID);
- int idx = pCombo->AddString(strRecipeName);
- pCombo->SetItemData(idx, nRecipeID);
- if (nSelectedRecipeID == nRecipeID) {
- pCombo->SetCurSel(idx);
- bFound = true;
- }
- }
+ auto& mapRecipeIds = pRecipeList->getIds();
+ bool bFound = false;
+ pCombo->ResetContent();
+ for (const auto& pair : mapRecipeIds) {
+ int nRecipeID = pair.second;
- if (nSelectedRecipeID != -1 && !bFound) {
- pCombo->SetCurSel(CB_ERR);
- }
- else if (pCombo->GetCount() > 0 && nSelectedRecipeID == -1) {
- pCombo->SetCurSel(0);
- }
+ std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(pEq->getName(), nRecipeID);
+ if (strRecipeName.empty()) {
+ strRecipeName = std::to_string(nRecipeID);
+ }
- return true;
+ CString str;
+ str.Format(_T("%s"), strRecipeName.c_str());
+ int idx = pCombo->AddString(str);
+ pCombo->SetItemData(idx, nRecipeID);
+ if (nSelectedRecipeID == nRecipeID) {
+ pCombo->SetCurSel(idx);
+ bFound = true;
+ }
+ }
+
+ if (nSelectedRecipeID != -1 && !bFound) {
+ pCombo->SetCurSel(CB_ERR);
+ }
+ else if (pCombo->GetCount() > 0 && nSelectedRecipeID == -1) {
+ pCombo->SetCurSel(0);
+ }
+
+ return true;
}
bool CRecipeDeviceBindDlg::FillDeviceInfo(int idx, int nDeviceID, const CString& strDeviceName, int nSelectedRecipeID)
{
- if (idx < 0 || idx >= (int)m_vecDevices.size()) {
- return false;
- }
+ if (idx < 0 || idx >= (int)m_vecDevices.size()) {
+ return false;
+ }
- auto& ctrl = m_vecDevices[idx];
- CString strID;
- strID.Format(_T("%d"), nDeviceID);
- ctrl.editDeviceID->SetWindowText(strID);
- ctrl.editDeviceID->SetReadOnly(TRUE);
- ctrl.editDeviceName->SetWindowText(strDeviceName);
- ctrl.editDeviceName->SetReadOnly(TRUE);
+ auto& ctrl = m_vecDevices[idx];
+ CString strID;
+ strID.Format(_T("%d"), nDeviceID);
+ ctrl.editDeviceID->SetWindowText(strID);
+ ctrl.editDeviceID->SetReadOnly(TRUE);
+ ctrl.editDeviceName->SetWindowText(strDeviceName);
+ ctrl.editDeviceName->SetReadOnly(TRUE);
- if (!FillComboRecipeList(ctrl.comboRecipeID, nDeviceID, nSelectedRecipeID)) {
- CString str;
- str.Format(_T("璁惧 [%s] 鎴栧叾閰嶆柟鍒楄〃鏈壘鍒帮紝璇锋鏌ヨ澶囬厤缃�"), strDeviceName.GetString());
- AfxMessageBox(str);
- return false;
- }
- return true;
+ if (!FillComboRecipeList(ctrl.comboRecipeID, nDeviceID, nSelectedRecipeID)) {
+ CString str;
+ str.Format(_T("璁惧 [%s] 鎴栧叾閰嶆柟鍒楄〃鏈壘鍒帮紝璇锋鏌ヨ澶囬厤缃�"), strDeviceName.GetString());
+ AfxMessageBox(str);
+ return false;
+ }
+ return true;
}
void CRecipeDeviceBindDlg::DoDataExchange(CDataExchange* pDX)
{
- CDialogEx::DoDataExchange(pDX);
- DDX_Text(pDX, IDC_EDIT_PPID, m_strPPID);
- DDX_Text(pDX, IDC_EDIT_DESC, m_strDesc);
+ CDialogEx::DoDataExchange(pDX);
+ DDX_Text(pDX, IDC_EDIT_PPID, m_strPPID);
+ DDX_Text(pDX, IDC_EDIT_DESC, m_strDesc);
}
BEGIN_MESSAGE_MAP(CRecipeDeviceBindDlg, CDialogEx)
- ON_WM_CLOSE()
- ON_WM_SIZE()
- ON_BN_CLICKED(IDOK, &CRecipeDeviceBindDlg::OnBnClickedOk)
+ ON_WM_CLOSE()
+ ON_WM_SIZE()
+ ON_BN_CLICKED(IDOK, &CRecipeDeviceBindDlg::OnBnClickedOk)
END_MESSAGE_MAP()
@@ -159,62 +165,62 @@
CDialogEx::OnInitDialog();
// 璁剧疆瀵硅瘽妗嗘爣棰�
- SetWindowText(m_recipe.vecDeviceList.empty() ? _T("鏂板缓閰嶆柟") : _T("缂栬緫閰嶆柟"));
+ SetWindowText(m_recipe.vecDeviceList.empty() ? _T("鏂板缓閰嶆柟") : _T("缂栬緫閰嶆柟"));
// 鍒涘缓鍔ㄦ�佹帶浠跺瓧浣�
- if (!m_font.m_hObject) {
- CFont* pDlgFont = GetFont();
- LOGFONT lf;
- if (pDlgFont && pDlgFont->GetLogFont(&lf)) {
- lf.lfHeight = -16;
- m_font.CreateFontIndirect(&lf);
- }
- }
+ if (!m_font.m_hObject) {
+ CFont* pDlgFont = GetFont();
+ LOGFONT lf;
+ if (pDlgFont && pDlgFont->GetLogFont(&lf)) {
+ lf.lfHeight = -16;
+ m_font.CreateFontIndirect(&lf);
+ }
+ }
- // 璁$畻鍧愭爣
- CRect rDesc;
- int nXStart = 30, nYStart = 30, nTotalControlWidth = 340;
- if (auto* pWndDesc = GetDlgItem(IDC_STATIC_DESC)) {
- pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc);
- nXStart = rDesc.left;
- }
- if (auto* pWndEdit = GetDlgItem(IDC_EDIT_DESC)) {
- pWndEdit->GetWindowRect(&rDesc); ScreenToClient(&rDesc);
- nYStart = rDesc.bottom + 20;
- }
- CRect rClient; GetClientRect(&rClient);
- nTotalControlWidth = rClient.Width() - nXStart * 2;
- const int nRowHeight = 30;
+ // 璁$畻鍧愭爣
+ CRect rDesc;
+ int nXStart = 30, nYStart = 30, nTotalControlWidth = 340;
+ if (auto* pWndDesc = GetDlgItem(IDC_STATIC_DESC)) {
+ pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc);
+ nXStart = rDesc.left;
+ }
+ if (auto* pWndEdit = GetDlgItem(IDC_EDIT_DESC)) {
+ pWndEdit->GetWindowRect(&rDesc); ScreenToClient(&rDesc);
+ nYStart = rDesc.bottom + 20;
+ }
+ CRect rClient; GetClientRect(&rClient);
+ nTotalControlWidth = rClient.Width() - nXStart * 2;
+ const int nRowHeight = 30;
- // 娓呯┖鏃ф帶浠�
- ReleaseDeviceControls();
+ // 娓呯┖鏃ф帶浠�
+ ReleaseDeviceControls();
- // 鍒涘缓鏂版帶浠�
- CreateDeviceControls(nXStart, nYStart, nTotalControlWidth, nRowHeight);
+ // 鍒涘缓鏂版帶浠�
+ CreateDeviceControls(nXStart, nYStart, nTotalControlWidth, nRowHeight);
- auto& master = theApp.m_model.getMaster();
+ auto& master = theApp.m_model.getMaster();
- // 濉厖鍐呭
- if (m_recipe.vecDeviceList.empty()) {
- // 鏂板缓
- for (size_t i = 0; i < g_vecBindDevices.size(); ++i) {
- const auto& meta = g_vecBindDevices[i];
- FillDeviceInfo((int)i, meta.nDeviceID, meta.strDeviceName);
- }
- }
- else {
- // 缂栬緫
- m_strPPID = CA2T(m_recipe.strPPID.c_str());
- m_strDesc = CA2T(m_recipe.strDescription.c_str());
- UpdateData(FALSE);
+ // 濉厖鍐呭
+ if (m_recipe.vecDeviceList.empty()) {
+ // 鏂板缓
+ for (size_t i = 0; i < g_vecBindDevices.size(); ++i) {
+ const auto& meta = g_vecBindDevices[i];
+ FillDeviceInfo((int)i, meta.nDeviceID, meta.strDeviceName);
+ }
+ }
+ else {
+ // 缂栬緫
+ m_strPPID = CA2T(m_recipe.strPPID.c_str());
+ m_strDesc = CA2T(m_recipe.strDescription.c_str());
+ UpdateData(FALSE);
- for (size_t i = 0; i < m_recipe.vecDeviceList.size() && i < m_vecDevices.size(); ++i) {
- const auto& d = m_recipe.vecDeviceList[i];
- FillDeviceInfo((int)i, d.nDeviceID, d.strDeviceName.c_str(), d.nRecipeID);
- }
- }
+ for (size_t i = 0; i < m_recipe.vecDeviceList.size() && i < m_vecDevices.size(); ++i) {
+ const auto& d = m_recipe.vecDeviceList[i];
+ FillDeviceInfo((int)i, d.nDeviceID, d.strDeviceName.c_str(), d.nRecipeID);
+ }
+ }
- CenterWindow();
+ CenterWindow();
return TRUE; // return TRUE unless you set the focus to a control
// 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
@@ -222,53 +228,53 @@
void CRecipeDeviceBindDlg::OnClose()
{
- // TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
- CDialogEx::OnClose();
+ // TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
+ CDialogEx::OnClose();
- // 娓呯悊鎺т欢
- ReleaseDeviceControls();
+ // 娓呯悊鎺т欢
+ ReleaseDeviceControls();
}
void CRecipeDeviceBindDlg::OnSize(UINT nType, int cx, int cy)
{
- CDialogEx::OnSize(nType, cx, cy);
+ CDialogEx::OnSize(nType, cx, cy);
- // TODO: 鍦ㄦ澶勬坊鍔犳秷鎭鐞嗙▼搴忎唬鐮�
+ // TODO: 鍦ㄦ澶勬坊鍔犳秷鎭鐞嗙▼搴忎唬鐮�
}
void CRecipeDeviceBindDlg::OnBnClickedOk()
{
- // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
- UpdateData(TRUE);
+ // TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+ UpdateData(TRUE);
- // 鏀堕泦鎵�鏈夎澶囨槧灏�
- m_recipe.vecDeviceList.clear();
- for (const auto& dev : m_vecDevices) {
- DeviceRecipe info;
- CString strID, strName;
- dev.editDeviceID->GetWindowText(strID);
- dev.editDeviceName->GetWindowText(strName);
+ // 鏀堕泦鎵�鏈夎澶囨槧灏�
+ m_recipe.vecDeviceList.clear();
+ for (const auto& dev : m_vecDevices) {
+ DeviceRecipe info;
+ CString strID, strName;
+ dev.editDeviceID->GetWindowText(strID);
+ dev.editDeviceName->GetWindowText(strName);
- int sel = dev.comboRecipeID->GetCurSel();
- info.nRecipeID = -1;
- if (sel != CB_ERR) {
- info.nRecipeID = (int)dev.comboRecipeID->GetItemData(sel);
- }
- info.nDeviceID = _ttoi(strID);
- info.strDeviceName = CT2A(strName);
+ int sel = dev.comboRecipeID->GetCurSel();
+ info.nRecipeID = -1;
+ if (sel != CB_ERR) {
+ info.nRecipeID = (int)dev.comboRecipeID->GetItemData(sel);
+ }
+ info.nDeviceID = _ttoi(strID);
+ info.strDeviceName = CT2A(strName);
- m_recipe.vecDeviceList.push_back(info);
- }
+ m_recipe.vecDeviceList.push_back(info);
+ }
- // 妫�鏌� PPID 鏄惁涓虹┖
- if (m_strPPID.IsEmpty()) {
- AfxMessageBox(_T("閰嶆柟 PPID 涓嶈兘涓虹┖"));
- return;
- }
+ // 妫�鏌� PPID 鏄惁涓虹┖
+ if (m_strPPID.IsEmpty()) {
+ AfxMessageBox(_T("閰嶆柟 PPID 涓嶈兘涓虹┖"));
+ return;
+ }
- // PPID鍜屾弿杩�
- m_recipe.strPPID = CT2A(m_strPPID);
- m_recipe.strDescription = CT2A(m_strDesc);
+ // PPID鍜屾弿杩�
+ m_recipe.strPPID = CT2A(m_strPPID);
+ m_recipe.strDescription = CT2A(m_strDesc);
- CDialogEx::OnOK();
+ CDialogEx::OnOK();
}
diff --git a/SourceCode/Bond/Servo/RecipeManager.cpp b/SourceCode/Bond/Servo/RecipeManager.cpp
index 5928d57..bc44b96 100644
--- a/SourceCode/Bond/Servo/RecipeManager.cpp
+++ b/SourceCode/Bond/Servo/RecipeManager.cpp
@@ -1,4 +1,4 @@
-#include "stdafx.h"
+锘�#include "stdafx.h"
#include "RecipeManager.h"
#include <sstream>
#include <iomanip>
@@ -8,408 +8,453 @@
std::recursive_mutex RecipeManager::m_mutex;
RecipeManager& RecipeManager::getInstance() {
- static RecipeManager instance;
- return instance;
+ static RecipeManager instance;
+ return instance;
}
RecipeManager::RecipeManager() {
- m_pDB = new BL::SQLiteDatabase();
+ m_pDB = new BL::SQLiteDatabase();
}
RecipeManager::~RecipeManager() {
- if (m_pDB) {
- delete m_pDB;
- m_pDB = nullptr;
- }
+ if (m_pDB) {
+ delete m_pDB;
+ m_pDB = nullptr;
+ }
}
bool RecipeManager::initRecipeTable() {
- char szPath[MAX_PATH];
- GetModuleFileNameA(NULL, szPath, MAX_PATH);
- std::string exePath(szPath);
- std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
- CreateDirectoryA(dbDir.c_str(), NULL);
+ char szPath[MAX_PATH];
+ GetModuleFileNameA(NULL, szPath, MAX_PATH);
+ std::string exePath(szPath);
+ std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
+ CreateDirectoryA(dbDir.c_str(), NULL);
- std::string dbPath = dbDir + "\\RecipeManager.db";
- if (!m_pDB->connect(dbPath, true)) {
- return false;
- }
+ std::string dbPath = dbDir + "\\RecipeManager.db";
+ if (!m_pDB->connect(dbPath, true)) {
+ return false;
+ }
- // 启用 SQLite 的外键约束支持
- if (!m_pDB->executeQuery("PRAGMA foreign_keys = ON;")) {
- std::cerr << "Failed to enable foreign keys." << std::endl;
- return false;
- }
+ // 鍚敤 SQLite 鐨勫閿害鏉熸敮鎸�
+ if (!m_pDB->executeQuery("PRAGMA foreign_keys = ON;")) {
+ std::cerr << "Failed to enable foreign keys." << std::endl;
+ return false;
+ }
- const std::string createRecipeTable = R"(
- CREATE TABLE IF NOT EXISTS recipes (
- ppid TEXT PRIMARY KEY NOT NULL,
- description TEXT,
- create_time TEXT DEFAULT (datetime('now', 'localtime'))
- );
- )";
+ const std::string createRecipeTable = R"(
+ CREATE TABLE IF NOT EXISTS recipes (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ ppid TEXT NOT NULL UNIQUE,
+ description TEXT,
+ create_time TEXT DEFAULT (datetime('now', 'localtime'))
+ );
+ )";
- const std::string createDeviceTable = R"(
- CREATE TABLE IF NOT EXISTS recipe_devices (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- ppid TEXT NOT NULL,
- device_id INTEGER NOT NULL,
- device_name TEXT NOT NULL,
- recipe_id INTEGER NOT NULL,
- FOREIGN KEY(ppid) REFERENCES recipes(ppid) ON DELETE CASCADE ON UPDATE CASCADE,
- UNIQUE (ppid, device_id),
- UNIQUE (ppid, device_name)
- );
- )";
+ const std::string createDeviceTable = R"(
+ CREATE TABLE IF NOT EXISTS recipe_devices (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ ppid TEXT NOT NULL,
+ device_id INTEGER NOT NULL,
+ device_name TEXT NOT NULL,
+ recipe_id INTEGER NOT NULL,
+ recipe_name TEXT NOT NULL,
+ FOREIGN KEY(ppid) REFERENCES recipes(ppid) ON DELETE CASCADE ON UPDATE CASCADE,
+ UNIQUE (ppid, device_id),
+ UNIQUE (ppid, device_name)
+ );
+ )";
- return m_pDB->executeQuery(createRecipeTable) && m_pDB->executeQuery(createDeviceTable);
+ return m_pDB->executeQuery(createRecipeTable) && m_pDB->executeQuery(createDeviceTable);
}
void RecipeManager::termRecipeTable() {
- if (!m_pDB) {
- return;
- }
+ if (!m_pDB) {
+ return;
+ }
- m_pDB->disconnect();
+ m_pDB->disconnect();
}
bool RecipeManager::destroyRecipeTable() {
- if (!m_pDB) {
+ if (!m_pDB) {
return false;
- }
+ }
- return m_pDB->executeQuery("DROP TABLE IF EXISTS recipe_devices;") && m_pDB->executeQuery("DROP TABLE IF EXISTS recipes;");
+ return m_pDB->executeQuery("DROP TABLE IF EXISTS recipe_devices;") && m_pDB->executeQuery("DROP TABLE IF EXISTS recipes;");
}
bool RecipeManager::ppidExists(const std::string& ppid) {
- std::ostringstream oss;
- oss << "SELECT COUNT(*) FROM recipes WHERE ppid = '" << ppid << "';";
- auto result = m_pDB->fetchResults(oss.str());
- return (!result.empty() && !result[0].empty() && result[0][0] != "0");
+ std::ostringstream oss;
+ oss << "SELECT COUNT(*) FROM recipes WHERE ppid = '" << ppid << "';";
+ auto result = m_pDB->fetchResults(oss.str());
+ return (!result.empty() && !result[0].empty() && result[0][0] != "0");
}
bool RecipeManager::deviceExists(const std::string& ppid, int nDeviceID) {
- std::ostringstream oss;
- oss << "SELECT COUNT(*) FROM recipe_devices WHERE ppid = '" << ppid
- << "' AND device_id = " << nDeviceID << ";";
- auto result = m_pDB->fetchResults(oss.str());
- return (!result.empty() && !result[0].empty() && result[0][0] != "0");
+ std::ostringstream oss;
+ oss << "SELECT COUNT(*) FROM recipe_devices WHERE ppid = '" << ppid
+ << "' AND device_id = " << nDeviceID << ";";
+ auto result = m_pDB->fetchResults(oss.str());
+ return (!result.empty() && !result[0].empty() && result[0][0] != "0");
}
bool RecipeManager::addRecipe(const RecipeInfo& recipe) {
- if (!m_pDB || recipe.strPPID.empty() || recipe.vecDeviceList.empty()) {
- std::cerr << "[AddRecipe] Invalid input." << std::endl;
- return false;
- }
+ if (!m_pDB || recipe.strPPID.empty() || recipe.vecDeviceList.empty()) {
+ std::cerr << "[AddRecipe] Invalid input." << std::endl;
+ return false;
+ }
- std::string strTime = recipe.strCreateTime;
- if (strTime.empty()) {
- std::time_t now = std::time(nullptr);
- std::tm tm_now = {};
- localtime_s(&tm_now, &now);
- std::stringstream ss;
- ss << std::put_time(&tm_now, "%Y-%m-%d %H:%M:%S");
- strTime = ss.str();
- }
+ std::string strTime = recipe.strCreateTime;
+ if (strTime.empty()) {
+ std::time_t now = std::time(nullptr);
+ std::tm tm_now = {};
+ localtime_s(&tm_now, &now);
+ std::stringstream ss;
+ ss << std::put_time(&tm_now, "%Y-%m-%d %H:%M:%S");
+ strTime = ss.str();
+ }
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
- // 开始事务
- m_pDB->executeQuery("BEGIN TRANSACTION;");
+ // 寮�濮嬩簨鍔�
+ m_pDB->executeQuery("BEGIN TRANSACTION;");
- std::ostringstream oss;
- oss << "INSERT OR REPLACE INTO recipes (ppid, description, create_time) VALUES ('"
- << recipe.strPPID << "', '"
- << recipe.strDescription << "', '"
- << strTime << "');";
+ std::ostringstream oss;
+ oss << "INSERT OR REPLACE INTO recipes (ppid, description, create_time) VALUES ('"
+ << recipe.strPPID << "', '"
+ << recipe.strDescription << "', '"
+ << strTime << "');";
- if (!m_pDB->executeQuery(oss.str())) {
- std::cerr << "[AddRecipe] Failed to insert recipe: " << recipe.strPPID << std::endl;
- m_pDB->executeQuery("ROLLBACK;");
- return false;
- }
+ if (!m_pDB->executeQuery(oss.str())) {
+ std::cerr << "[AddRecipe] Failed to insert recipe: " << recipe.strPPID << std::endl;
+ m_pDB->executeQuery("ROLLBACK;");
+ return false;
+ }
- for (const auto& device : recipe.vecDeviceList) {
- std::ostringstream devSql;
- devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('"
- << recipe.strPPID << "', "
- << device.nDeviceID << ", '"
- << device.strDeviceName << "', "
- << device.nRecipeID << ");";
+ for (const auto& device : recipe.vecDeviceList) {
+ std::ostringstream devSql;
+ devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id, recipe_name) VALUES ('"
+ << recipe.strPPID << "', "
+ << device.nDeviceID << ", '"
+ << device.strDeviceName << "', "
+ << device.nRecipeID << ", '"
+ << device.strRecipeName << "');";
- if (!m_pDB->executeQuery(devSql.str())) {
- std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl;
- m_pDB->executeQuery("ROLLBACK;");
- return false;
- }
- }
- // 提交事务
- m_pDB->executeQuery("COMMIT;");
- return true;
+ if (!m_pDB->executeQuery(devSql.str())) {
+ std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl;
+ m_pDB->executeQuery("ROLLBACK;");
+ return false;
+ }
+ }
+
+ // 鎻愪氦浜嬪姟
+ m_pDB->executeQuery("COMMIT;");
+ return true;
}
bool RecipeManager::addRecipeDevice(const std::string& ppid, const DeviceRecipe& device) {
- if (!m_pDB || ppid.empty() || device.nDeviceID <= 0 || device.nRecipeID <= 0) {
- std::cerr << "[addRecipeDevice] Invalid input." << std::endl;
- return false;
- }
+ if (!m_pDB || ppid.empty() || device.nDeviceID <= 0 || device.nRecipeID <= 0) {
+ std::cerr << "[addRecipeDevice] Invalid input." << std::endl;
+ return false;
+ }
- // 检查 ppid 是否存在
+ // 妫�鏌� ppid 鏄惁瀛樺湪
if (!ppidExists(ppid)) {
std::cerr << "[addRecipeDevice] PPID does not exist: " << ppid << std::endl;
return false;
}
- // 插入设备记录
- std::ostringstream oss;
- oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('"
- << ppid << "', "
- << device.nDeviceID << ", '"
- << device.strDeviceName << "', "
- << device.nRecipeID << ");";
+ // 鎻掑叆璁惧璁板綍
+ std::ostringstream oss;
+ oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id, recipe_name) VALUES ('"
+ << ppid << "', "
+ << device.nDeviceID << ", '"
+ << device.strDeviceName << "', "
+ << device.nRecipeID << ", '"
+ << device.strRecipeName << "');";
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
- return m_pDB->executeQuery(oss.str());
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ return m_pDB->executeQuery(oss.str());
}
bool RecipeManager::deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID) {
- if (!m_pDB || ppid.empty() || nDeviceID <= 0) {
- std::cerr << "[deleteRecipeDeviceByID] Invalid input." << std::endl;
- return false;
- }
+ if (!m_pDB || ppid.empty() || nDeviceID <= 0) {
+ std::cerr << "[deleteRecipeDeviceByID] Invalid input." << std::endl;
+ return false;
+ }
- std::ostringstream oss;
- oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";";
+ std::ostringstream oss;
+ oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";";
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
- return m_pDB->executeQuery(oss.str());
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ return m_pDB->executeQuery(oss.str());
}
bool RecipeManager::deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName) {
- if (!m_pDB || ppid.empty() || strDeviceName.empty()) {
- std::cerr << "[deleteRecipeDeviceByName] Invalid input." << std::endl;
- return false;
- }
+ if (!m_pDB || ppid.empty() || strDeviceName.empty()) {
+ std::cerr << "[deleteRecipeDeviceByName] Invalid input." << std::endl;
+ return false;
+ }
- std::ostringstream oss;
- oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';";
+ std::ostringstream oss;
+ oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';";
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
- return m_pDB->executeQuery(oss.str());
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ return m_pDB->executeQuery(oss.str());
}
std::vector<RecipeInfo> RecipeManager::getAllRecipes() {
- if (!m_pDB) {
- return {};
- }
+ if (!m_pDB) {
+ return {};
+ }
- std::vector<RecipeInfo> recipes;
- auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes;");
+ std::vector<RecipeInfo> recipes;
+ auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes;");
- for (const auto& row : rows) {
- RecipeInfo info;
- info.strPPID = row[0];
- info.strDescription = row[1];
- info.strCreateTime = row[2];
+ for (const auto& row : rows) {
+ RecipeInfo info;
+ info.strPPID = row[0];
+ info.strDescription = row[1];
+ info.strCreateTime = row[2];
- std::ostringstream devQuery;
- devQuery << "SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" << info.strPPID << "';";
- auto devs = m_pDB->fetchResults(devQuery.str());
+ std::ostringstream devQuery;
+ devQuery << "SELECT device_id, device_name, recipe_id, recipe_name FROM recipe_devices WHERE ppid = '" << info.strPPID << "'ORDER BY id ASC;";
+ auto devs = m_pDB->fetchResults(devQuery.str());
- for (const auto& dev : devs) {
- DeviceRecipe dr;
- try {
- dr.nDeviceID = std::stoi(dev[0]);
- dr.strDeviceName = dev[1];
- dr.nRecipeID = std::stoi(dev[2]);
- }
- catch (...) {
- std::cerr << "Invalid data in recipe_devices for PPID: " << info.strPPID << std::endl;
- continue;
- }
- info.vecDeviceList.push_back(dr);
- }
- recipes.push_back(info);
- }
+ for (const auto& dev : devs) {
+ DeviceRecipe dr;
+ try {
+ dr.nDeviceID = std::stoi(dev[0]);
+ dr.strDeviceName = dev[1];
+ dr.nRecipeID = std::stoi(dev[2]);
+ dr.strRecipeName = dev[3];
+ }
+ catch (...) {
+ std::cerr << "Invalid data in recipe_devices for PPID: " << info.strPPID << std::endl;
+ continue;
+ }
+ info.vecDeviceList.push_back(dr);
+ }
+ recipes.push_back(info);
+ }
- return recipes;
+ return recipes;
}
std::vector<RecipeInfo> RecipeManager::getRecipesByKeyword(const std::string& keyword) {
- std::vector<RecipeInfo> recipes;
- if (!m_pDB || keyword.empty()) {
- return recipes;
- }
+ std::vector<RecipeInfo> recipes;
+ if (!m_pDB || keyword.empty()) {
+ return recipes;
+ }
- std::ostringstream query;
- query << "SELECT ppid, description, create_time FROM recipes "
- << "WHERE ppid LIKE '%" << keyword << "%' OR description LIKE '%" << keyword << "%';";
+ std::ostringstream query;
+ query << "SELECT ppid, description, create_time FROM recipes "
+ << "WHERE ppid LIKE '%" << keyword << "%' OR description LIKE '%" << keyword << "%';";
- auto rows = m_pDB->fetchResults(query.str());
- for (const auto& row : rows) {
- if (row.size() >= 3) {
- RecipeInfo info;
- info.strPPID = row[0];
- info.strDescription = row[1];
- info.strCreateTime = row[2];
- recipes.push_back(info);
- }
- }
- return recipes;
+ auto rows = m_pDB->fetchResults(query.str());
+ for (const auto& row : rows) {
+ if (row.size() >= 3) {
+ RecipeInfo info;
+ info.strPPID = row[0];
+ info.strDescription = row[1];
+ info.strCreateTime = row[2];
+ recipes.push_back(info);
+ }
+ }
+ return recipes;
}
std::vector<std::string> RecipeManager::getAllPPID() const {
- std::vector<std::string> vecPPID;
+ std::vector<std::string> vecPPID;
- if (!m_pDB) {
- return vecPPID;
- }
+ if (!m_pDB) {
+ return vecPPID;
+ }
- const std::string query = "SELECT ppid FROM recipes ORDER BY ppid;";
- auto result = m_pDB->fetchResults(query);
+ const std::string query = "SELECT ppid FROM recipes ORDER BY ppid;";
+ auto result = m_pDB->fetchResults(query);
- for (const auto& row : result) {
- if (!row.empty()) {
- vecPPID.push_back(row[0]);
- }
- }
+ for (const auto& row : result) {
+ if (!row.empty()) {
+ vecPPID.push_back(row[0]);
+ }
+ }
- return vecPPID;
+ return vecPPID;
+}
+
+std::string RecipeManager::getPPIDById(int nId) {
+ if (!m_pDB) {
+ return {};
+ }
+
+ std::ostringstream query;
+ query << "SELECT ppid FROM recipes WHERE id = " << nId << ";";
+
+ auto rows = m_pDB->fetchResults(query.str());
+ if (rows.empty() || rows[0].empty()) {
+ return {};
+ }
+
+ return rows[0][0];
+}
+
+int RecipeManager::getIdByPPID(const std::string& ppid) {
+ if (!m_pDB) {
+ return -1;
+ }
+
+ std::ostringstream query;
+ query << "SELECT id FROM recipes WHERE ppid = '" << ppid << "';";
+
+ auto rows = m_pDB->fetchResults(query.str());
+ if (rows.empty() || rows[0].empty()) {
+ return -1;
+ }
+
+ try {
+ return std::stoi(rows[0][0]);
+ }
+ catch (...) {
+ std::cerr << "Invalid id value for PPID: " << ppid << std::endl;
+ return -1;
+ }
}
RecipeInfo RecipeManager::getRecipeByPPID(const std::string& ppid) {
- RecipeInfo info;
- auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes WHERE ppid = '" + ppid + "';");
- if (rows.empty()) {
- return info;
- }
+ RecipeInfo info;
+ auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes WHERE ppid = '" + ppid + "';");
+ if (rows.empty()) {
+ return info;
+ }
- info.strPPID = rows[0][0];
- info.strDescription = rows[0][1];
- info.strCreateTime = rows[0][2];
+ info.strPPID = rows[0][0];
+ info.strDescription = rows[0][1];
+ info.strCreateTime = rows[0][2];
- auto devs = m_pDB->fetchResults("SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" + ppid + "';");
- for (const auto& dev : devs) {
- DeviceRecipe dr;
- try {
- dr.nDeviceID = std::stoi(dev[0]);
- dr.strDeviceName = dev[1];
- dr.nRecipeID = std::stoi(dev[2]);
- }
- catch (...) {
- std::cerr << "Invalid data in recipe_devices for PPID: " << ppid << std::endl;
- continue;
- }
- info.vecDeviceList.push_back(dr);
- }
- return info;
+ auto devs = m_pDB->fetchResults("SELECT device_id, device_name, recipe_id, recipe_name FROM recipe_devices WHERE ppid = '" + ppid + "';");
+ for (const auto& dev : devs) {
+ DeviceRecipe dr;
+ try {
+ dr.nDeviceID = std::stoi(dev[0]);
+ dr.strDeviceName = dev[1];
+ dr.nRecipeID = std::stoi(dev[2]);
+ dr.strRecipeName = dev[3];
+ }
+ catch (...) {
+ std::cerr << "Invalid data in recipe_devices for PPID: " << ppid << std::endl;
+ continue;
+ }
+ info.vecDeviceList.push_back(dr);
+ }
+ return info;
}
int RecipeManager::getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID) {
- if (!m_pDB || ppid.empty() || nDeviceID <= 0) {
- return -1;
- }
+ if (!m_pDB || ppid.empty() || nDeviceID <= 0) {
+ return -1;
+ }
- std::ostringstream query;
- query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";";
+ std::ostringstream query;
+ query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";";
- auto result = m_pDB->fetchResults(query.str());
- if (!result.empty() && !result[0].empty()) {
- try {
- return std::stoi(result[0][0]);
- }
- catch (...) {
- return -1;
- }
- }
- return -1;
+ auto result = m_pDB->fetchResults(query.str());
+ if (!result.empty() && !result[0].empty()) {
+ try {
+ return std::stoi(result[0][0]);
+ }
+ catch (...) {
+ return -1;
+ }
+ }
+ return -1;
}
int RecipeManager::getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName) {
- if (!m_pDB || ppid.empty() || strDeviceName.empty()) {
- return -1;
- }
+ if (!m_pDB || ppid.empty() || strDeviceName.empty()) {
+ return -1;
+ }
- std::ostringstream query;
- query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';";
+ std::ostringstream query;
+ query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';";
- auto result = m_pDB->fetchResults(query.str());
- if (!result.empty() && !result[0].empty()) {
- try {
- return std::stoi(result[0][0]);
- }
- catch (...) {
- return -1;
- }
- }
- return -1;
+ auto result = m_pDB->fetchResults(query.str());
+ if (!result.empty() && !result[0].empty()) {
+ try {
+ return std::stoi(result[0][0]);
+ }
+ catch (...) {
+ return -1;
+ }
+ }
+ return -1;
}
bool RecipeManager::deleteRecipeByPPID(const std::string& ppid) {
- if (!m_pDB) {
- return false;
- }
+ if (!m_pDB) {
+ return false;
+ }
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
- return m_pDB->executeQuery("DELETE FROM recipes WHERE ppid = '" + ppid + "';");
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ return m_pDB->executeQuery("DELETE FROM recipes WHERE ppid = '" + ppid + "';");
}
bool RecipeManager::updateRecipe(const RecipeInfo& recipe) {
- if (!m_pDB) {
- return false;
- }
+ if (!m_pDB) {
+ return false;
+ }
if (recipe.strPPID.empty()) {
std::cerr << "Recipe PPID cannot be empty." << std::endl;
return false;
}
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
- deleteRecipeByPPID(recipe.strPPID);
- return addRecipe(recipe);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ deleteRecipeByPPID(recipe.strPPID);
+ return addRecipe(recipe);
}
bool RecipeManager::updatePPID(const std::string& oldPPID, const std::string& newPPID) {
- if (!m_pDB || oldPPID.empty() || newPPID.empty()) {
- std::cerr << "[updatePPID] Invalid input." << std::endl;
- return false;
- }
+ if (!m_pDB || oldPPID.empty() || newPPID.empty()) {
+ std::cerr << "[updatePPID] Invalid input." << std::endl;
+ return false;
+ }
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
- // 检查是否已经存在相同的 newPPID
- auto check = m_pDB->fetchResults("SELECT COUNT(*) FROM recipes WHERE ppid = '" + newPPID + "';");
- if (!check.empty() && !check[0].empty() && check[0][0] != "0") {
- std::cerr << "[updatePPID] New PPID already exists: " << newPPID << std::endl;
- return false;
- }
+ // 妫�鏌ユ槸鍚﹀凡缁忓瓨鍦ㄧ浉鍚岀殑 newPPID
+ auto check = m_pDB->fetchResults("SELECT COUNT(*) FROM recipes WHERE ppid = '" + newPPID + "';");
+ if (!check.empty() && !check[0].empty() && check[0][0] != "0") {
+ std::cerr << "[updatePPID] New PPID already exists: " << newPPID << std::endl;
+ return false;
+ }
- m_pDB->executeQuery("BEGIN TRANSACTION;");
+ m_pDB->executeQuery("BEGIN TRANSACTION;");
- std::ostringstream sql;
- sql << "UPDATE recipes SET ppid = '" << newPPID << "' WHERE ppid = '" << oldPPID << "';";
- if (!m_pDB->executeQuery(sql.str())) {
- std::cerr << "[updatePPID] Failed to update recipes table." << std::endl;
- m_pDB->executeQuery("ROLLBACK;");
- return false;
- }
+ std::ostringstream sql;
+ sql << "UPDATE recipes SET ppid = '" << newPPID << "' WHERE ppid = '" << oldPPID << "';";
+ if (!m_pDB->executeQuery(sql.str())) {
+ std::cerr << "[updatePPID] Failed to update recipes table." << std::endl;
+ m_pDB->executeQuery("ROLLBACK;");
+ return false;
+ }
- m_pDB->executeQuery("COMMIT;");
- return true;
+ m_pDB->executeQuery("COMMIT;");
+ return true;
}
bool RecipeManager::updateDescription(const std::string& ppid, const std::string& newDescription) {
- if (!m_pDB || ppid.empty()) {
- std::cerr << "[updateRecipeDescription] Invalid input." << std::endl;
- return false;
- }
+ if (!m_pDB || ppid.empty()) {
+ std::cerr << "[updateRecipeDescription] Invalid input." << std::endl;
+ return false;
+ }
- std::ostringstream oss;
- oss << "UPDATE recipes SET description = '" << newDescription << "' WHERE ppid = '" << ppid << "';";
+ std::ostringstream oss;
+ oss << "UPDATE recipes SET description = '" << newDescription << "' WHERE ppid = '" << ppid << "';";
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
- return m_pDB->executeQuery(oss.str());
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ return m_pDB->executeQuery(oss.str());
}
bool RecipeManager::updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID) {
@@ -418,7 +463,7 @@
}
std::ostringstream query;
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
query << "UPDATE recipe_devices SET recipe_id = " << nNewRecipeID
<< " WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";";
return m_pDB->executeQuery(query.str());
@@ -429,98 +474,222 @@
return false;
}
std::ostringstream query;
- std::lock_guard<std::recursive_mutex> lock(m_mutex);
+ std::lock_guard<std::recursive_mutex> lock(m_mutex);
query << "UPDATE recipe_devices SET recipe_id = " << nNewRecipeID
<< " WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';";
return m_pDB->executeQuery(query.str());
}
+bool RecipeManager::addDeviceRecipe(const std::string& strDeviceName, int nID, const std::string& strName, const std::string& strPara) {
+ if (!m_pDB || strDeviceName.empty() || nID <= 0 || strName.empty() || strPara.empty()) {
+ return false;
+ }
+
+ std::ostringstream sql;
+ sql << "CREATE TABLE IF NOT EXISTS " << strDeviceName << "_Recipes ("
+ << "recipe_id INTEGER PRIMARY KEY,"
+ << "recipe_name TEXT NOT NULL,"
+ << "recipe_para TEXT NOT NULL"
+ << ");";
+ m_pDB->executeQuery(sql.str());
+
+ std::ostringstream ins;
+ ins << "INSERT OR REPLACE INTO " << strDeviceName
+ << "_Recipes (recipe_id, recipe_name, recipe_para) VALUES ("
+ << nID << ", '" << strName << "', '" << strPara << "');";
+
+ std::lock_guard<std::recursive_mutex> lk(m_mutex);
+ return m_pDB->executeQuery(ins.str());
+}
+
+bool RecipeManager::updateDeviceRecipeName(const std::string& strDeviceName, int nID, const std::string& strNewName) {
+ if (!m_pDB || strDeviceName.empty() || nID <= 0 || strNewName.empty()) {
+ return false;
+ }
+
+ std::ostringstream sql;
+ sql << "UPDATE " << strDeviceName << "_Recipes SET recipe_name='" << strNewName
+ << "' WHERE recipe_id=" << nID << ";";
+
+ std::lock_guard<std::recursive_mutex> lk(m_mutex);
+ return m_pDB->executeQuery(sql.str());
+}
+
+bool RecipeManager::updateDeviceRecipePara(const std::string& strDeviceName, int nID, const std::string& strNewPara) {
+ if (!m_pDB || strDeviceName.empty() || nID <= 0) {
+ return false;
+ }
+
+ std::ostringstream sql;
+ sql << "UPDATE " << strDeviceName << "_Recipes SET recipe_para='" << strNewPara
+ << "' WHERE recipe_id=" << nID << ";";
+
+ std::lock_guard<std::recursive_mutex> lk(m_mutex);
+ return m_pDB->executeQuery(sql.str());
+}
+
+std::string RecipeManager::getDeviceRecipeName(const std::string& strDeviceName, int nID) {
+ if (!m_pDB || strDeviceName.empty() || nID <= 0) {
+ return "";
+ }
+
+ std::ostringstream sql;
+ sql << "SELECT recipe_name FROM " << strDeviceName << "_Recipes "
+ << "WHERE recipe_id=" << nID << " LIMIT 1;";
+
+ auto rows = m_pDB->fetchResults(sql.str());
+ if (!rows.empty() && !rows[0].empty()) {
+ return rows[0][0];
+ }
+ return "";
+}
+
+std::string RecipeManager::getDeviceRecipePara(const std::string& strDeviceName, int nID) {
+ if (!m_pDB || strDeviceName.empty() || nID <= 0) {
+ return "";
+ }
+
+ std::ostringstream sql;
+ sql << "SELECT recipe_para FROM " << strDeviceName << "_Recipes "
+ << "WHERE recipe_id=" << nID << " LIMIT 1;";
+
+ auto rows = m_pDB->fetchResults(sql.str());
+ if (!rows.empty() && !rows[0].empty()) {
+ return rows[0][0];
+ }
+ return "";
+}
+
+bool RecipeManager::deleteDeviceRecipe(const std::string& strDeviceName, int nID) {
+ if (!m_pDB || strDeviceName.empty() || nID <= 0) {
+ return false;
+ }
+
+ std::ostringstream sql;
+ sql << "DELETE FROM " << strDeviceName << "_Recipes WHERE recipe_id=" << nID << ";";
+
+ std::lock_guard<std::recursive_mutex> lk(m_mutex);
+ return m_pDB->executeQuery(sql.str());
+}
+
+std::vector<std::pair<int, std::string>> RecipeManager::getDeviceRecipes(const std::string& strDeviceName) {
+ std::vector<std::pair<int, std::string>> out;
+ if (!m_pDB || strDeviceName.empty()) {
+ return out;
+ }
+
+ std::ostringstream sql;
+ sql << "SELECT recipe_id, recipe_name FROM " << strDeviceName << "_Recipes ORDER BY recipe_id;";
+
+ auto rows = m_pDB->fetchResults(sql.str());
+ for (const auto& r : rows) {
+ if (r.size() < 2) continue;
+ try {
+ int id = std::stoi(r[0]);
+ out.emplace_back(id, r[1]);
+ }
+ catch (...) {}
+ }
+ return out;
+}
+
void RecipeManager::insertMockData() {
- if (!m_pDB) {
- return;
- }
+ if (!m_pDB) {
+ return;
+ }
- RecipeInfo recipe;
- recipe.strPPID = "P1001";
- recipe.strDescription = "Main Board Burn-in";
+ RecipeInfo recipe;
+ recipe.strPPID = "P1001";
+ recipe.strDescription = "Main Board Burn-in";
- recipe.vecDeviceList = {
- {1, 101, "Burner A"},
- {2, 102, "Burner B"}
- };
+ recipe.vecDeviceList = {
+ {9, 101, "VacuumBake", "VacuumBake"},
+ {10, 102, "Bonder1", "Bonder1"},
+ {11, 103, "Bonder2", "Bonder2"}
+ };
- addRecipe(recipe);
+ addRecipe(recipe);
+
+ addDeviceRecipe("Bonder1", 101, "鏍囧噯宸ヨ壓", "");
+ addDeviceRecipe("Bonder1", 102, "鏀硅壇宸ヨ壓", "");
+ addDeviceRecipe("Bonder1", 103, "楂橀�熸ā寮�", "");
+
+ addDeviceRecipe("Bonder2", 101, "鏍囧噯宸ヨ壓", "");
+ addDeviceRecipe("Bonder2", 102, "鏀硅壇宸ヨ壓", "");
+ addDeviceRecipe("Bonder2", 103, "楂橀�熸ā寮�", "");
}
bool RecipeManager::readRecipeFile(const std::string& filename) {
- if (!m_pDB) {
- return false;
- }
+ if (!m_pDB) {
+ return false;
+ }
- std::ifstream file(filename);
- if (!file.is_open()) {
- return false;
- }
+ std::ifstream file(filename);
+ if (!file.is_open()) {
+ return false;
+ }
- std::unordered_map<std::string, RecipeInfo> recipeMap;
- std::string line;
- std::getline(file, line); // skip header
+ std::unordered_map<std::string, RecipeInfo> recipeMap;
+ std::string line;
+ std::getline(file, line); // skip header
- while (std::getline(file, line)) {
- std::stringstream ss(line);
- std::string cell;
- std::string ppid, description, createTime;
- DeviceRecipe dev;
+ while (std::getline(file, line)) {
+ std::stringstream ss(line);
+ std::string cell;
+ std::string ppid, description, createTime;
+ DeviceRecipe dev;
- std::getline(ss, ppid, ',');
- std::getline(ss, cell, ',');
- try { dev.nDeviceID = std::stoi(cell); }
- catch (...) { continue; }
- std::getline(ss, dev.strDeviceName, ',');
- std::getline(ss, cell, ',');
- try { dev.nRecipeID = std::stoi(cell); }
- catch (...) { continue; }
- std::getline(ss, description, ',');
- std::getline(ss, createTime, ',');
+ std::getline(ss, ppid, ',');
+ std::getline(ss, cell, ',');
+ try { dev.nDeviceID = std::stoi(cell); }
+ catch (...) { continue; }
+ std::getline(ss, dev.strDeviceName, ',');
+ std::getline(ss, cell, ',');
+ try { dev.nRecipeID = std::stoi(cell); }
+ catch (...) { continue; }
+ std::getline(ss, dev.strRecipeName, ',');
+ std::getline(ss, description, ',');
+ std::getline(ss, createTime, ',');
- auto& recipe = recipeMap[ppid];
- recipe.strPPID = ppid;
- recipe.strDescription = description;
- recipe.strCreateTime = createTime;
- recipe.vecDeviceList.push_back(dev);
- }
+ auto& recipe = recipeMap[ppid];
+ recipe.strPPID = ppid;
+ recipe.strDescription = description;
+ recipe.strCreateTime = createTime;
+ recipe.vecDeviceList.push_back(dev);
+ }
- for (const auto& pair : recipeMap) {
- if (!updateRecipe(pair.second)) {
- std::cerr << "Failed to update recipe from file: " << pair.first << std::endl;
- }
- }
+ for (const auto& pair : recipeMap) {
+ if (!updateRecipe(pair.second)) {
+ std::cerr << "Failed to update recipe from file: " << pair.first << std::endl;
+ }
+ }
- return true;
+ return true;
}
bool RecipeManager::saveRecipeFile(const std::string& filename) {
- if (!m_pDB) {
- return false;
- }
+ if (!m_pDB) {
+ return false;
+ }
- std::ofstream file(filename);
- if (!file.is_open()) {
- return false;
- }
+ std::ofstream file(filename);
+ if (!file.is_open()) {
+ return false;
+ }
- file << "PPID,DeviceID,DeviceName,RecipeID,Description,CreateTime\n";
- auto recipes = getAllRecipes();
- for (const auto& recipe : recipes) {
- for (const auto& dev : recipe.vecDeviceList) {
- file << recipe.strPPID << ","
- << dev.nDeviceID << ","
- << dev.strDeviceName << ","
- << dev.nRecipeID << ","
- << recipe.strDescription << ","
- << recipe.strCreateTime << "\n";
- }
- }
+ file << "PPID,DeviceID,DeviceName,RecipeID,RecipeName,Description,CreateTime\n";
+ auto recipes = getAllRecipes();
+ for (const auto& recipe : recipes) {
+ for (const auto& dev : recipe.vecDeviceList) {
+ file << recipe.strPPID << ","
+ << dev.nDeviceID << ","
+ << dev.strDeviceName << ","
+ << dev.nRecipeID << ","
+ << dev.strRecipeName << ","
+ << recipe.strDescription << ","
+ << recipe.strCreateTime << "\n";
+ }
+ }
- return true;
+ return true;
}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/RecipeManager.h b/SourceCode/Bond/Servo/RecipeManager.h
index c588bb3..70837c0 100644
--- a/SourceCode/Bond/Servo/RecipeManager.h
+++ b/SourceCode/Bond/Servo/RecipeManager.h
@@ -1,4 +1,4 @@
-#ifndef RECIPE_MANAGER_H
+锘�#ifndef RECIPE_MANAGER_H
#define RECIPE_MANAGER_H
#include <string>
@@ -9,111 +9,125 @@
#include "CParam.h"
-// 单个设备配方映射信息
+// 鍗曚釜璁惧閰嶆柟鏄犲皠淇℃伅
struct DeviceRecipe {
- int nDeviceID; // 设备ID
- int nRecipeID; // 子配方ID
- std::string strRecipeName; // 子配方名称
- std::string strDeviceName; // 设备名称
- std::vector<uint8_t> paramsRawData; // 配方原始数据
- std::vector<CParam*> m_params; // 出站时记录参数
+ int nDeviceID; // 璁惧ID
+ int nRecipeID; // 瀛愰厤鏂笽D
+ std::string strRecipeName; // 璁惧鍚嶇О
+ std::string strDeviceName; // 瀛愰厤鏂瑰悕绉�
+ std::vector<uint8_t> paramsRawData; // 鍘熷鍙傛暟鏁版嵁
+ std::vector<CParam*> m_params; // 鍙傛暟瀵硅薄鍒楄〃
};
-// 配方信息
+// 閰嶆柟淇℃伅
struct RecipeInfo {
- std::string strPPID; // 配方ID
- std::string strDescription; // 配方描述
- std::string strCreateTime; // 创建时间
- std::vector<DeviceRecipe> vecDeviceList; // 关联的设备信息列表
+ std::string strPPID; // 閰嶆柟ID
+ std::string strDescription; // 閰嶆柟鎻忚堪
+ std::string strCreateTime; // 鍒涘缓鏃堕棿
+ std::vector<DeviceRecipe> vecDeviceList; // 鍏宠仈鐨勮澶囦俊鎭垪琛�
};
-using RecipeMap = std::unordered_map<std::string, RecipeInfo>; // 按 PPID 映射的配方表
+using RecipeMap = std::unordered_map<std::string, RecipeInfo>; // 鎸� PPID 鏄犲皠鐨勯厤鏂硅〃
class RecipeManager {
public:
- // 获取单例
- static RecipeManager& getInstance();
+ // 鑾峰彇鍗曚緥
+ static RecipeManager& getInstance();
- // 初始化配方数据库
- bool initRecipeTable();
+ // 鍒濆鍖栭厤鏂规暟鎹簱
+ bool initRecipeTable();
- // 销毁表或关闭连接
- void termRecipeTable();
- bool destroyRecipeTable();
+ // 閿�姣佽〃鎴栧叧闂繛鎺�
+ void termRecipeTable();
+ bool destroyRecipeTable();
- // 检查 PPID 是否存在
- bool ppidExists(const std::string& ppid);
+ // 妫�鏌� PPID 鏄惁瀛樺湪
+ bool ppidExists(const std::string& ppid);
- // 检查设备是否存在于指定 PPID 的配方中
+ // 妫�鏌ヨ澶囨槸鍚﹀瓨鍦ㄤ簬鎸囧畾 PPID 鐨勯厤鏂逛腑
bool deviceExists(const std::string& ppid, int nDeviceID);
- // 添加一个配方及其设备映射
- bool addRecipe(const RecipeInfo& recipe);
+ // 娣诲姞涓�涓厤鏂瑰強鍏惰澶囨槧灏�
+ bool addRecipe(const RecipeInfo& recipe);
- // 添加设备到指定配方
- bool addRecipeDevice(const std::string& ppid, const DeviceRecipe& device);
+ // 娣诲姞璁惧鍒版寚瀹氶厤鏂�
+ bool addRecipeDevice(const std::string& ppid, const DeviceRecipe& device);
- // 删除指定 PPID 的设备配方
- bool deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID);
+ // 鍒犻櫎鎸囧畾 PPID 鐨勮澶囬厤鏂�
+ bool deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID);
- // 删除指定 PPID 的设备配方(通过设备名称)
- bool deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName);
+ // 鍒犻櫎鎸囧畾 PPID 鐨勮澶囬厤鏂癸紙閫氳繃璁惧鍚嶇О锛�
+ bool deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName);
- // 查询所有配方
- std::vector<RecipeInfo> getAllRecipes();
+ // 鏌ヨ鎵�鏈夐厤鏂�
+ std::vector<RecipeInfo> getAllRecipes();
- // 根据 PPID 或描述查询配方
- std::vector<RecipeInfo> getRecipesByKeyword(const std::string& keyword);
+ // 鏍规嵁 PPID 鎴栨弿杩版煡璇㈤厤鏂�
+ std::vector<RecipeInfo> getRecipesByKeyword(const std::string& keyword);
- // 获取所有 PPID
- std::vector<std::string> getAllPPID() const;
+ // 鑾峰彇鎵�鏈� PPID
+ std::vector<std::string> getAllPPID() const;
- // 按 PPID 查询配方
- RecipeInfo getRecipeByPPID(const std::string& ppid);
+ // 鎸� ID 鏌ヨ PPID
+ std::string getPPIDById(int nId);
- // 根据 PPID 和设备ID 获取设备配方ID
- int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID);
+ // 鎸� PPID 鏌ヨ ID
+ int getIdByPPID(const std::string& ppid);
- // 根据 PPID 和设备名称 获取设备配方ID
- int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName);
+ // 鎸� PPID 鏌ヨ閰嶆柟
+ RecipeInfo getRecipeByPPID(const std::string& ppid);
- // 删除指定 PPID 的配方
- bool deleteRecipeByPPID(const std::string& ppid);
+ // 鏍规嵁 PPID 鍜岃澶嘔D 鑾峰彇璁惧閰嶆柟ID
+ int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID);
- // 更新指定 PPID 的配方
- bool updateRecipe(const RecipeInfo& recipe);
+ // 鏍规嵁 PPID 鍜岃澶囧悕绉� 鑾峰彇璁惧閰嶆柟ID
+ int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName);
- // 更新 PPID(通过旧 PPID 和新 PPID)
- bool updatePPID(const std::string& oldPPID, const std::string& newPPID);
+ // 鍒犻櫎鎸囧畾 PPID 鐨勯厤鏂�
+ bool deleteRecipeByPPID(const std::string& ppid);
- // 更新配方描述(通过 PPID)
- bool updateDescription(const std::string& ppid, const std::string& newDescription);
+ // 鏇存柊鎸囧畾 PPID 鐨勯厤鏂�
+ bool updateRecipe(const RecipeInfo& recipe);
- // 更新设备配方ID(通过 PPID 和设备ID)
- bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID);
+ // 鏇存柊 PPID锛堥�氳繃鏃� PPID 鍜屾柊 PPID锛�
+ bool updatePPID(const std::string& oldPPID, const std::string& newPPID);
- // 更新设备配方ID(通过 PPID 和设备名称)
- bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID);
+ // 鏇存柊閰嶆柟鎻忚堪锛堥�氳繃 PPID锛�
+ bool updateDescription(const std::string& ppid, const std::string& newDescription);
- // 模拟插入数据(测试用)
- void insertMockData();
+ // 鏇存柊璁惧閰嶆柟ID锛堥�氳繃 PPID 鍜岃澶嘔D锛�
+ bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID);
- // 读取配方文件(CSV 或 JSON)
- bool readRecipeFile(const std::string& filename);
+ // 鏇存柊璁惧閰嶆柟ID锛堥�氳繃 PPID 鍜岃澶囧悕绉帮級
+ bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID);
- // 保存配方到文件
- bool saveRecipeFile(const std::string& filename);
+ bool addDeviceRecipe(const std::string& strDeviceName, int nID, const std::string& strName, const std::string& strPara);
+ bool updateDeviceRecipeName(const std::string& strDeviceName, int nID, const std::string& strNewName);
+ bool updateDeviceRecipePara(const std::string& strDeviceName, int nID, const std::string& strNewPara);
+ std::string getDeviceRecipeName(const std::string& strDeviceName, int nID);
+ std::string getDeviceRecipePara(const std::string& strDeviceName, int nID);
+ bool deleteDeviceRecipe(const std::string& strDeviceName, int nID);
+ std::vector<std::pair<int, std::string>> getDeviceRecipes(const std::string& strDeviceName);
+
+ // 妯℃嫙鎻掑叆鏁版嵁锛堟祴璇曠敤锛�
+ void insertMockData();
+
+ // 璇诲彇閰嶆柟鏂囦欢锛圕SV 鎴� JSON锛�
+ bool readRecipeFile(const std::string& filename);
+
+ // 淇濆瓨閰嶆柟鍒版枃浠�
+ bool saveRecipeFile(const std::string& filename);
private:
- RecipeManager();
- ~RecipeManager();
+ RecipeManager();
+ ~RecipeManager();
- RecipeManager(const RecipeManager&) = delete;
- RecipeManager& operator=(const RecipeManager&) = delete;
+ RecipeManager(const RecipeManager&) = delete;
+ RecipeManager& operator=(const RecipeManager&) = delete;
private:
- BL::Database* m_pDB;
- static std::recursive_mutex m_mutex;
+ BL::Database* m_pDB;
+ static std::recursive_mutex m_mutex;
};
#endif // RECIPE_MANAGER_H
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index c1a4238..573a713 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -27,6 +27,7 @@
#include "CPageReport.h"
#include "CPageCollectionEvent.h"
#include "CControlJobDlg.h"
+#include "InputDialog.h"
#ifdef _DEBUG
@@ -956,6 +957,28 @@
LRESULT CServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
{
int id = (int)lParam;
+ if (id == IDC_BUTTON_RUN || id == IDC_BUTTON_STOP) {
+ //CInputDialog inputDialog(_T("验证用户"), _T("请输入用户密码:"));
+ //if (inputDialog.DoModal() != IDOK) {
+ // AfxMessageBox(_T("取消验证!"));
+ // return 0;
+ //}
+
+ //CString inputText = inputDialog.GetInputText();
+ //std::string strPass = UserManager::getInstance().getCurrentPass();
+ //if (inputText.Compare(strPass.c_str()) != 0) {
+ // AfxMessageBox(_T("密码错误!"));
+ // SystemLogManager::getInstance().log(SystemLogManager::LogType::Info, _T("验证时,密码错误!"));
+ // return 0;
+ //}
+
+ UserRole emRole = UserManager::getInstance().getCurrentUserRole();
+ if (emRole != UserRole::SuperAdmin) {
+ AfxMessageBox(_T("当前用户并非管理员!!!"));
+ return 1;
+ }
+ }
+
if (id == IDC_BUTTON_RUN) {
if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
diff --git a/SourceCode/Bond/Servo/UserManager.cpp b/SourceCode/Bond/Servo/UserManager.cpp
index 1e6d5f8..0c08e60 100644
--- a/SourceCode/Bond/Servo/UserManager.cpp
+++ b/SourceCode/Bond/Servo/UserManager.cpp
@@ -1,4 +1,4 @@
-#include "stdafx.h"
+锘�#include "stdafx.h"
#include "UserManager.h"
#include <chrono>
#include <iostream>
@@ -12,531 +12,531 @@
const std::string INITIAL_ADMIN_USERNAME = "admin";
const std::string INITIAL_ADMIN_PASSWORD = "admin";
-// 获取单例实例
+// 鑾峰彇鍗曚緥瀹炰緥
UserManager& UserManager::getInstance() {
- static UserManager instance;
- return instance;
+ 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();
+ : 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();
+ terminateIdleDetection();
}
-// 提供数据库连接
+// 鎻愪緵鏁版嵁搴撹繛鎺�
std::unique_ptr<BL::Database>& UserManager::getDatabaseInstance() {
- return m_pDB;
+ 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 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 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);
+ 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);
- }
+ 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;
+ return true;
}
-// 对密码进行哈希处理
+// 瀵瑰瘑鐮佽繘琛屽搱甯屽鐞�
std::string UserManager::hashPassword(const std::string& password) {
- return std::to_string(std::hash<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;
+ 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::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 encryptedData((std::istreambuf_iterator<char>(sessionFile)), std::istreambuf_iterator<char>());
+ sessionFile.close();
- // 解密数据
- std::string decryptedData = simpleEncryptDecrypt(encryptedData, "my_secret_key");
+ // 瑙e瘑鏁版嵁
+ std::string decryptedData = simpleEncryptDecrypt(encryptedData, "my_secret_key");
- // 解析解密的数据
- std::istringstream sessionData(decryptedData);
- std::string username;
+ // 瑙f瀽瑙e瘑鐨勬暟鎹�
+ std::istringstream sessionData(decryptedData);
+ std::string username;
std::string password;
- std::time_t lastLoginTime;
- int timeoutMinutes;
- int expirationHours;
+ std::time_t lastLoginTime;
+ int timeoutMinutes;
+ int expirationHours;
- sessionData >> username >> password >> lastLoginTime >> timeoutMinutes >> 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);
+ // 楠岃瘉鏃堕棿鎴虫湁鏁堟��
+ 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;
- }
+ if (sessionDuration > std::chrono::hours(expirationHours)) {
+ clearSession();
+ return false;
+ }
- // 恢复会话数据
- m_strCurrentUser = username;
+ // 鎭㈠浼氳瘽鏁版嵁
+ 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();
+ m_tpLastLogin = lastLogin;
+ m_tmSessionTimeout = std::chrono::minutes(timeoutMinutes);
+ m_tmSessionExpiration = std::chrono::hours(expirationHours);
+ m_isLoggedIn = true;
+ m_isRememberMe = true;
+ updateActivityTime();
- return true;
+ return true;
}
-// 保存会话信息到文件
+// 淇濆瓨浼氳瘽淇℃伅鍒版枃浠�
void UserManager::saveSession() {
- if (!m_isRememberMe) {
- clearSession();
- return;
- }
+ 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::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::string encryptedData = simpleEncryptDecrypt(sessionData.str(), "my_secret_key");
- // 写入加密数据到文件
- std::ofstream sessionFile(getSessionFilePath(), std::ios::binary);
- if (sessionFile.is_open()) {
- sessionFile << encryptedData;
- sessionFile.close();
- }
+ // 鍐欏叆鍔犲瘑鏁版嵁鍒版枃浠�
+ std::ofstream sessionFile(getSessionFilePath(), std::ios::binary);
+ if (sessionFile.is_open()) {
+ sessionFile << encryptedData;
+ sessionFile.close();
+ }
}
-// 清除会话文件
+// 娓呴櫎浼氳瘽鏂囦欢
void UserManager::clearSession() {
- std::remove(getSessionFilePath().c_str());
+ std::remove(getSessionFilePath().c_str());
}
-// 获取程序路径下的config文件夹路径
+// 鑾峰彇绋嬪簭璺緞涓嬬殑config鏂囦欢澶硅矾寰�
std::string UserManager::getConfigFolderPath() {
- char szPath[MAX_PATH];
- GetModuleFileName(NULL, szPath, MAX_PATH);
- std::string exePath(szPath);
- std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB\\";
+ char szPath[MAX_PATH];
+ GetModuleFileName(NULL, szPath, MAX_PATH);
+ std::string exePath(szPath);
+ std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB\\";
- // 检查并创建config文件夹
- DWORD fileAttr = GetFileAttributes(dbDir.c_str());
- if (fileAttr == INVALID_FILE_ATTRIBUTES) {
- CreateDirectory(dbDir.c_str(), NULL);
- }
+ // 妫�鏌ュ苟鍒涘缓config鏂囦欢澶�
+ DWORD fileAttr = GetFileAttributes(dbDir.c_str());
+ if (fileAttr == INVALID_FILE_ATTRIBUTES) {
+ CreateDirectory(dbDir.c_str(), NULL);
+ }
- return dbDir;
+ return dbDir;
}
-// 获取session.dat文件路径
+// 鑾峰彇session.dat鏂囦欢璺緞
std::string UserManager::getSessionFilePath() {
- return getConfigFolderPath() + SESSION_FILE;
+ return getConfigFolderPath() + SESSION_FILE;
}
-// 获取数据库文件路径
+// 鑾峰彇鏁版嵁搴撴枃浠惰矾寰�
std::string UserManager::getDatabaseFilePath() {
- return getConfigFolderPath() + DATABASE_FILE;
+ 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);
+ 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;
- }
+ 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_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();
+ 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);
+ std::string updateLoginTime = "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE username = '" + username + "'";
+ m_pDB->executeQuery(updateLoginTime);
- saveSession();
- return true;
+ saveSession();
+ return true;
}
-// 登出方法
+// 鐧诲嚭鏂规硶
void UserManager::logout() {
- if (m_isLoggedIn) {
- std::cout << "User logged out: " << m_strCurrentUser << std::endl;
- m_strCurrentUser.clear();
+ 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();
- }
+ m_isLoggedIn = false;
+ m_isRememberMe = false;
+ clearSession();
+ }
}
-// 返回当前用户的登录状态
+// 杩斿洖褰撳墠鐢ㄦ埛鐨勭櫥褰曠姸鎬�
bool UserManager::isLoggedIn() const {
- return m_isLoggedIn;
+ 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::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);
+ 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;
- }
+ 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::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 {};
- }
+ 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");
- }
+ // 鏌ヨ鏁翠釜鐢ㄦ埛琛�
+ 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;
+ 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;
- }
+ 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;
- }
+ // 娓呯┖鐢ㄦ埛琛�
+ 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;
- }
+ // 鎻掑叆鏂扮殑鐢ㄦ埛鏁版嵁
+ 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] + "')";
+ 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;
- }
- }
+ if (!m_pDB->executeQuery(insertQuery)) {
+ std::cerr << "Failed to insert user: " << user[0] << std::endl;
+ return false;
+ }
+ }
- return true;
+ 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;
- }
+ 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);
+ 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 (success && m_strCurrentUser == username) {
+ m_strCurrentUser = newUsername;
- // 如果“记住密码”已启用,更新会话文件
- if (m_isRememberMe) {
- saveSession();
- }
- }
- return success;
+ // 濡傛灉鈥滆浣忓瘑鐮佲�濆凡鍚敤锛屾洿鏂颁細璇濇枃浠�
+ 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;
- }
+ 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);
+ 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;
- }
+ // 濡傛灉鏄綋鍓嶇敤鎴蜂慨鏀硅嚜宸辩殑瀵嗙爜锛岄��鍑虹櫥褰曞苟娓呴櫎浼氳瘽鏂囦欢
+ if (success && m_strCurrentUser == username) {
+ logout();
+ std::cout << "Password changed successfully. Please log in again." << std::endl;
+ }
- return success;
+ 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_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;
- }
+ // 闃叉绠$悊鍛樻洿鏀硅嚜宸辩殑瑙掕壊
+ 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);
+ std::string query = "UPDATE users SET role = " + std::to_string(static_cast<int>(newRole)) +
+ " WHERE username = '" + username + "'";
+ return m_pDB->executeQuery(query);
}
-// 修改用户的 session_timeout,仅超级管理员有权限
+// 淇敼鐢ㄦ埛鐨� 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;
- }
+ 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);
+ 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;
+ if (m_isRememberMe) {
+ saveSession();
+ }
+ }
+ return success;
}
-// 修改用户的 session_expiration,仅超级管理员有权限
+// 淇敼鐢ㄦ埛鐨� 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;
- }
+ 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);
+ 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;
+ 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);
+ 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]); // 获取用户名列的值
- }
- }
+ for (const auto& row : results) {
+ if (!row.empty()) {
+ usernames.push_back(row[0]); // 鑾峰彇鐢ㄦ埛鍚嶅垪鐨勫��
+ }
+ }
- return usernames;
+ 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 << "'";
+ // 鏋勫缓鏌ヨ璇彞
+ 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 {};
- }
+ // 鎵ц鏌ヨ骞惰幏鍙栫粨鏋�
+ auto results = m_pDB->fetchResults(query.str());
+ if (results.empty()) {
+ return {};
+ }
- // 返回查询到的第一行数据
- return results[0];
+ // 杩斿洖鏌ヨ鍒扮殑绗竴琛屾暟鎹�
+ 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;
+ 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;
+ 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;
+ 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);
+ 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);
+ 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;
+ m_strCurrentUser = strName;
}
-// 获取当前登录用户密码
+// 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛瀵嗙爜
std::string UserManager::getCurrentPass() const {
return m_strCurrentPass;
}
-// 修改当前登录用户密码
+// 淇敼褰撳墠鐧诲綍鐢ㄦ埛瀵嗙爜
void UserManager::setCurrentPass(const std::string& strPass) {
- m_strCurrentPass = strPass;
+ m_strCurrentPass = strPass;
}
-// 获取当前登录用户角色
+// 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛瑙掕壊
UserRole UserManager::getCurrentUserRole() const {
return m_enCurrentUserRole;
}
-// 修改当前登录用户角色
+// 淇敼褰撳墠鐧诲綍鐢ㄦ埛瑙掕壊
void UserManager::setCurrentUserRole(UserRole emRole) {
- m_enCurrentUserRole = 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);
+ 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);
+ if (nCode == HC_ACTION) {
+ UserManager::getInstance().updateActivityTime();
+ std::cout << "Keyboard event detected. Activity time updated." << std::endl;
+ }
+ return CallNextHookEx(nullptr, nCode, wParam, lParam);
}
diff --git a/SourceCode/Bond/Servo/UserManager.h b/SourceCode/Bond/Servo/UserManager.h
index 590b2e1..cd1f3cc 100644
--- a/SourceCode/Bond/Servo/UserManager.h
+++ b/SourceCode/Bond/Servo/UserManager.h
@@ -1,4 +1,4 @@
-#ifndef USER_MANAGER_H
+锘�#ifndef USER_MANAGER_H
#define USER_MANAGER_H
#include <string>
@@ -7,124 +7,126 @@
#include <windows.h>
#include "Database.h"
-// 用户角色定义
+// 鐢ㄦ埛瑙掕壊瀹氫箟
enum class UserRole {
- SuperAdmin = 0, // 超级管理员
- Engineer, // 工程师
- Operator // 操作员
+ SuperAdmin = 0, // 瓒呯骇绠$悊鍛橈細绯荤粺鏈�楂樻潈闄愶紝绠$悊鎵�鏈夌敤鎴峰拰鏉冮檺
+ ProcessEngineer, // 鍒剁▼宸ョ▼甯堬細璐熻矗宸ヨ壓鍒跺畾涓庝紭鍖�
+ EquipmentEngineer,// 璁惧宸ョ▼甯堬細璐熻矗璁惧缁存姢涓庢妧鏈敮鎸�
+ Operator, // 鎿嶄綔鍛橈細鎵ц鏃ュ父鐢熶骇鎿嶄綔
+ Unknown // 鏈煡瑙掕壊锛氶粯璁ゆ垨鏈瘑鍒殑瑙掕壊
};
-// 用户管理类,采用单例模式
+// 鐢ㄦ埛绠$悊绫伙紝閲囩敤鍗曚緥妯″紡
class UserManager {
public:
- static UserManager& getInstance();
+ static UserManager& getInstance();
- UserManager(const UserManager&) = delete;
- UserManager& operator=(const UserManager&) = delete;
+ UserManager(const UserManager&) = delete;
+ UserManager& operator=(const UserManager&) = delete;
- // 提供数据库连接
- std::unique_ptr<BL::Database>& getDatabaseInstance();
+ // 鎻愪緵鏁版嵁搴撹繛鎺�
+ 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 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 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(); // 清除会话文件
+ // 浼氳瘽鏂囦欢鎿嶄綔
+ bool loadSession(); // 浠庝細璇濇枃浠跺姞杞戒細璇濅俊鎭�
+ void saveSession(); // 淇濆瓨浼氳瘽淇℃伅鍒版枃浠�
+ void clearSession(); // 娓呴櫎浼氳瘽鏂囦欢
- // 配置文件夹路径管理
- static std::string getConfigFolderPath();
- static std::string getSessionFilePath();
- static std::string getDatabaseFilePath();
+ // 閰嶇疆鏂囦欢澶硅矾寰勭鐞�
+ static std::string getConfigFolderPath();
+ static std::string getSessionFilePath();
+ static std::string getDatabaseFilePath();
- // 更新最后活动时间(用于无操作超时检测)
- void updateActivityTime();
+ // 鏇存柊鏈�鍚庢椿鍔ㄦ椂闂达紙鐢ㄤ簬鏃犳搷浣滆秴鏃舵娴嬶級
+ void updateActivityTime();
- // 设置用户的无操作超时时间
- void setSessionTimeout(std::chrono::minutes timeout);
+ // 璁剧疆鐢ㄦ埛鐨勬棤鎿嶄綔瓒呮椂鏃堕棿
+ void setSessionTimeout(std::chrono::minutes timeout);
- // 检查是否无操作超时
- bool isInactiveTimeout() const;
+ // 妫�鏌ユ槸鍚︽棤鎿嶄綔瓒呮椂
+ bool isInactiveTimeout() const;
- // 初始化无操作检测(设置全局钩子和定时器)
- void initializeIdleDetection(HWND hwnd);
+ // 鍒濆鍖栨棤鎿嶄綔妫�娴嬶紙璁剧疆鍏ㄥ眬閽╁瓙鍜屽畾鏃跺櫒锛�
+ void initializeIdleDetection(HWND hwnd);
- // 终止无操作检测(清除钩子和定时器)
- void terminateIdleDetection();
+ // 缁堟鏃犳搷浣滄娴嬶紙娓呴櫎閽╁瓙鍜屽畾鏃跺櫒锛�
+ void terminateIdleDetection();
- // 获取当前登录用户名
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛鍚�
std::string getCurrentUser() const;
- // 修改当前登录用户名
- void setCurrentUser(const std::string& strName);
+ // 淇敼褰撳墠鐧诲綍鐢ㄦ埛鍚�
+ void setCurrentUser(const std::string& strName);
- // 获取当前登录用户密码
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛瀵嗙爜
std::string getCurrentPass() const;
- // 修改当前登录用户密码
- void setCurrentPass(const std::string& strPass);
+ // 淇敼褰撳墠鐧诲綍鐢ㄦ埛瀵嗙爜
+ void setCurrentPass(const std::string& strPass);
- // 获取当前登录用户角色
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛瑙掕壊
UserRole getCurrentUserRole() const;
- // 修改当前登录用户角色
- void setCurrentUserRole(UserRole emRole);
+ // 淇敼褰撳墠鐧诲綍鐢ㄦ埛瑙掕壊
+ void setCurrentUserRole(UserRole emRole);
- // 获取当前登录用户的无操作超时时间
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛鐨勬棤鎿嶄綔瓒呮椂鏃堕棿
std::chrono::minutes getSessionTimeout() const;
- // 获取当前登录用户的会话过期时间
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛鐨勪細璇濊繃鏈熸椂闂�
std::chrono::hours getSessionExpiration() const;
private:
- UserManager();
- ~UserManager();
+ UserManager();
+ ~UserManager();
- // 初始化数据库连接和用户表
- bool initializeDatabase();
+ // 鍒濆鍖栨暟鎹簱杩炴帴鍜岀敤鎴疯〃
+ bool initializeDatabase();
- // 哈希密码,用于加密用户密码
- std::string hashPassword(const std::string& password);
+ // 鍝堝笇瀵嗙爜锛岀敤浜庡姞瀵嗙敤鎴峰瘑鐮�
+ std::string hashPassword(const std::string& password);
- // 加密和解密函数
- std::string simpleEncryptDecrypt(const std::string& data, const std::string& key);
+ // 鍔犲瘑鍜岃В瀵嗗嚱鏁�
+ 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);
+ // 閿洏鍜岄紶鏍囬挬瀛愬嚱鏁�
+ 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::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::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; // 数据库接口
+ std::unique_ptr<BL::Database> m_pDB; // 鏁版嵁搴撴帴鍙�
};
#endif // USER_MANAGER_H
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/UserManagerDlg.cpp b/SourceCode/Bond/Servo/UserManagerDlg.cpp
index 9f87215..7fde4bf 100644
--- a/SourceCode/Bond/Servo/UserManagerDlg.cpp
+++ b/SourceCode/Bond/Servo/UserManagerDlg.cpp
@@ -88,9 +88,10 @@
m_gridUserManager.ExpandLastColumn(); // 鏈�鍚庝竴鍒楀~鍏呯綉鏍�
m_mapRoleDescriptions.clear();
- m_mapRoleDescriptions.emplace(_T("绠$悊鍛�"), _T("绠$悊鎵�鏈夌敤鎴凤紝鍒嗛厤鏉冮檺"));
- m_mapRoleDescriptions.emplace(_T("宸ョ▼甯�"), _T("缁存姢绯荤粺锛岃В鍐虫妧鏈棶棰�"));
- m_mapRoleDescriptions.emplace(_T("鎿嶄綔鍛�"), _T("鎵ц鏃ュ父鎿嶄綔浠诲姟"));
+ m_mapRoleDescriptions.emplace(_T("绠$悊鍛�"), _T("绠$悊鎵�鏈夌敤鎴疯处鎴凤紝鍒嗛厤鍜岃皟鏁存潈闄愶紝璐熻矗绯荤粺瀹夊叏涓庢暣浣撹繍琛�"));
+ m_mapRoleDescriptions.emplace(_T("鍒剁▼宸ョ▼甯�"), _T("璐熻矗鐢熶骇宸ヨ壓鐨勫埗瀹氥�佷紭鍖栦笌鏀硅繘锛岀‘淇濆伐鑹虹ǔ瀹氬拰鑹巼鎻愬崌"));
+ m_mapRoleDescriptions.emplace(_T("璁惧宸ョ▼甯�"), _T("缁存姢鍜屼繚鍏昏澶囷紝澶勭悊鏁呴殰锛屼繚闅滆澶囩ǔ瀹氳繍琛岋紝鍙備笌鎶�鏈崌绾�"));
+ m_mapRoleDescriptions.emplace(_T("鎿嶄綔鍛�"), _T("鎸夌収鏍囧噯娴佺▼鎵ц鏃ュ父鎿嶄綔浠诲姟锛岀洃鎺х敓浜х姸鍐碉紝鍙婃椂鍙嶉寮傚父"));
FillUserManager();
}
@@ -134,12 +135,13 @@
CStringArray permissions;
permissions.Add(_T("绠$悊鍛�"));
- permissions.Add(_T("宸ョ▼甯�"));
+ 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, 0, GVIS_READONLY); // 绗竴鍒楀彧璇�
m_gridUserManager.SetItemState(i, nCols - 2, GVIS_READONLY); // 鍊掓暟绗簩鍒楀彧璇�
m_gridUserManager.SetItemState(i, nCols - 1, GVIS_READONLY); // 鏈�鍚庝竴鍒楀彧璇�
@@ -149,13 +151,12 @@
pCell->SetOptions(permissions);
pCell->SetStyle(CBS_DROPDOWNLIST);
- CString cstrRole = m_gridUserManager.GetItemText(i, 3);
- int nRole = _ttoi(cstrRole);
- if (nRole < 0 || nRole > 2) {
+ int nRole = _ttoi(m_gridUserManager.GetItemText(i, 3));
+ if (nRole < 0 || nRole > 3) {
CString cstrMessage;
cstrMessage.Format(_T("鐢ㄦ埛 [%s]锛屾潈闄愬紓甯革紒灏嗚缃垚鎿嶄綔鍛橈紒"), m_gridUserManager.GetItemText(i, 1));
AfxMessageBox(cstrMessage);
- nRole = 2;
+ nRole = 3;
}
m_gridUserManager.SetItemText(i, 3, permissions.GetAt(nRole));
@@ -237,7 +238,8 @@
// 绗洓鍒楄缃紙鏉冮檺鍒楋級涓轰笅鎷夋
CStringArray permissions;
permissions.Add(_T("绠$悊鍛�"));
- permissions.Add(_T("宸ョ▼甯�"));
+ permissions.Add(_T("鍒剁▼宸ョ▼甯�"));
+ permissions.Add(_T("璁惧宸ョ▼甯�"));
permissions.Add(_T("鎿嶄綔鍛�"));
if (pGridCtrl->SetCellType(newRowIndex, 3, RUNTIME_CLASS(CGridCellCombo))) {
@@ -443,7 +445,8 @@
CStringArray permissions;
permissions.Add(_T("绠$悊鍛�"));
- permissions.Add(_T("宸ョ▼甯�"));
+ permissions.Add(_T("鍒剁▼宸ョ▼甯�"));
+ permissions.Add(_T("璁惧宸ョ▼甯�"));
permissions.Add(_T("鎿嶄綔鍛�"));
if (m_gridUserManager.SetCellType(row, 3, RUNTIME_CLASS(CGridCellCombo))) {
@@ -527,12 +530,14 @@
if (j == 3) {
if (cellText == _T("绠$悊鍛�"))
cellString = "0";
- else if (cellText == _T("宸ョ▼甯�"))
+ else if (cellText == _T("鍒剁▼宸ョ▼甯�"))
cellString = "1";
+ else if (cellText == _T("璁惧宸ョ▼甯�"))
+ cellString = "2";
else if (cellText == _T("鎿嶄綔鍛�"))
- cellString = "2";
+ cellString = "3";
else
- cellString = "2";
+ cellString = "3";
}
rowData.push_back(cellString);
--
Gitblit v1.9.3