From 863f21995955fb3e9aa471430218967d4e642c27 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期四, 29 五月 2025 16:11:24 +0800
Subject: [PATCH] Merge branch 'liuyang'

---
 SourceCode/Bond/Servo/TransferManager.cpp |  550 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 550 insertions(+), 0 deletions(-)

diff --git a/SourceCode/Bond/Servo/TransferManager.cpp b/SourceCode/Bond/Servo/TransferManager.cpp
new file mode 100644
index 0000000..bfcf457
--- /dev/null
+++ b/SourceCode/Bond/Servo/TransferManager.cpp
@@ -0,0 +1,550 @@
+#include "stdafx.h"
+#include "TransferManager.h"
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <iomanip>
+#include <ctime>
+#include <stdexcept>
+
+// 静态互斥锁初始化
+std::mutex TransferManager::m_mutex;
+
+// 获取 TransferManager 单例
+TransferManager& TransferManager::getInstance() {
+    static TransferManager instance;
+    return instance;
+}
+
+// 构造函数
+TransferManager::TransferManager() {
+    m_pDB = new BL::SQLiteDatabase();
+}
+
+// 析构函数
+TransferManager::~TransferManager() {
+    if (m_pDB) {
+        delete m_pDB;
+        m_pDB = nullptr;
+    }
+}
+
+// 任务状态转换成 int 类型
+int TransferManager::statusToInt(TransferStatus status) {
+    return static_cast<int>(status);
+}
+
+// int 类型转换成任务状态
+TransferStatus TransferManager::intToStatus(int value) {
+    switch (value) {
+        case 0: return TransferStatus::Ready;
+        case 1: return TransferStatus::Running;
+        case 2: return TransferStatus::Error;
+        case 3: return TransferStatus::Abort;
+        case 4: return TransferStatus::Completed;
+        default: return TransferStatus::Error;
+    }
+}
+
+// 任务状态转换成字符串
+std::string TransferManager::statusToString(TransferStatus status) {
+    switch (status) {
+        case TransferStatus::Ready:     return "Ready";
+        case TransferStatus::Running:   return "Running";
+        case TransferStatus::Error:     return "Error";
+        case TransferStatus::Abort:     return "Abort";
+        case TransferStatus::Completed: return "Completed";
+        default:                        return "Unknown";
+    }
+}
+
+// 字符串转换成任务状态
+TransferStatus TransferManager::stringToStatus(const std::string& str) {
+    if (str == "Ready")     return TransferStatus::Ready;
+    if (str == "Running")   return TransferStatus::Running;
+    if (str == "Error")     return TransferStatus::Error;
+    if (str == "Abort")     return TransferStatus::Abort;
+    if (str == "Completed") return TransferStatus::Completed;
+    return TransferStatus::Error;
+}
+
+// 本地编码转为 UTF-8
+std::string TransferManager::ansiToUtf8(const std::string& ansiStr) {
+    // 1. ANSI → UTF-16
+    int wideLen = MultiByteToWideChar(CP_ACP, 0, ansiStr.c_str(), -1, nullptr, 0);
+    std::wstring wideStr(wideLen, 0);
+    MultiByteToWideChar(CP_ACP, 0, ansiStr.c_str(), -1, &wideStr[0], wideLen);
+
+    // 2. UTF-16 → UTF-8
+    int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, nullptr, 0, nullptr, nullptr);
+    std::string utf8Str(utf8Len, 0);
+    WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, &utf8Str[0], utf8Len, nullptr, nullptr);
+
+    utf8Str.pop_back(); // 去掉最后的 '\0'
+    return utf8Str;
+}
+
+// UTF-8 转为本地编码
+std::string TransferManager::utf8ToAnsi(const std::string& utf8Str) {
+    // 1. UTF-8 → UTF-16
+    int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0);
+    std::wstring wideStr(wideLen, 0);
+    MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wideStr[0], wideLen);
+
+    // 2. UTF-16 → ANSI
+    int ansiLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, NULL, 0, NULL, NULL);
+    std::string ansiStr(ansiLen, 0);
+    WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &ansiStr[0], ansiLen, NULL, NULL);
+
+    ansiStr.pop_back(); // 去掉最后的 '\0'
+    return ansiStr;
+}
+
+// 初始化搬运记录表
+bool TransferManager::initTransferTable() {
+    char szPath[MAX_PATH];
+    GetModuleFileName(NULL, szPath, MAX_PATH);
+    std::string exePath(szPath);
+    std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
+
+    if (!CreateDirectory(dbDir.c_str(), NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
+        throw std::runtime_error("创建数据库目录失败");
+    }
+
+    std::string dbPath = dbDir + "\\TransferManager.db";
+
+    if (!m_pDB->connect(dbPath, true)) {
+        throw std::runtime_error("连接数据库失败");
+    }
+
+    const std::string createTableSQL = R"(
+        CREATE TABLE IF NOT EXISTS transfers (
+            record_id    INTEGER PRIMARY KEY AUTOINCREMENT,
+            class_id     TEXT NOT NULL,
+            status       TEXT NOT NULL,
+            create_time  TEXT,
+            pick_time    TEXT,
+            place_time   TEXT,
+            end_time     TEXT,
+            description  TEXT
+        );
+    )";
+
+    return m_pDB->executeQuery(createTableSQL);
+}
+
+// 插入测试搬运记录
+void TransferManager::insertTestTransferRecord() {
+    TransferData data;
+    data.strClassID = "Task-20240529-001";
+    data.strStatus = "Running";
+    data.strCreateTime = "2024-05-29 10:30:00";
+    data.strPickTime = "2024-05-29 10:31:00";
+    data.strPlaceTime = "2024-05-29 10:32:00";
+    data.strEndTime = "2024-05-29 10:33:00";
+    data.strDescription = "搬运动作:从 Port1 取片 → Port2 放片";
+
+    int nRecordId = -1;
+    if (TransferManager::getInstance().addTransferRecord(data, nRecordId)) {
+        std::cout << "插入成功,记录 ID = " << nRecordId << std::endl;
+    }
+    else {
+        std::cerr << "插入失败!" << std::endl;
+    }
+}
+
+// 断开数据库连接
+void TransferManager::termTransferTable() {
+    if (m_pDB) {
+        m_pDB->disconnect();
+    }
+}
+
+// 删除搬运记录表
+bool TransferManager::destroyTransferTable() {
+    if (!m_pDB) return false;
+
+    const std::string dropTableSQL = "DROP TABLE IF EXISTS transfers;";
+    return m_pDB->executeQuery(dropTableSQL);
+}
+
+// 插入搬运记录
+bool TransferManager::addTransferRecord(const TransferData& data, int& outRecordId) {
+    if (!m_pDB) {
+        return false;
+    }
+
+    std::ostringstream oss;
+    oss << "INSERT INTO transfers (class_id, status, create_time, pick_time, place_time, end_time, description) "
+        << "VALUES ('"
+        << ansiToUtf8(data.strClassID) << "', '"
+        << ansiToUtf8(data.strStatus) << "', '"
+        << data.strCreateTime << "', '"
+        << data.strPickTime << "', '"
+        << data.strPlaceTime << "', '"
+        << data.strEndTime << "', '"
+        << ansiToUtf8(data.strDescription) << "') RETURNING record_id;";
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+
+    auto results = m_pDB->fetchResults(oss.str());
+    if (!results.empty() && !results[0].empty()) {
+        try {
+            outRecordId = std::stoi(results[0][0]);
+            return true;
+        }
+        catch (const std::exception& e) {
+            std::cerr << "解析 record_id 出错: " << e.what() << std::endl;
+        }
+    }
+
+    return false;
+}
+
+// 查询所有搬运记录
+std::vector<TransferData> TransferManager::getAllTransfers() {
+    std::vector<TransferData> records;
+
+    if (!m_pDB) {
+        return records;
+    }
+
+    const std::string query = R"(
+        SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description
+        FROM transfers
+        ORDER BY record_id DESC
+    )";
+
+    auto results = m_pDB->fetchResults(query);
+    for (const auto& row : results) {
+        if (row.size() != 8) continue;
+
+        TransferData data;
+        data.nRecordId = std::stoi(row[0]);
+        data.strClassID = row[1];
+        data.strStatus = row[2];
+        data.strCreateTime = row[3];
+        data.strPickTime = row[4];
+        data.strPlaceTime = row[5];
+        data.strEndTime = row[6];
+        data.strDescription = row[7];
+
+        records.push_back(data);
+    }
+
+    return records;
+}
+
+// 根据 ID 查询搬运记录
+TransferData TransferManager::getTransferById(int id) {
+	TransferData data;
+	if (!m_pDB) {
+		return data;
+	}
+	std::ostringstream oss;
+	oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
+		<< "FROM transfers WHERE record_id = " << id;
+	auto results = m_pDB->fetchResults(oss.str());
+	if (!results.empty() && results[0].size() == 8) {
+		data.nRecordId = std::stoi(results[0][0]);
+		data.strClassID = results[0][1];
+		data.strStatus = results[0][2];
+		data.strCreateTime = results[0][3];
+		data.strPickTime = results[0][4];
+		data.strPlaceTime = results[0][5];
+		data.strEndTime = results[0][6];
+		data.strDescription = results[0][7];
+	}
+	return data;
+}
+
+// 根据时间范围查询搬运记录
+std::vector<TransferData> TransferManager::getTransfersByTimeRange(const std::string& startTime, const std::string& endTime) {
+	std::vector<TransferData> records;
+	if (!m_pDB) {
+		return records;
+	}
+	std::ostringstream oss;
+	oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
+		<< "FROM transfers WHERE 1=1";
+	if (!startTime.empty()) {
+		oss << " AND create_time >= '" << startTime << "'";
+	}
+	if (!endTime.empty()) {
+		oss << " AND end_time <= '" << endTime << "'";
+	}
+	auto results = m_pDB->fetchResults(oss.str());
+	for (const auto& row : results) {
+		if (row.size() != 8) continue;
+		TransferData data;
+		data.nRecordId = std::stoi(row[0]);
+		data.strClassID = row[1];
+		data.strStatus = row[2];
+		data.strCreateTime = row[3];
+		data.strPickTime = row[4];
+		data.strPlaceTime = row[5];
+		data.strEndTime = row[6];
+		data.strDescription = row[7];
+		records.push_back(data);
+	}
+	return records;
+}
+
+// 查询指定状态的搬运记录
+std::vector<TransferData> TransferManager::getTransfersByStatus(const std::string& status) {
+    std::vector<TransferData> records;
+    if (!m_pDB) {
+        return records;
+    }
+
+    std::ostringstream oss;
+    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
+        << "FROM transfers WHERE status = '" << status << "' "
+        << "ORDER BY create_time DESC";
+
+    auto results = m_pDB->fetchResults(oss.str());
+    for (const auto& row : results) {
+        if (row.size() != 8) continue;
+
+        TransferData data;
+        data.nRecordId = std::stoi(row[0]);
+        data.strClassID = row[1];
+        data.strStatus = row[2];
+        data.strCreateTime = row[3];
+        data.strPickTime = row[4];
+        data.strPlaceTime = row[5];
+        data.strEndTime = row[6];
+        data.strDescription = row[7];
+
+        records.push_back(data);
+    }
+
+    return records;
+}
+
+// 分页获取搬运记录
+//std::vector<TransferData> TransferManager::getTransfers(int startPosition, int count) {
+//	std::vector<TransferData> records;
+//	if (!m_pDB) {
+//		return records;
+//	}
+//	std::ostringstream oss;
+//	oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
+//		<< "FROM transfers ORDER BY create_time DESC LIMIT " << count << " OFFSET " << startPosition;
+//	auto results = m_pDB->fetchResults(oss.str());
+//	for (const auto& row : results) {
+//		if (row.size() != 8) continue;
+//		TransferData data;
+//		data.nRecordId = std::stoi(row[0]);
+//		data.strClassID = row[1];
+//		data.strStatus = row[2];
+//		data.strCreateTime = row[3];
+//		data.strPickTime = row[4];
+//		data.strPlaceTime = row[5];
+//		data.strEndTime = row[6];
+//		data.strDescription = row[7];
+//		records.push_back(data);
+//	}
+//	return records;
+//}
+
+// 获取符合条件的记录总数
+int TransferManager::getTotalTransferCount() {
+    if (!m_pDB) {
+        return 0;
+    }
+
+    const std::string query = "SELECT COUNT(*) FROM transfers;";
+    auto results = m_pDB->fetchResults(query);
+
+    if (!results.empty() && !results[0].empty()) {
+        try {
+            return std::stoi(results[0][0]);
+        }
+        catch (const std::exception& e) {
+            std::cerr << "Error parsing total count: " << e.what() << std::endl;
+        }
+    }
+
+    return 0;
+}
+
+// 获取符合条件的记录总数
+int TransferManager::getTotalTransferCount(const TransferData& filter) {
+    if (!m_pDB) {
+        return 0;
+    }
+
+    std::ostringstream oss;
+    oss << "SELECT COUNT(*) FROM transfers WHERE 1=1";
+
+    // 状态筛选(完全匹配)
+    if (!filter.strStatus.empty()) {
+        oss << " AND status = '" << filter.strStatus << "'";
+    }
+
+    // 描述关键字模糊匹配
+    if (!filter.strDescription.empty()) {
+        oss << " AND description LIKE '%" << filter.strDescription << "%'";
+    }
+
+    // 时间范围筛选
+    if (!filter.strCreateTime.empty()) {
+        oss << " AND create_time >= '" << filter.strCreateTime << "'";
+    }
+    if (!filter.strEndTime.empty()) {
+        oss << " AND end_time <= '" << filter.strEndTime << "'";
+    }
+
+    auto results = m_pDB->fetchResults(oss.str());
+    if (!results.empty() && !results[0].empty()) {
+        try {
+            return std::stoi(results[0][0]);
+        }
+        catch (const std::exception& e) {
+            std::cerr << "Error parsing total count: " << e.what() << std::endl;
+        }
+    }
+
+    return 0;
+}
+
+std::vector<TransferData> TransferManager::getTransfers(const TransferData& filter, int pageNum, int pageSize) {
+    std::vector<TransferData> records;
+
+    if (!m_pDB) {
+        return records;
+    }
+
+    std::ostringstream oss;
+    oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
+        << "FROM transfers WHERE 1=1";
+
+    // 条件拼接(与 getTotalTransferCount 保持一致)
+    if (!filter.strStatus.empty()) {
+        oss << " AND status = '" << filter.strStatus << "'";
+    }
+    if (!filter.strDescription.empty()) {
+        oss << " AND description LIKE '%" << filter.strDescription << "%'";
+    }
+    if (!filter.strCreateTime.empty()) {
+        oss << " AND create_time >= '" << filter.strCreateTime << "'";
+    }
+    if (!filter.strEndTime.empty()) {
+        oss << " AND end_time <= '" << filter.strEndTime << "'";
+    }
+
+    // 分页控制
+    int offset = (pageNum - 1) * pageSize;
+    oss << " ORDER BY create_time DESC";
+    oss << " LIMIT " << pageSize << " OFFSET " << offset;
+
+    // 查询
+    auto results = m_pDB->fetchResults(oss.str());
+    for (const auto& row : results) {
+        if (row.size() != 8) continue;
+
+        TransferData data;
+        data.nRecordId = std::stoi(row[0]);
+        data.strClassID = row[1];
+        data.strStatus = row[2];
+        data.strCreateTime = row[3];
+        data.strPickTime = row[4];
+        data.strPlaceTime = row[5];
+        data.strEndTime = row[6];
+        data.strDescription = row[7];
+
+        records.push_back(data);
+    }
+
+    return records;
+}
+
+// 清理早于某一时间的搬运记录
+void TransferManager::cleanOldTransfers(int daysToKeep) {
+	if (!m_pDB) {
+		return;
+	}
+	std::ostringstream oss;
+	oss << "DELETE FROM transfers WHERE create_time < datetime('now', '-" << daysToKeep << " days')";
+
+	m_pDB->executeQuery(oss.str());
+}
+
+// 读取搬运记录 CSV 文件
+bool TransferManager::readTransferFile(const std::string& filename) {
+    std::ifstream file(filename);
+    if (!file.is_open()) {
+        std::cerr << "无法打开文件: " << filename << std::endl;
+        return false;
+    }
+
+    std::string line;
+    bool firstLine = true;
+    int insertedCount = 0;
+
+    while (std::getline(file, line)) {
+        if (firstLine) {
+            firstLine = false;
+            continue;
+        }
+
+        std::stringstream ss(line);
+        std::string cell;
+        TransferData data;
+
+        try {
+            std::getline(ss, cell, ',');
+            data.nRecordId = std::stoi(cell);
+
+            std::getline(ss, data.strClassID, ',');
+            std::getline(ss, data.strStatus, ',');
+            std::getline(ss, data.strCreateTime, ',');
+            std::getline(ss, data.strPickTime, ',');
+            std::getline(ss, data.strPlaceTime, ',');
+            std::getline(ss, data.strEndTime, ',');
+            std::getline(ss, data.strDescription, ',');
+
+            int newId = -1;
+            if (addTransferRecord(data, newId)) {
+                ++insertedCount;
+            }
+        }
+        catch (const std::exception& e) {
+            std::cerr << "读取错误行: " << line << ",错误: " << e.what() << std::endl;
+            continue;
+        }
+    }
+
+    file.close();
+    std::cout << "成功导入记录数: " << insertedCount << std::endl;
+    return true;
+}
+
+// 保存搬运记录到 CSV 文件
+bool TransferManager::saveTransferFile(const std::string& filename) {
+    std::ofstream file(filename);
+    if (!file.is_open()) {
+        std::cerr << "无法写入文件: " << filename << std::endl;
+        return false;
+    }
+
+    // 写入标题
+    file << "RecordID,ClassID,Status,CreateTime,PickTime,PlaceTime,EndTime,Description\n";
+
+    auto records = getAllTransfers();
+    for (const auto& data : records) {
+        file << data.nRecordId << ","
+            << data.strClassID << ","
+            << data.strStatus << ","
+            << data.strCreateTime << ","
+            << data.strPickTime << ","
+            << data.strPlaceTime << ","
+            << data.strEndTime << ","
+            << data.strDescription << "\n";
+    }
+
+    file.close();
+    std::cout << "已导出 " << records.size() << " 条记录到: " << filename << std::endl;
+    return true;
+}
\ No newline at end of file

--
Gitblit v1.9.3