GKTGD 工业监控系统-00设计文档

GKTGD 工业监控系统设计文档

项目名称 : GKTGD 工业监控系统
架构模式 : MVVM + 模块化架构
技术栈 : WPF + .NET 8.0
创建日期 : 2026-05-06
版本: 1.0

1. 项目概述

1.1 项目目标

开发一个基于WPF MVVM架构的工业自动化监控系统,支持设备控制、机器视觉、数据监测、实时曲线、工艺配方、数据报表、用户管理、系统设置等核心功能模块。

1.2 技术架构

  • UI框架: WPF (Windows Presentation Foundation)
  • 架构模式: MVVM (Model-View-ViewModel)
  • 开发环境: .NET 8.0-windows
  • 图表库: LiveCharts.Wpf 0.9.7 + ScottPlot(双图表库策略)
  • 数据库: SQLite / MySQL
  • 通讯协议: Modbus, 西门子S7, 倍福ADS, Ethernet
  • 视觉库: Halcon, VM, OpenCV

1.3 设计原则

  • 模块化: 每个功能模块独立封装,便于维护和扩展
  • 可配置: 通过配置文件动态启用/禁用功能模块
  • 可复用: 通讯、视觉、数据库功能封装为独立类库
  • 用户权限: 基于角色的权限管理系统,三层权限控制策略
  • UI一致性: 参考现有WPF项目的UI设计风格和控件
  • 双图表库策略: LiveCharts.Wpf + ScottPlot,根据应用场景选择最优图表方案

1.4 双图表库策略说明

本项目采用LiveCharts.Wpf和ScottPlot双图表库策略,充分发挥各自优势

1.4.1 LiveCharts.Wpf 应用场景

优势 : 实时数据绑定友好,动画流畅,仪表盘风格
适用模块:

  • 实时曲线模块: 实时数据监控、趋势显示、状态变化
  • 数据监测模块: 实时仪表盘、设备状态显示、KPI指标监控
  • 设备控制模块: 设备状态可视化、运行参数实时显示

技术特点:

csharp 复制代码
// LiveCharts.Wpf 实时数据更新示例
public class RealtimeChartViewModel : ViewModelBase
{
    public ChartValues<double> Values { get; set; }
    
    public RealtimeChartViewModel()
    {
        Values = new ChartValues<double>();
        
        // 定时器实时更新数据
        var timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(100);
        timer.Tick += (s, e) =>
        {
            Values.Add(GetLatestValue());
            if (Values.Count > 100) Values.RemoveAt(0); // 保持数据量
        };
        timer.Start();
    }
}
1.4.2 ScottPlot 应用场景

优势 : 科学绘图能力强,性能优秀,适合大数据量和精确分析
适用模块:

  • 机器视觉模块: 图像处理结果显示、像素值分析、边缘检测可视化
  • 数据报表模块: 统计分析图表、生产趋势分析、质量分布图
  • 工艺配方模块: 配方曲线对比、工艺参数优化分析

技术特点:

csharp 复制代码
// ScottPlot 精确数据绘图示例
public class AnalysisChartViewModel : ViewModelBase
{
    public WpfPlot PlotControl { get; set; }
    
    public void LoadAnalysisData(double[] xData, double[] yData)
    {
        PlotControl.Plot.Clear();
        PlotControl.Plot.AddScatter(xData, yData, label="测量数据");
        PlotControl.Plot.AddSignal(yData, label="趋势线");
        PlotControl.Plot.Title("数据分析图表");
        PlotControl.Plot.XLabel("时间");
        PlotControl.Plot.YLabel("数值");
        PlotControl.Plot.Legend();
        PlotControl.Render();
    }
}
1.4.3 双图表库协同工作

模块间数据共享:

csharp 复制代码
public class DataSharingService
{
    // 实时监控使用 LiveCharts.Wpf
    public void UpdateRealtimeChart(double value)
    {
        var liveChartModel = _serviceProvider.GetRequiredService<RealtimeChartViewModel>();
        liveChartModel.Values.Add(value);
    }
    
    // 分析报告使用 ScottPlot
    public void GenerateAnalysisChart(double[] historicalData)
    {
        var scottPlotModel = _serviceProvider.GetRequiredService<AnalysisChartViewModel>();
        scottPlotModel.LoadAnalysisData(historicalData);
    }
}
1.4.4 图表库选择决策树
复制代码
需求分析
    ↓
是否需要实时数据绑定和动画?
    ├─ 是 → LiveCharts.Wpf
    └─ 否 ↓
    是否处理大量数据点(>1000点)?
    ├─ 是 → ScottPlot  
    └─ 否 ↓
    是否需要科学绘图(信号处理、统计分析)?
    ├─ 是 → ScottPlot
    └─ 否 → LiveCharts.Wpf

2. 解决方案架构

2.1 项目结构

复制代码
GKTGD.sln
├── NET8_Comm/                     # 通讯类库
├── NET8_Vision/                   # 视觉类库  
├── NET8_SQLData/                  # 数据访问类库
└── GKTGD/                         # 主应用程序

2.2 项目依赖关系

复制代码
NET8_Comm (独立通讯类库)
    ↑
