import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_new_badger/flutter_new_badger.dart'; import 'package:qhd_prevention/http/ApiService.dart'; import 'package:flutter/material.dart'; /// 优化版 BadgeManager:每个接口超时保护、增量更新、notify 合并、原生角标 debounce class BadgeManager extends ChangeNotifier { BadgeManager._internal(); static final BadgeManager _instance = BadgeManager._internal(); factory BadgeManager() => _instance; // 各模块未读 int _appCount = 0; int _appDysCount = 0; int _appDzgCount = 0; int _notifCount = 0; int _envInspectCount = 0; int _eightWorkCount = 0; // 读取接口值的公开 getter int get count => _appCount + _notifCount + _envInspectCount + _eightWorkCount; int get appCount => _appCount; int get appDysCount => _appDysCount; int get appDzgCount => _appDzgCount; int get notifCount => _notifCount; int get envInspectCount => _envInspectCount; int get eightWorkCount => _eightWorkCount; // 通知合并控制(短时间内多次更新只触发一次 notify) Timer? _notifyTimer; Duration _notifyDelay = const Duration(milliseconds: 180); void _scheduleNotify() { // 如果已有计划,不需要再立即计划(合并) _notifyTimer?.cancel(); _notifyTimer = Timer(_notifyDelay, () { try { notifyListeners(); } catch (e) { debugPrint('BadgeManager.notifyListeners error: $e'); } _notifyTimer = null; }); } // 原生角标同步 debounce(防止短时间内频繁调用) Timer? _syncTimer; Duration _syncDelay = const Duration(milliseconds: 250); void _syncNativeDebounced() { _syncTimer?.cancel(); _syncTimer = Timer(_syncDelay, () { try { final total = count; if (total > 0) { FlutterNewBadger.setBadge(total); } else { FlutterNewBadger.removeBadge(); } } catch (e) { debugPrint('BadgeManager._syncNativeDebounced error: $e'); } _syncTimer = null; }); } // safe wrapper: 给单个 future 加超时与兜底返回 Future _safe(Future future, T fallback, {Duration timeout = const Duration(seconds: 5)}) async { try { return await future.timeout(timeout); } catch (e, st) { // 报错不抛出到外层,记录并返回 fallback debugPrint('BadgeManager._safe error: $e\n$st'); return fallback; } } /// 初始化所有模块(并行发起,但每个接口独立 timeout & 提交结果) Future initAllModules() async { // 不 await 整个 Future.wait,使调用方不会因为单个慢接口阻塞 try { // 每个请求都通过 _safe 包裹,设置超时与兜底 final fWork = _safe>( ApiService.getWork().then((r) => r as Map), {}, timeout: const Duration(seconds: 6), ); final fNotif = _safe>( ApiService.getNotifRedPoint().then((r) => r as Map), {}, timeout: const Duration(seconds: 4), ); final fCheck = _safe>( ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map), {}, timeout: const Duration(seconds: 5), ); final fRed = _safe>( ApiService.getRedPoint().then((r) => r as Map), {}, timeout: const Duration(seconds: 5), ); // 按接口独立处理:完成即更新并合并通知(progressive update) fWork.then((workJson) { try { final hid = (workJson['hidCount'] as Map?) ?? {}; _appDysCount = (hid['dys'] ?? 0) as int? ?? 0; _appDzgCount = (hid['dzg'] ?? 0) as int? ?? 0; _appCount = _appDysCount + _appDzgCount; } catch (e, st) { debugPrint('BadgeManager.parse workJson error: $e\n$st'); } _scheduleNotify(); _syncNativeDebounced(); }); fNotif.then((notifJson) { try { _notifCount = (notifJson['count'] as int?) ?? 0; } catch (e, st) { debugPrint('BadgeManager.parse notifJson error: $e\n$st'); } _scheduleNotify(); _syncNativeDebounced(); }); fCheck.then((checkJson) { try { // 兼容不同返回结构,防止空指针 int checkedCount = 0, repulseAndCheckCount = 0, confirmCount = 0, repulseCount = 0; if (checkJson['checkedCount'] is Map) checkedCount = (checkJson['checkedCount']['checkedCount'] ?? 0) as int? ?? 0; if (checkJson['repulseAndCheckCount'] is Map) repulseAndCheckCount = (checkJson['repulseAndCheckCount']['repulseAndCheckCount'] ?? 0) as int? ?? 0; if (checkJson['confirmCount'] is Map) confirmCount = (checkJson['confirmCount']['confirmCount'] ?? 0) as int? ?? 0; if (checkJson['repulseCount'] is Map) repulseCount = (checkJson['repulseCount']['repulseCount'] ?? 0) as int? ?? 0; _envInspectCount = checkedCount + repulseAndCheckCount + confirmCount + repulseCount; } catch (e, st) { debugPrint('BadgeManager.parse checkJson error: $e\n$st'); } _scheduleNotify(); _syncNativeDebounced(); }); fRed.then((redPointJson) { try { _eightWorkCount = 0; final m = (redPointJson['count'] as Map?) ?? {}; for (final v in m.values) { _eightWorkCount += (v ?? 0) as int? ?? 0; } } catch (e, st) { debugPrint('BadgeManager.parse redPointJson error: $e\n$st'); } _scheduleNotify(); _syncNativeDebounced(); }); // 可选:等待所有结束(不阻塞调用方),用于 debug 或需要最终一致性的场景 unawaited(Future.wait([fWork, fNotif, fCheck, fRed]).then((_) { debugPrint('BadgeManager.initAllModules: all done at ${DateTime.now()}'); })); } catch (e, st) { debugPrint('BadgeManager.initAllModules unexpected error: $e\n$st'); } } // 下面的 updateX 方法也做了超时保护并使用 _onModuleChanged 合并通知 void updateAppCount() async { try { final workJson = await _safe>( ApiService.getWork().then((r) => r as Map), {}, timeout: const Duration(seconds: 5), ); final hid = (workJson['hidCount'] as Map?) ?? {}; _appDysCount = (hid['dys'] ?? 0) as int? ?? 0; _appDzgCount = (hid['dzg'] ?? 0) as int? ?? 0; _appCount = _appDysCount + _appDzgCount; _onModuleChanged(); } catch (e) { debugPrint('updateAppCount error: $e'); } } void updateNotifCount() async { try { final notifJson = await _safe>( ApiService.getNotifRedPoint().then((r) => r as Map), {}, timeout: const Duration(seconds: 4), ); _notifCount = (notifJson['count'] as int?) ?? 0; _onModuleChanged(); } catch (e) { debugPrint('updateNotifCount error: $e'); } } void updateEnvInspectCount() async { try { final checkJson = await _safe>( ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map), {}, timeout: const Duration(seconds: 5), ); int checkedCount = 0, repulseAndCheckCount = 0, confirmCount = 0, repulseCount = 0; if (checkJson['checkedCount'] is Map) checkedCount = (checkJson['checkedCount']['checkedCount'] ?? 0) as int? ?? 0; if (checkJson['repulseAndCheckCount'] is Map) repulseAndCheckCount = (checkJson['repulseAndCheckCount']['repulseAndCheckCount'] ?? 0) as int? ?? 0; if (checkJson['confirmCount'] is Map) confirmCount = (checkJson['confirmCount']['confirmCount'] ?? 0) as int? ?? 0; if (checkJson['repulseCount'] is Map) repulseCount = (checkJson['repulseCount']['repulseCount'] ?? 0) as int? ?? 0; _envInspectCount = checkedCount + repulseAndCheckCount + confirmCount + repulseCount; _onModuleChanged(); } catch (e) { debugPrint('updateEnvInspectCount error: $e'); } } void updateEightWorkCount() async { try { final redPointJson = await _safe>( ApiService.getRedPoint().then((r) => r as Map), {}, timeout: const Duration(seconds: 5), ); int sum = 0; final m = (redPointJson['count'] as Map?) ?? {}; for (final v in m.values) sum += (v ?? 0) as int? ?? 0; _eightWorkCount = sum; _onModuleChanged(); } catch (e) { debugPrint('updateEightWorkCount error: $e'); } } void clearAll() { _appCount = _notifCount = _envInspectCount = _eightWorkCount = 0; _appDysCount = _appDzgCount = 0; _syncNativeDebounced(); _scheduleNotify(); } void _onModuleChanged() { _syncNativeDebounced(); _scheduleNotify(); } }