diff --git a/CHANGELOG-client.md b/CHANGELOG-client.md index 0c785dc..92b4310 100644 --- a/CHANGELOG-client.md +++ b/CHANGELOG-client.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.80] - 2026-06-24 + +### 新功能 +- 出库单详情新增「售价」与「利润」列,利润 = 售价 − 成本,一眼看清每笔出库的盈亏。 + +### 改进 +- 出库 / 入库单详情改为全屏展示,内容更大更清晰,左上角返回箭头关闭。 +- 出库单详情自动带出商品的生产日期与批次号(明细未单独填写时回退商品资料),去掉冗余的「数量」列。 + ## [1.0.79] - 2026-06-24 ### 改进 diff --git a/client/lib/models/stock_out.dart b/client/lib/models/stock_out.dart index 4ea52b8..cdc51ec 100644 --- a/client/lib/models/stock_out.dart +++ b/client/lib/models/stock_out.dart @@ -61,8 +61,9 @@ class StockOutItem { productSeries: lineOrProduct('series', 'series'), productSpec: lineOrProduct('spec', 'spec'), productUnit: (json['product'] as Map?)?['unit'] as String?, - batchNo: json['batch_no'] as String?, - productionDate: json['production_date'] as String?, + // 批次号/生产日期:优先明细行快照,回退 product 关联(App 新建单据快照列常为空) + batchNo: lineOrProduct('batch_no', 'batch_no'), + productionDate: lineOrProduct('production_date', 'production_date'), ); } } 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 a168c2f..e86871d 100644 --- a/client/lib/screens/stock_in/stock_in_list_screen.dart +++ b/client/lib/screens/stock_in/stock_in_list_screen.dart @@ -1044,24 +1044,21 @@ class _StockInDetailDialogState extends ConsumerState<_StockInDetailDialog> { @override Widget build(BuildContext context) { - return Dialog( - child: Container( - width: context.dialogWidth(720), - constraints: const BoxConstraints(maxHeight: 600), + return Dialog.fullscreen( + child: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), - decoration: const BoxDecoration( - color: AppTheme.primary, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(12), - topRight: Radius.circular(12), - ), - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: const BoxDecoration(color: AppTheme.primary), child: Row( children: [ + IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + tooltip: '返回', + onPressed: () => Navigator.of(context).pop(), + ), const Text('入库单详情', style: TextStyle( fontSize: 16, @@ -1074,10 +1071,6 @@ class _StockInDetailDialogState extends ConsumerState<_StockInDetailDialog> { tooltip: '打印', onPressed: () => safePrint(context, () => printStockInOrder(_loadedOrder!)), ), - IconButton( - icon: const Icon(Icons.close, color: Colors.white), - onPressed: () => Navigator.of(context).pop(), - ), ], ), ), diff --git a/client/lib/screens/stock_out/stock_out_list_screen.dart b/client/lib/screens/stock_out/stock_out_list_screen.dart index 28f149a..c06ef3d 100644 --- a/client/lib/screens/stock_out/stock_out_list_screen.dart +++ b/client/lib/screens/stock_out/stock_out_list_screen.dart @@ -957,24 +957,21 @@ class _StockOutDetailDialogState extends ConsumerState<_StockOutDetailDialog> { @override Widget build(BuildContext context) { - return Dialog( - child: Container( - width: context.dialogWidth(720), - constraints: const BoxConstraints(maxHeight: 600), + return Dialog.fullscreen( + child: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), - decoration: const BoxDecoration( - color: AppTheme.primary, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(12), - topRight: Radius.circular(12), - ), - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: const BoxDecoration(color: AppTheme.primary), child: Row( children: [ + IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + tooltip: '返回', + onPressed: () => Navigator.of(context).pop(), + ), const Text('出库单详情', style: TextStyle( fontSize: 16, @@ -987,10 +984,6 @@ class _StockOutDetailDialogState extends ConsumerState<_StockOutDetailDialog> { tooltip: '打印', onPressed: () => safePrint(context, () => printStockOutOrder(_loadedOrder!)), ), - IconButton( - icon: const Icon(Icons.close, color: Colors.white), - onPressed: () => Navigator.of(context).pop(), - ), ], ), ), @@ -1073,7 +1066,7 @@ class _StockOutDetailDialogState extends ConsumerState<_StockOutDetailDialog> { children: [ TableRow( decoration: const BoxDecoration(color: Color(0xFFF0F4FF)), - children: ['序号', '商品编码', '名称', '系列', '规格', '生产日期', '批次号', '数量', '单价', '金额'] + children: ['序号', '商品编码', '名称', '系列', '规格', '生产日期', '批次号', '成本价', '售价', '利润'] .map((h) => Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text(h, @@ -1102,9 +1095,9 @@ class _StockOutDetailDialogState extends ConsumerState<_StockOutDetailDialog> { : (item.productionDate ?? '-')), _TableCell( (item.batchNo?.isNotEmpty ?? false) ? item.batchNo! : '-'), - _TableCell(item.quantity.toStringAsFixed(3)), _TableCell('¥${item.unitPrice.toStringAsFixed(2)}'), - _TableCell('¥${item.totalPrice.toStringAsFixed(2)}'), + _TableCell('¥${item.salePrice.toStringAsFixed(2)}'), + _TableCell('¥${(item.salePrice - item.unitPrice).toStringAsFixed(2)}'), ], ); }),