1. 添加配方管理类(数据库)
2. 修改用户管理和系统日志管理类的路径和名称
3. 修复合并代码导致系统日志管理窗口的资源异常的问题
已添加2个文件
已修改7个文件
574 ■■■■■ 文件已修改
SourceCode/Bond/Servo/RecipeManager.cpp 446 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.h 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.cpp 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/SystemLogManager.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/UserManager.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,446 @@
#include "stdafx.h"
#include "RecipeManager.h"
#include <sstream>
#include <iomanip>
#include <fstream>
#include <iostream>
std::recursive_mutex RecipeManager::m_mutex;
RecipeManager& RecipeManager::getInstance() {
    static RecipeManager instance;
    return instance;
}
RecipeManager::RecipeManager() {
    m_pDB = new BL::SQLiteDatabase();
}
RecipeManager::~RecipeManager() {
    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);
    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;
    }
    const std::string createRecipeTable = R"(
        CREATE TABLE IF NOT EXISTS recipes (
            ppid TEXT PRIMARY KEY NOT NULL,
            description TEXT,
            create_time TEXT DEFAULT (datetime('now', 'localtime'))
        );
    )";
    const std::string createDeviceTable = R"(
        CREATE TABLE IF NOT EXISTS recipe_devices (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ppid TEXT NOT NULL,
            device_id INTEGER NOT NULL,
            device_name TEXT NOT NULL,
            recipe_id INTEGER NOT NULL,
            FOREIGN KEY(ppid) REFERENCES recipes(ppid) ON DELETE CASCADE,
            UNIQUE (ppid, device_id),
            UNIQUE (ppid, device_name)
        );
    )";
    return m_pDB->executeQuery(createRecipeTable)
        && m_pDB->executeQuery(createDeviceTable);
}
void RecipeManager::termRecipeTable() {
    if (!m_pDB) {
        return;
    }
    m_pDB->disconnect();
}
bool RecipeManager::destroyRecipeTable() {
    if (!m_pDB) {
        return false;
    }
    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");
}
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");
}
bool RecipeManager::addRecipe(const RecipeInfo& recipe) {
    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::lock_guard<std::recursive_mutex> lock(m_mutex);
    // å¼€å§‹äº‹åŠ¡
    m_pDB->executeQuery("BEGIN TRANSACTION;");
    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;
    }
    for (const auto& device : recipe.vecDeviceList) {
        std::ostringstream devSql;
        devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('"
            << recipe.strPPID << "', "
            << device.nDeviceID << ", '"
            << device.strDeviceName << "', "
            << device.nRecipeID << ");";
        if (!m_pDB->executeQuery(devSql.str())) {
            std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl;
            m_pDB->executeQuery("ROLLBACK;");
            return false;
        }
    }
    // æäº¤äº‹åŠ¡
    m_pDB->executeQuery("COMMIT;");
    return true;
}
bool RecipeManager::addRecipeDevice(const std::string& ppid, const DeviceRecipe& device) {
    if (!m_pDB || ppid.empty() || device.nDeviceID <= 0 || device.nRecipeID <= 0) {
        std::cerr << "[addRecipeDevice] Invalid input." << std::endl;
        return false;
    }
    // æ£€æŸ¥ ppid æ˜¯å¦å­˜åœ¨
    if (!ppidExists(ppid)) {
        std::cerr << "[addRecipeDevice] PPID does not exist: " << ppid << std::endl;
        return false;
    }
    // æ’入设备记录
    std::ostringstream oss;
    oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('"
        << ppid << "', "
        << device.nDeviceID << ", '"
        << device.strDeviceName << "', "
        << device.nRecipeID << ");";
    std::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;
    }
    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());
}
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;
    }
    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::vector<RecipeInfo> RecipeManager::getAllRecipes() {
    if (!m_pDB) {
        return {};
    }
    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];
        std::ostringstream devQuery;
        devQuery << "SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" << info.strPPID << "';";
        auto devs = m_pDB->fetchResults(devQuery.str());
        for (const auto& dev : devs) {
            DeviceRecipe dr;
            dr.strPPID = info.strPPID;
            try {
                dr.nDeviceID = std::stoi(dev[0]);
                dr.strDeviceName = dev[1];
                dr.nRecipeID = std::stoi(dev[2]);
            }
            catch (...) {
                std::cerr << "Invalid data in recipe_devices for PPID: " << info.strPPID << std::endl;
                continue;
            }
            info.vecDeviceList.push_back(dr);
        }
        recipes.push_back(info);
    }
    return recipes;
}
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;
    }
    info.strPPID = rows[0][0];
    info.strDescription = rows[0][1];
    info.strCreateTime = rows[0][2];
    auto devs = m_pDB->fetchResults("SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" + ppid + "';");
    for (const auto& dev : devs) {
        DeviceRecipe dr;
        dr.strPPID = ppid;
        try {
            dr.nDeviceID = std::stoi(dev[0]);
            dr.strDeviceName = dev[1];
            dr.nRecipeID = std::stoi(dev[2]);
        }
        catch (...) {
            std::cerr << "Invalid data in recipe_devices for PPID: " << ppid << std::endl;
            continue;
        }
        info.vecDeviceList.push_back(dr);
    }
    return info;
}
int RecipeManager::getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID) {
    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 << ";";
    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;
    }
    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;
}
bool RecipeManager::deleteRecipeByPPID(const std::string& ppid) {
    if (!m_pDB) {
        return false;
    }
    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 (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);
}
bool RecipeManager::updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID) {
    if (!m_pDB || ppid.empty() || nDeviceID <= 0 || nNewRecipeID <= 0) {
        return false;
    }
    std::ostringstream query;
    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());
}
bool RecipeManager::updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID) {
    if (!m_pDB || ppid.empty() || strDeviceName.empty() || nNewRecipeID <= 0) {
        return false;
    }
    std::ostringstream query;
    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());
}
void RecipeManager::insertMockData() {
    if (!m_pDB) {
        return;
    }
    RecipeInfo recipe;
    recipe.strPPID = "P1001";
    recipe.strDescription = "Main Board Burn-in";
    recipe.vecDeviceList = {
        {1, 101, "P1001","Burner A"},
        {2, 102, "P1001", "Burner B"}
    };
    addRecipe(recipe);
}
bool RecipeManager::readRecipeFile(const std::string& filename) {
    if (!m_pDB) {
        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
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string cell;
        std::string ppid, description, createTime;
        DeviceRecipe dev;
        std::getline(ss, ppid, ',');
        std::getline(ss, cell, ',');
        try { dev.nDeviceID = std::stoi(cell); }
        catch (...) { continue; }
        std::getline(ss, dev.strDeviceName, ',');
        std::getline(ss, cell, ',');
        try { dev.nRecipeID = std::stoi(cell); }
        catch (...) { continue; }
        std::getline(ss, description, ',');
        std::getline(ss, createTime, ',');
        dev.strPPID = ppid;
        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;
        }
    }
    return true;
}
bool RecipeManager::saveRecipeFile(const std::string& filename) {
    if (!m_pDB) {
        return false;
    }
    std::ofstream file(filename);
    if (!file.is_open()) {
        return false;
    }
    file << "PPID,DeviceID,DeviceName,RecipeID,Description,CreateTime\n";
    auto recipes = getAllRecipes();
    for (const auto& recipe : recipes) {
        for (const auto& dev : recipe.vecDeviceList) {
            file << recipe.strPPID << ","
                << dev.nDeviceID << ","
                << dev.strDeviceName << ","
                << dev.nRecipeID << ","
                << recipe.strDescription << ","
                << recipe.strCreateTime << "\n";
        }
    }
    return true;
}
SourceCode/Bond/Servo/RecipeManager.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
#ifndef RECIPE_MANAGER_H
#define RECIPE_MANAGER_H
#include <string>
#include <vector>
#include <mutex>
#include <unordered_map>
#include "Database.h"
// å•个设备配方映射信息
struct DeviceRecipe {
    int nDeviceID;               // è®¾å¤‡ID
    int nRecipeID;               // è¯¥è®¾å¤‡å¯¹åº”的子配方ID
    std::string strPPID;         // é…æ–¹ID(主键)
    std::string strDeviceName;   // è®¾å¤‡åç§°
};
// é…æ–¹ä¿¡æ¯
struct RecipeInfo {
    std::string strPPID;         // é…æ–¹ID
    std::string strDescription;  // é…æ–¹æè¿°
    std::string strCreateTime;   // åˆ›å»ºæ—¶é—´
    std::vector<DeviceRecipe> vecDeviceList;  // å…³è”的设备信息列表
};
using RecipeMap = std::unordered_map<std::string, RecipeInfo>; // æŒ‰ PPID æ˜ å°„的配方表
class RecipeManager {
public:
    // èŽ·å–å•ä¾‹
    static RecipeManager& getInstance();
    // åˆå§‹åŒ–配方数据库
    bool initRecipeTable();
    // é”€æ¯è¡¨æˆ–关闭连接
    void termRecipeTable();
    bool destroyRecipeTable();
    // æ£€æŸ¥ PPID æ˜¯å¦å­˜åœ¨
    bool ppidExists(const std::string& ppid);
    // æ£€æŸ¥è®¾å¤‡æ˜¯å¦å­˜åœ¨äºŽæŒ‡å®š PPID çš„配方中
    bool deviceExists(const std::string& ppid, int nDeviceID);
    // æ·»åŠ ä¸€ä¸ªé…æ–¹åŠå…¶è®¾å¤‡æ˜ å°„
    bool addRecipe(const RecipeInfo& recipe);
    // æ·»åŠ è®¾å¤‡åˆ°æŒ‡å®šé…æ–¹
    bool addRecipeDevice(const std::string& ppid, const DeviceRecipe& device);
    // åˆ é™¤æŒ‡å®š PPID çš„设备配方
    bool deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID);
    // åˆ é™¤æŒ‡å®š PPID çš„设备配方(通过设备名称)
    bool deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName);
    // æŸ¥è¯¢æ‰€æœ‰é…æ–¹
    std::vector<RecipeInfo> getAllRecipes();
    // æŒ‰ PPID æŸ¥è¯¢é…æ–¹
    RecipeInfo getRecipeByPPID(const std::string& ppid);
    // æ ¹æ® PPID å’Œè®¾å¤‡ID èŽ·å–è®¾å¤‡é…æ–¹ID
    int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID);
    // æ ¹æ® PPID å’Œè®¾å¤‡åç§° èŽ·å–è®¾å¤‡é…æ–¹ID
    int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName);
    // åˆ é™¤æŒ‡å®š PPID çš„配方
    bool deleteRecipeByPPID(const std::string& ppid);
    // æ›´æ–°æŒ‡å®š PPID çš„配方
    bool updateRecipe(const RecipeInfo& recipe);
    // æ›´æ–°è®¾å¤‡é…æ–¹ID(通过 PPID å’Œè®¾å¤‡ID)
    bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID);
    // æ›´æ–°è®¾å¤‡é…æ–¹ID(通过 PPID å’Œè®¾å¤‡åç§°ï¼‰
    bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID);
    // æ¨¡æ‹Ÿæ’入数据(测试用)
    void insertMockData();
    // è¯»å–配方文件(CSV æˆ– JSON)
    bool readRecipeFile(const std::string& filename);
    // ä¿å­˜é…æ–¹åˆ°æ–‡ä»¶
    bool saveRecipeFile(const std::string& filename);
