From 8e7305a65a804f3736fa17292856f87365ef644a Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期四, 04 九月 2025 14:00:20 +0800
Subject: [PATCH] 1. 细分工程师用户权限(扩展制程工程师和设备工程师) 2. 配方修复选空白配方列表时,新建按钮不可点击的问题 3. 新添加双击配方列表事件

---
 SourceCode/Bond/Servo/RecipeManager.cpp       |  892 +++++++++++++++++-----------------
 SourceCode/Bond/Servo/UserManagerDlg.cpp      |   33 
 SourceCode/Bond/Servo/RecipeManager.h         |  150 +++---
 SourceCode/Bond/Servo/UserManager.h           |    8 
 SourceCode/Bond/Servo/PageRecipe.h            |    3 
 SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp |  332 ++++++------
 SourceCode/Bond/Servo/PageRecipe.cpp          |   50 +
 7 files changed, 753 insertions(+), 715 deletions(-)

diff --git a/SourceCode/Bond/Servo/PageRecipe.cpp b/SourceCode/Bond/Servo/PageRecipe.cpp
index ab54bcf..c238efd 100644
--- a/SourceCode/Bond/Servo/PageRecipe.cpp
+++ b/SourceCode/Bond/Servo/PageRecipe.cpp
@@ -237,7 +237,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()
 
@@ -575,19 +576,48 @@
 	}
 }
 
-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 > 0);
+	GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem > 0);
+	GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem > 0);
+}
+
+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()
@@ -614,4 +644,4 @@
 		SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0);
 		FillRecipeListToListCtrl(pRecipeList);
 	}
-}
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/PageRecipe.h b/SourceCode/Bond/Servo/PageRecipe.h
index c723630..d695564 100644
--- a/SourceCode/Bond/Servo/PageRecipe.h
+++ b/SourceCode/Bond/Servo/PageRecipe.h
@@ -37,7 +37,8 @@
 	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()
 
diff --git a/SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp b/SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
index 22d0386..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,122 +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;
+	auto& mapRecipeIds = pRecipeList->getIds();
+	bool bFound = false;
+	pCombo->ResetContent();
+	for (const auto& pair : mapRecipeIds) {
+		int nRecipeID = pair.second;
 
-        std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(pEq->getName(), nRecipeID);
-        if (strRecipeName.empty()) {
-            strRecipeName = std::to_string(nRecipeID);
-        }
+		std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(pEq->getName(), nRecipeID);
+		if (strRecipeName.empty()) {
+			strRecipeName = std::to_string(nRecipeID);
+		}
 
-        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;
-        }
-    }
+		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);
-    }
+	if (nSelectedRecipeID != -1 && !bFound) {
+		pCombo->SetCurSel(CB_ERR);
+	}
+	else if (pCombo->GetCount() > 0 && nSelectedRecipeID == -1) {
+		pCombo->SetCurSel(0);
+	}
 
-    return true;
+	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()
 
 
@@ -165,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
@@ -228,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 8cb7a51..ce7b91f 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,453 +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 (
-            id INTEGER PRIMARY KEY AUTOINCREMENT,
-            ppid TEXT NOT NULL UNIQUE,
-            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,
-            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)
-        );
-    )";
+	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, recipe_name) VALUES ('"
-            << recipe.strPPID << "', "
-            << device.nDeviceID << ", '"
-            << device.strDeviceName << "', "
-            << device.nRecipeID << ", '"
-            << device.strRecipeName << "');";
+	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;
-        }
-    }
+		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;
+	// 鎻愪氦浜嬪姟
+	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, recipe_name) VALUES ('"
-        << ppid << "', "
-        << device.nDeviceID << ", '"
-        << device.strDeviceName << "', "
-        << device.nRecipeID << ", '"
-        << device.strRecipeName << "');";
+	// 鎻掑叆璁惧璁板綍
+	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, recipe_name FROM recipe_devices WHERE ppid = '" << info.strPPID << "'ORDER BY id ASC;";
-        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]);
+		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);
-    }
+			}
+			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 {};
-    }
+	if (!m_pDB) {
+		return {};
+	}
 