NET8_Vision (独立视觉类库)
    ↑
NET8_SQLData (独立数据访问类库)
    ↑
GKTGD (主应用程序) → 引用 NET8_Comm, NET8_Vision, NET8_SQLData

引用机制: 每个项目根据需求选择性引用功能类库

示例引用:

  • GKTGD项目: 引用所有三个类库 (Modbus + ADS + SQLite + Halcon)
  • 其他项目: 可只引用需要的类库 (如只使用Ethernet + MySQL)

3. 功能模块设计

3.1 八大功能模块

3.1.1 设备控制模块 (DeviceControl)
  • 主页面: DeviceControlMainView
  • 子页面 :
    • 设备总控页面 (DeviceControlOverviewView)
    • 设备1控制页面 (Device1ControlView)
    • 设备2控制页面 (Device2ControlView)
  • 功能: 设备状态监控、控制指令发送、设备参数配置
3.1.2 机器视觉模块 (MachineVision)
  • 主页面: MachineVisionMainView
  • 子页面 :
    • 视觉任务1页面 (VisionTask1View)
    • 视觉任务2页面 (VisionTask2View)
  • 功能: 图像采集、缺陷检测、尺寸测量、模式匹配
  • 图表库 : ScottPlot (适合图像处理结果显示和精确数据分析)
3.1.3 数据监测模块 (DataMonitoring)
  • 主页面: DataMonitoringMainView
  • 子页面 :
    • 实时数据页面 (RealtimeDataView)
    • 历史数据页面 (HistoryDataView)
  • 功能: 实时数据采集、数据缓存、历史数据查询、数据导出
  • 图表库 : LiveCharts.Wpf (仪表盘风格,实时数据监控,状态显示)
3.1.4 实时曲线模块 (RealtimeChart)
  • 主页面: RealtimeChartMainView
  • 子页面 :
    • 趋势图页面 (TrendChartView)
    • 对比图页面 (ComparisonChartView)
  • 功能: 实时曲线绘制、历史趋势分析、多曲线对比
  • 图表库 : LiveCharts.Wpf (适合实时数据监控,动画流畅,数据绑定友好)
3.1.5 工艺配方模块 (ProcessRecipe)
  • 主页面: ProcessRecipeMainView
  • 子页面 :
    • 配方管理页面 (RecipeManagementView)
    • 配方执行页面 (RecipeExecutionView)
  • 功能: 配方创建、配方存储、配方执行、配方版本管理
3.1.6 数据报表模块 (DataReport)
  • 主页面: DataReportMainView
  • 子页面 :
    • 生产报表页面 (ProductionReportView)
    • 质量报表页面 (QualityReportView)
  • 功能: 报表生成、数据统计、报表导出、定时报表
  • 图表库 : ScottPlot (适合统计分析图表,科学绘图,性能优秀)
3.1.7 用户管理模块 (UserManagement)
  • 主页面: UserManagementMainView
  • 子页面 :
    • 用户列表页面 (UserListView)
    • 角色管理页面 (RoleManagementView)
    • 权限设置页面 (PermissionSettingView)
  • 功能: 用户增删改查、角色管理、权限分配、密码策略
3.1.8 系统设置模块 (SystemSettings)
  • 主页面: SystemSettingsMainView
  • 子页面 :
    • 通讯设置页面 (CommunicationSettingView)
    • 数据库设置页面 (DatabaseSettingView)
    • 系统配置页面 (SystemConfigView)
  • 功能: 通讯参数配置、数据库连接配置、系统参数配置

3.2 模块导航结构

MainWindow左侧菜单:

复制代码
GKTGD工业监控系统
├── 设备控制
│   ├── 设备总控
│   ├── 设备1控制  
│   └── 设备2控制
├── 机器视觉
│   ├── 视觉任务1
│   └── 视觉任务2
├── 数据监测
│   ├── 实时数据
│   └── 历史数据
├── 实时曲线
│   ├── 趋势图
│   └── 对比图
├── 工艺配方
│   ├── 配方管理
│   └── 配方执行
├── 数据报表
│   ├── 生产报表
│   └── 质量报表
├── 用户管理
│   ├── 用户列表
│   ├── 角色管理
│   └── 权限设置
└── 系统设置
    ├── 通讯设置
    ├── 数据库设置
    └── 系统配置

4. 独立类库设计

4.1 NET8_Comm 通讯类库

职责: 实现所有工业通讯协议,提供统一的通讯接口

目录结构:

复制代码
NET8_Comm/
├── Interfaces/                    # 通讯接口
│   ├── IModbusService.cs
│   ├── ISiemensS7Service.cs
│   ├── IBeckhoffADSService.cs
│   └── IEthernetService.cs
├── Modbus/                        # Modbus实现
│   ├── ModbusSerialService.cs
│   └── ModbusTcpService.cs
├── SiemensS7/                     # 西门子S7实现
│   ├── S7TcpService.cs
│   └── S7MpIService.cs
├── BeckhoffADS/                   # 倍福ADS实现
│   └── AdsClientService.cs
├── Ethernet/                      # Ethernet实现
│   └── TcpClientService.cs
├── Models/                        # 通讯相关模型
│   ├── CommunicationResult.cs
│   └── DeviceConnection.cs
└── Configuration/                 # 通讯配置
    ├── CommunicationSettings.cs
    └── ModbusSettings.cs