private:
    RecipeManager();
    ~RecipeManager();
    RecipeManager(const RecipeManager&) = delete;
    RecipeManager& operator=(const RecipeManager&) = delete;
private:
    BL::Database* m_pDB;
    static std::recursive_mutex m_mutex;
};
#endif // RECIPE_MANAGER_H
SourceCode/Bond/Servo/Servo.cpp
@@ -11,6 +11,7 @@
#include "TransferManager.h"
#include "SystemLogManager.h"
#include "UserManager.h"
#include "RecipeManager.h"
#include "VerticalLine.h"
#include "HorizontalLine.h"
#include "EqsGraphWnd.h"
@@ -134,7 +135,6 @@
        AfxMessageBox(errorMsg, MB_ICONERROR);
        return FALSE;
    }
    AlarmManager::getInstance().insertMockData();
    // åˆå§‹åŒ–SECS运行设置管理库
    try {
@@ -194,6 +194,19 @@
        return FALSE;
    }
    // åˆå§‹åŒ–配方管理库
    try {
        if (!RecipeManager::getInstance().initRecipeTable()) {
            AfxMessageBox("初始化配方管理库失败!");
            return FALSE;
        }
    }
    catch (const std::exception& ex) {
        CString errorMsg;
        errorMsg.Format(_T("初始化配方管理库失败:%s"), CString(ex.what()));
        AfxMessageBox(errorMsg, MB_ICONERROR);
        return FALSE;
    }
    CServoDlg dlg;
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -317,6 +317,7 @@
    <ClInclude Include="PageTransferLog.h" />
    <ClInclude Include="PortConfigurationDlg.h" />
    <ClInclude Include="ProductionLogManager.h" />
    <ClInclude Include="RecipeManager.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SECSRuntimeManager.h" />
    <ClInclude Include="SecsTestDlg.h" />