-    std::ostringstream query;
-    query << "SELECT ppid FROM recipes WHERE id = " << nId << ";";
+	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 {};
-    }
+	auto rows = m_pDB->fetchResults(query.str());
+	if (rows.empty() || rows[0].empty()) {
+		return {};
+	}
 
-    return rows[0][0];
+	return rows[0][0];
 }
 
 int RecipeManager::getIdByPPID(const std::string& ppid) {
-    if (!m_pDB) {
-        return -1;
-    }
+	if (!m_pDB) {
+		return -1;
+	}
 
-    std::ostringstream query;
-    query << "SELECT id FROM recipes WHERE ppid = '" << ppid << "';";
+	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;
-    }
+	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;
-    }
+	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, 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;
+	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) {
@@ -463,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());
@@ -474,191 +474,191 @@
 		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& deviceName, int nRecipeID, const std::string& strRecipeName) {
-    if (!m_pDB || deviceName.empty() || nRecipeID <= 0 || strRecipeName.empty()) { 
-        return false;
-    }
+	if (!m_pDB || deviceName.empty() || nRecipeID <= 0 || strRecipeName.empty()) { 
+		return false;
+	}
 
-    std::ostringstream sql;
-    sql << "CREATE TABLE IF NOT EXISTS " << deviceName << "_Recipes ("
-        << "recipe_id INTEGER PRIMARY KEY, "
-        << "recipe_name TEXT NOT NULL"
-        << ");";
-    m_pDB->executeQuery(sql.str());
+	std::ostringstream sql;
+	sql << "CREATE TABLE IF NOT EXISTS " << deviceName << "_Recipes ("
+		<< "recipe_id INTEGER PRIMARY KEY, "
+		<< "recipe_name TEXT NOT NULL"
+		<< ");";
+	m_pDB->executeQuery(sql.str());
 
-    std::ostringstream ins;
-    ins << "INSERT OR REPLACE INTO " << deviceName << "_Recipes (recipe_id, recipe_name) VALUES ("
-        << nRecipeID << ", '" << strRecipeName << "');";
+	std::ostringstream ins;
+	ins << "INSERT OR REPLACE INTO " << deviceName << "_Recipes (recipe_id, recipe_name) VALUES ("
+		<< nRecipeID << ", '" << strRecipeName << "');";
 
-    std::lock_guard<std::recursive_mutex> lk(m_mutex);
-    return m_pDB->executeQuery(ins.str());
+	std::lock_guard<std::recursive_mutex> lk(m_mutex);
+	return m_pDB->executeQuery(ins.str());
 }
 
 bool RecipeManager::updateDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& newName) {
-    if (!m_pDB || deviceName.empty() || nRecipeID <= 0 || newName.empty()) { 
-        return false;
-    }
+	if (!m_pDB || deviceName.empty() || nRecipeID <= 0 || newName.empty()) { 
+		return false;
+	}
 
-    std::ostringstream sql;
-    sql << "UPDATE " << deviceName << "_Recipes SET recipe_name='" << newName
-        << "' WHERE recipe_id=" << nRecipeID << ";";
+	std::ostringstream sql;
+	sql << "UPDATE " << deviceName << "_Recipes SET recipe_name='" << newName
+		<< "' WHERE recipe_id=" << nRecipeID << ";";
 
-    std::lock_guard<std::recursive_mutex> lk(m_mutex);
-    return m_pDB->executeQuery(sql.str());
+	std::lock_guard<std::recursive_mutex> lk(m_mutex);
+	return m_pDB->executeQuery(sql.str());
 }
 
 std::string RecipeManager::getDeviceRecipeName(const std::string& deviceName, int nRecipeID) {
-    if (!m_pDB || deviceName.empty() || nRecipeID <= 0) {
-        return "";
-    }
+	if (!m_pDB || deviceName.empty() || nRecipeID <= 0) {
+		return "";
+	}
 
-    std::ostringstream sql;
-    sql << "SELECT recipe_name FROM " << deviceName << "_Recipes "
-        << "WHERE recipe_id=" << nRecipeID << " LIMIT 1;";
+	std::ostringstream sql;
+	sql << "SELECT recipe_name FROM " << deviceName << "_Recipes "
+		<< "WHERE recipe_id=" << nRecipeID << " LIMIT 1;";
 
-    auto rows = m_pDB->fetchResults(sql.str());
-    if (!rows.empty() && !rows[0].empty()) {
-        return rows[0][0];
-    }
-    return "";
+	auto rows = m_pDB->fetchResults(sql.str());
+	if (!rows.empty() && !rows[0].empty()) {
+		return rows[0][0];
+	}
+	return "";
 }
 
 bool RecipeManager::deleteDeviceRecipe(const std::string& deviceName, int nRecipeID) {
-    if (!m_pDB || deviceName.empty() || nRecipeID <= 0) { 
-        return false;
-    }
+	if (!m_pDB || deviceName.empty() || nRecipeID <= 0) { 
+		return false;
+	}
 
-    std::ostringstream sql;
-    sql << "DELETE FROM " << deviceName << "_Recipes WHERE recipe_id=" << nRecipeID << ";";
+	std::ostringstream sql;
+	sql << "DELETE FROM " << deviceName << "_Recipes WHERE recipe_id=" << nRecipeID << ";";
 
-    std::lock_guard<std::recursive_mutex> lk(m_mutex);
-    return m_pDB->executeQuery(sql.str());
+	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& deviceName) {
-    std::vector<std::pair<int, std::string>> out;
-    if (!m_pDB || deviceName.empty()) { 
-        return out;
-    }
+	std::vector<std::pair<int, std::string>> out;
+	if (!m_pDB || deviceName.empty()) { 
+		return out;
+	}
 
-    std::ostringstream sql;
-    sql << "SELECT recipe_id, recipe_name FROM " << deviceName << "_Recipes ORDER BY recipe_id;";
+	std::ostringstream sql;
+	sql << "SELECT recipe_id, recipe_name FROM " << deviceName << "_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;
+	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 = {
-        {9, 101, "VacuumBake", "VacuumBake"},
-        {10, 102, "Bonder1", "Bonder1"},
-        {11, 103, "Bonder2", "Bonder2"}
-    };
+	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("Bonder1", 101, "鏍囧噯宸ヨ壓");
+	addDeviceRecipe("Bonder1", 102, "鏀硅壇宸ヨ壓");
+	addDeviceRecipe("Bonder1", 103, "楂橀�熸ā寮�");
 
-    addDeviceRecipe("Bonder2", 101, "标准工艺");
-    addDeviceRecipe("Bonder2", 102, "改良工艺");
-    addDeviceRecipe("Bonder2", 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, 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, ',');
+		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,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 << ","
+	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";
-        }
-    }
+				<< 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 008a1fd..72bf9cc 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>
@@ -7,121 +7,121 @@
 #include <unordered_map>
 #include "Database.h"
 
