From d119dcff794370b1852c0e9a3cda28d8d2bc6ae8 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期五, 30 五月 2025 17:24:51 +0800
Subject: [PATCH] 1. 添加搬运记录对话框 2. 修复搬运记录的数据库管理类的中文问题
---
SourceCode/Bond/Servo/Servo.vcxproj | 2
SourceCode/Bond/Servo/PageAlarm.cpp | 7
SourceCode/Bond/Servo/Servo.vcxproj.filters | 2
SourceCode/Bond/Servo/resource.h | 0
SourceCode/Bond/Servo/TransferManager.h | 22
SourceCode/Bond/Servo/Servo.rc | 0
SourceCode/Bond/Servo/PageTransferLog.cpp | 498 +++++++++++++++++++++++++++++++++++++++++
SourceCode/Bond/Servo/PageTransferLog.h | 70 +++++
SourceCode/Bond/Servo/TransferManager.cpp | 90 ++++---
9 files changed, 643 insertions(+), 48 deletions(-)
diff --git a/SourceCode/Bond/Servo/PageAlarm.cpp b/SourceCode/Bond/Servo/PageAlarm.cpp
index 51c0f1a..f86f5a2 100644
--- a/SourceCode/Bond/Servo/PageAlarm.cpp
+++ b/SourceCode/Bond/Servo/PageAlarm.cpp
@@ -39,6 +39,13 @@
CPageAlarm::~CPageAlarm()
{
+ if (m_hbrBkgnd != nullptr) {
+ ::DeleteObject(m_hbrBkgnd);
+ }
+ if (m_pObserver != nullptr) {
+ m_pObserver->unsubscribe();
+ m_pObserver = nullptr;
+ }
}
void CPageAlarm::InitRxWindow()
diff --git a/SourceCode/Bond/Servo/PageTransferLog.cpp b/SourceCode/Bond/Servo/PageTransferLog.cpp
new file mode 100644
index 0000000..8000c23
--- /dev/null
+++ b/SourceCode/Bond/Servo/PageTransferLog.cpp
@@ -0,0 +1,498 @@
+锘�// PageTransferLog.cpp: 瀹炵幇鏂囦欢
+//
+
+#include "stdafx.h"
+#include "Servo.h"
+#include "afxdialogex.h"
+#include "PageTransferLog.h"
+#include "Common.h"
+
+#define PAGE_SIZE 100
+#define PAGE_BACKGROUND_COLOR RGB(252, 252, 255)
+
+// CPageTransferLog 瀵硅瘽妗�
+
+IMPLEMENT_DYNAMIC(CPageTransferLog, CDialogEx)
+
+CPageTransferLog::CPageTransferLog(CWnd* pParent /*=nullptr*/)
+ : CDialogEx(IDD_PAGE_TRANSFER_LOG, pParent)
+{
+ m_crBkgnd = PAGE_BACKGROUND_COLOR;
+ m_hbrBkgnd = nullptr;
+ m_pObserver = nullptr;
+
+ m_strStatus = "";
+ m_strKeyword = "";
+ m_nCurPage = 0;
+ m_nTotalPages = 0;
+
+ memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
+ memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
+ m_szTimeStart[0] = '\0';
+ m_szTimeEnd[0] = '\0';
+}
+
+CPageTransferLog::~CPageTransferLog()
+{
+ if (m_hbrBkgnd != nullptr) {
+ ::DeleteObject(m_hbrBkgnd);
+ }
+ if (m_pObserver != nullptr) {
+ m_pObserver->unsubscribe();
+ m_pObserver = nullptr;
+ }
+}
+
+void CPageTransferLog::DoDataExchange(CDataExchange* pDX)
+{
+ DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart);
+ DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd);
+ DDX_Control(pDX, IDC_LIST_ALARM, m_listCtrl);
+ CDialogEx::DoDataExchange(pDX);
+}
+
+void CPageTransferLog::InitRxWindow()
+{
+ /* code */
+ // 璁㈤槄鏁版嵁
+ IRxWindows* pRxWindows = RX_GetRxWindows();
+ pRxWindows->enableLog(5);
+ if (m_pObserver == NULL) {
+ m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void {
+ // onNext
+ pAny->addRef();
+ int code = pAny->getCode();
+
+ //if (RX_CODE_ALARM_SET == code) {
+ // UpdatePageData();
+ //}
+ //else if (RX_CODE_ALARM_CLEAR == code) {
+ // UpdatePageData();
+ //}
+
+ pAny->release();
+ }, [&]() -> void {
+ // onComplete
+ }, [&](IThrowable* pThrowable) -> void {
+ // onErrorm
+ pThrowable->printf();
+ });
+
+ theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())->subscribe(m_pObserver);
+ }
+}
+
+void CPageTransferLog::Resize()
+{
+ CRect rcClient;
+ GetClientRect(&rcClient);
+
+ // ===== 甯搁噺瀹氫箟 =====
+ const int nLeft = 12;
+ const int nRight = 12;
+ const int nTop = 58;
+ const int nButtonHeight = 28;
+ const int nButtonMarginBottom = 12;
+ const int nSpacing = 8;
+ const int nButtonWidth = 80;
+ const int nLabelWidth = 100;
+
+ // ===== 鍒嗛〉鎺т欢甯冨眬 =====
+ int yBottom = rcClient.bottom - nButtonMarginBottom - nButtonHeight;
+ int xRight = rcClient.Width() - nRight;
+
+ CWnd* pBtnNext = GetDlgItem(IDC_BUTTON_NEXT_PAGE);
+ CWnd* pBtnPrev = GetDlgItem(IDC_BUTTON_PREV_PAGE);
+ CWnd* pLabelPage = GetDlgItem(IDC_LABEL_PAGE_NUMBER);
+
+ if (pBtnNext && pBtnPrev && pLabelPage) {
+ // 鑾峰彇鍒嗛〉鏂囨湰瀹藉害浼扮畻
+ //CString strLabel;
+ //GetDlgItemText(IDC_LABEL_PAGE_NUMBER, strLabel);
+ //if (strLabel.IsEmpty()) {
+ // strLabel = _T("绗� 1 / 1 椤�");
+ //}
+ //int nCharWidth = 8;
+ //int nLabelWidth = strLabel.GetLength() * nCharWidth + 20;
+
+ // 璁剧疆鎸夐挳鍜屾爣绛句綅缃�
+ pBtnNext->MoveWindow(xRight - nButtonWidth, yBottom, nButtonWidth, nButtonHeight);
+ xRight -= nButtonWidth + nSpacing;
+
+ pLabelPage->MoveWindow(xRight - nLabelWidth, yBottom, nLabelWidth, nButtonHeight);
+ xRight -= nLabelWidth + nSpacing;
+
+ pBtnPrev->MoveWindow(xRight - nButtonWidth, yBottom, nButtonWidth, nButtonHeight);
+ }
+
+ // ===== 琛ㄦ牸鍖哄煙甯冨眬 =====
+ if (nullptr != m_listCtrl.m_hWnd) {
+ int listHeight = yBottom - nTop - nSpacing;
+ m_listCtrl.MoveWindow(nLeft, nTop, rcClient.Width() - nLeft - nRight, listHeight);
+ }
+}
+
+void CPageTransferLog::InitStatusCombo()
+{
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_STATUS_FILTER);
+ if (nullptr != pComboBox) {
+ pComboBox->ResetContent();
+ pComboBox->AddString(_T("鍏ㄩ儴"));
+ pComboBox->AddString(_T("Ready"));
+ pComboBox->AddString(_T("Running"));
+ pComboBox->AddString(_T("Error"));
+ pComboBox->AddString(_T("Abort"));
+ pComboBox->AddString(_T("Completed"));
+ pComboBox->SetCurSel(0);
+ }
+}
+
+void CPageTransferLog::InitTimeRangeCombo()
+{
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
+ if (nullptr != pComboBox) {
+ pComboBox->ResetContent();
+ pComboBox->AddString(_T("涓嶉檺"));
+ pComboBox->AddString(_T("浠婂ぉ"));
+ pComboBox->AddString(_T("涓冨ぉ鍐�"));
+ pComboBox->AddString(_T("鏈湀"));
+ pComboBox->AddString(_T("浠婂勾"));
+ pComboBox->AddString(_T("鑷畾涔�"));
+ pComboBox->SetCurSel(0);
+ }
+}
+
+void CPageTransferLog::InitDateTimeControls()
+{
+ if (m_dateTimeStart.m_hWnd == nullptr || m_dateTimeEnd.m_hWnd == nullptr) {
+ return;
+ }
+
+ // 绂佺敤鍒濆鐘舵��
+ m_dateTimeStart.EnableWindow(FALSE);
+ m_dateTimeEnd.EnableWindow(FALSE);
+
+ // 璁剧疆鏍煎紡锛氭樉绀烘棩鏈� + 鏃堕棿
+ //m_dateTimeStart.SetFormat(_T("yyyy/MM/dd HH:mm:ss"));
+ //m_dateTimeEnd.SetFormat(_T("yyyy/MM/dd HH:mm:ss"));
+
+ // 淇敼鏍峰紡浠ユ敮鎸佹椂闂存牸寮�
+ //DWORD dwStyleStart = m_dateTimeStart.GetStyle();
+ //DWORD dwStyleEnd = m_dateTimeEnd.GetStyle();
+
+ //m_dateTimeStart.ModifyStyle(0, DTS_TIMEFORMAT | DTS_UPDOWN);
+ //m_dateTimeEnd.ModifyStyle(0, DTS_TIMEFORMAT);
+}
+
+void CPageTransferLog::LoadTransfers()
+{
+ m_nCurPage = 1;
+ UpdatePageData();
+}
+
+void CPageTransferLog::UpdatePageData()
+{
+ TransferData filter;
+ filter.strStatus = m_strStatus;
+ filter.strDescription = m_strKeyword;
+ filter.strCreateTime = m_szTimeStart;
+ filter.strEndTime = m_szTimeEnd;
+ auto vecData = TransferManager::getInstance().getTransfers(filter, m_nCurPage, PAGE_SIZE);
+ FillDataToListCtrl(vecData);
+
+ int nTotalRecords = TransferManager::getInstance().getFilteredTransferCount(filter);
+ m_nTotalPages = (nTotalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
+ UpdatePageControls();
+}
+
+void CPageTransferLog::UpdatePageControls()
+{
+ CString strPage;
+ strPage.Format(_T("绗� %d / %d 椤�"), m_nCurPage, m_nTotalPages);
+ SetDlgItemText(IDC_LABEL_PAGE_NUMBER, strPage);
+ GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurPage > 1);
+ GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages);
+
+ Resize();
+}
+
+void CPageTransferLog::UpdateDateFilter()
+{
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
+ if (nullptr != pComboBox) {
+ int nIndex = pComboBox->GetCurSel();
+ if (nIndex == 0) {
+ memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
+ memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
+ m_szTimeStart[0] = '\0';
+ m_szTimeEnd[0] = '\0';
+ }
+ else {
+ CTime time = CTime::GetCurrentTime();
+ if (nIndex == 1) {
+ sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time.GetYear(), time.GetMonth(), time.GetDay());
+ sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
+ }
+ else if (nIndex == 2) {
+ CTime time2 = time - CTimeSpan(7, 0, 0, 0);
+ sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time2.GetYear(), time2.GetMonth(), time2.GetDay());
+ sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
+ }
+ else if (nIndex == 3) {
+ sprintf_s(m_szTimeStart, 64, "%d-%02d-01 00:00:00", time.GetYear(), time.GetMonth());
+ sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay());
+ }
+ else if (nIndex == 4) {
+ sprintf_s(m_szTimeStart, 64, "%d-01-01 00:00:00", time.GetYear());
+ sprintf_s(m_szTimeEnd, 64, "%d-12-31 23:59:59", time.GetYear());
+ }
+ else if (nIndex == 5) {
+ SYSTEMTIME t1, t2;
+ m_dateTimeStart.GetTime(&t1);
+ m_dateTimeEnd.GetTime(&t2);
+ //sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d %02d:%02d:%02d", t1.wYear, t1.wMonth, t1.wDay, t1.wHour, t1.wMinute, t1.wSecond);
+ //sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d %02d:%02d:%02d", t2.wYear, t2.wMonth, t2.wDay, t2.wHour, t2.wMinute, t2.wSecond);
+
+ sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", t1.wYear, t1.wMonth, t1.wDay);
+ sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", t2.wYear, t2.wMonth, t2.wDay);
+ }
+ }
+ }
+}
+
+void CPageTransferLog::FillDataToListCtrl(const std::vector<TransferData>& vecData)
+{
+ if (m_listCtrl.m_hWnd == nullptr) {
+ return;
+ }
+
+ m_listCtrl.DeleteAllItems();
+ for (const auto& item : vecData) {
+ InsertTransferData(item);
+ }
+}
+
+void CPageTransferLog::InsertTransferData(const TransferData& data)
+{
+ if (m_listCtrl.m_hWnd == nullptr) {
+ return;
+ }
+
+ int nItem = m_listCtrl.InsertItem(0, _T(""));
+ CString str;
+ str.Format(_T("%d"), data.nRecordId);
+ m_listCtrl.SetItemText(nItem, 1, str);
+ m_listCtrl.SetItemText(nItem, 2, CString(data.strStatus.c_str()));
+ m_listCtrl.SetItemText(nItem, 3, CString(data.strClassID.c_str()));
+ m_listCtrl.SetItemText(nItem, 4, CString(data.strCreateTime.c_str()));
+ m_listCtrl.SetItemText(nItem, 5, CString(data.strPickTime.c_str()));
+ m_listCtrl.SetItemText(nItem, 6, CString(data.strPlaceTime.c_str()));
+ m_listCtrl.SetItemText(nItem, 7, CString(data.strEndTime.c_str()));
+ m_listCtrl.SetItemText(nItem, 8, CString(data.strDescription.c_str()));
+}
+
+BEGIN_MESSAGE_MAP(CPageTransferLog, CDialogEx)
+ ON_WM_CTLCOLOR()
+ ON_WM_DESTROY()
+ ON_WM_SIZE()
+ ON_WM_TIMER()
+ ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CPageTransferLog::OnCbnSelchangeComboDatetime)
+ ON_CBN_SELCHANGE(IDC_COMBO_STATUS_FILTER, &CPageTransferLog::OnCbnSelchangeComboStatusFilter)
+ ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageTransferLog::OnBnClickedButtonSearch)
+ ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CPageTransferLog::OnBnClickedButtonExport)
+ ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CPageTransferLog::OnBnClickedButtonPrevPage)
+ ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CPageTransferLog::OnBnClickedButtonNextPage)
+END_MESSAGE_MAP()
+
+
+// CPageTransferLog 娑堟伅澶勭悊绋嬪簭
+
+BOOL CPageTransferLog::OnInitDialog()
+{
+ CDialogEx::OnInitDialog();
+
+ // TODO: 鍦ㄦ娣诲姞棰濆鐨勫垵濮嬪寲
+ SetTimer(1, 3000, nullptr);
+
+ // 涓嬫媺妗嗘帶浠�
+ InitStatusCombo();
+ InitTimeRangeCombo();
+
+ // 鏃ユ湡鎺т欢
+ InitDateTimeControls();
+
+ // 鎶ヨ〃鎺т欢
+ DWORD dwStyle = m_listCtrl.GetExtendedStyle();
+ dwStyle |= LVS_EX_FULLROWSELECT;
+ dwStyle |= LVS_EX_GRIDLINES;
+ m_listCtrl.SetExtendedStyle(dwStyle);
+
+ HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
+ ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
+
+ CString headers[] = { _T(""), _T("浠诲姟ID"), _T("鐘舵��"), _T("ClassID"), _T("鍒涘缓鏃堕棿"), _T("鍙栫墖鏃堕棿"), _T("鏀剧墖鏃堕棿"), _T("缁撴潫鏃堕棿"), _T("鎻忚堪") };
+ int widths[] = { 0, 80, 80, 100, 120, 120, 120, 120, 200 };
+ for (int i = 0; i < 9; ++i) {
+ m_listCtrl.InsertColumn(i, headers[i], LVCFMT_LEFT, widths[i]);
+ }
+ m_listCtrl.SetColumnWidth(8, LVSCW_AUTOSIZE_USEHEADER);
+
+ // 璇诲嚭鍒楀
+ CString strIniFile, strItem;
+ strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+ int width[8] = { 0, 80, 180, 80, 80, 100, 80, 180 };
+ for (int i = 0; i < 8; i++) {
+ strItem.Format(_T("Col_%d_Width"), i);
+ width[i] = GetPrivateProfileInt("TransferListCtrl", strItem, width[i], strIniFile);
+ }
+
+ // 璁$畻鎬婚〉鏁�
+ int nTotalRecords = TransferManager::getInstance().getTotalTransferCountAll();
+ m_nTotalPages = (nTotalRecords + PAGE_SIZE - 1) / PAGE_SIZE;
+ m_nCurPage = 1;
+
+ Resize();
+ LoadTransfers();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+}
+
+HBRUSH CPageTransferLog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+ if (nCtlColor == CTLCOLOR_STATIC) {
+ pDC->SetBkColor(m_crBkgnd);
+ }
+
+ if (m_hbrBkgnd == nullptr) {
+ m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
+ }
+
+ return m_hbrBkgnd;
+}
+
+void CPageTransferLog::OnDestroy()
+{
+ CDialogEx::OnDestroy();
+ if (m_hbrBkgnd != nullptr) {
+ ::DeleteObject(m_hbrBkgnd);
+ m_hbrBkgnd = nullptr;
+ }
+ if (m_pObserver != nullptr) {
+ m_pObserver->unsubscribe();
+ m_pObserver = nullptr;
+ }
+
+ // 淇濆瓨鍒楀
+ CString strIniFile, strItem, strTemp;
+ strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
+ CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl();
+ for (int i = 0; i < pHeader->GetItemCount(); i++) {
+ RECT rect;
+ pHeader->GetItemRect(i, &rect);
+ strItem.Format(_T("Col_%d_Width"), i);
+ strTemp.Format(_T("%d"), rect.right - rect.left);
+ WritePrivateProfileString("TransferListCtrl", strItem, strTemp, strIniFile);
+ }
+}
+
+void CPageTransferLog::OnSize(UINT nType, int cx, int cy)
+{
+ CDialogEx::OnSize(nType, cx, cy);
+ Resize();
+}
+
+void CPageTransferLog::OnTimer(UINT_PTR nIDEvent)
+{
+ if (nIDEvent == 1) {
+ KillTimer(1);
+ InitRxWindow();
+ }
+ CDialogEx::OnTimer(nIDEvent);
+}
+
+void CPageTransferLog::OnCbnSelchangeComboDatetime()
+{
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
+ int nIndex = pComboBox->GetCurSel();
+ int nCount = pComboBox->GetCount();
+ m_dateTimeStart.EnableWindow(nIndex == nCount - 1);
+ m_dateTimeEnd.EnableWindow(nIndex == nCount - 1);
+
+ // 鏇存柊鏃ユ湡杩囨护鍣ㄥ拰椤甸潰鏁版嵁
+ UpdateDateFilter();
+ LoadTransfers();
+}
+
+void CPageTransferLog::OnCbnSelchangeComboStatusFilter()
+{
+ CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_STATUS_FILTER);
+ int nIndex = pComboBox->GetCurSel();
+ if (nIndex == 0) {
+ m_strStatus.clear();
+ }
+ else {
+ CString cstrText;
+ pComboBox->GetLBText(nIndex, cstrText);
+ m_strStatus = CT2A(cstrText);
+ }
+ LoadTransfers();
+}
+
+void CPageTransferLog::OnBnClickedButtonSearch()
+{
+ // 鑾峰彇鍏抽敭瀛楄緭鍏ユ鍐呭
+ CString strKeyword;
+ GetDlgItemText(IDC_EDIT_KEYWORD, strKeyword);
+ m_strKeyword = CT2A(strKeyword);
+
+ // 鏇存柊鏃ユ湡杩囨护鍣ㄥ拰椤甸潰鏁版嵁
+ UpdateDateFilter();
+ LoadTransfers();
+}
+
+void CPageTransferLog::OnBnClickedButtonExport()
+{
+ CFileDialog fileDialog(FALSE, _T("csv"), NULL, OFN_HIDEREADONLY, _T("CSV Files (*.csv)|*.csv||"));
+ if (fileDialog.DoModal() != IDOK) {
+ return;
+ }
+
+ CStdioFile file;
+ if (!file.Open(fileDialog.GetPathName(), CFile::modeCreate | CFile::modeWrite | CFile::typeText)) {
+ AfxMessageBox(_T("鍒涘缓鏂囦欢澶辫触锛�"));
+ return;
+ }
+
+ CString strHeader = _T("浠诲姟ID,鐘舵��,ClassID,鍒涘缓鏃堕棿,鍙栫墖鏃堕棿,鏀剧墖鏃堕棿,缁撴潫鏃堕棿,鎻忚堪\n");
+ file.WriteString(strHeader);
+
+ for (int i = 0; i < m_listCtrl.GetItemCount(); ++i) {
+ CString row;
+ for (int j = 1; j <= 8; ++j) {
+ row += m_listCtrl.GetItemText(i, j);
+ if (j != 8) {
+ row += ",";
+ }
+ }
+ row += "\n";
+ file.WriteString(row);
+ }
+ file.Close();
+}
+
+void CPageTransferLog::OnBnClickedButtonPrevPage()
+{
+ if (m_nCurPage > 1) {
+ m_nCurPage--;
+ UpdatePageData();
+ }
+}
+
+void CPageTransferLog::OnBnClickedButtonNextPage()
+{
+ if (m_nCurPage < m_nTotalPages) {
+ m_nCurPage++;
+ UpdatePageData();
+ }
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/PageTransferLog.h b/SourceCode/Bond/Servo/PageTransferLog.h
new file mode 100644
index 0000000..1a26e90
--- /dev/null
+++ b/SourceCode/Bond/Servo/PageTransferLog.h
@@ -0,0 +1,70 @@
+锘�#pragma once
+#include "afxdialogex.h"
+#include "ListCtrlEx.h"
+#include "TransferManager.h"
+
+
+// CPageTransferLog 瀵硅瘽妗�
+
+class CPageTransferLog : public CDialogEx
+{
+ DECLARE_DYNAMIC(CPageTransferLog)
+
+public:
+ CPageTransferLog(CWnd* pParent = nullptr); // 鏍囧噯鏋勯�犲嚱鏁�
+ virtual ~CPageTransferLog();
+
+private:
+ COLORREF m_crBkgnd;
+ HBRUSH m_hbrBkgnd;
+ IObserver* m_pObserver;
+
+ // 鎼滅储鍏抽敭瀛�
+ std::string m_strStatus;
+ std::string m_strKeyword;
+
+ // 椤电爜
+ int m_nCurPage;
+ int m_nTotalPages;
+
+ // 鏃ユ湡
+ char m_szTimeStart[64];
+ char m_szTimeEnd[64];
+
+ // 鎺т欢
+ CDateTimeCtrl m_dateTimeStart;
+ CDateTimeCtrl m_dateTimeEnd;
+ CListCtrlEx m_listCtrl;
+
+ void InitRxWindow();
+ void Resize();
+ void InitStatusCombo();
+ void InitTimeRangeCombo();
+ void InitDateTimeControls();
+ void LoadTransfers();
+ void UpdatePageData();
+ void UpdatePageControls();
+ void UpdateDateFilter();
+ void FillDataToListCtrl(const std::vector<TransferData>& vecData);
+ void InsertTransferData(const TransferData& data);
+
+// 瀵硅瘽妗嗘暟鎹�
+#ifdef AFX_DESIGN_TIME
+ enum { IDD = IDD_PAGE_TRANSFER_LOG };
+#endif
+
+protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 鏀寔
+ virtual BOOL OnInitDialog();
+ afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+ afx_msg void OnDestroy();
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnTimer(UINT_PTR nIDEvent);
+ afx_msg void OnCbnSelchangeComboDatetime();
+ afx_msg void OnCbnSelchangeComboStatusFilter();
+ afx_msg void OnBnClickedButtonSearch();
+ afx_msg void OnBnClickedButtonExport();
+ afx_msg void OnBnClickedButtonPrevPage();
+ afx_msg void OnBnClickedButtonNextPage();
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index 140d51f..eedce8b 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index 11eb375..e776f64 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -304,6 +304,7 @@
<ClInclude Include="MapPosWnd.h" />
<ClInclude Include="Model.h" />
<ClInclude Include="PageRobotCmd.h" />
+ <ClInclude Include="PageTransferLog.h" />
<ClInclude Include="PortConfigurationDlg.h" />
<ClInclude Include="ProductionLogManager.h" />
<ClInclude Include="Resource.h" />
@@ -424,6 +425,7 @@
<ClCompile Include="MapPosWnd.cpp" />
<ClCompile Include="Model.cpp" />
<ClCompile Include="PageRobotCmd.cpp" />
+ <ClCompile Include="PageTransferLog.cpp" />
<ClCompile Include="PortConfigurationDlg.cpp" />
<ClCompile Include="ProductionLogManager.cpp" />
<ClCompile Include="SECSRuntimeManager.cpp" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 1a8bb3f..790d462 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -150,6 +150,7 @@
</ClCompile>
<ClCompile Include="PortConfigurationDlg.cpp" />
<ClCompile Include="TransferManager.cpp" />
+ <ClCompile Include="PageTransferLog.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AlarmManager.h" />
@@ -305,6 +306,7 @@
</ClInclude>
<ClInclude Include="PortConfigurationDlg.h" />
<ClInclude Include="TransferManager.h" />
+ <ClInclude Include="PageTransferLog.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/TransferManager.cpp b/SourceCode/Bond/Servo/TransferManager.cpp
index bfcf457..6079a79 100644
--- a/SourceCode/Bond/Servo/TransferManager.cpp
+++ b/SourceCode/Bond/Servo/TransferManager.cpp
@@ -135,21 +135,37 @@
// 插入测试搬运记录
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 放片";
+ if (nullptr != m_pDB) {
+ int nCount = 10000;
+ for (int i = 0; i < nCount; ++i) {
+ TransferData data;
+ data.strClassID = "T-" + std::to_string(1000 + i);
+ data.strStatus = statusToString(static_cast<TransferStatus>(i % 5));
- int nRecordId = -1;
- if (TransferManager::getInstance().addTransferRecord(data, nRecordId)) {
- std::cout << "插入成功,记录 ID = " << nRecordId << std::endl;
- }
- else {
- std::cerr << "插入失败!" << std::endl;
+ std::time_t now = std::time(nullptr) + i * 60; // 每条记录间隔1分钟
+
+ std::tm tmCreate = {}, tmPick = {}, tmPlace = {}, tmEnd = {};
+ localtime_s(&tmCreate, &now);
+ localtime_s(&tmPick, &(now += 60));
+ localtime_s(&tmPlace, &(now += 60));
+ localtime_s(&tmEnd, &(now += 60));
+
+ char szTime[64];
+ strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmCreate);
+ data.strCreateTime = szTime;
+ strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmPick);
+ data.strPickTime = szTime;
+ strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmPlace);
+ data.strPlaceTime = szTime;
+ strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", &tmEnd);
+ data.strEndTime = szTime;
+
+ data.strDescription = "Mock transfer task " + std::to_string(i);
+ int nRecordId = 0;
+ addTransferRecord(data, nRecordId);
+ }
+
+ std::cout << "[Mock] 成功插入 " << nCount << " 条测试搬运记录。" << std::endl;
}
}
@@ -221,13 +237,13 @@
TransferData data;
data.nRecordId = std::stoi(row[0]);
- data.strClassID = row[1];
- data.strStatus = row[2];
+ 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 = row[7];
+ data.strDescription = utf8ToAnsi(row[7]);
records.push_back(data);
}
@@ -247,13 +263,13 @@
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.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 = results[0][7];
+ data.strDescription = utf8ToAnsi(results[0][7]);
}
return data;
}
@@ -278,13 +294,13 @@
if (row.size() != 8) continue;
TransferData data;
data.nRecordId = std::stoi(row[0]);
- data.strClassID = row[1];
- data.strStatus = row[2];
+ 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 = row[7];
+ data.strDescription = utf8ToAnsi(row[7]);
records.push_back(data);
}
return records;
@@ -299,7 +315,7 @@
std::ostringstream oss;
oss << "SELECT record_id, class_id, status, create_time, pick_time, place_time, end_time, description "
- << "FROM transfers WHERE status = '" << status << "' "
+ << "FROM transfers WHERE status = '" << ansiToUtf8(status) << "' "
<< "ORDER BY create_time DESC";
auto results = m_pDB->fetchResults(oss.str());
@@ -308,13 +324,13 @@
TransferData data;
data.nRecordId = std::stoi(row[0]);
- data.strClassID = row[1];
- data.strStatus = row[2];
+ 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 = row[7];
+ data.strDescription = utf8ToAnsi(row[7]);
records.push_back(data);
}
@@ -348,8 +364,8 @@
// return records;
//}
-// 获取符合条件的记录总数
-int TransferManager::getTotalTransferCount() {
+// 获取记录总数
+int TransferManager::getTotalTransferCountAll() {
if (!m_pDB) {
return 0;
}
@@ -370,7 +386,7 @@
}
// 获取符合条件的记录总数
-int TransferManager::getTotalTransferCount(const TransferData& filter) {
+int TransferManager::getFilteredTransferCount(const TransferData& filter) {
if (!m_pDB) {
return 0;
}
@@ -380,12 +396,12 @@
// 状态筛选(完全匹配)
if (!filter.strStatus.empty()) {
- oss << " AND status = '" << filter.strStatus << "'";
+ oss << " AND status = '" << ansiToUtf8(filter.strStatus) << "'";
}
// 描述关键字模糊匹配
if (!filter.strDescription.empty()) {
- oss << " AND description LIKE '%" << filter.strDescription << "%'";
+ oss << " AND description LIKE '%" << ansiToUtf8(filter.strDescription) << "%'";
}
// 时间范围筛选
@@ -422,10 +438,10 @@
// 条件拼接(与 getTotalTransferCount 保持一致)
if (!filter.strStatus.empty()) {
- oss << " AND status = '" << filter.strStatus << "'";
+ oss << " AND status = '" << ansiToUtf8(filter.strStatus) << "'";
}
if (!filter.strDescription.empty()) {
- oss << " AND description LIKE '%" << filter.strDescription << "%'";
+ oss << " AND description LIKE '%" << ansiToUtf8(filter.strDescription) << "%'";
}
if (!filter.strCreateTime.empty()) {
oss << " AND create_time >= '" << filter.strCreateTime << "'";
@@ -446,13 +462,13 @@
TransferData data;
data.nRecordId = std::stoi(row[0]);
- data.strClassID = row[1];
- data.strStatus = row[2];
+ 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 = row[7];
+ data.strDescription = utf8ToAnsi(row[7]);
records.push_back(data);
}
diff --git a/SourceCode/Bond/Servo/TransferManager.h b/SourceCode/Bond/Servo/TransferManager.h
index ed1bbf6..9dde8c8 100644
--- a/SourceCode/Bond/Servo/TransferManager.h
+++ b/SourceCode/Bond/Servo/TransferManager.h
@@ -109,24 +109,24 @@
//std::vector<TransferData> getTransfers(int startPosition, int count);
/**
- * 获取符合条件的记录总数
+ * 获取记录总数
*/
- int getTotalTransferCount();
-
- /**
- * 分页获取符合条件的搬运记录
- * @param filter 过滤条件
- * @param pageNum 页码
- * @param pageSize 每页记录数
- */
- std::vector<TransferData> getTransfers(const TransferData& filter, int pageNum, int pageSize);
+ int getTotalTransferCountAll();
/**
* 获取符合条件的记录总数
* @param filter 过滤条件
* @return 符合条件的记录总数
*/
- int getTotalTransferCount(const TransferData& filter);;
+ int getFilteredTransferCount(const TransferData& filter);
+
+ /**
+ * 分页获取符合条件的搬运记录
+ * @param filter 过滤条件
+ * @param pageNum 页码
+ * @param pageSize 每页记录数
+ */
+ std::vector<TransferData> getTransfers(const TransferData& filter, int pageNum, int pageSize);
/**
* 清理早于某一时间的搬运记录
diff --git a/SourceCode/Bond/Servo/resource.h b/SourceCode/Bond/Servo/resource.h
index f530d52..05eec9c 100644
--- a/SourceCode/Bond/Servo/resource.h
+++ b/SourceCode/Bond/Servo/resource.h
Binary files differ
--
Gitblit v1.9.3