flutter_integrated_whb/lib/pages/badge_manager.dart

246 lines
9.1 KiB
Dart
Raw Normal View History

2025-09-10 13:48:03 +08:00
import 'dart:async';
import 'package:flutter/foundation.dart';
2025-08-07 17:33:16 +08:00
import 'package:flutter_new_badger/flutter_new_badger.dart';
import 'package:qhd_prevention/http/ApiService.dart';
2025-09-10 13:48:03 +08:00
import 'package:flutter/material.dart';
2025-08-07 17:33:16 +08:00
2025-09-10 13:48:03 +08:00
/// 优化版 BadgeManager每个接口超时保护、增量更新、notify 合并、原生角标 debounce
2025-08-07 17:33:16 +08:00
class BadgeManager extends ChangeNotifier {
BadgeManager._internal();
static final BadgeManager _instance = BadgeManager._internal();
factory BadgeManager() => _instance;
// 各模块未读
int _appCount = 0;
2025-09-10 13:48:03 +08:00
int _appDysCount = 0;
int _appDzgCount = 0;
2025-08-07 17:33:16 +08:00
int _notifCount = 0;
int _envInspectCount = 0;
int _eightWorkCount = 0;
2025-09-10 13:48:03 +08:00
// 读取接口值的公开 getter
2025-08-07 17:33:16 +08:00
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;
2025-09-10 13:48:03 +08:00
// 通知合并控制(短时间内多次更新只触发一次 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<T> _safe<T>(Future<T> 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 & 提交结果)
2025-08-07 17:33:16 +08:00
Future<void> initAllModules() async {
2025-09-10 13:48:03 +08:00
// 不 await 整个 Future.wait使调用方不会因为单个慢接口阻塞
2025-08-07 17:33:16 +08:00
try {
2025-09-10 13:48:03 +08:00
// 每个请求都通过 _safe 包裹,设置超时与兜底
final fWork = _safe<Map<String, dynamic>>(
ApiService.getWork().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 6),
);
final fNotif = _safe<Map<String, dynamic>>(
ApiService.getNotifRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 4),
);
final fCheck = _safe<Map<String, dynamic>>(
ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
final fRed = _safe<Map<String, dynamic>>(
ApiService.getRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
// 按接口独立处理完成即更新并合并通知progressive update
fWork.then((workJson) {
try {
final hid = (workJson['hidCount'] as Map<String, dynamic>?) ?? {};
_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();
});
2025-08-07 17:33:16 +08:00
2025-09-10 13:48:03 +08:00
fNotif.then((notifJson) {
try {
_notifCount = (notifJson['count'] as int?) ?? 0;
} catch (e, st) {
debugPrint('BadgeManager.parse notifJson error: $e\n$st');
}
_scheduleNotify();
_syncNativeDebounced();
2025-08-07 17:33:16 +08:00
});
2025-09-10 13:48:03 +08:00
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<String, dynamic>?) ?? {};
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');
2025-08-07 17:33:16 +08:00
}
}
2025-09-10 13:48:03 +08:00
// 下面的 updateX 方法也做了超时保护并使用 _onModuleChanged 合并通知
2025-08-07 17:33:16 +08:00
void updateAppCount() async {
try {
2025-09-10 13:48:03 +08:00
final workJson = await _safe<Map<String, dynamic>>(
ApiService.getWork().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
final hid = (workJson['hidCount'] as Map<String, dynamic>?) ?? {};
_appDysCount = (hid['dys'] ?? 0) as int? ?? 0;
_appDzgCount = (hid['dzg'] ?? 0) as int? ?? 0;
2025-08-07 17:33:16 +08:00
_appCount = _appDysCount + _appDzgCount;
_onModuleChanged();
} catch (e) {
debugPrint('updateAppCount error: $e');
}
}
void updateNotifCount() async {
try {
2025-09-10 13:48:03 +08:00
final notifJson = await _safe<Map<String, dynamic>>(
ApiService.getNotifRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 4),
);
_notifCount = (notifJson['count'] as int?) ?? 0;
2025-08-07 17:33:16 +08:00
_onModuleChanged();
} catch (e) {
debugPrint('updateNotifCount error: $e');
}
}
void updateEnvInspectCount() async {
try {
2025-09-10 13:48:03 +08:00
final checkJson = await _safe<Map<String, dynamic>>(
ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
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;
2025-08-07 17:33:16 +08:00
_onModuleChanged();
} catch (e) {
debugPrint('updateEnvInspectCount error: $e');
}
}
void updateEightWorkCount() async {
try {
2025-09-10 13:48:03 +08:00
final redPointJson = await _safe<Map<String, dynamic>>(
ApiService.getRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
2025-08-07 17:33:16 +08:00
int sum = 0;
2025-09-10 13:48:03 +08:00
final m = (redPointJson['count'] as Map<String, dynamic>?) ?? {};
for (final v in m.values) sum += (v ?? 0) as int? ?? 0;
2025-08-07 17:33:16 +08:00
_eightWorkCount = sum;
_onModuleChanged();
} catch (e) {
debugPrint('updateEightWorkCount error: $e');
}
}
void clearAll() {
_appCount = _notifCount = _envInspectCount = _eightWorkCount = 0;
_appDysCount = _appDzgCount = 0;
2025-09-10 13:48:03 +08:00
_syncNativeDebounced();
_scheduleNotify();
2025-08-07 17:33:16 +08:00
}
void _onModuleChanged() {
2025-09-10 13:48:03 +08:00
_syncNativeDebounced();
_scheduleNotify();
2025-08-07 17:33:16 +08:00
}
}