-// 单个设备配方映射信息
+// 鍗曚釜璁惧閰嶆柟鏄犲皠淇℃伅
 struct DeviceRecipe {
-    int nDeviceID;               // 设备ID
-    int nRecipeID;               // 子配方ID
-    std::string strDeviceName;   // 设备名称 
-	std::string strRecipeName;   // 子配方名称
+	int nDeviceID;               // 璁惧ID
+	int nRecipeID;               // 瀛愰厤鏂笽D
+	std::string strDeviceName;   // 璁惧鍚嶇О 
+	std::string strRecipeName;   // 瀛愰厤鏂瑰悕绉�
 };
 
-// 配方信息
+// 閰嶆柟淇℃伅
 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;
 
-	// 按 ID 查询 PPID
-    std::string getPPIDById(int nId);
+	// 鎸� ID 鏌ヨ PPID
+	std::string getPPIDById(int nId);
 
-	// 按 PPID 查询 ID
-    int getIdByPPID(const std::string& ppid);
+	// 鎸� PPID 鏌ヨ ID
+	int getIdByPPID(const std::string& ppid);
 
-    // 按 PPID 查询配方
-    RecipeInfo getRecipeByPPID(const std::string& ppid);
+	// 鎸� PPID 鏌ヨ閰嶆柟
+	RecipeInfo getRecipeByPPID(const std::string& ppid);
 
