This commit is contained in:
2025-12-15 20:53:20 +08:00
parent 3cdf68651f
commit c73555cb9b
8 changed files with 360 additions and 238 deletions

View File

@@ -1,79 +0,0 @@
using System;
using System.IO;
using System.Windows;
namespace DrillTools
{
/// <summary>
/// 备份功能测试类
/// </summary>
public static class BackupTest
{
/// <summary>
/// 测试备份功能
/// </summary>
public static void TestBackupFunctionality()
{
Console.WriteLine("=== 备份功能测试 ===");
// 创建测试文件
string testFilePath = "test_file.drl";
string testContent = "M48\nT01C1.000\n%\nT01\nX1000Y1000\nM30";
try
{
// 1. 创建原始测试文件
File.WriteAllText(testFilePath, testContent);
Console.WriteLine("✓ 创建测试文件成功");
// 2. 第一次备份(应该直接创建.bak文件
string backupPath1 = testFilePath + ".bak";
if (File.Exists(backupPath1))
File.Delete(backupPath1);
File.Copy(testFilePath, backupPath1);
Console.WriteLine("✓ 第一次备份成功");
// 3. 模拟第二次备份(检测到.bak文件已存在
if (File.Exists(backupPath1))
{
Console.WriteLine("✓ 检测到备份文件已存在");
// 模拟用户选择创建时间戳备份
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string timestampBackupPath = $"{testFilePath}.{timestamp}.bak";
File.Copy(testFilePath, timestampBackupPath);
Console.WriteLine($"✓ 创建时间戳备份成功: {Path.GetFileName(timestampBackupPath)}");
}
// 4. 验证备份文件内容
if (File.Exists(backupPath1) && File.ReadAllText(backupPath1) == testContent)
{
Console.WriteLine("✓ 备份文件内容验证成功");
}
// 5. 清理测试文件
File.Delete(testFilePath);
if (File.Exists(backupPath1))
File.Delete(backupPath1);
// 删除时间戳备份文件
var timestampFiles = Directory.GetFiles(".", "*.bak");
foreach (var file in timestampFiles)
{
if (file.Contains("test_file.") && file.Contains(".bak"))
{
File.Delete(file);
Console.WriteLine($"✓ 清理测试文件: {Path.GetFileName(file)}");
}
}
Console.WriteLine("=== 备份功能测试完成 ===");
}
catch (Exception ex)
{
Console.WriteLine($"✗ 测试失败: {ex.Message}");
}
}
}
}

View File

