feat(client): 入库表单关联商品属性字典(产地/保质期/储存方式/描述文档)
- product_option.dart: 新增 4 个字典 model(Origin/ShelfLife/Storage/DescriptionDoc) - product_option_repository.dart: 新增 4 个 list 方法(listOrigins/ShelfLives/Storages/DescriptionDocs) - product_option_provider.dart: 新增 4 个 FutureProvider 供表单使用 - product_repository.dart: findOrCreate 加 originId/shelfLifeId/storageId/descriptionDocId 可选参数 - stock_in_form_screen.dart: _ItemRow 加 4 个可选 ID 字段;新增 4 个 SearchableOptionField 方法;移动端卡片视图增加 4 个可选字段;提交时传入属性 ID Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -127,4 +127,56 @@ class ProductOptionRepository {
|
||||
statusCode: e.response?.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
// ── 产地 ────────────────────────────────────────────────────
|
||||
|
||||
Future<List<ProductOriginOption>> listOrigins() async {
|
||||
try {
|
||||
final resp = await _client.get('/product-options/origins');
|
||||
final data = (resp.data as Map<String, dynamic>)['data'] as List? ?? [];
|
||||
return data.map((e) => ProductOriginOption.fromJson(e as Map<String, dynamic>)).toList();
|
||||
} on DioException catch (e) {
|
||||
throw AppException(e.response?.data?['error'] as String? ?? '获取产地列表失败',
|
||||
statusCode: e.response?.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
// ── 保质期 ──────────────────────────────────────────────────
|
||||
|
||||
Future<List<ProductShelfLifeOption>> listShelfLives() async {
|
||||
try {
|
||||
final resp = await _client.get('/product-options/shelf-lives');
|
||||
final data = (resp.data as Map<String, dynamic>)['data'] as List? ?? [];
|
||||
return data.map((e) => ProductShelfLifeOption.fromJson(e as Map<String, dynamic>)).toList();
|
||||
} on DioException catch (e) {
|
||||
throw AppException(e.response?.data?['error'] as String? ?? '获取保质期列表失败',
|
||||
statusCode: e.response?.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
// ── 储存方式 ─────────────────────────────────────────────────
|
||||
|
||||
Future<List<ProductStorageOption>> listStorages() async {
|
||||
try {
|
||||
final resp = await _client.get('/product-options/storages');
|
||||
final data = (resp.data as Map<String, dynamic>)['data'] as List? ?? [];
|
||||
return data.map((e) => ProductStorageOption.fromJson(e as Map<String, dynamic>)).toList();
|
||||
} on DioException catch (e) {
|
||||
throw AppException(e.response?.data?['error'] as String? ?? '获取储存方式列表失败',
|
||||
statusCode: e.response?.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
// ── 描述文档 ─────────────────────────────────────────────────
|
||||
|
||||
Future<List<ProductDescriptionDoc>> listDescriptionDocs() async {
|
||||
try {
|
||||
final resp = await _client.get('/product-options/description-docs');
|
||||
final data = (resp.data as Map<String, dynamic>)['data'] as List? ?? [];
|
||||
return data.map((e) => ProductDescriptionDoc.fromJson(e as Map<String, dynamic>)).toList();
|
||||
} on DioException catch (e) {
|
||||
throw AppException(e.response?.data?['error'] as String? ?? '获取描述文档列表失败',
|
||||
statusCode: e.response?.statusCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,13 +135,22 @@ class ProductRepository {
|
||||
required String name,
|
||||
String series = '',
|
||||
String spec = '',
|
||||
int? originId,
|
||||
int? shelfLifeId,
|
||||
int? storageId,
|
||||
int? descriptionDocId,
|
||||
}) async {
|
||||
try {
|
||||
final resp = await _client.post('/products/find-or-create', data: {
|
||||
final body = <String, dynamic>{
|
||||
'name': name,
|
||||
'series': series,
|
||||
'spec': spec,
|
||||
});
|
||||
};
|
||||
if (originId != null) body['origin_id'] = originId;
|
||||
if (shelfLifeId != null) body['shelf_life_id'] = shelfLifeId;
|
||||
if (storageId != null) body['storage_id'] = storageId;
|
||||
if (descriptionDocId != null) body['description_doc_id'] = descriptionDocId;
|
||||
final resp = await _client.post('/products/find-or-create', data: body);
|
||||
return Product.fromJson(
|
||||
(resp.data as Map<String, dynamic>)['data'] as Map<String, dynamic>);
|
||||
} on DioException catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user