核心接口:

csharp 复制代码
public interface ICommunicationService
{
    bool Connect();
    void Disconnect();
    bool IsConnected { get; }
    Task<T> ReadAsync<T>(string address);
    Task<bool> WriteAsync<T>(string address, T value);
    event EventHandler<CommunicationEventArgs> DataReceived;
}

特点:

  • 完全独立,可单独使用
  • 支持多种通讯协议
  • 统一的接口设计
  • 连接池和错误重试机制

4.2 NET8_Vision 视觉类库

职责: 实现所有机器视觉功能,提供统一的视觉接口

目录结构:

复制代码
NET8_Vision/
├── Interfaces/                    # 视觉接口
│   ├── IHalconService.cs
│   ├── IVMService.cs
│   └── IOpenCVService.cs
├── Halcon/                        # Halcon实现
│   ├── HalconDetector.cs
│   ├── HalconMatcher.cs
│   └── HalconCamera.cs
├── VM/                            # VM实现
│   ├── VMDetector.cs
│   ├── VMMatcher.cs
│   └── VMCamera.cs
├── OpenCV/                        # OpenCV实现
│   ├── OpenCVDetector.cs
│   ├── OpenCVMatcher.cs
│   └── OpenCVCamera.cs
├── Models/                        # 视觉相关模型
│   ├── VisionResult.cs
│   └── CameraInfo.cs
└── Configuration/                 # 视觉配置
    ├── VisionSettings.cs
    └── CameraSettings.cs

核心接口:

csharp 复制代码
public interface IVisionService
{
    bool InitializeCamera(int cameraIndex);
    void ReleaseCamera();
    Task<ImageData> CaptureImageAsync();
    Task<DetectionResult> DetectDefectsAsync(ImageData image);
    Task<MatchResult> MatchPatternAsync(ImageData image, string patternPath);
}

特点:

  • 完全独立,可单独使用
  • 支持多种视觉库
  • 统一的图像处理接口
  • 相机管理和图像采集

4.3 NET8_SQLData 数据访问类库

职责: 实现数据库操作,提供统一的数据访问接口

目录结构:

复制代码
NET8_SQLData/
├── Interfaces/                    # 数据接口
│   ├── ISQLiteService.cs
│   ├── IMySQLService.cs
│   ├── IRepository.cs
│   └── IDbContext.cs
├── SQLite/                        # SQLite实现
│   ├── SQLiteService.cs
│   ├── SQLiteRepository.cs
│   └── SQLiteContext.cs
├── MySQL/                         # MySQL实现
│   ├── MySQLService.cs
│   ├── MySQLRepository.cs
│   └── MySQLContext.cs
├── Models/                        # 数据模型
│   ├── BaseEntity.cs
│   └── DbResult.cs
├── Migrations/                    # 数据库迁移
│   └── MigrationHistory.cs
└── Configuration/                 # 数据库配置
    ├── DatabaseSettings.cs
    └── ConnectionSettings.cs

核心接口:

csharp 复制代码
public interface IDataService
{
    Task<bool> ConnectAsync();
    Task DisconnectAsync();
    Task<IEnumerable<T>> QueryAsync<T>(string sql, object parameters = null);
    Task<bool> ExecuteAsync(string sql, object parameters = null);
    Task<int> InsertAsync<T>(T entity);
    Task<bool> UpdateAsync<T>(T entity);
    Task<bool> DeleteAsync<T>(int id);
}

特点:

  • 完全独立,可单独使用
  • 支持SQLite和MySQL
  • Repository模式实现
  • 数据库迁移和版本管理

5. 配置系统设计

5.1 配置文件结构 (appsettings.json)

json 复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "Communication": {
    "EnabledProviders": [
      "Modbus",
      "BeckhoffADS"
    ],
    "Modbus": {
      "ConnectionType": "Tcp",
      "IpAddress": "192.168.1.100",
      "Port": 502,
      "SlaveId": 1,
      "Enabled": true
    },
    "BeckhoffADS": {
      "AmsNetId": "192.168.1.100.1.1",
      "Port": 851,
      "LocalAmsNetId": "192.168.1.1.1.1",
      "Enabled": true
    },
    "SiemensS7": {
      "IpAddress": "192.168.1.101",
      "CpuType": "S7-1200",
      "Rack": 0,
      "Slot": 1,
      "Enabled": false
    },
    "Ethernet": {
      "IpAddress": "192.168.1.102",
      "Port": 2000,
      "Enabled": false
    }
  },
  "Vision": {
    "EnabledProviders": [
      "Halcon"
    ],
    "Halcon": {
      "LicensePath": "C:/Halcon/license.dat",
      "Enabled": true
    },
    "VM": {
      "LicensePath": "C:/VM/License",
      "Enabled": false
    },
    "OpenCV": {
      "Enabled": false
    }
  },
  "Database": {
    "Provider": "SQLite",
    "SQLite": {
      "ConnectionString": "Data Source=GKTGD.db",
      "Enabled": true
    },
    "MySQL": {
      "ConnectionString": "Server=localhost;Database=gktgd;Uid=root;Pwd=password;",
      "Enabled": false
    }
  },
  "Authentication": {
    "DefaultAdmin": {
      "Username": "admin",
      "Password": "123456",
      "ForceChangePassword": true
    },
    "PasswordPolicy": {
      "MinLength": 6,
      "RequireUppercase": false,
      "RequireLowercase": false,
      "RequireNumbers": false,
      "RequireSpecialChars": false
    },
    "SessionTimeout": 30
  },
  "UI": {
    "Theme": "Light",
    "Language": "zh-CN",
    "AutoLogout": true,
    "AutoLogoutInterval": 15
  }
}

