From e2aba4b899f691b68a5d95f27981d25581142cb1 Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期一, 16 十二月 2024 16:59:54 +0800
Subject: [PATCH] 1. 创建配方和删除配方 2. 配方数据分模块,比如轴的数据就是一个模块

---
 SourceCode/Bond/BondEq/View/RecipeListDlg.h          |   34 +++
 SourceCode/Bond/BondEq/Resource.h                    |    0 
 /dev/null                                            |   28 ---
 SourceCode/Bond/BondEq/ToolUnits.h                   |    2 
 SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp      |    1 
 SourceCode/Bond/BondEq/ToolUnits.cpp                 |   40 ++++
 SourceCode/Bond/BondEq/stdafx.h                      |    2 
 SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp |   96 +++++-----
 SourceCode/Bond/BondEq/BondEqDlg.cpp                 |    7 
 SourceCode/Bond/BondEq/View/RecipeListDlg.cpp        |  300 +++++++++++++++++++++++++++++++++
 SourceCode/Bond/BondEq/BondEq.vcxproj                |    4 
 SourceCode/Bond/BondEq/FileManager/RecipeManager.h   |    4 
 12 files changed, 437 insertions(+), 81 deletions(-)

diff --git a/SourceCode/Bond/BondEq/BondEq.vcxproj b/SourceCode/Bond/BondEq/BondEq.vcxproj
index 0a2cb62..32e3fdd 100644
--- a/SourceCode/Bond/BondEq/BondEq.vcxproj
+++ b/SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -263,7 +263,7 @@
     <ClInclude Include="View\ChangePasswordDlg.h" />
     <ClInclude Include="View\IOMonitoringDlg.h" />
     <ClInclude Include="View\LoginDlg.h" />
-    <ClInclude Include="View\RecipeLiseDlg.h" />
+    <ClInclude Include="View\RecipeListDlg.h" />
     <ClInclude Include="View\SystemLogManagerDlg.h" />
     <ClInclude Include="View\UserManagerDlg.h" />
   </ItemGroup>
@@ -344,7 +344,7 @@
     <ClCompile Include="View\ChangePasswordDlg.cpp" />
     <ClCompile Include="View\IOMonitoringDlg.cpp" />
     <ClCompile Include="View\LoginDlg.cpp" />
-    <ClCompile Include="View\RecipeLiseDlg.cpp" />
+    <ClCompile Include="View\RecipeListDlg.cpp" />
     <ClCompile Include="View\SystemLogManagerDlg.cpp" />
     <ClCompile Include="View\UserManagerDlg.cpp" />
   </ItemGroup>
diff --git a/SourceCode/Bond/BondEq/BondEqDlg.cpp b/SourceCode/Bond/BondEq/BondEqDlg.cpp
index d4c6c60..0124a85 100644
--- a/SourceCode/Bond/BondEq/BondEqDlg.cpp
+++ b/SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -17,7 +17,7 @@
 #include "SystemLogManagerDlg.h"
 
 // 测试
-#include "RecipeLiseDlg.h"
+#include "RecipeListDlg.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -253,7 +253,7 @@
 
 	// 设置配方文件夹路径
 	RecipeManager& recipeManager = RecipeManager::getInstance();
-	std::string strRecipePath =  CToolUnits::getCurrentExePath() + _T("\\Recipe");
+	std::string strRecipePath =  CToolUnits::getRecipePath();
 	CToolUnits::createDir(strRecipePath.c_str());
 	recipeManager.setRecipeFolder(strRecipePath);
 