@@ -1,141 +0,0 @@
using System;
using DrillTools.Integration;
namespace DrillTools.Tests
{
/// <summary>
/// 调试测试程序,用于验证孔数计算问题
/// </summary>
public class DebugTest
{
public static void RunTest()
{
Console.WriteLine("=== 调试测试:孔数计算问题 ===");
// 使用用户提供的钻带数据
string drillTapeContent = @"M48
;厚铜板参数-镀膜-EA-250618
T01C1.049H05000Z+0.000S060.00F105.0U0700.0
T02C1.550H01500Z+0.150S070.00F008.0U0800.0
T03C1.156H03000Z-0.200S040.00F030.0U0900.0
T04C1.451H04000Z-0.200S040.00F030.0U0900.0
T05C1.153H05000Z-0.200S040.00F030.0U0900.0
T06C0.499
%
T01
X-167525Y013500
X-167525Y018500
X-167525Y023500
X167525Y013500
X167525Y018500
X167525Y023500
X099366Y502000
T02
X-065975Y115250
X-085825Y122450
X-085825Y124550
X-097425Y115250
X103093Y502000
T03
X-069659Y016450G85X-094159Y016450
X-181341Y195550G85X-156841Y195550
X-069659Y210450G85X-094159Y210450
X-181341Y389550G85X-156841Y389550
X-069659Y404450G85X-094159Y404450
X-181341Y583550G85X-156841Y583550
X162939Y596000
T04
X-069659Y016450G85X-094159Y016450
X-181341Y195550G85X-156841Y195550
X-069659Y210450G85X-094159Y210450
X-181341Y389550G85X-156841Y389550
X-069659Y404450G85X-094159Y404450
X-181341Y583550G85X-156841Y583550
T05
X-069659Y016450G85X-094159Y016450
X-181341Y195550G85X-156841Y195550
X-069659Y210450G85X-094159Y210450
X-181341Y389550G85X-156841Y389550
X-069659Y404450G85X-094159Y404450
X-181341Y583550G85X-156841Y583550
T06
M97,A*,$S $N
X-194000Y002000
M30";
// 处理钻带
var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent);
// 输出结果
Console.WriteLine($"处理状态: {(result.Success ? "" : "")}");
if (!result.Success)
{
Console.WriteLine($"错误信息: {result.Message}");
return;
}
Console.WriteLine("\n刀具统计:");
Console.WriteLine("刀具\t孔径(mm)\t类型\t\t普通孔数\t槽孔数\t总孔数");
Console.WriteLine("========================================================");
foreach (var tool in result.ToolResults)
{
string toolTypeDisplay = tool.ToolType switch
{
ToolType.Regular => "圆孔",
ToolType.Slot => "槽孔",
ToolType.MachineCode => "机台码",
_ => "未知"
};
Console.WriteLine($"T{tool.ToolNumber:D2}\t{tool.Diameter:F3}\t\t{toolTypeDisplay}\t{tool.RegularHoles}\t\t{tool.SlotHoles}\t{tool.TotalHoles}");
}
Console.WriteLine($"\n总孔数: {result.TotalHoles}");
// 验证结果
Console.WriteLine("\n=== 验证结果 ===");
VerifyResults(result);
}
private static void VerifyResults(DrillTapeResult result)
{
// CAM350的预期结果
var expectedResults = new[]
{
new { ToolNumber = 1, Diameter = 1.049, ExpectedHoles = 7 },
new { ToolNumber = 2, Diameter = 1.550, ExpectedHoles = 5 },
new { ToolNumber = 3, Diameter = 1.156, ExpectedHoles = 619 },
new { ToolNumber = 4, Diameter = 1.451, ExpectedHoles = 5 },
new { ToolNumber = 5, Diameter = 1.153, ExpectedHoles = 5 },
new { ToolNumber = 6, Diameter = 0.499, ExpectedHoles = 57 }
};
bool allMatch = true;
foreach (var expected in expectedResults)
{
var actual = result.ToolResults.Find(t => t.ToolNumber == expected.ToolNumber);
if (actual != null)
{
bool match = Math.Abs(actual.Diameter - expected.Diameter) < 0.001 &&
actual.TotalHoles == expected.ExpectedHoles;
Console.WriteLine($"T{expected.ToolNumber:D2} ({expected.Diameter:F3}mm): " +
$"预期={expected.ExpectedHoles}, 实际={actual.TotalHoles}, " +
$"{(match ? "" : "")}");
if (!match)
allMatch = false;
}
else
{
Console.WriteLine($"T{expected.ToolNumber:D2}: 未找到结果 ✗");
allMatch = false;
}
}
Console.WriteLine($"\n总体结果: {(allMatch ? " CAM350一致" : " ")}");
}
}
}

View File

@@ -8,6 +8,11 @@
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<Platforms>x86</Platforms> <Platforms>x86</Platforms>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Content Include="favicon.ico" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@@ -182,6 +183,16 @@ namespace DrillTools
// 保存原始文件路径 // 保存原始文件路径
ViewModel.OriginalFilePath = files[0]; ViewModel.OriginalFilePath = files[0];
Encoding ansiEncoding;
try
{
ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页
}
catch
{
ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码
}
var process = new Process var process = new Process
{ {
StartInfo = new ProcessStartInfo StartInfo = new ProcessStartInfo
@@ -190,7 +201,8 @@ namespace DrillTools
Arguments = $"/c type \"{files[0]}\"", Arguments = $"/c type \"{files[0]}\"",
RedirectStandardOutput = true, RedirectStandardOutput = true,
UseShellExecute = false, UseShellExecute = false,
CreateNoWindow = true CreateNoWindow = true,
StandardOutputEncoding = ansiEncoding
} }
}; };

View File

