chenluhua1980
2025-11-18 3cb4638bcb93a8fdf4cfea140025bbc299d35d47
1.权限完善。操作日志等
已添加2个文件
已修改7个文件
298 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CUserManager2.cpp 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CUserXLogDlg.cpp 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CUserXLogDlg.h 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PageRecipe.cpp 34 ●●●● 补丁 | 查看 | 原始文档 | 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/ServoDlg.cpp 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CUserManager2.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "CUserManager2.h"
#include "ToolUnits.h"
#include <vector>
@@ -40,7 +40,7 @@
    return L"";
}
// èŽ·å–å•ä¾‹å®žä¾‹
// èŽ·å–å•ä¾‹å®žä¾‹
CUserManager2& CUserManager2::getInstance() {
    static CUserManager2 instance;
    return instance;
@@ -69,6 +69,10 @@
        const wchar_t* roles = L"Admin:100\nEngineer:50\nOperator:10\n";
        (void)UX_SetRoleDefinitions(roles);
        (void)UX_AddUser(L"admin", L"Administrator", L"admin123", L"Admin");
        UX_DefineAction(L"start", L"启动机台", L"Operator");
        UX_DefineAction(L"stop", L"停机", L"Operator");
        UX_DefineAction(L"recipe", L"编辑配方", L"Engineer");
    }
}
SourceCode/Bond/Servo/CUserXLogDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,178 @@
#include "stdafx.h"
#include "Servo.h"
#include "CUserXLogDlg.h"
#include "afxdialogex.h"
#include <functional>
#include <vector>
#include <sstream>
namespace
{
    std::wstring ReadBufferVia(const std::function<int(wchar_t*, int)>& fn)
    {
        int need = fn(nullptr, 0);
        if (need <= 0) {
            return L"";
        }
        std::wstring buffer;
        buffer.resize(static_cast<size_t>(need));
        if (fn(buffer.data(), need) == UX_OK) {
            if (!buffer.empty() && buffer.back() == L'\0') {
                buffer.pop_back();
            }
            return buffer;
        }
        return L"";
    }
    std::vector<std::wstring> SplitLines(const std::wstring& text)
    {
        std::vector<std::wstring> lines;
        std::wstringstream ss(text);
        std::wstring line;
        while (std::getline(ss, line)) {
            lines.push_back(line);
        }
        return lines;
    }
}
IMPLEMENT_DYNAMIC(CUserXLogDlg, CDialogEx)
CUserXLogDlg::CUserXLogDlg(CWnd* pParent)
    : CDialogEx(IDD_DIALOG_USERX_LOG, pParent)
{
}
CUserXLogDlg::~CUserXLogDlg()
{
}
void CUserXLogDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST1, m_listLogs);
}
BEGIN_MESSAGE_MAP(CUserXLogDlg, CDialogEx)
    ON_WM_SIZE()
    ON_WM_DESTROY()