5.2 动态服务注册

在App.xaml.cs中的服务注册:

csharp 复制代码
public partial class App : Application
{
    private ServiceProvider _serviceProvider;
    
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        
        var configuration = LoadConfiguration();
        var services = new ServiceCollection();
        
        ConfigureServices(services, configuration);
        
        _serviceProvider = services.BuildServiceProvider();
        
        var loginWindow = _serviceProvider.GetRequiredService<LoginWindow>();
        loginWindow.Show();
    }
    
    private void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // 注册核心服务
        services.AddSingleton<IConfiguration>(configuration);
        services.AddSingleton<INavigationService, NavigationService>();
        services.AddSingleton<IAuthenticationService, AuthenticationService>();
        services.AddSingleton<ILoggingService, LoggingService>();
        
        // 动态注册通讯服务
        if (configuration.Communication.Modbus.Enabled)
        {
            services.AddSingleton<IModbusService, ModbusTcpService>();
        }
        
        if (configuration.Communication.BeckhoffADS.Enabled)
        {
            services.AddSingleton<IBeckhoffADSService, BeckhoffADSService>();
        }
        
        // 动态注册视觉服务
        if (configuration.Vision.Halcon.Enabled)
        {
            services.AddSingleton<IHalconService, HalconService>();
        }
        
        // 动态注册数据库服务
        if (configuration.Database.SQLite.Enabled)
        {
            services.AddSingleton<IDataService, SQLiteService>();
        }
        
        // 注册主窗口和视图模型
        services.AddTransient<LoginWindow>();
        services.AddTransient<MainWindow>();
        services.AddTransient<LoginViewModel>();
        services.AddTransient<MainViewModel>();
    }
}

6. MVVM架构实现

6.1 MVVM层次结构

Model层: 数据模型和业务逻辑

  • 实体类 (Entities)
  • 数据访问对象 (DAO)
  • 业务逻辑服务

View层: UI界面和用户交互

  • XAML文件 (UI定义)
  • Code-behind (最小化代码逻辑)
  • 数据绑定和命令绑定

ViewModel层: 视图逻辑和数据绑定

  • 属性通知 (INotifyPropertyChanged)
  • 命令实现 (ICommand)
  • 数据转换和验证

6.2 ViewModel基类设计

csharp 复制代码
public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    
    protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
            return false;
            
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

public class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;
    
    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }
    
    public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
    
    public void Execute(object parameter) => _execute(parameter);
    
    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

6.3 数据绑定示例

ViewModel:

csharp 复制代码
public class DeviceControlViewModel : ViewModelBase
{
    private bool _isConnected;
    private string _deviceStatus;
    private ObservableCollection<DeviceData> _deviceData;
    
    public bool IsConnected
    {
        get => _isConnected;
        set => SetProperty(ref _isConnected, value);
    }
    
    public string DeviceStatus
    {
        get => _deviceStatus;
        set => SetProperty(ref _deviceStatus, value);
    }
    
    public ObservableCollection<DeviceData> DeviceData
    {
        get => _deviceData;
        set => SetProperty(ref _deviceData, value);
    }
    
    public ICommand ConnectCommand { get; }
    public ICommand DisconnectCommand { get; }
    
    public DeviceControlViewModel()
    {
        ConnectCommand = new RelayCommand(ExecuteConnect, CanExecuteConnect);
        DisconnectCommand = new RelayCommand(ExecuteDisconnect, CanExecuteDisconnect);
    }
    
    private bool CanExecuteConnect(object obj) => !IsConnected;
    private bool CanExecuteDisconnect(object obj) => IsConnected;
    
    private void ExecuteConnect(object obj)
    {
        // 连接逻辑
    }
    
    private void ExecuteDisconnect(object obj)
    {
        // 断开连接逻辑
    }
}

View (XAML):

xml 复制代码
<UserControl x:Class="GKTGD.Modules.DeviceControl.Views.DeviceControlMainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.DataContext>
        <local:DeviceControlViewModel />
    </UserControl.DataContext>
    
    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding DeviceStatus}" />
            <Button Content="连接" Command="{Binding ConnectCommand}" />
            <Button Content="断开" Command="{Binding DisconnectCommand}" />
            <DataGrid ItemsSource="{Binding DeviceData}" />
        </StackPanel>
    </Grid>
</UserControl>

7. 导航系统设计

7.1 导航服务接口