@@ -5,6 +5,7 @@ using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows; using System.Windows;
using DrillTools.Integration; using DrillTools.Integration;
@@ -194,6 +195,12 @@ namespace DrillTools
// 更新按钮状态 // 更新按钮状态
UpdateMoveButtonsState(); UpdateMoveButtonsState();
// 检查并应用-sort.txt文件中的刀具排序
if (!string.IsNullOrEmpty(OriginalFilePath))
{
CheckAndApplySortFile(OriginalFilePath, Tools);
}
} }
else else
{ {
@@ -418,13 +425,31 @@ namespace DrillTools
} }
} }
// 3. 将重新排序后的钻带内容写入原始文件 // 3. 将重新排序后的钻带内容写入原始文件使用ANSI编码
File.WriteAllText(OriginalFilePath, reorderedDrillTape); Encoding ansiEncoding;
try
{
ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页
}
catch
{
ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码
}
// 使用StreamWriter写入文件确保编码正确应用
using (var writer = new StreamWriter(OriginalFilePath, false, ansiEncoding))
{
writer.Write(reorderedDrillTape);
writer.Flush(); // 确保所有数据都被写入
}
// 4. 更新当前钻带内容 // 4. 更新当前钻带内容
DrillTapeContent = reorderedDrillTape; DrillTapeContent = reorderedDrillTape;
// 5. 打开文件资源管理器并选中文件 // 5. 生成刀具直径列表文件
GenerateToolDiameterListFile(OriginalFilePath, Tools);
// 6. 打开文件资源管理器并选中文件
OpenFileExplorerAndSelectFile(OriginalFilePath); OpenFileExplorerAndSelectFile(OriginalFilePath);
return reorderedDrillTape; return reorderedDrillTape;
@@ -481,6 +506,11 @@ namespace DrillTools
MachineCodeType = t.MachineCodeType MachineCodeType = t.MachineCodeType
}).ToList(); }).ToList();
//重新排一下 reorderedTools 的刀序Txx
int number = 1;
foreach (var item in reorderedTools)
item.ToolNumber = number++;
//检查是否所有刀序没有变化 //检查是否所有刀序没有变化
int checkindex = 1; int checkindex = 1;
for (int i = 0; i < originalTools.Count; i++) for (int i = 0; i < originalTools.Count; i++)
@@ -1071,5 +1101,197 @@ M30";
System.Windows.MessageBox.Show($"打开文件资源管理器失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); System.Windows.MessageBox.Show($"打开文件资源管理器失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
} }
} }
/// <summary>
/// 生成刀具直径列表文件
/// </summary>
/// <param name="originalFilePath">原始文件路径</param>
/// <param name="tools">刀具列表</param>
private void GenerateToolDiameterListFile(string originalFilePath, ObservableCollection<ToolItem> tools)
{
try
{
// 获取原文件的目录和文件名(不含扩展名)
string directory = Path.GetDirectoryName(originalFilePath) ?? "";
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(originalFilePath);
string outputFilePath = Path.Combine(directory, $"{fileNameWithoutExt}-sort.txt");
// 按刀具编号排序获取最终顺序
var sortedTools = tools.OrderBy(t => t.ToolNumber).ToList();
// 生成刀具直径列表内容
var diameterList = new StringBuilder();
foreach (var tool in sortedTools)
{
diameterList.AppendLine($"{tool.Diameter:F3}");
}
// 使用ANSI编码写入文件
Encoding ansiEncoding;
try
{
ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页
}
catch
{
ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码
}
File.WriteAllText(outputFilePath, diameterList.ToString(), ansiEncoding);
// 记录日志
System.Diagnostics.Debug.WriteLine($"刀具直径列表文件已生成: {outputFilePath}");
}
catch (Exception ex)
{
// 记录错误但不影响主要功能
System.Diagnostics.Debug.WriteLine($"生成刀具直径列表文件失败: {ex.Message}");
}
}
/// <summary>
/// 检查并应用-sort.txt文件中的刀具排序
/// </summary>
/// <param name="originalFilePath">原始文件路径</param>
/// <param name="tools">当前刀具列表</param>
private void CheckAndApplySortFile(string originalFilePath, ObservableCollection<ToolItem> tools)
{
try
{
// 获取-sort.txt文件路径
string directory = Path.GetDirectoryName(originalFilePath) ?? "";
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(originalFilePath);
string sortFilePath = Path.Combine(directory, $"{fileNameWithoutExt}-sort.txt");
// 检查-sort.txt文件是否存在
if (!File.Exists(sortFilePath))
return;
// 读取-sort.txt文件内容
List<double> sortDiameters = ReadSortFile(sortFilePath);
if (sortDiameters.Count == 0)
return;
// 检查直径数量是否一致
if (sortDiameters.Count != tools.Count)
return;
// 提示用户是否应用排序
var result = System.Windows.MessageBox.Show(
$"检测到之前刀序重排后的记录文件:{Path.GetFileName(sortFilePath)}\n\n" +
$"是否直接按该记录文件进行排序?\n\n" +
"是(Y):按记录文件排序\n" +
"否(N):保持当前顺序",
"刀具排序提示",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
// 按照-sort.txt文件中的直径顺序重新排列刀具
SortToolsByDiameterList(tools, sortDiameters);
// 执行完整的重排刀序流程,包括重新编号和更新钻带内容
try
{
string reorderedDrillTape = ReorderAndRenumberTools();
System.Diagnostics.Debug.WriteLine($"已按-sort.txt文件重新排序刀具并更新钻带内容");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"重排刀序失败: {ex.Message}");
// 即使重排失败,也保持列表的排序
OnPropertyChanged(nameof(Tools));
}
}
}
catch (Exception ex)
{
// 记录错误但不影响主要功能
System.Diagnostics.Debug.WriteLine($"检查-sort.txt文件失败: {ex.Message}");
}
}
/// <summary>
/// 读取-sort.txt文件内容并解析直径列表
/// </summary>
/// <param name="sortFilePath">-sort.txt文件路径</param>
/// <returns>直径列表</returns>
private List<double> ReadSortFile(string sortFilePath)
{
var diameters = new List<double>();
try
{
// 使用ANSI编码读取文件
Encoding ansiEncoding;
try
{
ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页
}
catch
{
ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码
}
string[] lines = File.ReadAllLines(sortFilePath, ansiEncoding);
foreach (string line in lines)
{
string trimmedLine = line.Trim();
if (!string.IsNullOrEmpty(trimmedLine))
{
if (double.TryParse(trimmedLine, out double diameter))
{
diameters.Add(diameter);
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"读取-sort.txt文件失败: {ex.Message}");
}
return diameters;
}
/// <summary>
/// 根据直径列表排序刀具
/// </summary>
/// <param name="tools">刀具列表</param>
/// <param name="diameterList">直径列表(目标顺序)</param>
private void SortToolsByDiameterList(ObservableCollection<ToolItem> tools, List<double> diameterList)
{
// 创建直径到刀具的映射
var diameterToTools = new Dictionary<double, List<ToolItem>>();
foreach (var tool in tools)
{
double roundedDiameter = Math.Round(tool.Diameter, 3);
if (!diameterToTools.ContainsKey(roundedDiameter))
{
diameterToTools[roundedDiameter] = new List<ToolItem>();
}
diameterToTools[roundedDiameter].Add(tool);
}
// 按照直径列表的顺序重新排列刀具
var sortedTools = new List<ToolItem>();
foreach (double diameter in diameterList)
{
double roundedDiameter = Math.Round(diameter, 3);
if (diameterToTools.ContainsKey(roundedDiameter))
{
sortedTools.AddRange(diameterToTools[roundedDiameter]);
}
}
// 清空原列表并添加排序后的刀具
tools.Clear();
foreach (var tool in sortedTools)
{
tools.Add(tool);
}
}
} }
} }

