From 025f3b7bbc8b0212e3c299129e673b03af3b39f9 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Sun, 21 Jun 2026 16:30:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(client):=20=E5=85=A5=E5=BA=93=E5=BD=95?= =?UTF-8?q?=E5=85=A5=E5=8E=BB=E9=99=A4=E6=8C=89=E5=90=8D=E7=A7=B0=E5=A4=8D?= =?UTF-8?q?=E7=94=A8=EF=BC=8C=E6=98=8E=E7=BB=86=E5=B8=A6=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E7=94=B1=E5=90=8E=E7=AB=AF=E5=BB=BA=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E4=BA=A7=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01YZ4DskSRKsSiheQonFtQvx --- CHANGELOG-client.md | 5 ++ .../stock_in/stock_in_form_screen.dart | 63 +++++-------------- 2 files changed, 19 insertions(+), 49 deletions(-) diff --git a/CHANGELOG-client.md b/CHANGELOG-client.md index 3b6a7a3..da46217 100644 --- a/CHANGELOG-client.md +++ b/CHANGELOG-client.md @@ -5,6 +5,11 @@ 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.65] - 2026-06-21 + +### 改进 +- 入库录入改为「每行一个独立产品」:每条明细对应一个独立编号,同名同规格录多次也各自独立(配合后端 server-v1.0.69) + ## [1.0.64] - 2026-06-20 ### 新功能 diff --git a/client/lib/screens/stock_in/stock_in_form_screen.dart b/client/lib/screens/stock_in/stock_in_form_screen.dart index 8dbfeb7..e9491ff 100644 --- a/client/lib/screens/stock_in/stock_in_form_screen.dart +++ b/client/lib/screens/stock_in/stock_in_form_screen.dart @@ -11,7 +11,6 @@ import '../../models/stock_in.dart'; import '../../core/config/app_constants.dart'; import '../../providers/partner_provider.dart'; import '../../providers/product_option_provider.dart'; -import '../../providers/product_provider.dart'; import '../../providers/inventory_provider.dart'; import '../../providers/stock_in_provider.dart'; import '../../providers/warehouse_provider.dart'; @@ -306,58 +305,22 @@ class _StockInFormScreenState extends ConsumerState { setState(() => _submitting = true); - // Resolve product IDs for items where productId is null + // 入库每行 = 一个特有产品:明细只带 名称/系列/规格(字典文本) + 批次/生产日期, + // 由后端为每行新建独立产品(序列号),前端不再 findOrCreate 复用。 final nameOpts = ref.read(productNameListProvider).valueOrNull ?? []; final seriesOpts = ref.read(productSeriesListProvider).valueOrNull ?? []; final specOpts = ref.read(productSpecListProvider).valueOrNull ?? []; + String optName(List opts, int? id) => + opts.where((o) => o.id == id).firstOrNull?.name as String? ?? ''; for (final item in _items) { - if (item.productId == null) { - final name = nameOpts - .where((o) => o.id == item.selectedNameId) - .firstOrNull - ?.name ?? - ''; - final series = seriesOpts - .where((o) => o.id == item.selectedSeriesId) - .firstOrNull - ?.name ?? - ''; - final spec = specOpts - .where((o) => o.id == item.selectedSpecId) - .firstOrNull - ?.name ?? - ''; - if (name.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('请选择商品名称'), backgroundColor: AppTheme.danger), - ); - setState(() => _submitting = false); - return; - } - try { - final product = - await ref.read(productRepositoryProvider).findOrCreate( - name: name, - series: series, - spec: spec, - originId: item.selectedOriginId, - shelfLifeId: item.selectedShelfLifeId, - storageId: item.selectedStorageId, - descriptionDocId: item.selectedDescriptionDocId, - ); - item.productId = product.id; - } catch (e) { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('商品查找失败:$e'), backgroundColor: AppTheme.danger), - ); - setState(() => _submitting = false); - } - return; - } + if (optName(nameOpts, item.selectedNameId).isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('请选择商品名称'), backgroundColor: AppTheme.danger), + ); + setState(() => _submitting = false); + return; } } @@ -367,7 +330,9 @@ class _StockInFormScreenState extends ConsumerState { final batchNo = item.batchNoCtrl.text.trim(); final productionDate = item.productionDateCtrl.text.trim(); return { - 'product_id': item.productId ?? 0, + 'product_name': optName(nameOpts, item.selectedNameId), + 'series': optName(seriesOpts, item.selectedSeriesId), + 'spec': optName(specOpts, item.selectedSpecId), 'quantity': qty, 'unit_price': price, 'total_price': qty * price,