diff --git a/client/lib/screens/stock_in/stock_in_list_screen.dart b/client/lib/screens/stock_in/stock_in_list_screen.dart index 2f99694..e755e6a 100644 --- a/client/lib/screens/stock_in/stock_in_list_screen.dart +++ b/client/lib/screens/stock_in/stock_in_list_screen.dart @@ -8,6 +8,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/responsive/responsive.dart'; import '../../core/theme/context_tokens.dart'; +import '../../core/theme/app_dims.g.dart'; import '../../models/stock_in.dart'; import '../../providers/stock_in_provider.dart'; import '../../repositories/stock_in_repository.dart'; @@ -333,7 +334,20 @@ class _StockInListScreenState extends ConsumerState { )) .toList(); - return DataTableCard( + return Column( + children: [ + // 副标(还原原型 .head .sub) + Container( + width: double.infinity, + color: context.tokens.bg, + padding: const EdgeInsets.fromLTRB( + AppDims.sp3, AppDims.sp3, AppDims.sp3, 0), + child: Text('共 $totalCount 笔入库单', + style: TextStyle( + fontSize: AppDims.fsSm, color: context.tokens.muted)), + ), + Expanded( + child: DataTableCard( totalCount: totalCount, page: page, pageSize: pageSize, @@ -512,6 +526,9 @@ class _StockInListScreenState extends ConsumerState { columns: columns, rows: rows, mobileCards: orders.map((o) => _orderCard(context, o)).toList(), + ), + ), + ], ); } @@ -1228,8 +1245,9 @@ class _StockInDetailDialogState extends ConsumerState<_StockInDetailDialog> { ].join(' · '); return TableRow( decoration: BoxDecoration( - color: - i.isEven ? Colors.white : const Color(0xFFFAFAFA)), + color: i.isEven + ? context.tokens.surface + : context.tokens.bg), children: [ _TableCell('${i + 1}'), _TableCell(item.productCode ?? '-'), @@ -1244,9 +1262,9 @@ class _StockInDetailDialogState extends ConsumerState<_StockInDetailDialog> { style: const TextStyle(fontSize: 13)), if (attrs.isNotEmpty) Text(attrs, - style: const TextStyle( + style: TextStyle( fontSize: 11, - color: Color(0xFF888888))), + color: context.tokens.muted)), ], ), ), diff --git a/client/lib/widgets/status_badge.dart b/client/lib/widgets/status_badge.dart index 64389f2..120538d 100644 --- a/client/lib/widgets/status_badge.dart +++ b/client/lib/widgets/status_badge.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import '../core/theme/context_tokens.dart'; +import 'kpi_card.dart'; enum OrderStatus { draft, pending, approved, rejected } @@ -24,37 +25,14 @@ class StatusBadge extends StatelessWidget { @override Widget build(BuildContext context) { - final Color bg; - final Color fg; - switch (status) { - case OrderStatus.draft: - bg = const Color(0xFFF5F5F5); - fg = context.tokens.muted; - break; - case OrderStatus.pending: - bg = const Color(0xFFFFF3E0); - fg = context.tokens.accent; - break; - case OrderStatus.approved: - bg = const Color(0xFFE8F5E9); - fg = context.tokens.success; - break; - case OrderStatus.rejected: - bg = const Color(0xFFFFEBEE); - fg = context.tokens.danger; - break; - } - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - decoration: BoxDecoration( - color: bg, - borderRadius: BorderRadius.circular(3), - ), - child: Text( - status.label, - style: TextStyle( - color: fg, fontSize: 12, fontWeight: FontWeight.w500), - ), - ); + final t = context.tokens; + // 还原原型 .badge.b-*:圆点 + 软底,色全走 token。 + final (Color fg, Color bg) = switch (status) { + OrderStatus.draft => (t.muted, t.infoSoft), + OrderStatus.pending => (t.warn, t.warnBg), + OrderStatus.approved => (t.success, t.successBg), + OrderStatus.rejected => (t.danger, t.dangerBg), + }; + return StatusPill(label: status.label, color: fg, background: bg); } } diff --git a/client/test/golden/goldens/stock_in_list_a.png b/client/test/golden/goldens/stock_in_list_a.png new file mode 100644 index 0000000..b5cf351 Binary files /dev/null and b/client/test/golden/goldens/stock_in_list_a.png differ diff --git a/client/test/golden/goldens/stock_in_list_b.png b/client/test/golden/goldens/stock_in_list_b.png new file mode 100644 index 0000000..66e43b0 Binary files /dev/null and b/client/test/golden/goldens/stock_in_list_b.png differ diff --git a/client/test/golden/goldens/stock_in_list_c.png b/client/test/golden/goldens/stock_in_list_c.png new file mode 100644 index 0000000..4a10d1c Binary files /dev/null and b/client/test/golden/goldens/stock_in_list_c.png differ diff --git a/client/test/golden/goldens/stock_in_list_mobile_a.png b/client/test/golden/goldens/stock_in_list_mobile_a.png new file mode 100644 index 0000000..94478fc Binary files /dev/null and b/client/test/golden/goldens/stock_in_list_mobile_a.png differ diff --git a/client/test/golden/goldens/stock_in_list_mobile_b.png b/client/test/golden/goldens/stock_in_list_mobile_b.png new file mode 100644 index 0000000..c00df3e Binary files /dev/null and b/client/test/golden/goldens/stock_in_list_mobile_b.png differ diff --git a/client/test/golden/goldens/stock_in_list_mobile_c.png b/client/test/golden/goldens/stock_in_list_mobile_c.png new file mode 100644 index 0000000..f2153f1 Binary files /dev/null and b/client/test/golden/goldens/stock_in_list_mobile_c.png differ diff --git a/client/test/golden/stock_in_list_golden_test.dart b/client/test/golden/stock_in_list_golden_test.dart new file mode 100644 index 0000000..8c5f952 --- /dev/null +++ b/client/test/golden/stock_in_list_golden_test.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:jiu_client/core/models/page_result.dart'; +import 'package:jiu_client/core/auth/auth_state.dart'; +import 'package:jiu_client/models/stock_in.dart'; +import 'package:jiu_client/providers/stock_in_provider.dart'; +import 'package:jiu_client/screens/stock_in/stock_in_list_screen.dart'; + +import '../support/golden_harness.dart'; + +/// design-distill 阶段4:入库列表整屏 golden × 三主题(桌面 + 移动)。 +/// 重点验证 StatusBadge → StatusPill(草稿/待审核/已审核/已拒绝)随主题换色。 +/// 更新基准:flutter test --update-goldens test/golden/stock_in_list_golden_test.dart + +const _orders = [ + StockInOrder( + id: 1, orderNo: 'RK-20260620-014', warehouseId: 1, warehouseName: '主仓', + partnerName: '贵州茅台经销', operatorName: '王经理', reviewerName: '张管理', + status: 'approved', orderDate: '2026-06-20', totalAmount: 34320), + StockInOrder( + id: 2, orderNo: 'RK-20260618-009', warehouseId: 1, warehouseName: '主仓', + partnerName: '宜宾五粮液', operatorName: '李销售', + status: 'pending', orderDate: '2026-06-18', totalAmount: 6700), + StockInOrder( + id: 3, orderNo: 'RK-20260615-003', warehouseId: 1, warehouseName: '二号仓', + partnerName: '泸州老窖', operatorName: '王经理', + status: 'draft', orderDate: '2026-06-15', totalAmount: 5000), + StockInOrder( + id: 4, orderNo: 'RK-20260612-001', warehouseId: 1, warehouseName: '主仓', + partnerName: '绵竹剑南春', operatorName: '李销售', reviewerName: '张管理', + status: 'rejected', orderDate: '2026-06-12', totalAmount: 3500), +]; + +class _FakeStockInNotifier extends StockInListNotifier { + @override + Future> build() async => + const PageResult(data: _orders, total: 4, page: 1, pageSize: 20); + @override + void setPage(int page) {} + @override + void setPageSize(int pageSize) {} + @override + void setStatus(String status) {} + @override + void setDateRange(String? startDate, String? endDate) {} + @override + void setKeyword(String keyword) {} + @override + void reload() {} +} + +List _overrides() => [ + stockInListProvider.overrideWith(() => _FakeStockInNotifier()), + isReadonlyProvider.overrideWithValue(false), + ]; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + SharedPreferences.setMockInitialValues({}); + + goldenAcrossThemes( + 'stock-in list 整屏(桌面)', + goldenPrefix: 'stock_in_list', + child: () => const Scaffold(body: StockInListScreen()), + overrides: _overrides, + logical: const Size(1280, 900), + ); + + goldenAcrossThemes( + 'stock-in list 整屏(移动)', + goldenPrefix: 'stock_in_list_mobile', + child: () => const Scaffold(body: StockInListScreen()), + overrides: _overrides, + logical: const Size(390, 1300), + ); +}