View File

@@ -46,7 +46,7 @@
<!-- 原始刀序 --> <!-- 原始刀序 -->
<GroupBox Grid.Column="0" Header="原始刀序" Margin="0,0,5,0"> <GroupBox Grid.Column="0" Header="原始刀序" Margin="0,0,5,0">
<ListView Name="OriginalToolsListView" ItemsSource="{Binding OriginalTools}" ScrollViewer.ScrollChanged="OriginalToolsListView_ScrollChanged"> <ListView Name="OriginalToolsListView" ItemsSource="{Binding OriginalTools}" ScrollViewer.ScrollChanged="OriginalToolsListView_ScrollChanged" SelectionChanged="OriginalToolsListView_SelectionChanged">
<ListView.View> <ListView.View>
<GridView> <GridView>
<GridViewColumn Header="序号" Width="60" DisplayMemberBinding="{Binding Order}"/> <GridViewColumn Header="序号" Width="60" DisplayMemberBinding="{Binding Order}"/>
@@ -65,7 +65,7 @@
<!-- 重排后刀序 --> <!-- 重排后刀序 -->
<GroupBox Grid.Column="1" Header="重排后刀序" Margin="5,0,0,0"> <GroupBox Grid.Column="1" Header="重排后刀序" Margin="5,0,0,0">
<ListView Name="ReorderedToolsListView" ItemsSource="{Binding ReorderedTools}" ScrollViewer.ScrollChanged="ReorderedToolsListView_ScrollChanged"> <ListView Name="ReorderedToolsListView" ItemsSource="{Binding ReorderedTools}" ScrollViewer.ScrollChanged="ReorderedToolsListView_ScrollChanged" SelectionChanged="ReorderedToolsListView_SelectionChanged">
<ListView.View> <ListView.View>
<GridView> <GridView>
<GridViewColumn Header="序号" Width="60" DisplayMemberBinding="{Binding Order}"/> <GridViewColumn Header="序号" Width="60" DisplayMemberBinding="{Binding Order}"/>

