From 3cb4638bcb93a8fdf4cfea140025bbc299d35d47 Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期二, 18 十一月 2025 17:02:07 +0800
Subject: [PATCH] 1.权限完善。操作日志等
---
SourceCode/Bond/Servo/CControlJobDlg.cpp | 286 ++++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 252 insertions(+), 34 deletions(-)
diff --git a/SourceCode/Bond/Servo/CControlJobDlg.cpp b/SourceCode/Bond/Servo/CControlJobDlg.cpp
index d388c2c..2a57dcd 100644
--- a/SourceCode/Bond/Servo/CControlJobDlg.cpp
+++ b/SourceCode/Bond/Servo/CControlJobDlg.cpp
@@ -6,13 +6,35 @@
#include "CControlJobDlg.h"
#include "afxdialogex.h"
+// ===== 鏂板锛氭爣鍑嗗簱澶� =====
+#include <array>
+#include <string>
+#include <unordered_set>
+#include <algorithm>
+
+// ===== 鏂板锛欳String 鐨� Hash/Equal锛堣法 ANSI/Unicode 閫氬悆锛�=====
+struct CStringHash {
+ size_t operator()(const CString& s) const noexcept {
+#ifdef _UNICODE
+ return std::hash<std::wstring>{}(std::wstring(s.GetString()));
+#else
+ return std::hash<std::string>{}(std::string(s.GetString()));
+#endif
+ }
+};
+struct CStringEqual {
+ bool operator()(const CString& a, const CString& b) const noexcept {
+ return a == b;
+ }
+};
+
// CControlJobDlg 瀵硅瘽妗�
IMPLEMENT_DYNAMIC(CControlJobDlg, CDialogEx)
CControlJobDlg::CControlJobDlg(CWnd* pParent /*=nullptr*/)
- : CDialogEx(IDD_DIALOG_CONTROL_JOB, pParent)
+ : CDialogEx(IDD_DIALOG_CONTROL_JOB, pParent)
{
m_pControlJob = nullptr;
}
@@ -23,14 +45,16 @@
void CControlJobDlg::DoDataExchange(CDataExchange* pDX)
{
- CDialogEx::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_LIST1, m_listCtrl);
+ CDialogEx::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_LIST1, m_listCtrl);
}
BEGIN_MESSAGE_MAP(CControlJobDlg, CDialogEx)
ON_WM_SIZE()
ON_BN_CLICKED(IDC_BUTTON_COMPLETION_BATH, &CControlJobDlg::OnBnClickedButtonCompletionBath)
+ ON_BN_CLICKED(IDC_BUTTON_RELOAD, &CControlJobDlg::OnBnClickedButtonReload)
+ ON_WM_TIMER()
END_MESSAGE_MAP()
@@ -42,7 +66,7 @@
// CControlJobDlg 娑堟伅澶勭悊绋嬪簭
BOOL CControlJobDlg::OnInitDialog()
{
- CDialogEx::OnInitDialog();
+ CDialogEx::OnInitDialog();
// label瀛椾綋
@@ -69,20 +93,12 @@
// 鎺т欢鐘舵��
Resize();
+ OnBnClickedButtonReload();
+ SetTimer(1, 2000, nullptr);
- // 濡傛灉m_pControlJob涓虹┖锛屽彇master鐨�
- auto* cj = m_pControlJob;
- if (cj == nullptr) {
- cj = theApp.m_model.getMaster().getControlJob();
- }
- ShowGroup1(cj == nullptr);
- ShowGroup2(cj != nullptr);
- GetDlgItem(IDC_BUTTON_COMPLETION_BATH)->EnableWindow(cj != nullptr);
- LoadData(cj);
-
- return TRUE; // return TRUE unless you set the focus to a control
- // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
+ return TRUE; // return TRUE unless you set the focus to a control
+ // 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
}
void CControlJobDlg::OnSize(UINT nType, int cx, int cy)
@@ -101,15 +117,30 @@
// 鍏抽棴鎸夐挳
+ int x2 = rcClient.right - 12;
int y = rcClient.bottom - 12;
pItem = GetDlgItem(IDCANCEL);
pItem->GetClientRect(&rcItem);
- pItem->MoveWindow(rcClient.right - 12 - rcItem.Width(),
+ pItem->MoveWindow(x2 - rcItem.Width(),
y - rcItem.Height(),
+ rcItem.Width(), rcItem.Height());
+ x2 -= rcItem.Width();
+ x2 -= 8;
+
+ pItem = GetDlgItem(IDC_BUTTON_RELOAD);
+ pItem->GetClientRect(&rcItem);
+ pItem->MoveWindow(x2 - rcItem.Width(),
+ y - rcItem.Height(),
+ rcItem.Width(), rcItem.Height());
+
+
+ // 缁撴壒鎸夐挳
+ pItem = GetDlgItem(IDC_BUTTON_COMPLETION_BATH);
+ pItem->GetClientRect(&rcItem);
+ pItem->MoveWindow(12, y - rcItem.Height(),
rcItem.Width(), rcItem.Height());
y -= rcItem.Height();
y -= 12;
-
// 绾�
pItem = GetDlgItem(IDC_LINE1);
@@ -143,43 +174,221 @@
void CControlJobDlg::LoadData(SERVO::CControlJob* pControlJob)
{
- m_listCtrl.ClearTree();
- if (pControlJob == nullptr) return;
+ // 鈥斺�� 宸ュ叿锛氭寜鈥滅涓�鍒楅敭鈥濆湪 parent 涓嬫煡鎵惧瓙鑺傜偣
+ auto FindChildByKey = [&](CExpandableListCtrl::Node* parent, LPCTSTR key)->CExpandableListCtrl::Node* {
+ if (!parent) return nullptr;
+ for (auto& up : parent->children) {
+ auto* n = up.get();
+ if (n && n->cols.size() > 0 && n->cols[0].CompareNoCase(key) == 0)
+ return n;
+ }
+ return nullptr;
+ };
- auto* root1 = m_listCtrl.InsertRoot({ pControlJob->id().c_str(), _T("ControlJob"),
- pControlJob->getStateText().c_str(), _T(""), _T(""), pControlJob->failReason().c_str()});
+ // 鈥斺�� 宸ュ叿锛氭湁鍒欐洿鏂般�佹棤鍒欏垱寤猴紙6鍒楋級
+ auto EnsureChild = [&](CExpandableListCtrl::Node* parent, const std::array<CString, 6>& cols)->CExpandableListCtrl::Node* {
+ CExpandableListCtrl::Node* n = FindChildByKey(parent, cols[0]);
+ if (!n) {
+ n = m_listCtrl.InsertChild(parent, { cols[0], cols[1], cols[2], cols[3], cols[4], cols[5] });
+ }
+ else {
+ if ((int)n->cols.size() < 6) n->cols.resize(6);
+ for (int i = 0; i < 6; i++) if (n->cols[i] != cols[i]) n->cols[i] = cols[i];
+ }
+ return n;
+ };
+
+ // 鈥斺�� 宸ュ叿锛氬垹闄� parent 涓嬧�滄湰娆℃湭鍑虹幇鈥濈殑瀛愯妭鐐癸紙鍩轰簬绗竴鍒楅敭锛�
+ auto RemoveStaleChildren = [&](CExpandableListCtrl::Node* parent, const std::unordered_set<CString, CStringHash, CStringEqual>& keep) {
+ if (!parent) return;
+ auto& vec = parent->children;
+ vec.erase(std::remove_if(vec.begin(), vec.end(), [&](const std::unique_ptr<CExpandableListCtrl::Node>& up) {
+ auto* n = up.get();
+ if (!n || n->cols.empty()) return true; // 闃插尽锛氭棤鏁堣鐩存帴鍒�
+ return keep.find(n->cols[0]) == keep.end();
+ }), vec.end());
+ };
+
+ // 鈥斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�� 1) 鏃犳暟鎹細娓呯┖骞跺浣嶇紦瀛� 鈥斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�斺��
+ if (!pControlJob) {
+ m_listCtrl.ClearTree();
+ m_rootNode = nullptr;
+ m_lastCjPtr = nullptr;
+ m_lastCjId.Empty();
+ m_listCtrl.RebuildVisible();
+ return;
+ }
+
+ const CString curId = pControlJob->id().c_str();
+ const bool cjChanged = (pControlJob != m_lastCjPtr) || (curId != m_lastCjId);
+
+ // 鈥斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�� 2) CJ 鍙樹簡锛氭暣妫甸噸寤猴紙淇濈暀灞曞紑鏍囪涓嶅繀绠★紝閲嶅缓鍗冲彲锛� 鈥斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�斺��
+ if (cjChanged || !m_rootNode) {
+ m_listCtrl.ClearTree();
+
+ m_rootNode = m_listCtrl.InsertRoot({
+ pControlJob->id().c_str(), _T("ControlJob"),
+ pControlJob->getStateText().c_str(), _T(""), _T(""),
+ pControlJob->failReason().c_str()
+ });
+
+ auto pjs = pControlJob->getPjs();
+ for (auto pj : pjs) {
+ auto* pjNode = m_listCtrl.InsertChild(m_rootNode, {
+ pj->id().c_str(), _T("ProcessJob"),
+ pj->getStateText().c_str(), pj->recipeSpec().c_str(), _T(""),
+ pj->failReason().c_str()
+ });
+
+ auto cs = pj->carriers();
+ for (auto c : cs) {
+ for (auto g : c.contexts) {
+ auto* pGlass = static_cast<SERVO::CGlass*>(g);
+ if (pGlass) {
+ int port = 0, slot = 0;
+ pGlass->getOrginPort(port, slot);
+ CString carrier; carrier.Format(_T("%s / Port%d / Slot%d"),
+ CString(c.carrierId.c_str()), port + 1, slot + 1);
+
+ m_listCtrl.InsertChild(pjNode, {
+ pGlass->getID().c_str(), _T("Glass"),
+ pGlass->getStateText().c_str(), _T(""),
+ carrier, _T("")
+ });
+ }
+ else {
+ m_listCtrl.InsertChild(pjNode, {
+ _T("Null@") + CString(c.carrierId.c_str()), _T("Glass"),
+ _T(""), _T(""), CString(c.carrierId.c_str()), _T("")
+ });
+ }
+ }
+ }
+ pjNode->expanded = true;
+ }
+ m_rootNode->expanded = true;
+
+ m_lastCjPtr = pControlJob;
+ m_lastCjId = curId;
+
+ m_listCtrl.RebuildVisible();
+ return;
+ }
+
+ // 鈥斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�� 3) CJ 鏈彉锛氬閲忔洿鏂� 鈥斺�斺�斺�斺�斺�斺�斺�斺�斺�斺�斺��
+
+ // 3.1 鏇存柊 CJ 琛屾枃鏈紙鐘舵�佸彲鑳藉彉鍖栵級
+ if ((int)m_rootNode->cols.size() < 6) m_rootNode->cols.resize(6);
+ m_rootNode->cols[0] = pControlJob->id().c_str();
+ m_rootNode->cols[1] = _T("ControlJob");
+ m_rootNode->cols[2] = pControlJob->getStateText().c_str();
+ // cols[3] 淇濈暀涓虹┖
+ // cols[4] 淇濈暀涓虹┖
+ m_rootNode->cols[5] = pControlJob->failReason().c_str();
+
+ // 3.2 鍚屾 PJ 灞�
+ std::unordered_set<CString, CStringHash, CStringEqual> pjKeysWanted;
+
auto pjs = pControlJob->getPjs();
for (auto pj : pjs) {
- auto* root2 = m_listCtrl.InsertChild(root1, {pj->id().c_str(), _T("ProcessJob"),
- pj->getStateText().c_str(), pj->recipeSpec().c_str(), _T(""), pj->failReason().c_str()});
+ CString pjId = pj->id().c_str();
+ pjKeysWanted.insert(pjId);
+
+ auto* pjNode = FindChildByKey(m_rootNode, pjId);
+ if (!pjNode) {
+ pjNode = m_listCtrl.InsertChild(m_rootNode, {
+ pjId, _T("ProcessJob"),
+ pj->getStateText().c_str(), pj->recipeSpec().c_str(), _T(""),
+ pj->failReason().c_str()
+ });
+ pjNode->expanded = true; // 鍒濇鍑虹幇榛樿灞曞紑
+ }
+ else {
+ if ((int)pjNode->cols.size() < 6) pjNode->cols.resize(6);
+ pjNode->cols[1] = _T("ProcessJob");
+ pjNode->cols[2] = pj->getStateText().c_str();
+ pjNode->cols[3] = pj->recipeSpec().c_str();
+ pjNode->cols[5] = pj->failReason().c_str();
+ }
+
+ // 3.3 鍚屾 Glass 灞傦紙绗竴鍒楅敭锛欸lassID锛涚┖瀵硅薄鐢� "Null@CarrierId" 闃插啿绐侊級
+ std::unordered_set<CString, CStringHash, CStringEqual> gKeysWanted;
+
auto cs = pj->carriers();
for (auto c : cs) {
for (auto g : c.contexts) {
- SERVO::CGlass* pGlass = (SERVO::CGlass*)g;
- if (pGlass != nullptr) {
- int port, slot;
+ auto* pGlass = static_cast<SERVO::CGlass*>(g);
+ if (pGlass) {
+ int port = 0, slot = 0;
pGlass->getOrginPort(port, slot);
- std::string carrier = c.carrierId + " / Port" + std::to_string(port + 1) + " / Slot" + std::to_string(slot + 1);
- m_listCtrl.InsertChild(root2, { pGlass->getID().c_str(), _T("Glass"),
- pGlass->getStateText().c_str(), _T(""), carrier.c_str(), _T("") });
+ CString carrier; carrier.Format(_T("%s / Port%d / Slot%d"),
+ CString(c.carrierId.c_str()), port + 1, slot + 1);
+
+ CString gid = pGlass->getID().c_str();
+ gKeysWanted.insert(gid);
+
+ auto* rowG = FindChildByKey(pjNode, gid);
+ if (!rowG) {
+ m_listCtrl.InsertChild(pjNode, {
+ gid, _T("Glass"),
+ pGlass->getStateText().c_str(), _T(""),
+ carrier, _T("")
+ });
+ }
+ else {
+ if ((int)rowG->cols.size() < 6) rowG->cols.resize(6);
+ rowG->cols[1] = _T("Glass");
+ rowG->cols[2] = pGlass->getStateText().c_str();
+ rowG->cols[3] = _T("");
+ rowG->cols[4] = carrier;
+ rowG->cols[5] = _T("");
+ }
}
else {
- m_listCtrl.InsertChild(root2, { "Null", _T("Glass"), _T(""), _T(""), c.carrierId.c_str(), _T("") });
+ CString key = _T("Null@") + CString(c.carrierId.c_str());
+ gKeysWanted.insert(key);
+
+ auto* rowG = FindChildByKey(pjNode, key);
+ if (!rowG) {
+ m_listCtrl.InsertChild(pjNode, {
+ key, _T("Glass"), _T(""), _T(""),
+ CString(c.carrierId.c_str()), _T("")
+ });
+ }
+ else {
+ if ((int)rowG->cols.size() < 6) rowG->cols.resize(6);
+ rowG->cols[1] = _T("Glass");
+ rowG->cols[2] = _T("");
+ rowG->cols[3] = _T("");
+ rowG->cols[4] = CString(c.carrierId.c_str());
+ rowG->cols[5] = _T("");
+ }
}
}
}
- root2->expanded = true;
+
+ // 鍒犻櫎鏈涓嶅瓨鍦ㄧ殑 Glass 瀛愯妭鐐�
+ RemoveStaleChildren(pjNode, gKeysWanted);
}
- root1->expanded = true;
+
+ // 鍒犻櫎鏈涓嶅瓨鍦ㄧ殑 PJ 瀛愯妭鐐�
+ RemoveStaleChildren(m_rootNode, pjKeysWanted);
+
+ // 3.4 閲嶅缓鍙琛岋紙涓嶆敼鍙� expanded 鏍囧織锛岄伩鍏嶉棯鐑�/鎶樺彔鐘舵�佷涪澶憋級
m_listCtrl.RebuildVisible();
}
void CControlJobDlg::OnBnClickedButtonCompletionBath()
{
- if (theApp.m_model.getMaster().completeControlJob("娴嬭瘯鎵嬪姩缁撴壒")) {
+ if (theApp.m_model.getMaster().forceCompleteControlJob("娴嬭瘯鎵嬪姩缁撴壒")) {
AfxMessageBox("缁撴壒瀹屾垚");
}
+ OnBnClickedButtonReload();
+}
+
+void CControlJobDlg::OnBnClickedButtonReload()
+{
auto* cj = m_pControlJob;
if (cj == nullptr) {
cj = theApp.m_model.getMaster().getControlJob();
@@ -190,3 +399,12 @@
GetDlgItem(IDC_BUTTON_COMPLETION_BATH)->EnableWindow(cj != nullptr);
LoadData(cj);
}
+
+void CControlJobDlg::OnTimer(UINT_PTR nIDEvent)
+{
+ if (1 == nIDEvent) {
+ OnBnClickedButtonReload();
+ }
+
+ CDialogEx::OnTimer(nIDEvent);
+}
--
Gitblit v1.9.3