# Flutter 布局 Bug 报告 ## BUG-001 **严重程度**:高 **问题描述**: `DataTableCard` 将 toolbar 包裹在 `SingleChildScrollView(scrollDirection: Axis.horizontal)` 中, 而 toolbar 内使用了 `Spacer`(`Flexible` 组件)。`Spacer` 在无界宽度约束下无法布局,导致运行时 抛出 Flutter assertion: ``` RenderFlex children have non-zero flex but incoming width constraints are unbounded. ``` 受影响页面: - `ProductsScreen`(`products_screen.dart:139`) - `PartnersScreen`(`partners_screen.dart`) - `StockInListScreen`(`stock_in_list_screen.dart`) **复现步骤**: 1. 打开包含 `DataTableCard` 的任意页面(商品、往来单位、入库单等) 2. 由于 `SingleChildScrollView` 提供无界宽度,toolbar 中的 `Spacer` 无法展开 3. Flutter 抛出断言错误,页面渲染失败(测试中表现为所有 Widget 测试失败) **失败的测试用例**: 所有 `products_screen_test.dart`、`partners_screen_test.dart`、`stock_in_screen_test.dart` 中的 测试均失败,错误来自 `data_table_card.dart:35` 的布局计算。 **根因分析**: `client/lib/widgets/data_table_card.dart` 第 33-46 行: ```dart SingleChildScrollView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 12), child: Row( children: [ ConstrainedBox( constraints: BoxConstraints( minWidth: (MediaQuery.of(context).size.width - 212 - 24).clamp(0.0, double.infinity), ), child: toolbar!, // toolbar 中含有 Spacer,而父容器宽度无界 ), ], ), ), ``` `ConstrainedBox` 设置了 `minWidth`,但 `SingleChildScrollView` 为子组件提供的是 `BoxConstraints(minWidth, Infinity)` — 最大宽度无界。`Spacer` 尝试填充剩余空间 (即无限空间),触发 Flutter 的约束断言。 **修复建议**: 方案 A:将 `ConstrainedBox` 改为固定宽度的 `SizedBox`,让 toolbar 占满 `minWidth`, 并把 toolbar 的 `Spacer` 替换为 `MainAxisAlignment.spaceBetween` 或 `SizedBox(width: X)` 固定间距: ```dart // data_table_card.dart - 去掉 SingleChildScrollView 横向滚动, // 改用固定宽度容器,或让 toolbar Row 使用 mainAxisSize: MainAxisSize.min SizedBox( width: (MediaQuery.of(context).size.width - 212 - 24).clamp(0.0, double.infinity), child: toolbar!, ) ``` 方案 B:在各 Screen 的 toolbar Row 中将 `Spacer()` 替换为 `SizedBox(width: 8)`, 并在 `DataTableCard` 中改用非横向滚动的固定宽度容器。