// CPageGlassList.cpp: 实现文件
|
//
|
|
#include "stdafx.h"
|
#include "Servo.h"
|
#include "CPageGlassList.h"
|
#include "afxdialogex.h"
|
#include "GlassJson.h"
|
#include "CServoUtilsTool.h"
|
#include "ToolUnits.h"
|
|
|
#define PAGE_SIZE 10
|
#define PAGE_BACKGROUND_COLOR RGB(252, 252, 255)
|
|
// CPageGlassList 对话框
|
|
IMPLEMENT_DYNAMIC(CPageGlassList, CDialogEx)
|
|
CPageGlassList::CPageGlassList(CWnd* pParent /*=nullptr*/)
|
: CDialogEx(IDD_PAGE_GLASS_LIST, pParent)
|
{
|
m_crBkgnd = PAGE_BACKGROUND_COLOR;
|
m_hbrBkgnd = nullptr;
|
m_pObserver = nullptr;
|
|
m_strStatus = "";
|
m_nCurPage = 0;
|
m_nTotalPages = 1;
|
|
memset(m_szTimeStart, 0, sizeof(m_szTimeStart));
|
memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd));
|
m_szTimeStart[0] = '\0';
|
m_szTimeEnd[0] = '\0';
|
}
|
|
CPageGlassList::~CPageGlassList()
|
{
|
if (m_hbrBkgnd != nullptr) {
|
::DeleteObject(m_hbrBkgnd);
|
}
|
if (m_pObserver != nullptr) {
|
m_pObserver->unsubscribe();
|
m_pObserver = nullptr;
|
}
|
}
|
|
void CPageGlassList::DoDataExchange(CDataExchange* pDX)
|
{
|
CDialogEx::DoDataExchange(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);
|
}
|
|
|
BEGIN_MESSAGE_MAP(CPageGlassList, CDialogEx)
|
ON_WM_CTLCOLOR()
|
ON_WM_DESTROY()
|
ON_WM_SIZE()
|
ON_WM_TIMER()
|
ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CPageGlassList::OnCbnSelchangeComboDatetime)
|
ON_CBN_SELCHANGE(IDC_COMBO_STATUS_FILTER, &CPageGlassList::OnCbnSelchangeComboStatusFilter)
|
ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageGlassList::OnBnClickedButtonSearch)
|
ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CPageGlassList::OnBnClickedButtonExport)
|
ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CPageGlassList::OnBnClickedButtonPrevPage)
|
ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CPageGlassList::OnBnClickedButtonNextPage)
|
END_MESSAGE_MAP()
|
|
|
// CPageGlassList 消息处理程序
|
void CPageGlassList::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_EQ_ROBOT_TASK == code) {
|
UpdatePageData();
|
}
|
|
pAny->release();
|
}, [&]() -> void {
|
// onComplete
|
}, [&](IThrowable* pThrowable) -> void {
|
// onErrorm
|
pThrowable->printf();
|
});
|
|
theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())->subscribe(m_pObserver);
|
}
|
}
|
|
void CPageGlassList::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 CPageGlassList::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 CPageGlassList::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 CPageGlassList::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 CPageGlassList::LoadData()
|
{
|
m_nCurPage = 1;
|
UpdatePageData();
|
}
|
|
void CPageGlassList::UpdatePageData()
|
{
|
// 查询
|
auto& db = GlassLogDb::Instance();
|
auto page = db.queryPaged(m_filters, PAGE_SIZE, PAGE_SIZE * (m_nCurPage - 1));
|
m_listCtrl.DeleteAllItems();
|
for (const auto& r : page.items) {
|
int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), std::to_string(r.id).c_str());
|
m_listCtrl.SetItemText(index, 1, std::to_string(r.cassetteSeqNo).c_str());
|
m_listCtrl.SetItemText(index, 2, std::to_string(r.jobSeqNo).c_str());
|
m_listCtrl.SetItemText(index, 3, r.classId.c_str());
|
m_listCtrl.SetItemText(index, 4, SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str());
|
m_listCtrl.SetItemText(index, 5, SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str());
|
m_listCtrl.SetItemText(index, 6, r.tStart.c_str());
|
m_listCtrl.SetItemText(index, 7, r.tEnd.c_str());
|
m_listCtrl.SetItemText(index, 8, r.buddyId.c_str());
|
m_listCtrl.SetItemText(index, 9, SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str());
|
m_listCtrl.SetItemText(index, 10, r.path.c_str());
|
m_listCtrl.SetItemText(index, 11, r.params.c_str());
|
|
// 测试反序列化
|
/*
|
SERVO::CGlass g2;
|
std::string err;
|
if (GlassJson::FromString(r.pretty, g2, &err)) {
|
AfxMessageBox(r.pretty.c_str());
|
}
|
*/
|
}
|
|
// 上一页 / 下一页
|
UpdatePageControls();
|
}
|
|
void CPageGlassList::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);
|
}
|
|
// CPageTransferLog 消息处理程序
|
|
BOOL CPageGlassList::OnInitDialog()
|
{
|
CDialogEx::OnInitDialog();
|
|
// TODO: 在此添加额外的初始化
|
SetTimer(1, 3000, nullptr);
|
|
// 下拉框控件
|
InitStatusCombo();
|
InitTimeRangeCombo();
|
|
// 日期控件
|
InitDateTimeControls();
|
|
// 报表控件
|
CString strIniFile, strItem;
|
strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
|
|
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("id"),
|
_T("Cassette Sequence No"),
|
_T("Job Sequence No"),
|
_T("Class ID"),
|
_T("物料类型"),
|
_T("状态"),
|
_T("工艺开始时间"),
|
_T("工艺结束时间"),
|
_T("邦定Glass ID"),
|
_T("AOI检测结果"),
|
_T("路径"),
|
_T("工艺参数")
|
};
|
int widths[] = { 80, 80, 80, 100, 120, 120, 120, 120, 200, 200, 200, 200 };
|
for (int i = 0; i < _countof(headers); ++i) {
|
strItem.Format(_T("Col_%d_Width"), i);
|
widths[i] = GetPrivateProfileInt("GlassListCtrl", strItem, widths[i], strIniFile);
|
m_listCtrl.InsertColumn(i, headers[i], LVCFMT_LEFT, widths[i]);
|
}
|
|
Resize();
|
OnBnClickedButtonSearch();
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
// 异常: OCX 属性页应返回 FALSE
|
}
|
|
HBRUSH CPageGlassList::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 CPageGlassList::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("GlassListCtrl", strItem, strTemp, strIniFile);
|
}
|
}
|
|
void CPageGlassList::OnSize(UINT nType, int cx, int cy)
|
{
|
CDialogEx::OnSize(nType, cx, cy);
|
Resize();
|
}
|
|
void CPageGlassList::OnTimer(UINT_PTR nIDEvent)
|
{
|
if (nIDEvent == 1) {
|
KillTimer(1);
|
InitRxWindow();
|
}
|
CDialogEx::OnTimer(nIDEvent);
|
}
|
|
void CPageGlassList::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 CPageGlassList::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 CPageGlassList::OnBnClickedButtonSearch()
|
{
|
// 获取关键字输入框内容
|
CString strKeyword;
|
GetDlgItemText(IDC_EDIT_KEYWORD, strKeyword);
|
m_filters.keyword = CT2A(strKeyword);
|
|
CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME);
|
int index = pComboBox->GetCurSel();
|
if (index == 0) {
|
// 不限
|
m_filters.tStartFrom = std::nullopt;
|
m_filters.tStartTo = std::nullopt;
|
}
|
else if (index == 1) {
|
auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::Today);
|
m_filters.tStartFrom = fromUtc;
|
m_filters.tStartTo = toUtc;
|
}
|
else if (index == 2) {
|
auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::Last7Days);
|
m_filters.tStartFrom = fromUtc;
|
m_filters.tStartTo = toUtc;
|
}
|
else if (index == 3) {
|
auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::ThisMonth);
|
m_filters.tStartFrom = fromUtc;
|
m_filters.tStartTo = toUtc;
|
}
|
else if (index == 4) {
|
auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::ThisYear);
|
m_filters.tStartFrom = fromUtc;
|
m_filters.tStartTo = toUtc;
|
}
|
else if(index == 5){
|
// 自定义
|
std::chrono::system_clock::time_point tp;
|
if (CToolUnits::GetCtrlDateRangeUtc_StartOfDay(m_dateTimeStart, tp)) m_filters.tStartFrom = tp;
|
if (CToolUnits::GetCtrlDateRangeUtc_EndOfDay(m_dateTimeEnd, tp)) m_filters.tStartTo = tp;
|
}
|
|
auto& db = GlassLogDb::Instance();
|
long long total = db.count(m_filters);
|
m_nTotalPages = (PAGE_SIZE > 0) ? int((total + PAGE_SIZE - 1) / PAGE_SIZE) : 1;
|
|
LoadData();
|
}
|
|
void CPageGlassList::OnBnClickedButtonExport()
|
{
|
CFileDialog fileDialog(FALSE, _T("csv"), NULL, OFN_HIDEREADONLY, _T("CSV Files (*.csv)|*.csv||"));
|
if (fileDialog.DoModal() != IDOK) {
|
return;
|
}
|
|
// 导出 CSV:导出符合 filters 的“全部记录”(不受分页限制)
|
// 返回导出的行数(不含表头)
|
// csvPath:目标文件路径(UTF-8)
|
auto& db = GlassLogDb::Instance();
|
std::string csvPath((LPTSTR)(LPCTSTR)fileDialog.GetPathName());
|
if (db.exportCsv(csvPath, m_filters) > 0) {
|
AfxMessageBox("导出CSV成功!");
|
}
|
}
|
|
void CPageGlassList::OnBnClickedButtonPrevPage()
|
{
|
if (m_nCurPage > 1) {
|
m_nCurPage--;
|
UpdatePageData();
|
}
|
}
|
|
void CPageGlassList::OnBnClickedButtonNextPage()
|
{
|
if (m_nCurPage < m_nTotalPages) {
|
m_nCurPage++;
|
UpdatePageData();
|
}
|
}
|