feat:设备日志模块
feat:定时任务 feat:设置页面用路由重构
This commit is contained in:
1 parent
1033f403b1
commit
2efa7a3c19
60 files changed
+6560
-643
No files matched your search
@@ -0,0 +1,117 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:pj_supermarket_cloud/common/services/face_recognition_session_service.dart';
|
||||
|
||||
/// 同步调度与顶栏共用的空闲状态快照,避免界面自行拼装支付、弹窗和重型任务规则。
|
||||
class SyncIdleSnapshot {
|
||||
/// 创建一次不可变的终端空闲判断快照。
|
||||
const SyncIdleSnapshot({
|
||||
required this.foreground,
|
||||
required this.safeWindow,
|
||||
required this.idle,
|
||||
required this.inactiveFor,
|
||||
required this.reason,
|
||||
});
|
||||
|
||||
/// 应用当前是否处于 resumed 前台状态。
|
||||
final bool foreground;
|
||||
|
||||
/// 当前是否避开了支付遮罩、人脸会话、业务弹窗和其他重型任务。
|
||||
final bool safeWindow;
|
||||
|
||||
/// 当前是否同时满足安全窗口和连续 60 秒无人操作。
|
||||
final bool idle;
|
||||
|
||||
/// 距离最近一次指针操作或应用恢复前台经过的时长。
|
||||
final Duration inactiveFor;
|
||||
|
||||
/// 当前未达到空闲状态的首要中文原因;空闲时为空字符串。
|
||||
final String reason;
|
||||
|
||||
/// 返回顶栏使用的简短空闲状态文案。
|
||||
String get label => idle ? '空闲' : '忙碌';
|
||||
}
|
||||
|
||||
/// 统一记录终端用户活动和重型后台任务,用于选择不会干扰支付、人脸和弹框的安全执行窗口。
|
||||
class SyncIdleTool {
|
||||
/// 隐藏构造器,空闲判断必须通过全局单例维护同一份活动时间和任务计数。
|
||||
SyncIdleTool._();
|
||||
|
||||
/// 应用级空闲检测单例。
|
||||
static final SyncIdleTool instance = SyncIdleTool._();
|
||||
|
||||
/// 自动空闲任务要求的最短连续无人操作时间。
|
||||
static const Duration idleDuration = Duration(seconds: 60);
|
||||
|
||||
/// 最近一次用户指针操作或恢复前台的本地时间。
|
||||
DateTime _lastActivityAt = DateTime.now();
|
||||
|
||||
/// 应用是否处于可安全执行终端任务的前台生命周期。
|
||||
bool _foreground = true;
|
||||
|
||||
/// 当前并行执行的重型同步任务数量,用计数支持嵌套开始和结束。
|
||||
int _heavyTaskCount = 0;
|
||||
|
||||
/// 记录一次终端触控活动并重新开始 60 秒空闲计时。
|
||||
void recordUserActivity() {
|
||||
_lastActivityAt = DateTime.now();
|
||||
}
|
||||
|
||||
/// 根据应用生命周期更新前台状态,恢复前台时视为一次用户活动。
|
||||
void updateLifecycle(AppLifecycleState state) {
|
||||
_foreground = state == AppLifecycleState.resumed;
|
||||
if (_foreground) recordUserActivity();
|
||||
}
|
||||
|
||||
/// 标记一个重型任务开始,阻止其他需要安全窗口的任务并发执行。
|
||||
void beginHeavyTask() => _heavyTaskCount++;
|
||||
|
||||
/// 标记一个重型任务结束;计数最低保持为零以容忍重复清理。
|
||||
void endHeavyTask() {
|
||||
if (_heavyTaskCount > 0) _heavyTaskCount--;
|
||||
}
|
||||
|
||||
/// 手动任务和后台拉取只等待业务安全窗口,不额外要求 60 秒无人操作。
|
||||
SyncIdleSnapshot get snapshot {
|
||||
final faceActive = Get.isRegistered<FaceRecognitionSessionService>() &&
|
||||
Get.find<FaceRecognitionSessionService>().isActive;
|
||||
final route = Get.context == null ? null : ModalRoute.of(Get.context!);
|
||||
final dialogOpen = Get.isDialogOpen == true ||
|
||||
Get.isBottomSheetOpen == true ||
|
||||
route?.isCurrent == false;
|
||||
final inactiveFor = DateTime.now().difference(_lastActivityAt);
|
||||
final reason = !_foreground
|
||||
? '应用不在前台'
|
||||
: EasyLoading.isShow
|
||||
? '前台操作进行中'
|
||||
: faceActive
|
||||
? '人脸识别进行中'
|
||||
: dialogOpen
|
||||
? '业务弹窗处理中'
|
||||
: _heavyTaskCount > 0
|
||||
? '后台同步进行中'
|
||||
: inactiveFor < idleDuration
|
||||
? '最近有终端操作'
|
||||
: '';
|
||||
final safeWindow = _foreground &&
|
||||
!EasyLoading.isShow &&
|
||||
!faceActive &&
|
||||
!dialogOpen &&
|
||||
_heavyTaskCount == 0;
|
||||
return SyncIdleSnapshot(
|
||||
foreground: _foreground,
|
||||
safeWindow: safeWindow,
|
||||
idle: safeWindow && inactiveFor >= idleDuration,
|
||||
inactiveFor: inactiveFor,
|
||||
reason: reason,
|
||||
);
|
||||
}
|
||||
|
||||
/// 当前是否满足手动执行和 MQTT 拉取所需的业务安全窗口。
|
||||
bool get isSafeWindow => snapshot.safeWindow;
|
||||
|
||||
/// 当前是否满足自动空闲任务的完整空闲条件。
|
||||
bool get isIdle => snapshot.idle;
|
||||
}
|
||||
Reference in new issue
Block a user