464 lines
16 KiB
C#
464 lines
16 KiB
C#
using Google.Protobuf.WellKnownTypes;
|
|
using JinYuan.Models;
|
|
using JinYuan.VirtualDataLibrary;
|
|
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.Windows.Forms;
|
|
|
|
namespace LargeSquareOne
|
|
{
|
|
public partial class FDConfigForm : MultiLanguageForm
|
|
{
|
|
// 定义事件
|
|
public static event EventHandler OnFDConfigChanged;
|
|
private readonly string fdConfigMappingPath = CommonMethods.FdConfigMappingPath;
|
|
private List<FDConfigMapping> configMappings = new List<FDConfigMapping>();
|
|
private BindingList<FDConfigMapping> bindList = new BindingList<FDConfigMapping>();
|
|
private bool _isLoading = false;
|
|
|
|
private readonly DataGridViewCellStyle _centerCellStyle = new DataGridViewCellStyle()
|
|
{
|
|
Alignment = DataGridViewContentAlignment.MiddleCenter
|
|
};
|
|
|
|
public FDConfigForm()
|
|
{
|
|
InitializeComponent();
|
|
groupTable.AutoGenerateColumns = false;
|
|
|
|
InitializeDataGridView();
|
|
EnsureConfigDirectoryExists();
|
|
configMappings = GetALLConfigs();
|
|
bindList = new BindingList<FDConfigMapping>(configMappings);
|
|
|
|
_isLoading = true;
|
|
LoadConfigs();
|
|
_isLoading = false;
|
|
}
|
|
|
|
private void EnsureConfigDirectoryExists()
|
|
{
|
|
string dir = Path.GetDirectoryName(fdConfigMappingPath);
|
|
if (!Directory.Exists(dir))
|
|
Directory.CreateDirectory(dir);
|
|
}
|
|
|
|
private void InitializeDataGridView()
|
|
{
|
|
// 禁用自动添加新行
|
|
groupTable.AllowUserToAddRows = false;
|
|
groupTable.AllowUserToDeleteRows = false;
|
|
groupTable.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
|
groupTable.MultiSelect = false;
|
|
groupTable.ReadOnly = false;
|
|
groupTable.DoubleBuffered(true);
|
|
|
|
// 设置默认单元格样式
|
|
groupTable.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
|
|
groupTable.RowHeadersVisible = false;
|
|
|
|
groupTable.Columns.AddRange(new DataGridViewColumn[]
|
|
{
|
|
new DataGridViewTextBoxColumn
|
|
{
|
|
Name = "FDNum",
|
|
HeaderText = "分档编号".Translated(),
|
|
Width = 120,
|
|
ReadOnly = true,
|
|
DataPropertyName = "FDNum",
|
|
DefaultCellStyle = _centerCellStyle
|
|
},
|
|
new DataGridViewTextBoxColumn
|
|
{
|
|
Name = "FDName",
|
|
HeaderText = "分档类型".Translated(),
|
|
Width = 120,
|
|
DataPropertyName = "FDName",
|
|
DefaultCellStyle = _centerCellStyle
|
|
},
|
|
new DataGridViewTextBoxColumn
|
|
{
|
|
Name = "ModelType",
|
|
HeaderText = "电池型号".Translated(),
|
|
Width = 120,
|
|
DataPropertyName = "ModelType",
|
|
DefaultCellStyle = _centerCellStyle
|
|
},
|
|
new DataGridViewButtonColumn
|
|
{
|
|
Name = "SaveBtn",
|
|
HeaderText = "操作".Translated(),
|
|
Width = 100,
|
|
Text = "保存该行".Translated(),
|
|
UseColumnTextForButtonValue = true
|
|
},
|
|
new DataGridViewButtonColumn
|
|
{
|
|
Name = "DeleteBtn",
|
|
HeaderText = "操作".Translated(),
|
|
Width = 100,
|
|
Text = "删除".Translated(),
|
|
UseColumnTextForButtonValue = true
|
|
}
|
|
});
|
|
|
|
// 事件绑定
|
|
groupTable.CellContentClick += GroupTable_CellContentClick;
|
|
groupTable.DataError += GroupTable_DataError;
|
|
groupTable.CellBeginEdit += GroupTable_CellBeginEdit;
|
|
groupTable.CellValidating += GroupTable_CellValidating; // 添加验证事件
|
|
}
|
|
|
|
#region 数据错误处理
|
|
private void GroupTable_DataError(object sender, DataGridViewDataErrorEventArgs e)
|
|
{
|
|
e.Cancel = true;
|
|
}
|
|
#endregion
|
|
|
|
#region 单元格编辑前事件 - 阻止编辑FDNum
|
|
private void GroupTable_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
|
|
{
|
|
if (groupTable.Columns[e.ColumnIndex].Name == "FDNum")
|
|
{
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region 单元格验证 - 实时更新绑定数据
|
|
private void GroupTable_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
|
|
{
|
|
// 当单元格编辑完成时,确保数据更新到绑定列表
|
|
if (e.RowIndex < 0 || e.RowIndex >= bindList.Count)
|
|
return;
|
|
|
|
var row = groupTable.Rows[e.RowIndex];
|
|
var item = bindList[e.RowIndex];
|
|
string colName = groupTable.Columns[e.ColumnIndex].Name;
|
|
|
|
if (colName == "FDName")
|
|
{
|
|
string newValue = e.FormattedValue?.ToString()?.Trim() ?? string.Empty;
|
|
// 如果值为空,设置为空字符串
|
|
if (string.IsNullOrEmpty(newValue))
|
|
{
|
|
item.FDName = string.Empty;
|
|
}
|
|
else
|
|
{
|
|
item.FDName = newValue;
|
|
}
|
|
}
|
|
else if (colName == "ModelType")
|
|
{
|
|
string newValue = e.FormattedValue?.ToString()?.Trim() ?? string.Empty;
|
|
item.ModelType = newValue;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
private void LoadConfigs()
|
|
{
|
|
try
|
|
{
|
|
groupTable.DataSource = null;
|
|
groupTable.DataSource = bindList;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError($"加载数据失败:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
private List<FDConfigMapping> GetALLConfigs()
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(fdConfigMappingPath))
|
|
return new List<FDConfigMapping>();
|
|
return MiniExcel.Query<FDConfigMapping>(fdConfigMappingPath).ToList();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError($"读取配置文件失败:{ex.Message}");
|
|
return new List<FDConfigMapping>();
|
|
}
|
|
}
|
|
|
|
private void GroupTable_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (e.RowIndex < 0) return;
|
|
if (e.ColumnIndex < 0) return;
|
|
|
|
int rowIdx = e.RowIndex;
|
|
string colName = groupTable.Columns[e.ColumnIndex].Name;
|
|
|
|
// 检查行索引是否有效
|
|
if (rowIdx >= bindList.Count)
|
|
{
|
|
ShowError("数据行索引无效".Translated());
|
|
return;
|
|
}
|
|
|
|
if (colName == "SaveBtn")
|
|
{
|
|
var item = bindList[rowIdx];
|
|
|
|
// 验证数据
|
|
if (!ValidateSingleConfig(item, rowIdx))
|
|
return;
|
|
|
|
try
|
|
{
|
|
// 提交当前编辑
|
|
groupTable.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
|
|
|
configMappings = new List<FDConfigMapping>(bindList);
|
|
SaveToExcel(configMappings);
|
|
ShowSuccess("保存成功".Translated());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError($"保存失败:{ex.Message}");
|
|
}
|
|
}
|
|
else if (colName == "DeleteBtn")
|
|
{
|
|
var delItem = bindList[rowIdx];
|
|
string msg = $"{"确定删除该分档配置?".Translated()}\n{"分档编号:".Translated()}{delItem.FDNum}\n{"分档类型:".Translated()}{delItem.FDName}";
|
|
var res = MessageBox.Show(msg, "确认删除".Translated(), MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
|
if (res != DialogResult.Yes) return;
|
|
|
|
try
|
|
{
|
|
bindList.RemoveAt(rowIdx);
|
|
configMappings = new List<FDConfigMapping>(bindList);
|
|
SaveToExcel(configMappings);
|
|
ShowSuccess("删除成功".Translated());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError($"删除失败:{ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// 保存成功后更新全局配置
|
|
private void SaveToExcel(List<FDConfigMapping> configs)
|
|
{
|
|
EnsureConfigDirectoryExists();
|
|
string dir = Path.GetDirectoryName(fdConfigMappingPath);
|
|
string tempFile = Path.Combine(dir, $"_tmp_{Path.GetFileName(fdConfigMappingPath)}");
|
|
|
|
try
|
|
{
|
|
MiniExcel.SaveAs(tempFile, configs);
|
|
if (!File.Exists(tempFile))
|
|
throw new Exception("临时文件生成失败".Translated());
|
|
|
|
// 备份原文件
|
|
string backupFile = Path.Combine(dir, $"{Path.GetFileNameWithoutExtension(fdConfigMappingPath)}_backup_{DateTime.Now:yyyyMMddHHmmss}.xlsx");
|
|
if (File.Exists(fdConfigMappingPath))
|
|
{
|
|
File.Copy(fdConfigMappingPath, backupFile, true);
|
|
}
|
|
|
|
if (File.Exists(fdConfigMappingPath))
|
|
File.Delete(fdConfigMappingPath);
|
|
File.Move(tempFile, fdConfigMappingPath);
|
|
|
|
// 删除旧备份
|
|
CleanOldBackups(dir, 5);
|
|
|
|
// 更新全局分档配置
|
|
CommonMethods.FDConfigMappings = configs;
|
|
|
|
// 更新分档类型列表到全局
|
|
var gradeTypes = configs.Select(x => x.FDName).Distinct().ToList();
|
|
if (!gradeTypes.Contains("不设置"))
|
|
gradeTypes.Insert(0, "不设置");
|
|
if (!gradeTypes.Contains("NG"))
|
|
gradeTypes.Add("NG");
|
|
CommonMethods.FDGradeTypes = gradeTypes;
|
|
|
|
// 保存成功后,触发刷新事件
|
|
CommonMethods.LoadFDGradeTypes();
|
|
|
|
// 如果需要通知主窗体刷新,可以触发事件
|
|
OnFDConfigChanged?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception($"保存Excel失败:{ex.Message}", ex);
|
|
}
|
|
finally
|
|
{
|
|
if (File.Exists(tempFile))
|
|
{
|
|
try { File.Delete(tempFile); } catch { }
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CleanOldBackups(string directory, int keepCount)
|
|
{
|
|
try
|
|
{
|
|
var backupFiles = Directory.GetFiles(directory, "*_backup_*.xlsx")
|
|
.OrderByDescending(f => f)
|
|
.Skip(keepCount)
|
|
.ToList();
|
|
|
|
foreach (var file in backupFiles)
|
|
{
|
|
try { File.Delete(file); } catch { }
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private bool ValidateSingleConfig(FDConfigMapping config, int rowIndex = -1)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(config.FDName))
|
|
{
|
|
ShowError("分档类型不能为空".Translated());
|
|
return false;
|
|
}
|
|
if (config.FDNum <= 0)
|
|
{
|
|
ShowError("分档编号必须大于0".Translated());
|
|
return false;
|
|
}
|
|
|
|
bool duplicate;
|
|
if (rowIndex == -1)
|
|
{
|
|
duplicate = bindList.Any(x => x.FDNum == config.FDNum);
|
|
}
|
|
else
|
|
{
|
|
duplicate = bindList.Take(rowIndex).Any(x => x.FDNum == config.FDNum)
|
|
|| bindList.Skip(rowIndex + 1).Any(x => x.FDNum == config.FDNum);
|
|
}
|
|
|
|
if (duplicate)
|
|
{
|
|
ShowError($"分档编号 {config.FDNum} 已存在,不可重复".Translated());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#region 按钮事件
|
|
private void BtnAdd_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// 先提交当前编辑,防止数据丢失
|
|
groupTable.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
|
|
|
// 计算新的编号
|
|
int maxNum = bindList.Count > 0 ? bindList.Max(x => x.FDNum) : 0;
|
|
int autoNum = maxNum + 1;
|
|
|
|
// 添加到绑定列表
|
|
var newItem = new FDConfigMapping
|
|
{
|
|
FDNum = autoNum,
|
|
FDName = string.Empty,
|
|
ModelType = string.Empty
|
|
};
|
|
|
|
bindList.Add(newItem);
|
|
|
|
// 刷新显示,不重新加载整个数据源,只刷新视图
|
|
int newIndex = bindList.Count - 1;
|
|
groupTable.Refresh();
|
|
|
|
// 选中新行并开始编辑
|
|
if (newIndex >= 0 && newIndex < groupTable.Rows.Count)
|
|
{
|
|
groupTable.ClearSelection();
|
|
groupTable.Rows[newIndex].Selected = true;
|
|
groupTable.CurrentCell = groupTable.Rows[newIndex].Cells["FDName"];
|
|
groupTable.BeginEdit(true);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError($"添加行失败:{ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void btn_Close_Click(object sender, EventArgs e)
|
|
{
|
|
// 关闭前提交所有编辑
|
|
try
|
|
{
|
|
groupTable.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
|
}
|
|
catch { }
|
|
this.Close();
|
|
}
|
|
#endregion
|
|
|
|
#region 提示弹窗
|
|
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);
|
|
}
|
|
#endregion
|
|
|
|
#region 无边框拖动
|
|
private Point mPoint;
|
|
private void Panel_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
mPoint = e.Location;
|
|
}
|
|
|
|
private void Panel_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Left)
|
|
{
|
|
this.Left += e.X - mPoint.X;
|
|
this.Top += e.Y - mPoint.Y;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region 窗口防闪烁
|
|
protected override CreateParams CreateParams
|
|
{
|
|
get
|
|
{
|
|
var cp = base.CreateParams;
|
|
cp.ExStyle |= 0x02000000;
|
|
return cp;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
public static class DgvExt
|
|
{
|
|
public static void DoubleBuffered(this DataGridView dgv, bool enable)
|
|
{
|
|
var prop = dgv.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
|
|
prop?.SetValue(dgv, enable, null);
|
|
}
|
|
}
|
|
} |