feat(client): 所有表格列头加筛选,图标更大靠右对齐
FilterableColumnHeader: - mainAxisAlignment.spaceBetween 将图标推到列头右侧 - 漏斗图标从 13px 增大到 16px,清除图标 14px 各页面改动: - batch_tracking:状态/仓库/供应商筛选移入列头,工具栏合并为一行 - finance:类型/往来单位筛选移入列头,工具栏保留月份选择和显示字段 - inventory:仓库筛选从 API 端单选改为客户端多选,移入"仓库"列头 - products:品牌列头加筛选,从加载数据中动态派生选项 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import '../../core/theme/app_theme.dart';
|
||||
import '../../models/product.dart';
|
||||
import '../../providers/product_provider.dart';
|
||||
import '../../widgets/data_table_card.dart';
|
||||
import '../../widgets/multi_select_dropdown.dart' show FilterableColumnHeader;
|
||||
import '../../widgets/page_scaffold.dart';
|
||||
|
||||
class ProductsScreen extends ConsumerStatefulWidget {
|
||||
@@ -17,6 +18,7 @@ class ProductsScreen extends ConsumerStatefulWidget {
|
||||
class _ProductsScreenState extends ConsumerState<ProductsScreen> {
|
||||
final _searchCtrl = TextEditingController();
|
||||
Timer? _debounce;
|
||||
Set<String> _filterBrand = {};
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@@ -133,6 +135,17 @@ class _ProductsScreenState extends ConsumerState<ProductsScreen> {
|
||||
|
||||
Widget _buildProductList(
|
||||
List<Product> products, int totalCount, int page) {
|
||||
// 品牌选项从当前数据中派生,客户端筛选
|
||||
final brandOptions = products
|
||||
.map((p) => p.brand ?? '')
|
||||
.where((s) => s.isNotEmpty)
|
||||
.toSet()
|
||||
.toList()
|
||||
..sort();
|
||||
final filteredProducts = _filterBrand.isEmpty
|
||||
? products
|
||||
: products.where((p) => _filterBrand.contains(p.brand ?? '')).toList();
|
||||
|
||||
return DataTableCard(
|
||||
totalCount: totalCount,
|
||||
page: page,
|
||||
@@ -160,18 +173,25 @@ class _ProductsScreenState extends ConsumerState<ProductsScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
columns: const [
|
||||
DataColumn(label: Text('商品编码')),
|
||||
DataColumn(label: Text('商品名称')),
|
||||
DataColumn(label: Text('品牌')),
|
||||
DataColumn(label: Text('规格')),
|
||||
DataColumn(label: Text('单位')),
|
||||
DataColumn(label: Text('进价'), numeric: true),
|
||||
DataColumn(label: Text('售价'), numeric: true),
|
||||
DataColumn(label: Text('安全库存'), numeric: true),
|
||||
DataColumn(label: Text('操作')),
|
||||
columns: [
|
||||
const DataColumn(label: Text('商品编码')),
|
||||
const DataColumn(label: Text('商品名称')),
|
||||
DataColumn(
|
||||
label: FilterableColumnHeader(
|
||||
text: '品牌',
|
||||
options: brandOptions,
|
||||
selected: _filterBrand,
|
||||
onChanged: (v) => setState(() => _filterBrand = v),
|
||||
),
|
||||
),
|
||||
const DataColumn(label: Text('规格')),
|
||||
const DataColumn(label: Text('单位')),
|
||||
const DataColumn(label: Text('进价'), numeric: true),
|
||||
const DataColumn(label: Text('售价'), numeric: true),
|
||||
const DataColumn(label: Text('安全库存'), numeric: true),
|
||||
const DataColumn(label: Text('操作')),
|
||||
],
|
||||
rows: products.isEmpty
|
||||
rows: filteredProducts.isEmpty
|
||||
? [
|
||||
const DataRow(cells: [
|
||||
DataCell(SizedBox()),
|
||||
@@ -186,7 +206,7 @@ class _ProductsScreenState extends ConsumerState<ProductsScreen> {
|
||||
DataCell(SizedBox()),
|
||||
])
|
||||
]
|
||||
: products
|
||||
: filteredProducts
|
||||
.map((p) => DataRow(
|
||||
cells: [
|
||||
DataCell(Text(p.code,
|
||||
|
||||
Reference in New Issue
Block a user