From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点
---
Plugin.DeviceConfig/BatchGenerateModal.xaml.cs | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 252 insertions(+), 0 deletions(-)
diff --git a/Plugin.DeviceConfig/BatchGenerateModal.xaml.cs b/Plugin.DeviceConfig/BatchGenerateModal.xaml.cs
new file mode 100644
index 0000000..b5eb211
--- /dev/null
+++ b/Plugin.DeviceConfig/BatchGenerateModal.xaml.cs
@@ -0,0 +1,252 @@
+using HMI.UI.Util;
+using Panuon.WPF.UI;
+using Plugin.DeviceConfig.Entity;
+using Plugin.DeviceConfig.Model;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows;
+
+namespace Plugin.DeviceConfig
+{
+ /// <summary>
+ /// BatchGenerateModal.xaml 鐨勪氦浜掗�昏緫
+ /// </summary>
+ public partial class BatchGenerateModal : WindowX
+ {
+ private DeviceConfigModel _model;
+ private ObservableCollection<BatchPreviewItem> _previewItems = new();
+
+ public BatchGenerateModal()
+ {
+ DataContext = this;
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// 鎵撳紑寮圭獥
+ /// </summary>
+ public bool? Open(DeviceConfigModel model)
+ {
+ _model = model;
+
+ // 鍒濆鍖栨灇涓句笅鎷�
+ cbDeviceType.ItemsSource = Enum.GetValues(typeof(DeviceKind)).Cast<DeviceKind>().ToList();
+ cbTransport.ItemsSource = Enum.GetValues(typeof(TransportType)).Cast<TransportType>().ToList();
+
+ // 榛樿鍊�
+ cbDeviceType.SelectedIndex = 0;
+ cbTransport.SelectedIndex = 0;
+ tbAddressRule.Text = "192.168.10.{0}";
+ tbSlotStart.Text = "Slot001";
+ tbDeviceIdPrefix.Text = "DEV";
+
+ previewListView.ItemsSource = _previewItems;
+
+ return ShowDialog();
+ }
+
+ #region 棰勮
+
+ private void PreviewBtn_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ GeneratePreview();
+ }
+ catch (Exception ex)
+ {
+ tbConflictMsg.Text = $"鐢熸垚棰勮澶辫触: {ex.Message}";
+ tbConflictMsg.Visibility = Visibility.Visible;
+ }
+ }
+
+ private void GeneratePreview()
+ {
+ _previewItems.Clear();
+ tbConflictMsg.Visibility = Visibility.Collapsed;
+
+ if (cbDeviceType.SelectedItem is not DeviceKind kind)
+ {
+ ShowConflict("璇烽�夋嫨璁惧绫诲瀷");
+ return;
+ }
+ if (cbTransport.SelectedItem is not TransportType transport)
+ {
+ ShowConflict("璇烽�夋嫨浼犺緭鏂瑰紡");
+ return;
+ }
+
+ int count = (int)(niDeviceCount.Value ?? 1);
+ int channelsPerDevice = (int)(niChannelsPerDevice.Value ?? 1);
+ int startPort = (int)(niStartPort.Value ?? 30000);
+ string addressRule = tbAddressRule.Text?.Trim() ?? string.Empty;
+ string slotStart = tbSlotStart.Text?.Trim() ?? string.Empty;
+ string prefix = tbDeviceIdPrefix.Text?.Trim() ?? "DEV";
+ string driverType = tbDriverType.Text?.Trim() ?? string.Empty;
+
+ // 妫�娴嬪凡鏈夎澶嘔D
+ var existingDevices = _model.GetAllDevices();
+ var existingIds = new HashSet<string>(existingDevices.Select(d => d.DeviceId));
+ var existingEndpoints = new HashSet<string>(existingDevices.Select(d => d.Endpoint));
+
+ var conflicts = new List<string>();
+ var generatedIds = new HashSet<string>();
+ var generatedEndpoints = new HashSet<string>();
+
+ for (int i = 1; i <= count; i++)
+ {
+ var deviceId = $"{prefix}{i:D3}";
+ var endpoint = string.Format(addressRule, i);
+ if (transport == TransportType.Tcp && !string.IsNullOrEmpty(addressRule))
+ {
+ endpoint = $"{endpoint}:{startPort + i - 1}";
+ }
+ else if (transport == TransportType.Serial)
+ {
+ endpoint = $"COM{i}";
+ }
+
+ // 瑙f瀽 SlotStart 鐨勫簭鍙烽儴鍒嗗苟閫掑
+ var slotPrefix = new string(slotStart.TakeWhile(c => !char.IsDigit(c)).ToArray());
+ var slotNumStr = new string(slotStart.SkipWhile(c => !char.IsDigit(c)).ToArray());
+ int.TryParse(slotNumStr, out int startNum);
+ var slotId = $"{slotPrefix}{(startNum + i - 1):D3}";
+
+ // 妫�娴嬪啿绐�
+ if (existingIds.Contains(deviceId) || generatedIds.Contains(deviceId))
+ conflicts.Add($"璁惧ID鍐茬獊: {deviceId}");
+ if (existingEndpoints.Contains(endpoint) || generatedEndpoints.Contains(endpoint))
+ conflicts.Add($"Endpoint鍐茬獊: {endpoint}");
+
+ generatedIds.Add(deviceId);
+ generatedEndpoints.Add(endpoint);
+
+ _previewItems.Add(new BatchPreviewItem
+ {
+ DeviceId = deviceId,
+ Kind = kind,
+ DriverType = driverType,
+ Transport = transport,
+ Endpoint = endpoint,
+ ChannelCount = channelsPerDevice,
+ SlotStart = slotId,
+ });
+ }
+
+ if (conflicts.Count > 0)
+ {
+ ShowConflict(string.Join("\n", conflicts));
+ }
+ }
+
+ private void ShowConflict(string msg)
+ {
+ tbConflictMsg.Text = msg;
+ tbConflictMsg.Visibility = Visibility.Visible;
+ }
+
+ #endregion
+
+ #region 淇濆瓨
+
+ private void SaveBtn_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (_previewItems.Count == 0)
+ {
+ ToastHelper.Warning("璇峰厛鐢熸垚棰勮");
+ return;
+ }
+
+ if (tbConflictMsg.Visibility == Visibility.Visible)
+ {
+ if (MsgBoxHelper.WarnMessage(this, "瀛樺湪鍐茬獊椤癸紝鏄惁浠嶈缁х画淇濆瓨锛�") != MessageBoxResult.OK)
+ {
+ return;
+ }
+ }
+
+ int channelsPerDevice = (int)(niChannelsPerDevice.Value ?? 1);
+ string slotStart = tbSlotStart.Text?.Trim() ?? string.Empty;
+
+ foreach (var item in _previewItems)
+ {
+ // 淇濆瓨璁惧
+ var device = new DeviceDefinition
+ {
+ DeviceId = item.DeviceId,
+ Kind = item.Kind,
+ DriverType = item.DriverType,
+ Transport = item.Transport,
+ Endpoint = item.Endpoint,
+ CreatedAt = DateTime.Now,
+ UpdatedAt = DateTime.Now,
+ };
+ _model.SaveDevice(device);
+
+ // 淇濆瓨閫氶亾
+ for (int ch = 0; ch < channelsPerDevice; ch++)
+ {
+ var channel = new DeviceChannel
+ {
+ DeviceId = item.DeviceId,
+ ChannelId = ch,
+ Capability = $"CH{ch}",
+ MaxVoltage = 0,
+ MaxCurrent = 0,
+ };
+ _model.SaveChannel(channel);
+ }
+
+ // 淇濆瓨 Slot 鏄犲皠
+ if (!string.IsNullOrEmpty(item.SlotStart))
+ {
+ var mapping = new SlotDeviceMapping
+ {
+ SlotId = item.SlotStart,
+ Capability = "Default",
+ Version = "1.0",
+ DeviceId = item.DeviceId,
+ ChannelId = 0,
+ MappingVersion = "1.0",
+ };
+ _model.SaveSlotMapping(mapping);
+ }
+ }
+
+ ToastHelper.Success($"鎴愬姛鐢熸垚 {_previewItems.Count} 涓澶�");
+ DialogResult = true;
+ Close();
+ }
+ catch (Exception ex)
+ {
+ ToastHelper.Error($"淇濆瓨澶辫触: {ex.Message}");
+ }
+ }
+
+ private void CancelBtn_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = false;
+ Close();
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// 鎵归噺鐢熸垚棰勮椤�
+ /// </summary>
+ public class BatchPreviewItem
+ {
+ public string DeviceId { get; set; } = string.Empty;
+ public DeviceKind Kind { get; set; }
+ public string DriverType { get; set; } = string.Empty;
+ public TransportType Transport { get; set; }
+ public string Endpoint { get; set; } = string.Empty;
+ public int ChannelCount { get; set; }
+ public string SlotStart { get; set; } = string.Empty;
+ }
+}
--
Gitblit v1.9.1