csharp 复制代码
public interface INavigationService
{
    void NavigateTo(string viewName, object parameter = null);
    void NavigateTo<T>(object parameter = null) where T : class;
    bool CanGoBack { get; }
    void GoBack();
    event EventHandler<NavigatedEventArgs> Navigated;
}

7.2 导航服务实现

csharp 复制代码
public class NavigationService : INavigationService
{
    private readonly Frame _frame;
    private readonly Stack<string> _navigationStack;
    
    public NavigationService(Frame frame)
    {
        _frame = frame;
        _navigationStack = new Stack<string>();
    }
    
    public void NavigateTo(string viewName, object parameter = null)
    {
        var viewType = Type.GetType($"GKTGD.Modules.{viewName}");
        if (viewType == null)
            throw new ArgumentException($"View {viewName} not found");
            
        var view = Activator.CreateInstance(viewType) as Page;
        if (view == null)
            throw new ArgumentException($"View {viewName} is not a Page");
            
        _navigationStack.Push(viewName);
        _frame.Navigate(view, parameter);
        
        Navigated?.Invoke(this, new NavigatedEventArgs(viewName, parameter));
    }
    
    public void NavigateTo<T>(object parameter = null) where T : class
    {
        NavigateTo(typeof(T).Name, parameter);
    }
    
    public bool CanGoBack => _navigationStack.Count > 1;
    
    public void GoBack()
    {
        if (!CanGoBack) return;
        
        _navigationStack.Pop(); // 移除当前页面
        var previousView = _navigationStack.Peek();
        
        // 重新导航到上一页
        _frame.GoBack();
    }
    
    public event EventHandler<NavigatedEventArgs> Navigated;
}

7.3 MainWindow中的导航实现

参考项目的导航方式(需改为MVVM模式):

xml 复制代码
<!-- MainWindow.xaml -->
<Frame x:Name="frameContent" 
       Margin="10,0,10,10" 
       NavigationUIVisibility="Hidden" />

改为MVVM模式的导航:

xml 复制代码
<!-- MainWindow.xaml -->
<ContentControl Content="{Binding CurrentView}" />
csharp 复制代码
// MainViewModel.cs
public class MainViewModel : ViewModelBase
{
    private object _currentView;
    private readonly INavigationService _navigationService;
    
    public object CurrentView
    {
        get => _currentView;
        set => SetProperty(ref _currentView, value);
    }
    
    public MainViewModel(INavigationService navigationService)
    {
        _navigationService = navigationService;
        _navigationService.Navigated += OnNavigated;
    }
    
    private void OnNavigated(object sender, NavigatedEventArgs e)
    {
        // 根据导航的视图名称加载对应的View和ViewModel
        var viewType = GetViewType(e.ViewName);
        var viewModelType = GetViewModelType(e.ViewName);
        
        var view = Activator.CreateInstance(viewType);
        var viewModel = _serviceProvider.GetService(viewModelType);
        
        ((FrameworkElement)view).DataContext = viewModel;
        CurrentView = view;
    }
}

8. 用户认证和权限系统

8.1 用户认证流程

复制代码
LoginWindow (登录界面)
    ↓ 用户输入用户名密码
AuthenticationService (认证服务)
    ↓ 验证成功
MainWindow (主窗口)
    ↓ 根据用户权限加载模块菜单
    ↓ 控制功能访问权限

8.2 用户权限模型

csharp 复制代码
public class UserModel
{
    public int UserId { get; set; }
    public string Username { get; set; }
    public string PasswordHash { get; set; }
    public string RealName { get; set; }
    public int RoleId { get; set; }
    public DateTime? LastLoginTime { get; set; }
    public bool IsActive { get; set; }
}

public class RoleModel
{
    public int RoleId { get; set; }
    public string RoleName { get; set; }
    public string Description { get; set; }
    public List<int> PermissionIds { get; set; }
}

public class PermissionModel
{
    public int PermissionId { get; set; }
    public string PermissionName { get; set; }
    public string ModuleName { get; set; }  // 模块名称
    public string PermissionType { get; set; } // View, Edit, Delete, Export
}

8.3 三层权限控制策略

工业系统的权限控制采用三层防护策略,确保安全性和用户体验的最佳平衡

8.3.1 第一层:页面级权限(导航级别)

职责: 控制用户能否访问特定的模块和页面

实现示例:

csharp 复制代码
// MainWindowViewModel.cs - 根据权限过滤菜单
public class MainWindowViewModel : ViewModelBase
{
    private readonly IAuthenticationService _authService;
    public ObservableCollection<ModuleMenuItem> VisibleModules { get; }
    
    public MainWindowViewModel(IAuthenticationService authService)
    {
        _authService = authService;
        VisibleModules = FilterModulesByPermission();
    }
    
    private ObservableCollection<ModuleMenuItem> FilterModulesByPermission()
    {
        var allModules = GetAllModules();
        var authorizedModules = allModules
            .Where(m => _authService.HasPermission(m.Id, "View"))
            .ToList();
        return new ObservableCollection<ModuleMenuItem>(authorizedModules);
    }
    
