import 'dart:convert'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../app.dart'; import '../../core/data/api_cache.dart'; import '../../core/navigation/host_app_channel.dart'; import '../../core/network/api_client.dart'; import '../../shared/models/pagination_model.dart'; import '../expense_apply/expense_apply_api.dart'; import 'overtime_apply_model.dart'; final overtimeApplyApiProvider = Provider( (ref) => OvertimeApplyApi(ref.read(apiClientProvider)), ); class OvertimeApplyApi { final ApiClient _client; final _cache = ApiCache( keyPrefix: '${HostAppChannel.sn}_${HostAppChannel.compNo}_${HostAppChannel.usr}', ); OvertimeApplyApi(this._client); /// 清除所有基础资料缓存(picker 下拉刷新时调用)。 void clearRefCache() => _cache.clear(); /// 加班申请列表(分页) Future> fetchList({ String status = '', String keyword = '', String startDate = '', String endDate = '', String usr = '', String sortDir = 'DESC', int page = 1, int size = 20, }) async { final response = await _client.get>( '/OA/GetOTApplyList', queryParameters: { 'status': status, 'keyword': keyword, 'startDate': startDate, 'endDate': endDate, 'usr': usr, 'sortDir': sortDir, 'page': page, 'size': size, }, ); return PaginatedData.fromJson(response.data!, OvertimeApplyModel.fromJson); } /// 加班申请详情(主表+明细) Future fetchDetail(String billNo) async { final response = await _client.get>( '/OA/GetOTApplyDetail', queryParameters: {'billNo': billNo}, ); return OvertimeApplyModel.fromJson(response.data!); } /// 部门 Future> getDepartments({ String keyword = '', bool onlyActive = true, int page = 1, int size = 100, }) async { final cacheKey = 'getDepartments_${keyword}_${onlyActive}_$page'; return _cache.getOrFetch(cacheKey, () async { final response = await _client.get>( '/OA/GetDepartments', queryParameters: { 'keyword': keyword, 'onlyActive': onlyActive, 'page': page, 'size': size, }, ); final list = (response.data?['list'] as List?) ?? []; return list .map((e) => DepartmentItem.fromJson(e as Map)) .toList(); }); } /// 员工查询 Future> getEmployees({ String keyword = '', String salNo = '', int page = 1, int size = 100, }) async { final cacheKey = 'getEmployees_${keyword}_${salNo}_$page'; return _cache.getOrFetch(cacheKey, () async { final response = await _client.get>( '/OA/GetEmployees', queryParameters: { 'keyword': keyword, 'salNo': salNo, 'page': page, 'size': size, }, ); final list = (response.data?['list'] as List?) ?? []; return list .map((e) => EmployeeItem.fromJson(e as Map)) .toList(); }); } /// 提交审批,返回申请单号(提取失败时返回 null) Future submit(Map data) async { final response = await _client.post>( '/OA/BillSave', data: { 'erpCategory': 'MasterService', 'billId': 'JB', 'procId': '', 'data': data, }, ); final resData = response.data; if (resData == null) return null; // 从 resultData 中取 final resultData = resData['resultData']; if (resultData is Map) { final bilNo = resultData['BIL_NO'] as String?; if (bilNo != null && bilNo.isNotEmpty) return bilNo; } if (resultData is String && resultData.isNotEmpty) { try { final parsed = json.decode(resultData) as Map; final bilNo = parsed['BIL_NO'] as String?; if (bilNo != null && bilNo.isNotEmpty) return bilNo; } catch (_) {} } // 兜底 final rootBilNo = resData['BIL_NO'] as String?; if (rootBilNo != null && rootBilNo.isNotEmpty) return rootBilNo; return null; } /// 获取单据状态 Future> getBillStatus(String billNo) async { final response = await _client.get>( '/OA/GetBillStatus', queryParameters: {'billId': 'JB', 'billNo': billNo}, ); return response.data!; } }