# 基础信息叠板计算功能 ## Goal 在启动功能菜单的“基础信息”区域添加叠板计算能力,让用户输入板厚和单张板总铜厚后,系统根据当前钻孔文件解析出的最小钻咀、最小槽刀、最小 EA 刀,按《钻孔叠板参数表》计算建议叠板块数,帮助用户在打开钻带时快速判断生产叠板数量。 ## What I already know * 用户提供的规则来源是 `1009B-2013钻机参数表(D2-f)(A1A2厂) (1).doc`,文档主体是《钻孔叠板参数表》。 * 规则表按板材厚度和刀具直径给出叠板片数,分为短槽刀、槽刀、钻针三类。 * 备注规则包含:双面、多层板叠板后的总铜厚大于 `16oz` 时,叠板数需逐张递减,直到总铜厚不超过 `16oz` 或叠板数降到 `1`。 * 当前工具场景基本只有双面或多层 PCB,不需要在界面增加板类型选择。 * 如果钻咀、槽刀、短槽刀叠板数冲突,以最小叠板数为准。 * `D` 表示刀具直径;`/` 表示加工能力无法达到;如果板厚没有对应叠板数,由工程部提出、工艺部验证。 * 当前启动流程已在 `App.xaml.cs` 中读取并解析钻带一次,再把最小钻咀、最小槽刀、最小 EA 刀传给 `StartupSelectionWindow`。 * `StartupSelectionWindow.xaml` 的“基础信息”已经显示文件名、最小钻咀、最小槽刀、最小 EA 刀、PP 间距和 3.175 外围孔间距。 * `MainWindowViewModel.UpdateMinDiameterInfo()` 已负责计算三类最小直径;EA 刀对应尾号 `2` 或 `6`,槽刀排除 EA 类型。 * 现有 `StartupSelectionWindow` 使用匿名对象作为 `DataContext`,无法承载双向输入、动态结果和属性变更通知。 * 现有最小直径显示口径会排除 `0.749mm`;该排除只适合显示用途,叠板计算应按实际刀具参与计算,否则可能得到偏大的叠板数。 * 项目文档已明确粉尘刀、去毛刺刀的大类都是槽刀。 ## Assumptions (temporary) * 叠板计算只在启动选择窗口中做即时辅助显示,不写回钻带文件。 * EA 刀按规则表中的“短槽刀”规则计算。 ## Open Questions * 等待用户确认最终需求后进入实现。 ## Requirements (evolving) * 在启动功能菜单的“基础信息”区域增加叠板计算输入和结果显示。 * 本次 MVP 只做启动菜单即时计算,不做输入记忆,不在主窗口增加入口。 * 用户点击“计算叠板”按钮后执行计算;输入变化本身不自动触发计算。 * 铜厚输入为单张板总铜厚,最终叠板后的总铜厚按 `单张板总铜厚 × 候选叠板数` 计算。 * 用户输入板厚和铜厚后,系统使用当前钻带中实际参与加工的最小钻咀、最小槽刀、最小 EA 刀分别查表。 * 叠板计算的最小刀径口径独立于现有“最小钻咀/槽刀/EA刀”显示口径:`0.749mm` 不得因显示排除规则而被排除。 * 槽刀分类映射:`Slot`、`DustSlot`、`DeburrSlot` 均按规则表“槽刀”计算;`EASlot`、`EASlot2` 按规则表“短槽刀”计算;`Drill` 按规则表“钻针”计算。 * 当前钻带缺少某类刀具时,该类别不参与最终叠板数计算,结果明细显示该类别为“无”。 * 如果某类刀具在当前钻带中存在但无法匹配规则、规则格为 `/` 或 `-`、或刀具直径落在规则能力外,则整体显示无法计算,并在明细中标出失败类别和原因;不得跳过已存在但失败的类别。 * 如果三类刀具都不存在,则显示无法计算。 * 规则匹配严格照表执行:板厚不在表格区间、规则格为 `/` 或 `-`、刀具直径没有对应列时,显示无法计算原因,不自动取邻近规则。 * 多个刀具类别得到不同叠板数时,最终结果取最小叠板数。 * 不增加板类型输入,默认当前输入都是双面或多层 PCB,始终按 `16oz` 总铜厚限制递减叠板数,最小保留 `1` 张。 * 计算过程需要能说明最终结果来自哪个限制:钻咀、槽刀、EA 刀或铜厚递减。 * 输入校验先于查表执行:板厚和单张总铜厚不能为空,必须为大于 `0` 的数字;板厚必须落在规则表总范围 `0.4mm` 到 `3.4mm` 内。 ## Acceptance Criteria (evolving) * [x] 启动选择窗口的”基础信息”中能输入板厚和铜厚。 * [x] 点击”计算叠板”按钮后才更新计算结果。 * [x] 输入有效且当前钻带存在可参与计算的最小刀具时,显示建议叠板块数。 * [x] 叠板计算使用包含 `0.749mm` 的实际最小刀径口径,不受现有显示排除规则影响。 * [x] 铜厚限制使用单张板总铜厚乘以候选叠板数计算。 * [x] 钻咀、槽刀、EA 刀结果冲突时,显示取最小值后的最终结果。 * [x] 铜厚限制始终生效;触发时结果按每次减 `1` 张直到不超过 `16oz` 或保留 `1` 张。 * [x] 当前钻带缺少某类刀具时,该类不影响最终结果,结果明细显示为”无”。 * [x] 当前钻带存在某类刀具但该类无法匹配规则时,整体显示无法计算,不使用剩余类别继续给建议张数。 * [x] 三类刀具都不存在时,显示无法计算。 * [x] 板厚或刀具直径超出规则表、或规则为 `/` / `-` 时,界面显示无法计算原因,不默默给兜底值。 * [x] 非数字、空输入、`0` 或负数输入时,点击”计算叠板”显示中文校验提示,不进入查表逻辑。 ## Technical Approach * 将 `StartupSelectionWindow` 的匿名 `DataContext` 替换为正式 `StartupSelectionViewModel`,实现 `INotifyPropertyChanged`,承载文件信息、最小直径显示值、板厚输入、铜厚输入、计算结果和明细文本。 * 保持现有 code-behind 点击事件风格;按钮点击调用 ViewModel 的计算方法或窗口内转调 ViewModel,不强制引入命令体系。 * 新增独立叠板计算类,封装规则表、输入校验、三类刀具查表、取最小值和 `16oz` 铜厚递减逻辑;不建模板类型。 * `StartupSelectionWindow` 仅负责输入、点击按钮和显示结果,不承载规则表算法。 * `App.xaml.cs` 继续沿用现有启动流程,同时把 `MainWindowViewModel.Tools` 或由其派生出的叠板计算用最小刀径传入启动窗口;叠板计算不得复用排除 `0.749mm` 后的显示最小值。 * 计算类放在项目根目录 `StackCountCalculator.cs`,命名空间使用现有主命名空间 `DrillTools`,避免引入新的分层目录和依赖。 * 规则表在代码中以明确的厚度区间、直径区间和单元格值表达;每个失败路径返回中文原因,避免空结果。 * EA 刀按规则表中的“短槽刀”规则计算;普通槽刀按“槽刀”规则计算;钻咀按“钻针”规则计算。 * 规则录入验收:实现时必须用本文档“数字化规则表”逐项核对代码常量,并补充覆盖边界区间、`-` / `/` 单元格、缺失类别和 `0.749mm` 参与计算的验证样例。 ## Digital Rule Tables ### 短槽刀 / EA 刀 | 板厚范围 mm | D=0.60 | D=0.65 | D=0.70 | D>=0.75 | |---|---:|---:|---:|---:| | 0.40-0.65 | 5 | 5 | 5 | 5 | | 0.66-0.85 | 4 | 4 | 5 | 5 | | 0.86-0.95 | 3 | 4 | 5 | 5 | | 0.96-1.05 | 3 | 3 | 4 | 4 | | 1.06-1.15 | 3 | 3 | 4 | 4 | | 1.16-1.35 | 2 | 3 | 4 | 4 | | 1.36-1.65 | 2 | 2 | 3 | 3 | | 1.66-2.05 | 1 | 2 | 2 | 2 | | 2.06-2.55 | 1 | 1 | 1 | 1 | | 2.56-3.40 | 1 | 1 | 1 | 1 | 短槽刀直径匹配为精确列或下限列:`0.60`、`0.65`、`0.70`、`>=0.75`;其它直径视为无对应列,显示无法计算。 ### 槽刀 | 板厚范围 mm | D=0.50 | D=0.55 | D=0.60-0.65 | D>=0.70 | |---|---:|---:|---:|---:| | 0.40-0.65 | 5 | 5 | 5 | - | | 0.66-0.85 | 5 | 5 | 5 | 5 | | 0.86-0.95 | 5 | 5 | 5 | 5 | | 0.96-1.05 | 4 | 5 | 5 | 5 | | 1.06-1.15 | 3 | 4 | 4 | 5 | | 1.16-1.35 | 3 | 4 | 4 | 5 | | 1.36-1.65 | 2 | 3 | 3 | 4 | | 1.66-2.05 | 2 | 2 | 2 | 3 | | 2.06-2.55 | 1 | 2 | 2 | 2 | | 2.56-3.40 | 1 | 1 | 1 | 2 | 槽刀直径匹配为精确列或范围列:`0.50`、`0.55`、`0.60-0.65`、`>=0.70`;其它直径视为无对应列,显示无法计算。 ### 钻针 | 板厚范围 mm | D=0.20-0.225 | D=0.25 | D=0.275-0.30 | D=0.35-0.40 | D=0.45 | D>=0.50 | |---|---:|---:|---:|---:|---:|---:| | 0.40-0.65 | 5 | 5 | 5 | 5 | 5 | 5 | | 0.66-0.85 | 4 | 5 | 5 | 5 | 5 | 5 | | 0.86-0.95 | 3 | 5 | 5 | 5 | 5 | 5 | | 0.96-1.05 | 3 | 5 | 5 | 5 | 5 | 5 | | 1.06-1.15 | 2 | 4 | 4 | 4 | 5 | 5 | | 1.16-1.35 | 2 | 3 | 3 | 4 | 4 | 5 | | 1.36-1.65 | 2 | 3 | 3 | 3 | 3 | 4 | | 1.66-2.05 | 1 | 2 | 2 | 2 | 2 | 3 | | 2.06-2.55 | 1 | 2 | 2 | 2 | 2 | 2 | | 2.56-3.40 | 1 | 1 | 1 | 1 | 1 | 2 | 钻针直径匹配为范围列:`0.20-0.225`、`0.25`、`0.275-0.30`、`0.35-0.40`、`0.45`、`>=0.50`;其它直径视为无对应列,显示无法计算。 ## Decision (ADR-lite) **Context**: 叠板规则来自受控作业文件,且备注要求无对应板厚时由工程/工艺验证,不能由程序自行推断邻近值。 **Decision**: 第一版只在启动菜单“基础信息”做按钮触发的即时计算;规则严格照表;缺失刀具类别跳过;当前存在但规则失败的类别使整体无法计算;最终叠板数取当前存在且全部成功类别的最小规则值后,再套用 `16oz` 总铜厚递减限制。由于当前业务基本只有双面或多层 PCB,界面不增加板类型选择,铜厚限制始终生效。 **Consequences**: 功能改动面较小,计算口径可追溯;后续若规则频繁变化,可以再把规则表外置为配置。 ## Definition of Done (team quality bar) * Tests added/updated where appropriate;本项目未配置测试框架时至少补充可手工验证的样例。 * `dotnet build` 通过。 * UI 文案为简体中文。 * 不引入第三方依赖,不改变既有启动流程入口。 * 文档或说明同步更新,如果行为对用户可见。 ## Out of Scope (explicit) * 不自动修改钻带文件或导出生产工单。 * 不新增规则配置编辑器。 * 不记忆上次输入的板厚和铜厚。 * 不在主窗口“基础信息”区域增加同步入口。 * 不增加单面/双面/多层板类型选择。 * 不按邻近板厚或邻近刀具直径自动推断规则。 * 不改变最小钻咀、最小槽刀、最小 EA 刀的现有解析口径,除非实现时发现现有计算与规则冲突并另行确认。 ## Technical Notes * 可能影响文件: * `StartupSelectionWindow.xaml` * `StartupSelectionWindow.xaml.cs` * `App.xaml.cs` * `StartupSelectionViewModel.cs` * `StackCountCalculator.cs` * 规则来源文件:`C:\Users\14244\source\repos\Aoh\DrillTools\1009B-2013钻机参数表(D2-f)(A1A2厂) (1).doc`。 * 项目是 `.NET 6 WPF`,目标平台 `net6.0-windows`、`x86`。 * 项目没有测试框架;现有质量验证以 `dotnet build` 和真实钻带样例为主。 * 相关规范索引: * `.trellis/spec/backend/index.md` * `.trellis/spec/frontend/index.md` ## 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"`,避免中文长文本溢出。计算按钮放在基础信息区域内部,不加入底部功能按钮行。