fix: 修复EA刀叠板查表直径区间匹配,叠板区改为折叠输入即算
EA刀/短槽刀列按参数表下限区间 [0.60,0.65)/[0.65,0.70)/[0.70,0.75)/>=0.75 匹配,修复 0.706mm 等刀径查表失败;叠板计算改为 Expander 默认收折、移除计算按钮、输入变化自动计算。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -19,20 +19,21 @@
|
||||
* 现有最小直径显示口径会排除 `0.749mm`;该排除只适合显示用途,叠板计算应按实际刀具参与计算,否则可能得到偏大的叠板数。
|
||||
* 项目文档已明确粉尘刀、去毛刺刀的大类都是槽刀。
|
||||
|
||||
## Assumptions (temporary)
|
||||
## Assumptions
|
||||
|
||||
* 叠板计算只在启动选择窗口中做即时辅助显示,不写回钻带文件。
|
||||
* EA 刀按规则表中的“短槽刀”规则计算。
|
||||
* EA 刀按规则表中的”短槽刀”规则计算。
|
||||
|
||||
## Open Questions
|
||||
|
||||
* 等待用户确认最终需求后进入实现。
|
||||
无(全部已确认)。
|
||||
|
||||
## Requirements (evolving)
|
||||
## Requirements (finalized)
|
||||
|
||||
* 在启动功能菜单的“基础信息”区域增加叠板计算输入和结果显示。
|
||||
* 在启动功能菜单的”基础信息”区域增加叠板计算输入和结果显示。
|
||||
* 本次 MVP 只做启动菜单即时计算,不做输入记忆,不在主窗口增加入口。
|
||||
* 用户点击“计算叠板”按钮后执行计算;输入变化本身不自动触发计算。
|
||||
* 叠板计算区域使用 `Expander` 折叠控件,默认收折,仅显示”▸ 叠板计算”标题行;展开后显示输入框、结果和明细,不占用启动菜单的默认视觉面积。
|
||||
* 输入即计算:板厚和铜厚输入框使用 `UpdateSourceTrigger=PropertyChanged`,任一输入变化时自动计算;不设”计算叠板”按钮;输入不完整时静默清空结果,不报错。
|
||||
* 铜厚输入为单张板总铜厚,最终叠板后的总铜厚按 `单张板总铜厚 × 候选叠板数` 计算。
|
||||
* 用户输入板厚和铜厚后,系统使用当前钻带中实际参与加工的最小钻咀、最小槽刀、最小 EA 刀分别查表。
|
||||
* 叠板计算的最小刀径口径独立于现有“最小钻咀/槽刀/EA刀”显示口径:`0.749mm` 不得因显示排除规则而被排除。
|
||||
@@ -46,10 +47,10 @@
|
||||
* 计算过程需要能说明最终结果来自哪个限制:钻咀、槽刀、EA 刀或铜厚递减。
|
||||
* 输入校验先于查表执行:板厚和单张总铜厚不能为空,必须为大于 `0` 的数字;板厚必须落在规则表总范围 `0.4mm` 到 `3.4mm` 内。
|
||||
|
||||
## Acceptance Criteria (evolving)
|
||||
## Acceptance Criteria (finalized)
|
||||
|
||||
* [x] 启动选择窗口的”基础信息”中能输入板厚和铜厚。
|
||||
* [x] 点击”计算叠板”按钮后才更新计算结果。
|
||||
* [x] 叠板计算区域默认折叠,展开后输入板厚和铜厚自动计算,无需点击按钮。
|
||||
* [x] 输入有效且当前钻带存在可参与计算的最小刀具时,显示建议叠板块数。
|
||||
* [x] 叠板计算使用包含 `0.749mm` 的实际最小刀径口径,不受现有显示排除规则影响。
|
||||
* [x] 铜厚限制使用单张板总铜厚乘以候选叠板数计算。
|
||||
@@ -59,12 +60,12 @@
|
||||
* [x] 当前钻带存在某类刀具但该类无法匹配规则时,整体显示无法计算,不使用剩余类别继续给建议张数。
|
||||
* [x] 三类刀具都不存在时,显示无法计算。
|
||||
* [x] 板厚或刀具直径超出规则表、或规则为 `/` / `-` 时,界面显示无法计算原因,不默默给兜底值。
|
||||
* [x] 非数字、空输入、`0` 或负数输入时,点击”计算叠板”显示中文校验提示,不进入查表逻辑。
|
||||
* [x] 非数字、空输入、`0` 或负数输入时,静默清空结果区域,不进入查表逻辑。
|
||||
|
||||
## Technical Approach
|
||||
|
||||
* 将 `StartupSelectionWindow` 的匿名 `DataContext` 替换为正式 `StartupSelectionViewModel`,实现 `INotifyPropertyChanged`,承载文件信息、最小直径显示值、板厚输入、铜厚输入、计算结果和明细文本。
|
||||
* 保持现有 code-behind 点击事件风格;按钮点击调用 ViewModel 的计算方法或窗口内转调 ViewModel,不强制引入命令体系。
|
||||
* 保持现有 code-behind 风格;叠板计算不再使用按钮事件,改为输入属性 setter 中调用 ViewModel 的 `TryCalculateStackCount()` 方法。
|
||||
* 新增独立叠板计算类,封装规则表、输入校验、三类刀具查表、取最小值和 `16oz` 铜厚递减逻辑;不建模板类型。
|
||||
* `StartupSelectionWindow` 仅负责输入、点击按钮和显示结果,不承载规则表算法。
|
||||
* `App.xaml.cs` 继续沿用现有启动流程,同时把 `MainWindowViewModel.Tools` 或由其派生出的叠板计算用最小刀径传入启动窗口;叠板计算不得复用排除 `0.749mm` 后的显示最小值。
|
||||
@@ -130,7 +131,7 @@
|
||||
|
||||
**Context**: 叠板规则来自受控作业文件,且备注要求无对应板厚时由工程/工艺验证,不能由程序自行推断邻近值。
|
||||
|
||||
**Decision**: 第一版只在启动菜单“基础信息”做按钮触发的即时计算;规则严格照表;缺失刀具类别跳过;当前存在但规则失败的类别使整体无法计算;最终叠板数取当前存在且全部成功类别的最小规则值后,再套用 `16oz` 总铜厚递减限制。由于当前业务基本只有双面或多层 PCB,界面不增加板类型选择,铜厚限制始终生效。
|
||||
**Decision**: 只在启动菜单”基础信息”做叠板计算;规则严格照表;缺失刀具类别跳过;当前存在但规则失败的类别使整体无法计算;最终叠板数取当前存在且全部成功类别的最小规则值后,再套用 `16oz` 总铜厚递减限制。由于当前业务基本只有双面或多层 PCB,界面不增加板类型选择,铜厚限制始终生效。叠板计算区域改为 `Expander` 折叠式,默认收折,输入即计算,不设按钮,避免干扰启动菜单的快速择路动线。
|
||||
|
||||
**Consequences**: 功能改动面较小,计算口径可追溯;后续若规则频繁变化,可以再把规则表外置为配置。
|
||||
|
||||
@@ -169,15 +170,27 @@
|
||||
|
||||
## UI Sketch
|
||||
|
||||
默认收折状态:
|
||||
```text
|
||||
基础信息
|
||||
┌────────────────────────────────────────────────────────────────────┐
|
||||
│ 文件名:xxx │
|
||||
│ 最小钻咀:0.250 最小槽刀:0.600 最小EA刀:0.650 │
|
||||
│ 板厚(mm):[ 0.80 ] 单张总铜厚(oz):[ 2 ] [计算叠板] │
|
||||
│ 建议叠板:4 张 │
|
||||
│ 明细:钻咀 4 / 槽刀 5 / EA 5 / 铜厚通过,最终取 4 张 │
|
||||
│ ▸ 叠板计算 │
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
窗口允许从 `570px` 增宽到约 `680px`;叠板结果明细使用 `TextWrapping="Wrap"`,避免中文长文本溢出。计算按钮放在基础信息区域内部,不加入底部功能按钮行。
|
||||
展开后(输入即计算,无需按钮):
|
||||
```text
|
||||
基础信息
|
||||
┌────────────────────────────────────────────────────────────────────┐
|
||||
│ 文件名:xxx │
|
||||
│ 最小钻咀:0.250 最小槽刀:0.600 最小EA刀:0.650 │
|
||||
│ ▾ 叠板计算 │
|
||||
│ 板厚(mm):[ 0.80 ] 铜厚(oz):[ 2 ] │
|
||||
│ 建议叠板:4 张 │
|
||||
│ 钻针 4 / 槽刀 5 / EA 5 / 铜厚通过,最终取 4 张 │
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
叠板区域使用 `Expander` 控件,`IsExpanded="False"`;当两个输入框均有有效正数时自动计算并显示结果,输入不完整时静默清空。计算按钮已移除。
|
||||
|
||||
@@ -397,15 +397,16 @@ namespace DrillTools
|
||||
/// <summary>
|
||||
/// 短槽刀/EA刀列匹配
|
||||
/// 列定义:D=0.60, D=0.65, D=0.70, D>=0.75
|
||||
/// 各列为下限区间:[0.60,0.65)、[0.65,0.70)、[0.70,0.75)、[0.75,+∞)
|
||||
/// </summary>
|
||||
private static int FindEAColumnIndex(double diameter)
|
||||
{
|
||||
const double eps = 0.001;
|
||||
if (Math.Abs(diameter - 0.60) < eps) return 0;
|
||||
if (Math.Abs(diameter - 0.65) < eps) return 1;
|
||||
if (Math.Abs(diameter - 0.70) < eps) return 2;
|
||||
if (diameter >= 0.75 - eps) return 3;
|
||||
return -1;
|
||||
if (diameter < 0.60 - eps) return -1;
|
||||
if (diameter < 0.65 - eps) return 0;
|
||||
if (diameter < 0.70 - eps) return 1;
|
||||
if (diameter < 0.75 - eps) return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace DrillTools
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _boardThicknessInput, value))
|
||||
UpdateCanCalculate();
|
||||
TryCalculateStackCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace DrillTools
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _copperThicknessInput, value))
|
||||
UpdateCanCalculate();
|
||||
TryCalculateStackCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,16 +165,6 @@ namespace DrillTools
|
||||
set => SetProperty(ref _stackCountDetail, value);
|
||||
}
|
||||
|
||||
private bool _canCalculate;
|
||||
/// <summary>
|
||||
/// 是否可以执行计算(板厚和铜厚都已输入有效数字)
|
||||
/// </summary>
|
||||
public bool CanCalculate
|
||||
{
|
||||
get => _canCalculate;
|
||||
set => SetProperty(ref _canCalculate, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 叠板计算用最小刀径(不排除 0.749mm)
|
||||
@@ -199,47 +189,40 @@ namespace DrillTools
|
||||
#region 计算方法
|
||||
|
||||
/// <summary>
|
||||
/// 执行叠板计算(由按钮点击转调)
|
||||
/// 输入变化时自动尝试计算叠板数
|
||||
/// 两个输入均有效时计算,否则静默清空结果
|
||||
/// </summary>
|
||||
public void CalculateStackCount()
|
||||
private void TryCalculateStackCount()
|
||||
{
|
||||
// 解析输入
|
||||
if (!double.TryParse(BoardThicknessInput, out double boardThickness) ||
|
||||
!double.TryParse(CopperThicknessInput, out double copperThickness))
|
||||
// 两个输入都不为空且可解析为正数时才执行计算
|
||||
if (double.TryParse(BoardThicknessInput, out double boardThickness) && boardThickness > 0 &&
|
||||
double.TryParse(CopperThicknessInput, out double copperThickness) && copperThickness > 0)
|
||||
{
|
||||
StackCountResult = "请输入有效的板厚和铜厚数字";
|
||||
StackCountDetail = string.Empty;
|
||||
return;
|
||||
}
|
||||
var result = StackCountCalculator.Calculate(
|
||||
boardThickness, copperThickness,
|
||||
StackCalcMinDrill, StackCalcMinSlot, StackCalcMinEA);
|
||||
|
||||
// 调用计算器
|
||||
var result = StackCountCalculator.Calculate(
|
||||
boardThickness, copperThickness,
|
||||
StackCalcMinDrill, StackCalcMinSlot, StackCalcMinEA);
|
||||
|
||||
if (result.Success)
|
||||
{
|
||||
StackCountResult = $"建议叠板:{result.RecommendedCount} 张";
|
||||
StackCountDetail = result.Detail;
|
||||
if (result.Success)
|
||||
{
|
||||
StackCountResult = $"建议叠板:{result.RecommendedCount} 张";
|
||||
StackCountDetail = result.Detail;
|
||||
}
|
||||
else
|
||||
{
|
||||
StackCountResult = "无法计算";
|
||||
StackCountDetail = string.IsNullOrEmpty(result.Detail)
|
||||
? result.Message
|
||||
: $"{result.Message}\n{result.Detail}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StackCountResult = "无法计算";
|
||||
StackCountDetail = string.IsNullOrEmpty(result.Detail)
|
||||
? result.Message
|
||||
: $"{result.Message}\n{result.Detail}";
|
||||
// 输入不完整,静默清空
|
||||
StackCountResult = string.Empty;
|
||||
StackCountDetail = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新 CanCalculate 状态(板厚和铜厚均为大于 0 的数字时可用)
|
||||
/// </summary>
|
||||
private void UpdateCanCalculate()
|
||||
{
|
||||
CanCalculate = double.TryParse(BoardThicknessInput, out double bt) && bt > 0 &&
|
||||
double.TryParse(CopperThicknessInput, out double ct) && ct > 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INotifyPropertyChanged
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
@@ -92,46 +90,44 @@
|
||||
Text="{Binding Outer3175YSpacing, StringFormat=Y间距: {0:F3}}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 叠板计算输入行 -->
|
||||
<Grid Grid.Row="3" Margin="0,8,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="60" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- 叠板计算(折叠式,默认收折) -->
|
||||
<Expander Grid.Row="3" Margin="0,8,0,0"
|
||||
Header="叠板计算"
|
||||
IsExpanded="False">
|
||||
<Grid Margin="0,5,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" Text="板厚(mm):" />
|
||||
<TextBox Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding BoardThicknessInput, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBlock Grid.Column="2" Margin="15,0,0,0" VerticalAlignment="Center" Text="单张总铜厚(oz):" />
|
||||
<TextBox Grid.Column="3"
|
||||
Width="60"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding CopperThicknessInput, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="4" Margin="10,0,0,0"
|
||||
Width="75" Height="25"
|
||||
Content="计算叠板"
|
||||
IsEnabled="{Binding CanCalculate}"
|
||||
Click="CalculateStackCount_Click" />
|
||||
</Grid>
|
||||
<!-- 输入行 -->
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="板厚(mm):" />
|
||||
<TextBox Width="70"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding BoardThicknessInput, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBlock Margin="15,0,0,0" VerticalAlignment="Center" Text="铜厚(oz):" />
|
||||
<TextBox Width="60"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding CopperThicknessInput, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 叠板计算结果行 -->
|
||||
<TextBlock Grid.Row="4" Margin="0,5,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding StackCountResult}" />
|
||||
<!-- 结果行 -->
|
||||
<TextBlock Grid.Row="1" Margin="0,5,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding StackCountResult}" />
|
||||
|
||||
<!-- 叠板计算明细行 -->
|
||||
<TextBlock Grid.Row="5" Margin="0,2,0,0"
|
||||
Text="{Binding StackCountDetail}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding StackCountDetail, Converter={StaticResource NonEmptyToVisibilityConverter}}" />
|
||||
<!-- 明细行 -->
|
||||
<TextBlock Grid.Row="2" Margin="0,2,0,0"
|
||||
Text="{Binding StackCountDetail}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{Binding StackCountDetail, Converter={StaticResource NonEmptyToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</Expander>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
@@ -56,16 +56,5 @@ namespace DrillTools
|
||||
SelectedAction = StartupAction.ScaleDrillTape;
|
||||
Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算叠板按钮点击事件
|
||||
/// </summary>
|
||||
private void CalculateStackCount_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is StartupSelectionViewModel vm)
|
||||
{
|
||||
vm.CalculateStackCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user