    // 导航时再次验证(双重保护)
    public void NavigateToModule(string moduleId)
    {
        if (!_authService.HasPermission(moduleId, "View"))
        {
            _messageService.ShowError("您没有访问此模块的权限");
            _loggingService.LogWarning($"未授权访问模块: {moduleId}");
            return;
        }
        
        _navigationService.NavigateTo(moduleId);
    }
}
8.3.2 第二层:操作级权限(功能级别)

职责: 控制用户能否执行特定的操作,是核心安全层

实现示例:

csharp 复制代码
// DeviceControlViewModel.cs - 操作级权限控制
public class DeviceControlViewModel : ViewModelBase
{
    private readonly IAuthenticationService _authService;
    private readonly IMessageService _messageService;
    private readonly ILoggingService _loggingService;
    
    // 命令级别权限控制 - 按钮启用/禁用状态
    public ICommand ConnectCommand => new RelayCommand(
        ExecuteConnect,
        () => _authService.HasPermission("DeviceControl", "Connect")
    );
    
    public ICommand DeleteDeviceCommand => new RelayCommand(
        ExecuteDeleteDevice,
        () => _authService.HasPermission("DeviceControl", "Delete")
    );
    
    public ICommand EmergencyStopCommand => new RelayCommand(
        ExecuteEmergencyStop,
        () => _authService.HasPermission("DeviceControl", "EmergencyStop")
    );
    
    // 执行时再次验证(双重保护)
    private void ExecuteConnect()
    {
        if (!_authService.HasPermission("DeviceControl", "Connect"))
        {
            throw new UnauthorizedAccessException("无连接权限");
        }
        
        try
        {
            _deviceService.Connect();
            _loggingService.LogInfo($"用户 {_authService.CurrentUser.Username} 连接设备");
        }
        catch (Exception ex)
        {
            _loggingService.LogError("设备连接失败", ex);
            _messageService.ShowError("设备连接失败");
        }
    }
    
    // 关键操作需要三重验证
    private void ExecuteEmergencyStop()
    {
        // 1. 权限验证
        if (!_authService.HasPermission("DeviceControl", "EmergencyStop"))
        {
            _messageService.ShowError("您没有执行紧急停机的权限");
            _loggingService.LogCritical($"用户 {_authService.CurrentUser.Username} 尝试未授权紧急停机");
            return;
        }
        
        // 2. 二次确认
        var result = _messageService.Confirm("确认执行紧急停机?此操作不可撤销!", "紧急操作");
        if (!result) return;
        
        // 3. 操作日志记录
        _loggingService.LogCritical($"用户 {_authService.CurrentUser.Username} 执行紧急停机");
        
        // 4. 执行操作
        try
        {
            _deviceService.EmergencyStop();
            _messageService.ShowInfo("紧急停机已执行");
        }
        catch (Exception ex)
        {
            _loggingService.LogCritical("紧急停机执行失败", ex);
            _messageService.ShowError("紧急停机执行失败");
        }
    }
}
8.3.3 第三层:UI级权限(可见性级别)

职责: 根据权限动态显示/隐藏UI元素,优化用户体验

XAML实现示例:

xml 复制代码
<!-- DeviceControlMainView.xaml -->
<UserControl x:Class="GKTGD.Modules.DeviceControl.Views.DeviceControlMainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.DataContext>
        <local:DeviceControlViewModel />
    </UserControl.DataContext>
    
    <Grid>
        <StackPanel>
            <!-- 所有用户都能看到的基础信息 -->
            <TextBlock Text="设备状态监控" FontSize="18" FontWeight="Bold" />
            <TextBlock Text="{Binding DeviceStatus}" />
            
            <!-- 基础操作权限 - 大多数用户都有 -->
            <Button Content="连接设备" 
                    Command="{Binding ConnectCommand}"
                    Width="120" Height="35" Margin="5" />
            
            <Button Content="断开连接" 
                    Command="{Binding DisconnectCommand}"
                    Width="120" Height="35" Margin="5" />
            
            <!-- 配置权限 - 只有工程师级别才有 -->
            <Expander Header="高级配置"
                      Margin="0,10,0,10"
                      Visibility="{Binding CanConfigure, 
                                   Converter={StaticResource BoolToVisibilityConverter}}">
                <StackPanel Margin="20,5,0,10">
                    <TextBlock Text="IP地址:" />
                    <TextBox Text="{Binding DeviceIp}" Width="200" />
                    
                    <TextBlock Text="端口:" />
                    <TextBox Text="{Binding DevicePort}" Width="200" />
                    
                    <Button Content="保存配置" 
                            Command="{Binding SaveConfigCommand}"
                            Width="120" Height="35" Margin="5" />
                </StackPanel>
            </Expander>
            
            <!-- 删除权限 - 只有管理员才有 -->
            <Button Content="删除设备" 
                    Command="{Binding DeleteCommand}"
                    Width="120" Height="35" Margin="5"
                    Background="Red" Foreground="White"
                    Visibility="{Binding CanDeleteDevice, 
                                 Converter={StaticResource BoolToVisibilityConverter}}" />
            
            <!-- 紧急停机权限 - 特殊操作权限 -->
            <Button Content="紧急停机" 
                    Command="{Binding EmergencyStopCommand}"
                    Width="120" Height="35" Margin="5"
                    Background="DarkRed" Foreground="White" FontWeight="Bold"
                    Visibility="{Binding CanEmergencyStop, 
                                 Converter={StaticResource BoolToVisibilityConverter}}" />
        </StackPanel>
    </Grid>