View File

@@ -15,6 +15,11 @@ namespace DrillTools
/// </summary> /// </summary>
public bool IsConfirmed { get; private set; } public bool IsConfirmed { get; private set; }
/// <summary>
/// 标记是否正在处理选中项同步,防止递归调用
/// </summary>
private bool _isSynchronizingSelection = false;
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
@@ -97,6 +102,104 @@ namespace DrillTools
} }
} }
/// <summary>
/// 原始刀序列表选中项变化事件处理
/// </summary>
private void OriginalToolsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_isSynchronizingSelection)
return;
try
{
_isSynchronizingSelection = true;
if (OriginalToolsListView.SelectedItem is ToolOrderItem selectedOriginalItem)
{
// 在重排后列表中查找对应的刀具
var matchingItem = FindMatchingToolItem(ReorderedToolsListView, selectedOriginalItem);
if (matchingItem != null)
{
ReorderedToolsListView.SelectedItem = matchingItem;
// 确保选中的项可见
ReorderedToolsListView.ScrollIntoView(matchingItem);
}
}
else
{
// 如果原始列表没有选中项,清空重排后列表的选中项
ReorderedToolsListView.SelectedItem = null;
}
}
finally
{
_isSynchronizingSelection = false;
}
}
/// <summary>
/// 重排后刀序列表选中项变化事件处理
/// </summary>
private void ReorderedToolsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_isSynchronizingSelection)
return;
try
{
_isSynchronizingSelection = true;
if (ReorderedToolsListView.SelectedItem is ToolOrderItem selectedReorderedItem)
{
// 在原始列表中查找对应的刀具
var matchingItem = FindMatchingToolItem(OriginalToolsListView, selectedReorderedItem);
if (matchingItem != null)
{
OriginalToolsListView.SelectedItem = matchingItem;
// 确保选中的项可见
OriginalToolsListView.ScrollIntoView(matchingItem);
}
}
else
{
// 如果重排后列表没有选中项,清空原始列表的选中项
OriginalToolsListView.SelectedItem = null;
}
}
finally
{
_isSynchronizingSelection = false;
}
}
/// <summary>
/// 在ListView中查找匹配的刀具项
/// </summary>
/// <param name="listView">要搜索的ListView</param>
/// <param name="targetItem">目标刀具项</param>
/// <returns>匹配的刀具项如果未找到则返回null</returns>
private ToolOrderItem FindMatchingToolItem(System.Windows.Controls.ListView listView, ToolOrderItem targetItem)
{
if (listView?.ItemsSource == null || targetItem == null)
return null;
foreach (var item in listView.Items)
{
if (item is ToolOrderItem toolItem)
{
// 使用与ViewModel中相同的匹配逻辑基于孔径和刀具类型
// 注意这里使用ToolTypeDisplay进行比较因为ToolOrderItem中没有ToolType属性
if (Math.Abs(toolItem.Diameter - targetItem.Diameter) < 0.001 &&
toolItem.ToolTypeDisplay == targetItem.ToolTypeDisplay)
{
return toolItem;
}
}
}
return null;
}
/// <summary> /// <summary>
/// 获取ListView中的ScrollViewer控件 /// 获取ListView中的ScrollViewer控件
/// </summary> /// </summary>

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB