#include "stdafx.h" #include "TransferManager.h" #include #include #include #include #include #include // ¾²Ì¬»¥³âËø³õʼ»¯ 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; } } // ±¾µØ±àÂëתΪ 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(int nCount /*=10000*/) { if (nullptr != m_pDB) { static const char* STATUS_STR[] = { "Unknown", "Ready", "Running", "Picking", "Placing", "Restoring", "Error", "Abort", "Completed" }; auto formatTime = [](const std::tm& time) { char szTime[64]; strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &time); return std::string(szTime); }; std::time_t startTime = std::time(nullptr); for (int i = 0; i < nCount; ++i) { TransferData data; data.strClassID = "T-" + std::to_string(1000 + i); data.strStatus = STATUS_STR[i % 9]; std::time_t baseTime = startTime + i * 60; std::time_t pickTime = baseTime + 60; std::time_t placeTime = pickTime + 60; std::time_t endTime = placeTime + 60; std::tm tmCreate = {}, tmPick = {}, tmPlace = {}, tmEnd = {}; localtime_s(&tmCreate, &baseTime); localtime_s(&tmPick, &pickTime); localtime_s(&tmPlace, &placeTime); localtime_s(&tmEnd, &endTime); data.strCreateTime = formatTime(tmCreate); data.strPickTime = formatTime(tmPick); data.strPlaceTime = formatTime(tmPlace); data.strEndTime = formatTime(tmEnd); data.strDescription = "Mock transfer task " + std::to_string(i); int nRecordId = 0; if (!addTransferRecord(data, nRecordId)) { std::cerr << "[Error] ²åÈëµÚ " << i << " Ìõ¼Ç¼ʧ°Ü" << std::endl; } } std::cout << "[Mock] ³É¹¦²åÈë " << nCount << " Ìõ²âÊÔ°áÔ˼Ǽ¡£" << 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 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 TransferManager::getAllTransfers() { std::vector 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 = utf8ToAnsi(row[1]); data.strStatus = utf8ToAnsi(row[2]); data.strCreateTime = row[3]; data.strPickTime = row[4]; data.strPlaceTime = row[5]; data.strEndTime = row[6]; data.strDescription = utf8ToAnsi(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 = utf8ToAnsi(results[0][1]); data.strStatus = utf8ToAnsi(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 = utf8ToAnsi(results[0][7]); } return data; } // ¸ù¾Ýʱ¼ä·¶Î§²éѯ°áÔ˼Ǽ std::vector TransferManager::getTransfersByTimeRange(const std::string& startTime, const std::string& endTime) { std::vector 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 = utf8ToAnsi(row[1]); data.strStatus = utf8ToAnsi(row[2]); data.strCreateTime = row[3]; data.strPickTime = row[4]; data.strPlaceTime = row[5]; data.strEndTime = row[6]; data.strDescription = utf8ToAnsi(row[7]); records.push_back(data); } return records; } // ²éѯָ¶¨×´Ì¬µÄ°áÔ˼Ǽ std::vector TransferManager::getTransfersByStatus(const std::string& status) { std::vector 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 = '" << ansiToUtf8(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 = utf8ToAnsi(row[1]); data.strStatus = utf8ToAnsi(row[2]); data.strCreateTime = row[3]; data.strPickTime = row[4]; data.strPlaceTime = row[5]; data.strEndTime = row[6]; data.strDescription = utf8ToAnsi(row[7]); records.push_back(data); } return records; } // ·ÖÒ³»ñÈ¡°áÔ˼Ǽ //std::vector TransferManager::getTransfers(int startPosition, int count) { // std::vector 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::getTotalTransferCountAll() { 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::getFilteredTransferCount(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 = '" << ansiToUtf8(filter.strStatus) << "'"; } // ÃèÊö¹Ø¼ü×ÖÄ£ºýÆ¥Åä if (!filter.strDescription.empty()) { oss << " AND description LIKE '%" << ansiToUtf8(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 TransferManager::getTransfers(const TransferData& filter, int pageNum, int pageSize) { std::vector 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 = '" << ansiToUtf8(filter.strStatus) << "'"; } if (!filter.strDescription.empty()) { oss << " AND description LIKE '%" << ansiToUtf8(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 = utf8ToAnsi(row[1]); data.strStatus = utf8ToAnsi(row[2]); data.strCreateTime = row[3]; data.strPickTime = row[4]; data.strPlaceTime = row[5]; data.strEndTime = row[6]; data.strDescription = utf8ToAnsi(row[7]); records.push_back(data); } return records; } // ÇåÀíÔçÓÚijһʱ¼äµÄ°áÔ˼Ǽ 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; }