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