mrDarker
2025-05-30 d119dcff794370b1852c0e9a3cda28d8d2bc6ae8
1. 添加搬运记录对话框
2. 修复搬运记录的数据库管理类的中文问题
已添加2个文件
已修改7个文件
691 ■■■■■ 文件已修改
SourceCode/Bond/Servo/PageAlarm.cpp 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageTransferLog.cpp 498 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageTransferLog.h 70 ●●●●● 补丁 | 查看 | 原始文档 | 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/TransferManager.cpp 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TransferManager.h 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
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()
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();
    }
}
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()
};
SourceCode/Bond/Servo/Servo.rc
Binary files differ
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" />
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" />
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);
    }
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);
    /**
     * æ¸…理早于某一时间的搬运记录
SourceCode/Bond/Servo/resource.h
Binary files differ