@@ -454,6 +455,7 @@
    <ClCompile Include="PageTransferLog.cpp" />
    <ClCompile Include="PortConfigurationDlg.cpp" />
    <ClCompile Include="ProductionLogManager.cpp" />
    <ClCompile Include="RecipeManager.cpp" />
    <ClCompile Include="SECSRuntimeManager.cpp" />
    <ClCompile Include="SecsTestDlg.cpp" />
    <ClCompile Include="Servo.cpp" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -167,6 +167,7 @@
    <ClCompile Include="SystemLogManager.cpp" />
    <ClCompile Include="UserManager.cpp" />
    <ClCompile Include="InputDialog.cpp" />
    <ClCompile Include="RecipeManager.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -339,6 +340,7 @@
    <ClInclude Include="UserManager.h" />
    <ClInclude Include="SystemLogManager.h" />
    <ClInclude Include="InputDialog.h" />
    <ClInclude Include="RecipeManager.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/SystemLogManager.cpp
@@ -42,7 +42,7 @@
    }
    // æž„造数据库路径
    std::string dbPath = dbDir + "\\SystemLog.db";
    std::string dbPath = dbDir + "\\SystemLogManager.db";
    // è¿žæŽ¥æ•°æ®åº“
    if (!m_pDB->connect(dbPath, true)) {
SourceCode/Bond/Servo/UserManager.cpp
@@ -7,7 +7,7 @@
#include <sstream>
const std::string SESSION_FILE = R"(session.dat)";
const std::string DATABASE_FILE = R"(BondEq.db)";
const std::string DATABASE_FILE = R"(UserManager.db)";
const std::string INITIAL_ADMIN_USERNAME = "admin";
const std::string INITIAL_ADMIN_PASSWORD = "admin";
@@ -160,7 +160,7 @@
    char szPath[MAX_PATH];
    GetModuleFileName(NULL, szPath, MAX_PATH);
    std::string exePath(szPath);
    std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
    std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB\\";
    // æ£€æŸ¥å¹¶åˆ›å»ºconfig文件夹
    DWORD fileAttr = GetFileAttributes(dbDir.c_str());
SourceCode/Bond/Servo/resource.h
Binary files differ