@@ -540,8 +540,7 @@
 
 void CBondEqDlg::OnMenuFileSettings()
 {
-
-	CRecipeLiseDlg dlg;
+	CRecipeListDlg dlg;
 	dlg.DoModal();
 
 	//CSettingsDlg dlg;
diff --git a/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp b/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
index 86c978d..ed88767 100644
--- a/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
+++ b/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
@@ -12,33 +12,15 @@
 // 构造函数
 RecipeManager::RecipeManager() : m_recipeFolder("Recipe") {}
 
-// 设置配方文件夹
-void RecipeManager::setRecipeFolder(const std::string& folderPath) {
-    m_recipeFolder = folderPath;
-}
-
-// 加载配方(如果文件不存在,加载默认数据)
-bool RecipeManager::loadRecipe(const std::string& recipeName) {
-    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
-    pugi::xml_document doc;
-
-    if (!doc.load_file(filePath.c_str())) {
-        std::cerr << "Recipe file not found: " << filePath << ". Loading default recipe." << std::endl;
-        generateDefaultRecipe();
-        return false; // 文件不存在,但加载了默认数据
-    }
-
+// 加载轴信息
+bool RecipeManager::loadAxes(pugi::xml_node axesNode) {
     m_axes.clear();
-
-    auto recipe = doc.child("Recipe");
-    for (auto axisNode : recipe.child("Axes").children("Axis")) {
+    for (auto axisNode : axesNode.children("Axis")) {
         AxisInfo axisInfo;
         axisInfo.id = axisNode.attribute("id").as_int();
         axisInfo.number = axisNode.attribute("number").value();
         axisInfo.description = axisNode.attribute("description").value();
         axisInfo.startAddress = axisNode.attribute("start_address").value();
-        //axisInfo.maxPositioningSpeed = axisNode.attribute("maxPositioningSpeed").as_double();
-        //axisInfo.maxManualSpeed = axisNode.attribute("maxManualSpeed").as_double();
 
         // 加载 ValueRange 值
         axisInfo.jogDistance = ValueRange(
@@ -68,9 +50,9 @@
         );
 
         // 加载 PositionRange 值
-		axisInfo.positioningPointCount = axisNode.child("Positions").attribute("positioningPointCount").as_int();
+        axisInfo.positioningPointCount = axisNode.child("Positions").attribute("positioningPointCount").as_int();
         for (auto positionNode : axisNode.child("Positions").children("Position")) {
-			bool isEnable = positionNode.attribute("isEnable").as_bool();
+            bool isEnable = positionNode.attribute("isEnable").as_bool();
             std::string description = positionNode.attribute("description").value();
             ValueRange positionRange(
                 positionNode.attribute("min").as_double(),
@@ -87,26 +69,8 @@
     return true;
 }
 
-// 保存配方
-bool RecipeManager::saveRecipe(const std::string& recipeName) {
-    // 生成文件路径
-    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
-
-    // 创建 XML 文档对象
-    pugi::xml_document doc;
-
-    // 如果轴数据为空,生成默认配方
-    if (m_axes.empty()) {
-        generateDefaultRecipe();
-    }
-
-    // 添加配方根节点
-    auto recipe = doc.append_child("Recipe");
-
-    // 添加轴列表节点
-    auto axesNode = recipe.append_child("Axes");
-
-    // 遍历所有轴数据并写入 XML
+// 保存轴信息
+void RecipeManager::saveAxes(pugi::xml_node& axesNode) {
     for (const auto& axisEntry : m_axes) {
         const AxisInfo& axisInfo = axisEntry.second;
 
@@ -115,8 +79,6 @@
         axisNode.append_attribute("number") = axisInfo.number.c_str();
         axisNode.append_attribute("description") = axisInfo.description.c_str();
         axisNode.append_attribute("start_address") = axisInfo.startAddress.c_str();
-        //axisNode.append_attribute("maxPositioningSpeed") = axisInfo.maxPositioningSpeed;
-        //axisNode.append_attribute("maxManualSpeed") = axisInfo.maxManualSpeed;
 
         // 保存 ValueRange 值
         auto jog_distance = axisNode.append_child("jog_distance");
@@ -156,6 +118,50 @@
             positionNode.append_attribute("current") = position.range.currentValue;
         }
     }
+}
+
+// 设置配方文件夹
+void RecipeManager::setRecipeFolder(const std::string& folderPath) {
+    m_recipeFolder = folderPath;
+}
+
+// 加载配方(如果文件不存在,加载默认数据)
+bool RecipeManager::loadRecipe(const std::string& recipeName) {
+    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
+    pugi::xml_document doc;
+
+    if (!doc.load_file(filePath.c_str())) {
+        std::cerr << "Recipe file not found: " << filePath << ". Loading default recipe." << std::endl;
+        generateDefaultRecipe();
+        return false; // 文件不存在,但加载了默认数据
+    }
+
+    auto recipeNode = doc.child("Recipe");
+    auto axesNode = recipeNode.child("Axes");
+    loadAxes(axesNode);  // 加载轴信息
+
+    return true;
+}
+
+// 保存配方
+bool RecipeManager::saveRecipe(const std::string& recipeName) {
+    // 生成文件路径
+    std::string filePath = m_recipeFolder + "/" + recipeName + ".xml";
+
+    // 创建 XML 文档对象
+    pugi::xml_document doc;
+
+    // 如果轴数据为空,生成默认配方
+    if (m_axes.empty()) {
+        generateDefaultRecipe();
+    }
+
+    // 添加配方根节点
+    auto recipeNode = doc.append_child("Recipe");
+
+    // 添加轴信息
+    auto axesNode = recipeNode.append_child("Axes");
+    saveAxes(axesNode);
 
     // 保存 XML 文件
     return doc.save_file(filePath.c_str());
diff --git a/SourceCode/Bond/BondEq/FileManager/RecipeManager.h b/SourceCode/Bond/BondEq/FileManager/RecipeManager.h
index f0c873c..3407874 100644
--- a/SourceCode/Bond/BondEq/FileManager/RecipeManager.h
+++ b/SourceCode/Bond/BondEq/FileManager/RecipeManager.h
@@ -88,6 +88,10 @@
 private:
     RecipeManager();
 
+    // 轴加载和保存函数
+    bool loadAxes(pugi::xml_node axesNode);
+    void saveAxes(pugi::xml_node& axesNode);
+
 private:
     std::string m_recipeFolder;      // 配方文件夹路径
     std::map<int, AxisInfo> m_axes;  // 轴信息缓存
diff --git a/SourceCode/Bond/BondEq/Resource.h b/SourceCode/Bond/BondEq/Resource.h
index 90ab0eb..20a1626 100644
--- a/SourceCode/Bond/BondEq/Resource.h
+++ b/SourceCode/Bond/BondEq/Resource.h
Binary files differ
diff --git a/SourceCode/Bond/BondEq/ToolUnits.cpp b/SourceCode/Bond/BondEq/ToolUnits.cpp
index f9022f8..a9b5403 100644
--- a/SourceCode/Bond/BondEq/ToolUnits.cpp
+++ b/SourceCode/Bond/BondEq/ToolUnits.cpp
@@ -247,3 +247,43 @@
 	strText.Format(_T("%.03f"), value);
 	pWnd->SetDlgItemText(nCtrlId, strText);
 }
+
+std::vector<CString> CToolUnits::GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension)
+{
+	std::vector<CString> fileNames;
+
+	// 确保目录路径最后有反斜杠
+	CString strSearchPath = strFolderPath;
+	if (strSearchPath[strSearchPath.GetLength() - 1] != '\\') {
+		strSearchPath += '\\';
+	}
+
+	CString finalExtension = strExtension;
+	if (finalExtension.Find('.') == -1) {
+		finalExtension = '.' + finalExtension;
+	}
+	strSearchPath += "*" + finalExtension;
+
+	std::unique_ptr<CFileFind> finder = std::make_unique<CFileFind>();
+	BOOL bWorking = finder->FindFile(strSearchPath);
+
+	// 遍历文件夹
+	while (bWorking) {
+		bWorking = finder->FindNextFile();
+		if (!finder->IsDirectory()) {
+			CString fileName = finder->GetFileName();
+			int dotPos = fileName.ReverseFind('.');
+			if (dotPos != -1) {
+				fileName = fileName.Left(dotPos);
+			}
+			fileNames.push_back(fileName);
+		}
+	}
+
+	return fileNames;
+}
+
+std::string CToolUnits::getRecipePath()
+{
+	return getCurrentExePath() + "\\Recipe";
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/ToolUnits.h b/SourceCode/Bond/BondEq/ToolUnits.h
index cfd7de0..2e27f4c 100644
--- a/SourceCode/Bond/BondEq/ToolUnits.h
+++ b/SourceCode/Bond/BondEq/ToolUnits.h
@@ -25,5 +25,7 @@
 	static BOOL getBit(const char c, int index);
 	static void setBit(char* p, int index);
 	static void setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value);
+	static std::vector<CString> GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension);
+	static std::string getRecipePath();
 };
 
diff --git a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
index d8add62..a7b1d6a 100644
--- a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
+++ b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
@@ -299,7 +299,6 @@
 	RecipeManager& recipeManager = RecipeManager::getInstance();
 	if (m_strRecipeName.IsEmpty() || !recipeManager.loadRecipe(std::string(CT2A(m_strRecipeName)))) {
 		AfxMessageBox(_T("鍔犺浇閰嶆柟澶辫触锛�"));
-		recipeManager.saveRecipe(std::string(CT2A(m_strRecipeName)));
 		return;
 	}
 
diff --git a/SourceCode/Bond/BondEq/View/RecipeLiseDlg.cpp b/SourceCode/Bond/BondEq/View/RecipeLiseDlg.cpp
deleted file mode 100644
index a0c3848..0000000
--- a/SourceCode/Bond/BondEq/View/RecipeLiseDlg.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-锘�// RecipeLiseDlg.cpp: 瀹炵幇鏂囦欢
-//
-
-#include "stdafx.h"
-#include "BondEq.h"
-#include "afxdialogex.h"
-#include "RecipeLiseDlg.h"
-
-
-// CRecipeLiseDlg 瀵硅瘽妗�
-
-IMPLEMENT_DYNAMIC(CRecipeLiseDlg, CDialogEx)
-
-CRecipeLiseDlg::CRecipeLiseDlg(CWnd* pParent /*=nullptr*/)
-	: CDialogEx(IDD_DIALOG_RECIPE_LIST, pParent)
-{
-
-}
-
-CRecipeLiseDlg::~CRecipeLiseDlg()
-{
-}
-
-void CRecipeLiseDlg::DoDataExchange(CDataExchange* pDX)
-{
-	CDialogEx::DoDataExchange(pDX);
-	DDX_Control(pDX, IDC_CUSTOM_RECIPE_LIST, m_grid);
-}
-
-
-BEGIN_MESSAGE_MAP(CRecipeLiseDlg, CDialogEx)
-END_MESSAGE_MAP()
-
-
-// CRecipeLiseDlg 娑堟伅澶勭悊绋嬪簭
diff --git a/SourceCode/Bond/BondEq/View/RecipeLiseDlg.h b/SourceCode/Bond/BondEq/View/RecipeLiseDlg.h
deleted file mode 100644
index 230844b..0000000
--- a/SourceCode/Bond/BondEq/View/RecipeLiseDlg.h
+++ /dev/null
@@ -1,28 +0,0 @@
-锘�#pragma once
-#include "afxdialogex.h"
-#include "GridCtrl.h"
-
-
-// CRecipeLiseDlg 瀵硅瘽妗�
-
-class CRecipeLiseDlg : public CDialogEx
-{
-	DECLARE_DYNAMIC(CRecipeLiseDlg)
-
-public:
-	CRecipeLiseDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
-	virtual ~CRecipeLiseDlg();
-
-// 瀵硅瘽妗嗘暟鎹�
-#ifdef AFX_DESIGN_TIME
-	enum { IDD = IDD_DIALOG_RECIPE_LIST };
-#endif
-
-private:
-	CGridCtrl m_grid;
-
-protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
-
-	DECLARE_MESSAGE_MAP()
-};
diff --git a/SourceCode/Bond/BondEq/View/RecipeListDlg.cpp b/SourceCode/Bond/BondEq/View/RecipeListDlg.cpp
new file mode 100644
index 0000000..b62b949
--- /dev/null
+++ b/SourceCode/Bond/BondEq/View/RecipeListDlg.cpp
@@ -0,0 +1,300 @@
+锘�// RecipeLiseDlg.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "BondEq.h"
+#include "afxdialogex.h"
+#include "RecipeListDlg.h"
+#include "InputDialog.h"
+#include "ToolUnits.h"
+#include <fstream>
+#include <sstream>
+#include <map>
+
+
+// CRecipeListDlg 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CRecipeListDlg, CDialogEx)
+
+CRecipeListDlg::CRecipeListDlg(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DIALOG_RECIPE_LIST, pParent)
+{
+
+}
+
+CRecipeListDlg::~CRecipeListDlg()
+{
+}
+
+void CRecipeListDlg::InitRecipeLise()
+{
+	if (m_grid.GetSafeHwnd() == NULL)
+		return;
+
+	int nRows = 1;
+	int nCols = 4;
+
+	int nFixRows = 1;
+	int nFixCols = 0;
+	int nRowIdx = 0;
+	int nColIdx = 0;
+
+	m_grid.DeleteAllItems();
+	m_grid.SetVirtualMode(FALSE);
+	m_grid.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor); // 璁剧疆鍥哄畾琛岃儗鏅壊
+	m_grid.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor); // 璁剧疆鍥哄畾鍒楄儗鏅壊
+	m_grid.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor);	 // 璁剧疆鍗曞厓鏍艰儗鏅壊
+	m_grid.SetFixedTextColor(g_nGridFixFontColor);						 // 璁剧疆鍥哄畾琛屽垪瀛椾綋棰滆壊
+
+	m_grid.SetRowCount(nRows);
+	m_grid.SetColumnCount(nCols);
+	m_grid.SetFixedRowCount(nFixRows);
+	m_grid.SetFixedColumnCount(nFixCols);
+
+	// Col
+	m_grid.SetColumnWidth(nColIdx, 10);
+	m_grid.SetItemText(nRowIdx, nColIdx++, _T("No."));
+	m_grid.SetColumnWidth(nColIdx, 10);
+	m_grid.SetItemText(nRowIdx, nColIdx++, _T("鍚嶇О"));
+	m_grid.SetColumnWidth(nColIdx, 50);
+	m_grid.SetItemText(nRowIdx, nColIdx++, _T("鎻忚堪"));
+	m_grid.SetColumnWidth(nColIdx, 30);
+	m_grid.SetItemText(nRowIdx, nColIdx++, _T("鍒涘缓鏃堕棿"));
+
+	m_grid.SetFixedRowSelection(FALSE);
+	m_grid.SetFixedColumnSelection(FALSE);
+	m_grid.SetEditable(TRUE);
+	m_grid.SetRowResize(FALSE);
+	m_grid.SetColumnResize(TRUE);
+	m_grid.ExpandColumnsToFit(TRUE);
+	m_grid.SetListMode(TRUE);				// 鍚敤鍒楄〃妯″紡
+	m_grid.EnableSelection(TRUE);			// 鍚敤閫夋嫨
+	m_grid.SetSingleRowSelection(TRUE);		// 鑷姩鏁磋楂樹寒锛堥檺鍒朵负鍗曡閫夋嫨锛�
+	m_grid.ExpandLastColumn();				// 鏈�鍚庝竴鍒楀~鍏呯綉鏍�
+
+	FillRecipeLise();
+}
+
+void CRecipeListDlg::FillRecipeLise()
+{
+	// 娓呴櫎鏁版嵁琛岋紝淇濈暀琛ㄥご
+	for (int i = 1; i < m_grid.GetRowCount(); i++) {
+		m_grid.DeleteRow(i);
+	}
+
+	// 1. 閬嶅巻鏂囦欢澶逛笅鎵�鏈塜ML鏂囦欢
+	std::string strRecipePath = CToolUnits::getRecipePath();
+	std::vector<CString> vecFile = CToolUnits::GetFileNamesInDirectory(strRecipePath.c_str(), _T(".xml"));
+
+	// 2. 璇诲彇 RecipeList.txt 鏂囦欢
+	std::map<CString, std::pair<CString, CString>> recipeData; // {閰嶆柟鍚�, {鎻忚堪, 鍒涘缓鏃堕棿}}
+	std::ifstream inFile(strRecipePath + "\\RecipeList.txt");
+	if (inFile.is_open()) {
+		std::string line;
+		while (std::getline(inFile, line)) {
+			if (line.empty()) continue; // 璺宠繃绌鸿
+
+			std::istringstream ss(line);
+			std::string name, description, createTime;
+
+			// CSV鏍煎紡瑙f瀽锛堥�楀彿鍒嗛殧锛�
+			if (std::getline(ss, name, ',') &&
+				std::getline(ss, description, ',') &&
+				std::getline(ss, createTime)) {
+				recipeData[CString(name.c_str())] = std::make_pair(CString(description.c_str()), CString(createTime.c_str()));
+			}
+		}
+		inFile.close();
+	}
+
+	// 3. 鏇存柊琛ㄦ牸鏁版嵁
+	int rowIdx = 1;
+	m_grid.SetRowCount(static_cast<int>(vecFile.size()) + 1);
+	for (const auto& fileName : vecFile) {
+		// 浠� RecipeList.txt 鏁版嵁涓煡鎵惧搴旂殑鎻忚堪鍜屽垱寤烘椂闂�
+		CString description = _T("");
+		CString createTime = _T("");
+		auto it = recipeData.find(fileName);
+		if (it != recipeData.end()) {
+			description = it->second.first;  // 閰嶆柟鎻忚堪
+			createTime = it->second.second;  // 鍒涘缓鏃堕棿
+		}
+
+		// 濉厖琛ㄦ牸鏁版嵁
+		m_grid.SetItemText(rowIdx, 0, CString(std::to_string(rowIdx).c_str())); // No.
+		m_grid.SetItemText(rowIdx, 1, fileName);								// 閰嶆柟鍚嶇О
+		m_grid.SetItemText(rowIdx, 2, description);								// 閰嶆柟鎻忚堪
+		m_grid.SetItemText(rowIdx, 3, createTime);								// 鍒涘缓鏃堕棿
+
+		m_grid.SetItemState(rowIdx, 0, GVIS_READONLY);
+		m_grid.SetItemState(rowIdx, 1, GVIS_READONLY);
+		m_grid.SetItemState(rowIdx, 3, GVIS_READONLY);
+
+		++rowIdx;
+	}
+
+	m_grid.ExpandColumnsToFit(FALSE);
+	m_grid.ExpandLastColumn();
+	m_grid.Invalidate();
+	m_grid.UpdateWindow();
+}
+
+void CRecipeListDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+	DDX_Control(pDX, IDC_CUSTOM_RECIPE_LIST, m_grid);
+}
+
+
+BEGIN_MESSAGE_MAP(CRecipeListDlg, CDialogEx)
+	ON_BN_CLICKED(IDC_BUTTON_CREATE_RECIPE, &CRecipeListDlg::OnBnClickedButtonCreateRecipe)
+	ON_BN_CLICKED(IDC_BUTTON_DELETE_RECIPE, &CRecipeListDlg::OnBnClickedButtonDeleteRecipe)
+END_MESSAGE_MAP()
+
+
+// CRecipeListDlg 娑堟伅澶勭悊绋嬪簭
+
+
+BOOL CRecipeListDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// TODO:  鍦ㄦ娣诲姞棰濆鐨勫垵濮嬪寲
+	InitRecipeLise();
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+	// 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+void CRecipeListDlg::OnBnClickedButtonCreateRecipe()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	CInputDialog inputDialog(_T("閰嶆柟鍚嶇О"), _T("璇疯緭鍏ラ厤鏂瑰悕绉帮細"));
+	if (inputDialog.DoModal() != IDOK) {
+		return;
+	}
+	CString newRecipeName = inputDialog.GetInputText();
+
+	// 楠岃瘉鍚嶇О涓嶉噸澶�
+	std::string recipePath = CToolUnits::getRecipePath();
+	std::string recipeListPath = recipePath + "\\RecipeList.txt";
+	std::vector<CString> existingFiles = CToolUnits::GetFileNamesInDirectory(recipePath.c_str(), ".xml");
+
+	for (const auto& fileName : existingFiles) {
+		if (newRecipeName.Compare(fileName) == 0) {
+			AfxMessageBox(_T("閰嶆柟鍚嶇О宸插瓨鍦紝璇疯緭鍏ュ叾浠栧悕绉帮紒"));
+			return;
+		}
+	}
+
+	// 妫�鏌ユ槸鍚﹁澶嶅埗閫変腑閰嶆柟
+	CString strCopyRecipe = _T("");
+	for (int i = 1; i < m_grid.GetRowCount(); i++) {
+		if (m_grid.IsCellSelected(i, 1)) {
+			strCopyRecipe = m_grid.GetItemText(i, 1);
+
+			CString strMessage;
+			strMessage.Format(_T("Copy [%s] -> [%s]?"), strCopyRecipe, newRecipeName);
+			if (AfxMessageBox(strMessage, MB_YESNO | MB_ICONQUESTION) != IDYES) {
+				strCopyRecipe = _T("");
+			}
+			break;
+		}
+	}
+	
+	// 鍒涘缓鏂扮殑XML鏂囦欢
+	CString newRecipeFile = CString(recipePath.c_str()) + "\\" + newRecipeName + ".xml";
+	if (!strCopyRecipe.IsEmpty()) {
+		CString sourceFile = CString(recipePath.c_str()) + "\\" + strCopyRecipe + ".xml";
+		CopyFile(sourceFile, newRecipeFile, FALSE);
+	}
+	else {
+		// 鐢熸垚榛樿XML鏂囦欢
+		RecipeManager& recipeManager = RecipeManager::getInstance();
+		recipeManager.generateDefaultRecipe();
+		if (!recipeManager.saveRecipe(std::string(CT2A(newRecipeName)))) {
+			AfxMessageBox(_T("鍒涘缓閰嶆柟澶辫触锛�"));
+			return;
+		}
+	}
+
+	// 鏇存柊 RecipeList.txt
+	std::ofstream outFile(recipeListPath, std::ios::app); // 杩藉姞妯″紡
+	if (outFile.is_open()) {
+		SYSTEMTIME sysTime;
+		GetLocalTime(&sysTime);
+		char buffer[64];
+		sprintf_s(buffer, "%04d-%02d-%02d %02d:%02d:%02d",
+			sysTime.wYear, sysTime.wMonth, sysTime.wDay,
+			sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
+
+		outFile << CT2A(newRecipeName) << ",榛樿鎻忚堪," << buffer << std::endl;
+		outFile.close();
+	}
+
+	// 鍒锋柊缃戞牸鎺т欢
+	FillRecipeLise();
+}
+
+void CRecipeListDlg::OnBnClickedButtonDeleteRecipe()
+{
+	// TODO: 鍦ㄦ娣诲姞鎺т欢閫氱煡澶勭悊绋嬪簭浠g爜
+	int nSelect = -1;
+	for (int i = 1; i < m_grid.GetRowCount(); i++) {
+		if (m_grid.IsCellSelected(i, 1)) {
+			nSelect = i;
+			break;
+		}
+	}
+
+	if (nSelect < 0) {
+		AfxMessageBox(_T("璇烽�夋嫨瑕佸垹闄ょ殑閰嶆柟锛�"));
+		return;
+	}
+
+	CString selectedRecipe = m_grid.GetItemText(nSelect, 1);
+	if (selectedRecipe.IsEmpty()) {
+		AfxMessageBox(_T("閰嶆柟鍚嶇О鏃犳晥锛�"));
+		return;
+	}
+
+	CString message = _T("纭畾瑕佸垹闄ら厤鏂� \"") + selectedRecipe + _T("\" 鍚楋紵");
+	if (AfxMessageBox(message, MB_YESNO | MB_ICONQUESTION) != IDYES) {
+		return;
+	}
+
+	// 鍒犻櫎XML鏂囦欢
+	std::string recipePath = CToolUnits::getRecipePath();
+	CString xmlFilePath = CString(recipePath.c_str()) + "\\" + selectedRecipe + ".xml";
+	if (!DeleteFile(xmlFilePath)) {
+		AfxMessageBox(_T("鍒犻櫎XML鏂囦欢澶辫触锛�"));
+		return;
+	}
+
+	// 鏇存柊RecipeList.txt鏂囦欢
+	std::string recipeListPath = recipePath + "\\RecipeList.txt";
+	std::ifstream inFile(recipeListPath);
+	std::ofstream outFile(recipeListPath + ".tmp"); // 鍒涘缓涓存椂鏂囦欢
+
+	if (inFile.is_open() && outFile.is_open()) {
+		std::string line;
+		while (std::getline(inFile, line)) {
+			std::istringstream ss(line);
+			std::string name;
+			if (std::getline(ss, name, ',')) {
+				if (selectedRecipe != CString(name.c_str())) {
+					outFile << line << std::endl; // 淇濈暀涓嶅尮閰嶇殑琛�
+				}
+			}
+		}
+		inFile.close();
+		outFile.close();
+
+		// 鏇挎崲鏂囦欢
+		DeleteFile(CString(recipeListPath.c_str()));
+		MoveFile(CString((recipeListPath + ".tmp").c_str()), CString(recipeListPath.c_str()));
+	}
+
+	// 鍒锋柊缃戞牸鎺т欢
+	FillRecipeLise();
+}
diff --git a/SourceCode/Bond/BondEq/View/RecipeListDlg.h b/SourceCode/Bond/BondEq/View/RecipeListDlg.h
new file mode 100644
index 0000000..6d442e6
--- /dev/null
+++ b/SourceCode/Bond/BondEq/View/RecipeListDlg.h
@@ -0,0 +1,34 @@
+锘�#pragma once
+#include "afxdialogex.h"
+#include "GridCtrl.h"
+
+
+// CRecipeListDlg 瀵硅瘽妗�
+
+class CRecipeListDlg : public CDialogEx
+{
+	DECLARE_DYNAMIC(CRecipeListDlg)
+
+public:
+	CRecipeListDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
+	virtual ~CRecipeListDlg();
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DIALOG_RECIPE_LIST };
+#endif
+
+private:
+	void InitRecipeLise();
+	void FillRecipeLise();
+
+private:
+	CGridCtrl m_grid;
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 鏀寔
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBnClickedButtonCreateRecipe();
+	afx_msg void OnBnClickedButtonDeleteRecipe();
+	DECLARE_MESSAGE_MAP()
+};
diff --git a/SourceCode/Bond/BondEq/stdafx.h b/SourceCode/Bond/BondEq/stdafx.h
index 95c78f8..cef3da3 100644
--- a/SourceCode/Bond/BondEq/stdafx.h
+++ b/SourceCode/Bond/BondEq/stdafx.h
@@ -56,7 +56,7 @@
 // 控件样式
 static UINT g_nGridFixCellColor = RGB(144, 200, 246);
 static UINT g_nGridFixFontColor = RGB(0, 0, 0);
-static UINT g_nGridCellColor = RGB(255, 255, 255);
+static UINT g_nGridCellColor = RGB(255, 255, 224);
 static UINT g_nGridCellColor_NonSelect = RGB(150, 150, 150);
 static UINT g_nGridCellReadyColor = RGB(255, 255, 0);
 static UINT g_nGridCellOnColor = RGB(255, 69, 0);

--
Gitblit v1.9.3