-    // 根据 PPID 和设备ID 获取设备配方ID
-    int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID);
+	// 鏍规嵁 PPID 鍜岃澶嘔D 鑾峰彇璁惧閰嶆柟ID
+	int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID);
 
-    // 根据 PPID 和设备名称 获取设备配方ID
-    int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName);
+	// 鏍规嵁 PPID 鍜岃澶囧悕绉� 鑾峰彇璁惧閰嶆柟ID
+	int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName);
 
-    // 删除指定 PPID 的配方
-    bool deleteRecipeByPPID(const std::string& ppid);
+	// 鍒犻櫎鎸囧畾 PPID 鐨勯厤鏂�
+	bool deleteRecipeByPPID(const std::string& ppid);
 
-    // 更新指定 PPID 的配方
-    bool updateRecipe(const RecipeInfo& recipe);
+	// 鏇存柊鎸囧畾 PPID 鐨勯厤鏂�
+	bool updateRecipe(const RecipeInfo& recipe);
 
-	// 更新 PPID(通过旧 PPID 和新 PPID)
-    bool updatePPID(const std::string& oldPPID, const std::string& newPPID);
+	// 鏇存柊 PPID锛堥�氳繃鏃� PPID 鍜屾柊 PPID锛�
+	bool updatePPID(const std::string& oldPPID, const std::string& newPPID);
 
-	// 更新配方描述(通过 PPID)
-    bool updateDescription(const std::string& ppid, const std::string& newDescription);
+	// 鏇存柊閰嶆柟鎻忚堪锛堥�氳繃 PPID锛�
+	bool updateDescription(const std::string& ppid, const std::string& newDescription);
 
-	// 更新设备配方ID(通过 PPID 和设备ID)
-    bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID);
+	// 鏇存柊璁惧閰嶆柟ID锛堥�氳繃 PPID 鍜岃澶嘔D锛�
+	bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID);
 
-	// 更新设备配方ID(通过 PPID 和设备名称)
-    bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID);
+	// 鏇存柊璁惧閰嶆柟ID锛堥�氳繃 PPID 鍜岃澶囧悕绉帮級
+	bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID);
 
-    bool addDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& strRecipeName);
-    bool updateDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& newName);
-    std::string getDeviceRecipeName(const std::string& deviceName, int nRecipeID);
-    bool deleteDeviceRecipe(const std::string& deviceName, int nRecipeID);
-    std::vector<std::pair<int, std::string>> getDeviceRecipes(const std::string& deviceName);
+	bool addDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& strRecipeName);
+	bool updateDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& newName);
+	std::string getDeviceRecipeName(const std::string& deviceName, int nRecipeID);
+	bool deleteDeviceRecipe(const std::string& deviceName, int nRecipeID);
+	std::vector<std::pair<int, std::string>> getDeviceRecipes(const std::string& deviceName);
 
-    // 模拟插入数据(测试用)
-    void insertMockData();
+	// 妯℃嫙鎻掑叆鏁版嵁锛堟祴璇曠敤锛�
+	void insertMockData();
 
-    // 读取配方文件(CSV 或 JSON)
-    bool readRecipeFile(const std::string& filename);
+	// 璇诲彇閰嶆柟鏂囦欢锛圕SV 鎴� JSON锛�
+	bool readRecipeFile(const std::string& filename);
 
-    // 保存配方到文件
-    bool saveRecipeFile(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/UserManager.h b/SourceCode/Bond/Servo/UserManager.h
index 590b2e1..3e51e6d 100644
--- a/SourceCode/Bond/Servo/UserManager.h
+++ b/SourceCode/Bond/Servo/UserManager.h
@@ -9,9 +9,11 @@
 
 // 用户角色定义
 enum class UserRole {
-    SuperAdmin = 0,     // 超级管理员
-    Engineer,           // 工程师
-    Operator            // 操作员
+    SuperAdmin = 0,   // 超级管理员:系统最高权限,管理所有用户和权限
+    ProcessEngineer,  // 制程工程师:负责工艺制定与优化
+    EquipmentEngineer,// 设备工程师:负责设备维护与技术支持
+    Operator,         // 操作员:执行日常生产操作
+    Unknown           // 未知角色:默认或未识别的角色
 };
 
 // 用户管理类,采用单例模式
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