mrDarker
2025-09-01 d78ab86af696b7b762823db10ba0f126e697ae2d
1. 添加手动输入配方名称
已修改5个文件
210 ■■■■■ 文件已修改
SourceCode/Bond/Servo/PageRecipe.cpp 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.cpp 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.cpp
@@ -6,6 +6,7 @@
#include "afxdialogex.h"
#include "PageRecipe.h"
#include "MsgDlg.h"
#include "InputDialog.h"
#include "RecipeDeviceBindDlg.h"
// CPageRecipe 对话框
@@ -146,8 +147,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);
        }
@@ -167,6 +178,22 @@
        return;
    }
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
    if (pComboBox == nullptr || !::IsWindow(pComboBox->m_hWnd)) {
        return;
    }
    int nEqSel = pComboBox->GetCurSel();
    if (nEqSel == CB_ERR) {
        return;
    }
    auto& mgr = RecipeManager::getInstance();
    SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nEqSel);
    if (pEq == nullptr) {
        return;
    }
    // 清空当前CListCtrl中的所有项
    pListCtrl->DeleteAllItems();
    if (pList == nullptr) {
@@ -179,6 +206,13 @@
        int index = m_listPPID.InsertItem(m_listPPID.GetItemCount(), _T(""));
        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);
        if (strRecipeName.empty()) {
            strRecipeName = std::to_string(item.second);
            mgr.addDeviceRecipe(pEq->getName(), item.second, strRecipeName);
        }
        m_listPPID.SetItemText(index, 3, strRecipeName.c_str());
    }
    // 获取列数
@@ -416,15 +450,40 @@
void CPageRecipe::OnBnClickedButtonModify()
{
    // TODO: 在此添加控件通知处理程序代码
    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().updateDeviceRecipe(pEq->getName(), _ttoi(strID), std::string(CT2A(strText)))) {
            m_listPPID.SetItemText(nLine, 3, strText);
        }
    }
}
void CPageRecipe::OnBnClickedButtonDelete()
@@ -526,7 +585,7 @@
    int selectedCount = 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_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);
}
@@ -537,7 +596,7 @@
    int nEqSel = pComboBox->GetCurSel();
    int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd());
    GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0 && selectedCount > 0);
    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);
SourceCode/Bond/Servo/PageRecipe.h
@@ -43,4 +43,4 @@
private:
    CListCtrlEx m_listPPID;
};
};
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
@@ -95,9 +95,15 @@
    pCombo->ResetContent();
    for (const auto& pair : mapRecipeIds) {
        int nRecipeID = pair.second;
        CString strRecipeName;
        strRecipeName.Format(_T("%d"), nRecipeID);
        int idx = pCombo->AddString(strRecipeName);
        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);
SourceCode/Bond/Servo/RecipeManager.cpp
@@ -56,6 +56,7 @@
            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)
@@ -131,11 +132,13 @@
    for (const auto& device : recipe.vecDeviceList) {
        std::ostringstream devSql;
        devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('"
        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.nRecipeID << ", '"
            << device.strRecipeName << "');";
        if (!m_pDB->executeQuery(devSql.str())) {
            std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl;
@@ -163,11 +166,12 @@
    // 插入设备记录
    std::ostringstream oss;
    oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('"
    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.nRecipeID << ", '"
        << device.strRecipeName << "');";
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    return m_pDB->executeQuery(oss.str());
@@ -214,7 +218,7 @@
        info.strCreateTime = row[2];
        std::ostringstream devQuery;
        devQuery << "SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" << info.strPPID << "';";
        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) {
@@ -223,6 +227,7 @@
                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;
@@ -289,13 +294,14 @@
    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 + "';");
    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;
@@ -435,6 +441,88 @@
    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;
    }
    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::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;
    }
    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::string RecipeManager::getDeviceRecipeName(const std::string& deviceName, int nRecipeID) {
    if (!m_pDB || deviceName.empty() || nRecipeID <= 0) {
        return "";
    }
    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 "";
}
bool RecipeManager::deleteDeviceRecipe(const std::string& deviceName, int nRecipeID) {
    if (!m_pDB || deviceName.empty() || nRecipeID <= 0) {
        return false;
    }
    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::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::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;
}
void RecipeManager::insertMockData() {
    if (!m_pDB) {
        return;
@@ -445,11 +533,20 @@
    recipe.strDescription = "Main Board Burn-in";
    recipe.vecDeviceList = {
        {1, 101, "Burner A"},
        {2, 102, "Burner B"}
        {9, 101, "VacuumBake", "VacuumBake"},
        {10, 102, "Bonder1", "Bonder1"},
        {11, 103, "Bonder2", "Bonder2"}
    };
    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) {
@@ -480,6 +577,7 @@
        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, ',');
@@ -509,7 +607,7 @@
        return false;
    }
    file << "PPID,DeviceID,DeviceName,RecipeID,Description,CreateTime\n";
    file << "PPID,DeviceID,DeviceName,RecipeID,RecipeName,Description,CreateTime\n";
    auto recipes = getAllRecipes();
    for (const auto& recipe : recipes) {
        for (const auto& dev : recipe.vecDeviceList) {
@@ -517,6 +615,7 @@
                << dev.nDeviceID << ","
                << dev.strDeviceName << ","
                << dev.nRecipeID << ","
                << dev.strRecipeName << ","
                << recipe.strDescription << ","
                << recipe.strCreateTime << "\n";
        }
SourceCode/Bond/Servo/RecipeManager.h
@@ -11,8 +11,8 @@
struct DeviceRecipe {
    int nDeviceID;               // 设备ID
    int nRecipeID;               // 子配方ID
    std::string strRecipeName;   // 子配方名称
    std::string strDeviceName;   // 设备名称 
    std::string strRecipeName;   // 子配方名称
};
// 配方信息
@@ -91,6 +91,12 @@
    // 更新设备配方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);
    // 模拟插入数据(测试用)
    void insertMockData();