</UserControl>

ViewModel中的UI权限属性:

csharp 复制代码
public class DeviceControlViewModel : ViewModelBase
{
    private readonly IAuthenticationService _authService;
    
    // UI级权限属性
    public bool CanConfigure => _authService.HasPermission("DeviceControl", "Configure");
    public bool CanDeleteDevice => _authService.HasPermission("DeviceControl", "Delete");
    public bool CanEmergencyStop => _authService.HasPermission("DeviceControl", "EmergencyStop");
    
    // 当权限变化时通知UI更新
    public void RefreshPermissions()
    {
        OnPropertyChanged(nameof(CanConfigure));
        OnPropertyChanged(nameof(CanDeleteDevice));
        OnPropertyChanged(nameof(CanEmergencyStop));
    }
}

8.4 权限控制架构图

复制代码
用户登录
    ↓
┌─────────────────────────────────────┐
│    第一层:页面级权限                │
│  - 过滤导航菜单                      │
│  - 验证页面访问权限                  │
│  - 记录页面访问日志                  │
└─────────────────────────────────────┘
    ↓ 有页面访问权限
┌─────────────────────────────────────┐
│    第二层:操作级权限                │
│  - 按钮启用/禁用控制                 │
│  - 命令执行权限验证                  │
│  - 关键操作二次确认                  │
│  - 操作审计日志                      │
└─────────────────────────────────────┘
    ↓ 有操作权限
┌─────────────────────────────────────┐
│    第三层:UI级权限                  │
│  - UI元素显示/隐藏                   │
│  - 优化用户界面体验                  │
│  - 避免用户困惑                      │
└─────────────────────────────────────┘

8.5 权限矩阵示例

复制代码
用户角色        | 页面访问 | 设备操作 | 高级配置 | 用户管理 | 系统设置
---------------|---------|---------|---------|---------|----------
超级管理员     |   ✓    |   ✓    |   ✓    |   ✓    |   ✓
设备工程师     |   ✓    |   ✓    |   ✓    |   ✗    |   部分
操作员         |   ✓    |   部分  |   ✗    |   ✗    |   ✗
访客           |   部分  |   ✗    |   ✗    |   ✗    |   ✗

8.6 权限缓存策略

工业系统需要实时权限检查,但要平衡性能:

csharp 复制代码
public class CachedAuthenticationService : IAuthenticationService
{
    private readonly IAuthenticationService _authService;
    private readonly MemoryCache _permissionCache;
    private readonly ILogger _logger;
    
    public CachedAuthenticationService(IMemoryCache cache, ILogger logger)
    {
        _permissionCache = cache;
        _logger = logger;
    }
    
    public bool HasPermission(string module, string operation)
    {
        var currentUser = _authService.CurrentUser;
        if (currentUser == null) return false;
        
        string cacheKey = $"{currentUser.Id}_{module}_{operation}";
        
        // 缓存5秒,避免频繁查询数据库,同时保证权限变更的实时性
        if (!_permissionCache.TryGetValue(cacheKey, out bool hasPermission))
        {
            hasPermission = _authService.HasPermission(module, operation);
            _permissionCache.Set(cacheKey, hasPermission, TimeSpan.FromSeconds(5));
            
            _logger.LogDebug($"权限检查: {currentUser.Username} - {module}.{operation} = {hasPermission}");
        }
        
        return hasPermission;
    }
    
    // 权限变更时清除缓存
    public void ClearPermissionCache(int userId)
    {
        var keysToRemove = _permissionCache.Where(
            kvp => kvp.Key.StartsWith($"{userId}_")
        ).Select(kvp => kvp.Key).ToList();
        
        foreach (var key in keysToRemove)
        {
            _permissionCache.Remove(key);
        }
    }
}

8.7 三层权限控制的优势

1. 安全性 : 三层防护,即使某一层失效,其他层仍能保护系统
2. 用户体验 : 用户只看到有权操作的功能,界面简洁清晰
3. 性能优化 : 通过权限缓存减少数据库查询
4. 审计追踪 : 完整的操作日志记录,满足工业审计要求
5. 灵活配置: 支持动态权限变更,实时生效

9. UI设计和主题系统

9.1 UI设计风格参考

参考项目UI特点:

  • 左侧导航菜单,右侧内容区域
  • 支持菜单展开/收起动画
  • 自定义卡片按钮、进度条等控件
  • 浅色/深色主题切换
  • 图标+文字的菜单项显示

9.2 主题系统设计

主题颜色定义:

xml 复制代码
<!-- LightTheme.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="PrimaryBackgroundColor" Color="#EAEAEF"/>
    <SolidColorBrush x:Key="SecundaryBackgroundColor" Color="#F2F4F8"/>
    <SolidColorBrush x:Key="PrimaryTextColor" Color="#000000"/>
    <SolidColorBrush x:Key="SecundaryGreenColor" Color="#12C092"/>
    <SolidColorBrush x:Key="SecundaryBlueColor" Color="#3A6AA9"/>