END_MESSAGE_MAP()
BOOL CUserXLogDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitListCtrl();
    RefreshLogs();
    AdjustLayout();
    return TRUE;
}
void CUserXLogDlg::InitListCtrl()
{
    DWORD dwStyle = m_listLogs.GetExtendedStyle();
    m_listLogs.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    m_listLogs.InsertColumn(0, _T("时间"), LVCFMT_LEFT, 180);
    m_listLogs.InsertColumn(1, _T("用户"), LVCFMT_LEFT, 120);
    m_listLogs.InsertColumn(2, _T("动作"), LVCFMT_LEFT, 120);
    m_listLogs.InsertColumn(3, _T("描述"), LVCFMT_LEFT, 200);
}
void CUserXLogDlg::RefreshLogs()
{
    m_logs.clear();
    m_listLogs.DeleteAllItems();
    auto allLogs = ReadBufferVia([](wchar_t* buffer, int size) {
        return UX_QueryLogs(200, buffer, size);
    });
    for (auto& rawLine : SplitLines(allLogs)) {
        if (rawLine.empty()) continue;
        auto trim = [](std::wstring value) {
            size_t first = value.find_first_not_of(L" \t\r\n");
            size_t last = value.find_last_not_of(L" \t\r\n");
            if (first == std::wstring::npos || last == std::wstring::npos) {
                return std::wstring();
            }
            return value.substr(first, last - first + 1);
        };
        auto takeField = [&](size_t& cursor) {
            if (cursor == std::wstring::npos || cursor >= rawLine.length()) {
                return std::wstring();
            }
            size_t pos = rawLine.find(L',', cursor);
            std::wstring part = (pos == std::wstring::npos) ? rawLine.substr(cursor) : rawLine.substr(cursor, pos - cursor);
            cursor = (pos == std::wstring::npos) ? std::wstring::npos : pos + 1;
            return trim(part);
        };
        size_t cursor = 0;
        LogItem item;
        item.time = takeField(cursor).c_str();
        item.user = takeField(cursor).c_str();
        item.action = takeField(cursor).c_str();
        if (cursor != std::wstring::npos && cursor < rawLine.length()) {
            item.detail = trim(rawLine.substr(cursor)).c_str();
        }
        m_logs.push_back(item);
    }
    for (size_t i = 0; i < m_logs.size(); ++i) {
        const auto& log = m_logs[i];
        int row = m_listLogs.InsertItem(static_cast<int>(i), log.time);
        m_listLogs.SetItemText(row, 1, log.user);
        m_listLogs.SetItemText(row, 2, log.action);
        m_listLogs.SetItemText(row, 3, log.detail);
    }
}
void CUserXLogDlg::AdjustLayout()
{
    if (!::IsWindow(m_listLogs.GetSafeHwnd())) {
        return;
    }
    CRect rcClient;
    GetClientRect(&rcClient);
    const int margin = 7;
    CRect rcList(margin, margin, rcClient.right - margin, rcClient.bottom - 40);
    m_listLogs.MoveWindow(rcList);
    auto moveButton = [&](int id, int order) {
        if (CWnd* pBtn = GetDlgItem(id)) {
            CRect rc;
            pBtn->GetWindowRect(&rc);
            ScreenToClient(&rc);
            int width = rc.Width();
            int height = rc.Height();
            rc.left = rcClient.right - margin - width - order * (width + margin);
            rc.right = rc.left + width;
            rc.top = rcClient.bottom - margin - height;
            rc.bottom = rc.top + height;
            pBtn->MoveWindow(rc);
        }
    };
    moveButton(IDOK, 1);
    moveButton(IDCANCEL, 0);
}
void CUserXLogDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    AdjustLayout();
}
void CUserXLogDlg::OnDestroy()
{
    CDialogEx::OnDestroy();
}
SourceCode/Bond/Servo/CUserXLogDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
#pragma once
#include <vector>
#include <string>
class CUserXLogDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CUserXLogDlg)
public:
    CUserXLogDlg(CWnd* pParent = nullptr);
    virtual ~CUserXLogDlg();
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_USERX_LOG };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnDestroy();
private:
    struct LogItem
    {
        CString time;
        CString user;
        CString action;
        CString detail;
    };
    CListCtrl m_listLogs;
    std::vector<LogItem> m_logs;
    void InitListCtrl();
    void RefreshLogs();
    void AdjustLayout();
};
SourceCode/Bond/Servo/PageRecipe.cpp
@@ -386,13 +386,12 @@
void CPageRecipe::OnBnClickedButtonNew()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    //CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
    //int nSel = pComboBox->GetCurSel();
    //SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nSel);
    //if (pEq == nullptr) {
    //    return;
    //}
    int rc = UX_CanExecute(L"recipe");
    if (rc != 1) {
        AfxMessageBox("操作权限不足,请联系管理人员!");
        return;
    }
    UX_RecordAction(L"recipe");
    CRecipeDeviceBindDlg dlg(this);
    if (dlg.DoModal() == IDOK) {
@@ -452,6 +451,13 @@
void CPageRecipe::OnBnClickedButtonModify()
{
    int rc = UX_CanExecute(L"recipe");
    if (rc != 1) {
        AfxMessageBox("操作权限不足,请联系管理人员!");
        return;
    }
    UX_RecordAction(L"recipe");
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT);
    if (pComboBox == nullptr || !::IsWindow(pComboBox->m_hWnd)) {
@@ -492,6 +498,13 @@
void CPageRecipe::OnBnClickedButtonDelete()
{
    int rc = UX_CanExecute(L"recipe");
    if (rc != 1) {
        AfxMessageBox("操作权限不足,请联系管理人员!");
        return;
    }
    UX_RecordAction(L"recipe");
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    POSITION pos = m_listPPID.GetFirstSelectedItemPosition();
    if (!pos) { 
@@ -518,6 +531,13 @@
void CPageRecipe::OnBnClickedButtonDeleteAll()
{
    int rc = UX_CanExecute(L"recipe");
    if (rc != 1) {
        AfxMessageBox("操作权限不足,请联系管理人员!");
        return;
    }
    UX_RecordAction(L"recipe");
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    if (IDYES != AfxMessageBox(_T("确定要删除全部配方记录吗?"), MB_YESNO | MB_ICONWARNING)) {
        return;
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -258,6 +258,7 @@
    <ClInclude Include="CUserManager2.h" />
    <ClInclude Include="CUserManager2Dlg.h" />
    <ClInclude Include="CUserEdit2Dlg.h" />
    <ClInclude Include="CUserXLogDlg.h" />
    <ClInclude Include="CVariable.h" />
    <ClInclude Include="DeviceRecipeParamDlg.h" />
    <ClInclude Include="GlassJson.h" />
@@ -475,6 +476,7 @@
    <ClCompile Include="CUserManager2.cpp" />
    <ClCompile Include="CUserManager2Dlg.cpp" />
    <ClCompile Include="CUserEdit2Dlg.cpp" />
    <ClCompile Include="CUserXLogDlg.cpp" />
    <ClCompile Include="CVariable.cpp" />
    <ClCompile Include="DeviceRecipeParamDlg.cpp" />
    <ClCompile Include="GlassJson.cpp" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -232,6 +232,7 @@
    <ClCompile Include="CUserManager2.cpp" />
    <ClCompile Include="CUserManager2Dlg.cpp" />
    <ClCompile Include="CUserEdit2Dlg.cpp" />
    <ClCompile Include="CUserXLogDlg.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -507,6 +508,7 @@
    <ClInclude Include="CUserManager2.h" />
    <ClInclude Include="CUserManager2Dlg.h" />
    <ClInclude Include="CUserEdit2Dlg.h" />
    <ClInclude Include="CUserXLogDlg.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -33,6 +33,7 @@
#include "CControlJobManagerDlg.h"
#include "CUserManager2.h"
#include "CUserManager2Dlg.h"
#include "CUserXLogDlg.h"
#ifdef _DEBUG
@@ -1017,15 +1018,14 @@
LRESULT CServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
{
    int id = (int)lParam;
    if (id == IDC_BUTTON_RUN || id == IDC_BUTTON_STOP) {
        UserRole emRole = UserManager::getInstance().getCurrentUserRole();
        if (emRole != UserRole::SuperAdmin) {
            AfxMessageBox(_T("当前用户并非管理员!!!"));
            return 1;
        }
    }
    if (id == IDC_BUTTON_RUN) {
        int rc = UX_CanExecute(L"start");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return 0;
        }
        UX_RecordAction(L"start");
        if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
            AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
        }
@@ -1062,6 +1062,13 @@
        }
    }
    else if (id == IDC_BUTTON_STOP) {
        int rc = UX_CanExecute(L"stop");
        if (rc != 1) {
            AfxMessageBox("操作权限不足,请联系管理人员!");
            return 0;
        }
        UX_RecordAction(L"stop");
        if (theApp.m_model.getMaster().stop() == 0) {
            m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
        }
@@ -1101,12 +1108,13 @@
            CUserManager2Dlg dlg;
            dlg.DoModal();
        }
        else if (menuId == 1) {
            CUserXLogDlg dlg;
            dlg.DoModal();
        }
        else if (menuId == 2) {
            CLoginDlg2 dlg;
            if (dlg.DoModal() != IDOK) {
                PostMessage(WM_CLOSE);
            }
            else {
            if (dlg.DoModal() == IDOK) {
                bool bRet = CUserManager2::getInstance().login((LPTSTR)(LPCTSTR)dlg.m_strUsername,
                    (LPTSTR)(LPCTSTR)dlg.m_strPassword);
                if (!bRet) {
SourceCode/Bond/Servo/resource.h
Binary files differ