import 'dart:typed_data'; import 'package:dio/dio.dart'; import '../core/api/api_client.dart'; import '../core/exceptions.dart'; import '../core/models/page_result.dart'; import '../models/product.dart'; import '../models/product_image.dart'; class ProductRepository { final ApiClient _client; const ProductRepository(this._client); Future> list({ int page = 1, int pageSize = 20, String? keyword, int? categoryId, }) async { try { final params = { 'page': page, 'page_size': pageSize, if (keyword != null && keyword.isNotEmpty) 'keyword': keyword, if (categoryId != null) 'category_id': categoryId, }; final resp = await _client.get('/products', params: params); return PageResult.fromJson( resp.data as Map, Product.fromJson, ); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '获取商品列表失败', statusCode: e.response?.statusCode, ); } } Future create(Map data) async { try { final resp = await _client.post('/products', data: data); return Product.fromJson( (resp.data as Map)['data'] as Map); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '创建商品失败', statusCode: e.response?.statusCode, ); } } Future update(int id, Map data) async { try { final resp = await _client.put('/products/$id', data: data); return Product.fromJson( (resp.data as Map)['data'] as Map); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '更新商品失败', statusCode: e.response?.statusCode, ); } } Future delete(int id) async { try { await _client.delete('/products/$id'); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '删除商品失败', statusCode: e.response?.statusCode, ); } } Future getDetail(int id) async { try { final resp = await _client.get('/products/$id/detail'); return Product.fromJson( (resp.data as Map)['data'] as Map); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '获取商品详情失败', statusCode: e.response?.statusCode, ); } } Future uploadImage(int productId, String? filePath, {Uint8List? bytes, String? fileName}) async { try { final MultipartFile file; if (bytes != null) { file = MultipartFile.fromBytes(bytes, filename: fileName ?? 'image.jpg'); } else { file = await MultipartFile.fromFile(filePath!); } final formData = FormData.fromMap({'file': file}); final resp = await _client.post('/products/$productId/images', data: formData); return ProductImage.fromJson( (resp.data as Map)['data'] as Map); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '上传图片失败', statusCode: e.response?.statusCode, ); } } Future getQRCodeBytes(int productId) async { try { final bytes = await _client.getBytes('/products/$productId/qrcode'); return Uint8List.fromList(bytes); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '获取二维码失败', statusCode: e.response?.statusCode, ); } } Future deleteImage(int productId, int imageId) async { try { await _client.delete('/products/$productId/images/$imageId'); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '删除图片失败', statusCode: e.response?.statusCode, ); } } Future findOrCreate({ required String name, String series = '', String spec = '', int? originId, int? shelfLifeId, int? storageId, int? descriptionDocId, }) async { try { final body = { '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)['data'] as Map); } on DioException catch (e) { throw AppException( e.response?.data?['error'] as String? ?? '查找/创建商品失败', statusCode: e.response?.statusCode, ); } } }