c7f36b2d72
- 新组件 DsSortHeader(原型 thead .sh 对照,L1 已登记):未排序淡箭头暗示 可排,激活 primary + 方向箭头(↑升/↓降) - 库存屏 5 列(库存/成本价/总价/生产日期/入库时间)接线,排序走服务端 全局生效(跨分页),点击循环 无→升→降→无 - 原型 inventory.html COLS sort:true + toggleSort 交互 + atoms .sh 样式登记 - 桌面库存 golden 重录 ×3(列头带排序箭头) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
127 lines
4.1 KiB
Dart
127 lines
4.1 KiB
Dart
import 'package:dio/dio.dart';
|
||
import '../core/api/api_client.dart';
|
||
import '../core/exceptions.dart';
|
||
import '../core/models/page_result.dart';
|
||
import '../models/inventory.dart';
|
||
|
||
class InventoryRepository {
|
||
final ApiClient _client;
|
||
|
||
const InventoryRepository(this._client);
|
||
|
||
Future<PageResult<Inventory>> listInventory({
|
||
int? warehouseId,
|
||
int? productId,
|
||
String? keyword,
|
||
String? code,
|
||
List<String>? series,
|
||
List<String>? spec,
|
||
String? status, // 三态筛选:stock/on_sale/sold(逗号可多值);空=后端默认(排除已售)
|
||
String? sortBy, // 列头排序:qty/cost/price/prod_date/in_time(后端白名单)
|
||
bool sortAsc = true,
|
||
int page = 1,
|
||
int pageSize = 50,
|
||
}) async {
|
||
try {
|
||
final params = <String, dynamic>{
|
||
'page': page,
|
||
'page_size': pageSize,
|
||
if (warehouseId != null) 'warehouse_id': warehouseId,
|
||
if (productId != null) 'product_id': productId,
|
||
if (keyword != null && keyword.isNotEmpty) 'keyword': keyword,
|
||
if (code != null && code.isNotEmpty) 'code': code,
|
||
if (series != null && series.isNotEmpty) 'series': series.join(','),
|
||
if (spec != null && spec.isNotEmpty) 'spec': spec.join(','),
|
||
if (status != null && status.isNotEmpty) 'status': status,
|
||
if (sortBy != null && sortBy.isNotEmpty) ...{
|
||
'sort_by': sortBy,
|
||
'sort_dir': sortAsc ? 'asc' : 'desc',
|
||
},
|
||
};
|
||
final resp = await _client.get('/inventory', params: params);
|
||
return PageResult.fromJson(
|
||
resp.data as Map<String, dynamic>,
|
||
Inventory.fromJson,
|
||
);
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '获取库存失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
Future<InventorySummary> getSummary() async {
|
||
try {
|
||
final resp = await _client.get('/inventory/summary');
|
||
return InventorySummary.fromJson(resp.data as Map<String, dynamic>);
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '获取库存汇总失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
Future<Map<String, dynamic>> createCheck(Map<String, dynamic> data) async {
|
||
try {
|
||
final resp = await _client.post('/inventory/checks', data: data);
|
||
return resp.data as Map<String, dynamic>;
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '提交盘点失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 库存⇄在售 挂售切换(status 仅收 stock/on_sale;sold 由出库流程专属)
|
||
Future<void> updateStatus(int id, String status) async {
|
||
try {
|
||
await _client.put('/inventory/$id/status', data: {'status': status});
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '状态更新失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
Future<void> updateRemark(int id, String remark) async {
|
||
try {
|
||
await _client.put('/inventory/$id/remark', data: {'remark': remark});
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '更新备注失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
Future<PageResult<InventoryLog>> listLogs({
|
||
int? warehouseId,
|
||
int? productId,
|
||
int page = 1,
|
||
int pageSize = 50,
|
||
}) async {
|
||
try {
|
||
final params = <String, dynamic>{
|
||
'page': page,
|
||
'page_size': pageSize,
|
||
if (warehouseId != null) 'warehouse_id': warehouseId,
|
||
if (productId != null) 'product_id': productId,
|
||
};
|
||
final resp = await _client.get('/inventory/logs', params: params);
|
||
return PageResult.fromJson(
|
||
resp.data as Map<String, dynamic>,
|
||
InventoryLog.fromJson,
|
||
);
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '获取流水失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
}
|