first commit

This commit is contained in:
lq
2026-09-07 08:07:08 +08:00
commit e703fb2752
2488 changed files with 2784663 additions and 0 deletions
+722
View File
@@ -0,0 +1,722 @@
using JinYuan.Helper;
using JinYuan.Models;
using Language;
using MiniExcelLibs;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Xml.Schema;
namespace LargeSquareOne
{
public partial class CommunicationEditForm : MultiLanguageForm
{
private string groupPath = Application.StartupPath + "\\Config\\Group.xlsx";
private List<PlcGroupConfig> TotalGroups = new List<PlcGroupConfig>();
private PlcGroupConfig editingConfig;
private int PlcNum;
public CommunicationEditForm(int plcNum)
{
PlcNum = plcNum;
InitializeComponent();
this.groupTable.AutoGenerateColumns = false;
InitializeDataGridView();
TotalGroups = GetALLGroups();
LoadGroups();
}
/// <summary>
/// 初始化DataGridView
/// </summary>
private void InitializeDataGridView()
{
groupTable.AutoGenerateColumns = false;
groupTable.AllowUserToAddRows = false;
groupTable.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
groupTable.MultiSelect = false;
groupTable.ReadOnly = false;
// 添加列
groupTable.Columns.AddRange(new DataGridViewColumn[]
{
new DataGridViewTextBoxColumn
{
Name = "PlcNum",
HeaderText = "PLC编号",
Width = 120,
ReadOnly = true,
DataPropertyName = "PlcNum",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewTextBoxColumn
{
Name = "GroupName",
HeaderText = "组名",
Width = 120,
DataPropertyName = "GroupName",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewTextBoxColumn
{
Name = "Start",
HeaderText = "起始地址",
Width = 150,
DataPropertyName = "Start",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewTextBoxColumn
{
Name = "Length",
HeaderText = "长度",
Width = 120,
DataPropertyName = "Length",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewCheckBoxColumn
{
Name = "IsTiggerRead",
HeaderText = "触发读取",
Width = 150,
DataPropertyName = "IsTiggerRead",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewCheckBoxColumn
{
Name = "IsFeedbackPlc",
HeaderText = "反馈PLC",
Width = 150,
DataPropertyName = "IsFeedbackPlc",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewCheckBoxColumn
{
Name = "IsActive",
HeaderText = "是否启用",
Width = 150,
DataPropertyName = "IsActive",
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewTextBoxColumn
{
Name = "Remark",
HeaderText = "备注",
Width = 150,
DataPropertyName = "Remark",
Visible=false,
DefaultCellStyle = new DataGridViewCellStyle(){Alignment=DataGridViewContentAlignment.MiddleCenter},
},
new DataGridViewButtonColumn
{
Name = "Edit",
HeaderText = "操作",
Width = 100,
Text = "修改".Translated(),
UseColumnTextForButtonValue = true
},
new DataGridViewButtonColumn
{
Name = "Delete",
HeaderText = "",
Width = 100,
Text = "删除".Translated(),
UseColumnTextForButtonValue = true
}
});
// 添加事件处理
groupTable.CellBeginEdit += DataGridView_CellBeginEdit;
groupTable.CellEndEdit += DataGridView_CellEndEdit;
groupTable.CellContentClick += DataGridView_CellContentClick;
}
/// <summary>
/// 加载数据到表格
/// </summary>
private void LoadGroups()
{
var plcGroups = TotalGroups.Where(g => g.PlcNum == PlcNum).ToList();
groupTable.DataSource = null;
groupTable.DataSource = plcGroups;
}
/// <summary>
/// 获取所有通信组
/// </summary>
/// <returns></returns>
private List<PlcGroupConfig> GetALLGroups()
{
try
{
return MiniExcel.Query<PlcGroupConfig>(groupPath).ToList();
}
catch (Exception)
{
return new List<PlcGroupConfig>();
}
}
/// <summary>
/// 单元格开始编辑
/// </summary>
private void DataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.RowIndex < 0) return;
editingConfig = TotalGroups[e.RowIndex];
// 禁止编辑PLC编号和组名列
if (groupTable.Columns[e.ColumnIndex].Name == "PlcNum")
{
e.Cancel = true;
}
}
/// <summary>
/// 单元格结束编辑
/// </summary>
private void DataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || e.RowIndex >= TotalGroups.Count) return;
var config = TotalGroups[e.RowIndex];
var value = groupTable[e.ColumnIndex, e.RowIndex].Value;
try
{
UpdateConfigValue(config, e.ColumnIndex, value);
}
catch (Exception ex)
{
ShowError($"更新数据失败: {ex.Message}");
}
}
/// <summary>
/// 更新配置值
/// </summary>
private void UpdateConfigValue(PlcGroupConfig config, int columnIndex, object value)
{
switch (groupTable.Columns[columnIndex].Name)
{
case "GroupName":
if (string.IsNullOrWhiteSpace(value?.ToString()))
{
throw new Exception("组名不能为空".Translated());
}
config.GroupName = value.ToString();
break;
case "Start":
if (!ValidateAddressFormat(value?.ToString()))
{
throw new Exception("起始地址格式不正确".Translated());
}
config.Start = value.ToString();
break;
case "Length":
if (!int.TryParse(value?.ToString(), out int length) || length <= 0)
{
throw new Exception("长度必须是大于0的数字".Translated());
}
config.Length = length;
break;
case "IsTiggerRead":
config.IsTiggerRead = value != null && (bool)value;
break;
case "IsFeedbackPlc":
config.IsFeedbackPlc = value != null && (bool)value;
break;
case "IsActive":
config.IsActive = value != null && (bool)value;
break;
case "Remark":
config.Remark = value?.ToString() ?? string.Empty;
break;
}
}
/// <summary>
/// 单元格点击事件
/// </summary>
private void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;
// 获取当前行显示的数据
var currentRow = groupTable.Rows[e.RowIndex];
var config = (PlcGroupConfig)currentRow.DataBoundItem;
// 找到在 TotalGroups 中的真实索引
var realIndex = TotalGroups.FindIndex(g =>
g.PlcNum == config.PlcNum &&
g.GroupName == config.GroupName &&
g.Start == config.Start);
// 编辑按钮
if (groupTable.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
groupTable.Columns[e.ColumnIndex].Name == "Edit")
{
// 传递真实的索引,而不是显示的行索引
HandleEdit(config, realIndex);
}
// 删除按钮
else if (groupTable.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
groupTable.Columns[e.ColumnIndex].Name == "Delete")
{
HandleDelete(config);
}
}
/// <summary>
/// 处理编辑操作
/// </summary>
private void HandleEdit(PlcGroupConfig config, int rowIndex)
{
try
{
var result = MessageBox.Show("是否保存修改的配置?".Translated(), "确认保存".Translated(), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result != DialogResult.Yes) return;
if (!ValidateConfigAll(config)) return;
// 更新TotalGroups中的配置
TotalGroups[rowIndex] = config;
// 保存到Excel
SaveToExcel(TotalGroups);
// 重新加载显示
LoadGroups();
ShowSuccess("配置保存成功".Translated());
}
catch (Exception ex)
{
ShowError($"保存失败: {ex.Message}");
}
}
/// <summary>
/// 处理删除操作
/// </summary>
private void HandleDelete(PlcGroupConfig config)
{
var result = MessageBox.Show($"确定要删除该通信组吗?\n PLC编号[{config.PlcNum}] 组名: [{config.GroupName}]", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
try
{
TotalGroups.Remove(config);
SaveToExcel(TotalGroups);
LoadGroups();
ShowSuccess("删除成功".Translated());
}
catch (Exception ex)
{
ShowError($"删除失败: {ex.Message}");
}
}
}
/// <summary>
/// 保存配置到Excel文件
/// </summary>
private void SaveToExcel(List<PlcGroupConfig> configs)
{
try
{
// 创建临时文件路径
string tempFilePath = Path.Combine(
Path.GetDirectoryName(groupPath),
$"temp_{Path.GetFileName(groupPath)}");
// 先保存到临时文件
MiniExcel.SaveAs(tempFilePath, configs);
// 检查临时文件是否创建成功
if (!File.Exists(tempFilePath))
{
throw new Exception("创建临时文件失败".Translated());
}
try
{
// 如果原文件存在,先删除
if (File.Exists(groupPath))
{
File.Delete(groupPath);
}
// 将临时文件重命名为目标文件
File.Move(tempFilePath, groupPath);
}
finally
{
// 确保临时文件被删除
if (File.Exists(tempFilePath))
{
File.Delete(tempFilePath);
}
}
}
catch (Exception ex)
{
throw new Exception($"保存Excel文件时发生错误: {ex.Message}", ex);
}
}
/// <summary>
/// 验证单行配置
/// </summary>
private bool ValidateConfigAll(PlcGroupConfig config)
{
try
{
// 基本字段验证
if (string.IsNullOrWhiteSpace(config.GroupName))
{
ShowError("组名不能为空".Translated());
return false;
}
if (string.IsNullOrWhiteSpace(config.Start))
{
ShowError("起始地址不能为空".Translated());
return false;
}
if (config.Length <= 0)
{
ShowError("长度必须大于0".Translated());
return false;
}
// 地址格式验证
if (!ValidateAddressFormat(config.Start))
{
ShowError("起始地址格式不正确,应以'D'开头后跟数字".Translated());
return false;
}
// 打印调试信息
Console.WriteLine($"当前要添加的配置 - PLC号: {config.PlcNum}, 组名: {config.GroupName}");
//// 打印所有的配置
//Console.WriteLine("\n所有配置信息:");
//foreach (var g in TotalGroups)
//{
// Console.WriteLine($"PLC号: {g.PlcNum}, 组名: {g.GroupName}");
//}
// 筛选同PLC的配置(不包括当前正在添加的配置)
var groupsInSamePLC = TotalGroups.Where(g =>
g.PlcNum == config.PlcNum && // 筛选 PLC1 的配置
g != config // 这个条件是需要的,因为可能当前配置已经在集合中
).ToList();
// 3. 只在同一个PLC内检查地址是否冲突
if (groupsInSamePLC.Any(g => g.GroupName.Equals(config.GroupName, StringComparison.OrdinalIgnoreCase)))
{
ShowError($"在PLC {config.PlcNum} 中,组名 {config.GroupName} 已被使用");
return false;
}
//Console.WriteLine("\n筛选后的配置:");
//foreach (var g in groupsInSamePLC)
//{
// Console.WriteLine($"PLC号: {g.PlcNum}, 组名: {g.GroupName}");
//}
// 3. 只在同一个PLC内检查地址是否冲突
if (groupsInSamePLC.Any(g => g.Start.Equals(config.Start, StringComparison.OrdinalIgnoreCase)))
{
ShowError($"在PLC {config.PlcNum} 中,起始地址 {config.Start} 已被使用");
return false;
}
// 地址范围验证
int startAddress = int.Parse(config.Start.Substring(1));
int endAddress = startAddress + config.Length - 1;
if (endAddress > 32675)
{
ShowError($"地址范围超出限制,结束地址不能超过D32675".Translated());
return false;
}
// 检查地址范围冲突
foreach (var other in groupsInSamePLC)
{
int otherStart = int.Parse(other.Start.Substring(1));
int otherEnd = otherStart + other.Length - 1;
if (!(endAddress < otherStart || startAddress > otherEnd))
{
ShowError($"地址范围与组 \"{other.GroupName}\" 冲突");
return false;
}
}
return true;
}
catch (Exception ex)
{
ShowError($"验证配置时发生错误: {ex.Message}");
return false;
}
}
// 地址格式验证
private bool ValidateAddressFormat(string address)
{
if (string.IsNullOrWhiteSpace(address)) return false;
// 检查是否以D开头(不区分大小写)
if (!address.StartsWith("D", StringComparison.OrdinalIgnoreCase))
{
return false;
}
// 检查后面是否为有效数字
string numberPart = address.Substring(1);
if (!int.TryParse(numberPart, out int addressNum))
{
return false;
}
// 检查地址范围(根据实际需求调整范围)
if (addressNum < 0 || addressNum > 9999)
{
return false;
}
return true;
}
#region 添加新通信组
/// <summary>
/// 添加新通信组
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnAdd_Click(object sender, EventArgs e)
{
try
{
// 创建新组配置
var newGroup = new PlcGroupConfig
{
PlcNum = PlcNum, // 使用当前PlcNum而不是CurrentPLCConfig.PlcNum
GroupName = GenerateNewGroupName(),
Start = FindNextAvailableAddress(),
Length = 100,
IsTiggerRead = true,
IsFeedbackPlc = true,
IsActive = true,
Remark = ""
};
// 验证新配置
if (!ValidateConfigAll(newGroup))
{
return;
}
// 添加到总配置列表
TotalGroups.Add(newGroup);
// 保存到Excel文件
SaveToExcel(TotalGroups);
// 重新加载显示
LoadGroups();
ShowSuccess("新建通信组成功".Translated());
}
catch (Exception ex)
{
ShowError($"添加通信组失败: {ex.Message}");
}
}
/// <summary>
/// 生成新的组名
/// </summary>
private string GenerateNewGroupName()
{
int index = 1;
string baseName = "新建组".Translated();
string newName = baseName;
// 查找可用的组名
while (TotalGroups.Any(g => g.PlcNum == PlcNum && g.GroupName.Equals(newName, StringComparison.OrdinalIgnoreCase)))
{
index++;
newName = $"{baseName}{index}";
}
return newName;
}
/// <summary>
/// 查找下一个可用的地址
/// </summary>
private string FindNextAvailableAddress()
{
// 获取当前PLC的所有组
var plcGroups = TotalGroups.Where(g => g.PlcNum == PlcNum).ToList();
if (!plcGroups.Any())
{
return "D0"; // 如果没有现有组,从D0开始
}
// 找到最大的结束地址
int maxEndAddress = plcGroups.Max(g =>
{
int startAddr = int.Parse(g.Start.Substring(1));
return startAddr + g.Length;
});
// 确保地址不超过最大限制(32675)
if (maxEndAddress >= 32675)
{
throw new Exception("没有可用的地址空间".Translated());
}
// 返回下一个可用地址
return $"D{maxEndAddress}";
}
/// <summary>
/// 查找地址间隔
/// </summary>
private string FindAddressGap(int requiredLength = 100)
{
// 获取当前PLC的所有组,并按起始地址排序
var plcGroups = TotalGroups
.Where(g => g.PlcNum == PlcNum)
.Select(g => new
{
Start = int.Parse(g.Start.Substring(1)),
End = int.Parse(g.Start.Substring(1)) + g.Length - 1
})
.OrderBy(g => g.Start)
.ToList();
// 如果没有组,返回起始地址
if (!plcGroups.Any())
{
return "D0";
}
// 检查第一个组之前是否有足够空间
if (plcGroups.First().Start >= requiredLength)
{
return "D0";
}
// 检查组之间的间隔
for (int i = 0; i < plcGroups.Count - 1; i++)
{
int gapStart = plcGroups[i].End + 1;
int gapEnd = plcGroups[i + 1].Start - 1;
if (gapEnd - gapStart + 1 >= requiredLength)
{
return $"D{gapStart}";
}
}
// 检查最后一个组之后是否有足够空间
int lastEnd = plcGroups.Last().End;
if (lastEnd + requiredLength <= 32675)
{
return $"D{lastEnd + 1}";
}
throw new Exception("没有找到足够大的地址空间".Translated());
}
private void btn_Close_Click(object sender, EventArgs e)
{
this.Close();
}
#endregion
// 错误提示
private void ShowError(string message)
{
MessageBox.Show(message, "验证错误".Translated(), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// 成功提示
private void ShowSuccess(string message)
{
MessageBox.Show(message, "成功".Translated(), MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#region 无边框拖动
private Point mPoint;
private void Panel_MouseDown(object sender, MouseEventArgs e)
{
mPoint = new Point(e.X, e.Y);
}
private void Panel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
}
}
#endregion
#region 减少闪烁
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
#endregion
}
}