</ResourceDictionary>

<!-- DarkTheme.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="PrimaryBackgroundColor" Color="#121212"/>
    <SolidColorBrush x:Key="SecundaryBackgroundColor" Color="#1E1E1E"/>
    <SolidColorBrush x:Key="PrimaryTextColor" Color="#FFFFFF"/>
    <SolidColorBrush x:Key="SecundaryGreenColor" Color="#12C092"/>
    <SolidColorBrush x:Key="SecundaryBlueColor" Color="#3A6AA9"/>
</ResourceDictionary>

9.3 自定义控件复用

从参考项目复用的控件:

  • CardButton - 卡片按钮(带进度条)
  • CircularProgressBar - 圆形进度条
  • DataCard - 数据卡片
  • Paginator - 分页器
  • Switch - 开关控件

10. 错误处理和日志系统

10.1 错误处理策略

多层级错误处理:

  1. UI层: 用户输入验证
  2. ViewModel层: 业务逻辑验证
  3. Service层: 服务异常处理
  4. Data层: 数据访问异常处理

10.2 日志系统设计

csharp 复制代码
public interface ILoggingService
{
    void LogDebug(string message);
    void LogInfo(string message);
    void LogWarning(string message);
    void LogError(string message, Exception exception = null);
    void LogCritical(string message, Exception exception = null);
}

public class LoggingService : ILoggingService
{
    private readonly string _logFilePath;
    
    public LoggingService(IConfiguration configuration)
    {
        _logFilePath = configuration["Logging:FilePath"] ?? "Logs/GKTGD.log";
    }
    
    public void LogInfo(string message)
    {
        var logMessage = $"[INFO] {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}";
        File.AppendAllText(_logFilePath, logMessage + Environment.NewLine);
    }
    
    // 其他日志方法...
}

11. 开发和部署计划

11.1 开发阶段

阶段1: 基础架构搭建

  • 创建解决方案和项目结构
  • 实现MVVM基础框架
  • 搭建配置系统
  • 实现导航服务

阶段2: 独立类库开发

  • 开发NET8_Comm通讯类库
  • 开发NET8_Vision视觉类库
  • 开发NET8_SQLData数据访问类库

阶段3: 核心功能模块

  • 实现用户认证和权限管理
  • 开发设备控制模块
  • 开发机器视觉模块

阶段4: 扩展功能模块

  • 开发数据监测模块
  • 开发实时曲线模块
  • 开发工艺配方模块
  • 开发数据报表模块
  • 开发系统设置模块

阶段5: UI优化和测试

  • UI界面优化
  • 功能测试
  • 性能优化
  • 用户验收测试

11.2 技术风险和应对措施

风险1: 第三方库兼容性

  • Halcon、VM视觉库可能存在版本兼容问题
  • 应对:在开发初期进行技术验证

风险2: 通讯协议稳定性

  • 工业通讯环境复杂,可能存在干扰和断线
  • 应对:实现重连机制和错误恢复

风险3: 数据库性能

  • 实时数据量可能很大,影响数据库性能
  • 应对:实现数据缓存和分页查询

12. 总结

12.1 设计优势

  1. 高度模块化: 通讯、视觉、数据库功能独立为类库,便于复用和维护
  2. 灵活配置: 通过配置文件动态启用功能,按需引用类库
  3. 标准MVVM: 严格遵循MVVM模式,代码结构清晰
  4. 权限管理: 基于角色的权限控制,保障系统安全
  5. UI一致性: 参考成熟项目的UI设计,保证用户体验

12.2 扩展性

  1. 新增通讯协议: 在NET8_Comm中添加新的实现类
  2. 新增视觉库: 在NET8_Vision中添加新的实现类
  3. 新增功能模块: 在Modules文件夹中添加新的模块
  4. UI主题扩展: 在Themes文件夹中添加新的主题文件
  5. 数据库切换: 通过配置文件切换SQLite/MySQL

12.3 下一步

设计文档完成后,将进入实施计划阶段,创建详细的开发计划和任务分解。

相关推荐
秋の本名1 天前
第一章 鸿蒙生态架构与开发理念
华为·wpf·harmonyos
Bofu-1 天前
【音频测试】03-WPF 实现声道自动验证 + Whisper 语音识别录音检测
c#·whisper·wpf·音视频·音频测试·naudio 声道控制
秋の本名1 天前
DevEco Studio 版本演进揭秘:从3.0到5.0的分布式开发能力飞跃与智能体验革新
wpf·鸿蒙系统
heimeiyingwang4 天前
【架构实战】状态机架构:订单/工单状态流转设计
观察者模式·架构·wpf
KmSH8umpK5 天前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第三篇
redis·分布式·wpf
KmSH8umpK5 天前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案
redis·分布式·wpf
武藤一雄5 天前
WPF:MessageBox系统消息框
前端·microsoft·c#·.net·wpf
武藤一雄5 天前
WPF进阶:万字详解WPF如何性能优化
windows·性能优化·c#·.net·wpf·.netcore·鲁棒性