Files
biz_xfj_cloud/lib/pages/terminal/setting/face_setting_controller.dart
T
2026-07-24 20:41:17 +08:00

282 lines
10 KiB
Dart

import 'dart:async';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:pj_supermarket_cloud/common/index.dart';
import 'package:pj_supermarket_cloud/pages/terminal/setting/controller.dart';
/// 管理人脸插件状态、激活和内存库重建,避免硬件状态继续堆叠到设置主 Controller。
class FaceSettingController extends GetxController {
static const String _tag = '人脸设置 Controller';
final status = Rxn<FacePluginStatus>();
final progress = Rxn<FaceRegistrationProgress>();
final lastResult = Rxn<FaceRegistrationResult>();
final isLoading = false.obs;
final isActivating = false.obs;
final isRegistering = false.obs;
final isSyncingConfig = false.obs;
final errorMessage = ''.obs;
final permissionCanOpenSettings = false.obs;
final showFullParameters = false.obs;
final recognitionConfiguration = Rxn<FaceRecognitionConfiguration>();
final savedRecognitionConfiguration = Rxn<FaceRecognitionConfiguration>();
final isLoadingRecognitionConfiguration = false.obs;
final isSavingRecognitionConfiguration = false.obs;
final showAdvancedRecognitionConfiguration = false.obs;
StreamSubscription<FaceRegistrationProgress>? _progressSubscription;
@override
void onInit() {
super.onInit();
_progressSubscription = FaceDiscernPlugs.registrationStream.listen(
_handleProgress,
onError: (Object error, StackTrace stack) {
logger.w('|$_tag|进度监听失败error:|$error|stack:|$stack|');
},
);
refreshStatus();
refreshRecognitionConfiguration();
}
@override
void onClose() {
_progressSubscription?.cancel();
super.onClose();
}
Future<void> refreshStatus({bool showLoading = true}) async {
if (showLoading) isLoading.value = true;
errorMessage.value = '';
try {
final value = await AppFaceTool.getStatus();
if (value == null) {
errorMessage.value = '无法读取人脸插件状态,请稍后重试';
return;
}
status.value = value;
progress.value = value.registrationProgress;
lastResult.value = value.lastRegistrationResult;
isRegistering.value = value.registrationInProgress;
} catch (e, stack) {
errorMessage.value = '无法读取人脸插件状态,请稍后重试';
logger.e('|$_tag|刷新状态失败error:|$e|stack:|$stack|');
} finally {
if (showLoading) isLoading.value = false;
}
}
Future<void> refreshRecognitionConfiguration() async {
if (isLoadingRecognitionConfiguration.value) return;
isLoadingRecognitionConfiguration.value = true;
try {
final value = await FaceDiscernPlugs.getRecognizeConfiguration();
savedRecognitionConfiguration.value = value;
recognitionConfiguration.value = value;
} on PlatformException catch (e, stack) {
logger.e('|$_tag|读取识别策略失败error:|$e|stack:|$stack|');
Toast.error(msg: e.message ?? '读取人脸识别策略失败');
} catch (e, stack) {
logger.e('|$_tag|读取识别策略失败error:|$e|stack:|$stack|');
Toast.error(msg: '读取人脸识别策略失败');
} finally {
isLoadingRecognitionConfiguration.value = false;
}
}
void updateRecognitionConfiguration(
FaceRecognitionConfiguration Function(FaceRecognitionConfiguration value)
update,
) {
final current = recognitionConfiguration.value;
if (current == null || isSavingRecognitionConfiguration.value) return;
recognitionConfiguration.value = update(current);
}
Future<void> saveRecognitionConfiguration() async {
final current = recognitionConfiguration.value;
if (current == null || isSavingRecognitionConfiguration.value) return;
isSavingRecognitionConfiguration.value = true;
try {
final saved = await FaceDiscernPlugs.setRecognizeConfiguration(current);
savedRecognitionConfiguration.value = saved;
recognitionConfiguration.value = saved;
final active = Get.isRegistered<FaceRecognitionSessionService>() &&
Get.find<FaceRecognitionSessionService>().isActive;
Toast.success(
msg: active ? '配置已保存,将在当前识别结束后生效' : '人脸识别配置已保存',
);
} on PlatformException catch (e, stack) {
logger.e('|$_tag|保存识别策略失败error:|$e|stack:|$stack|');
Toast.error(msg: e.message ?? '保存人脸识别配置失败');
} catch (e, stack) {
logger.e('|$_tag|保存识别策略失败error:|$e|stack:|$stack|');
Toast.error(msg: '保存人脸识别配置失败');
} finally {
isSavingRecognitionConfiguration.value = false;
}
}
Future<void> resetRecognitionConfiguration() async {
if (isSavingRecognitionConfiguration.value) return;
final confirmed = await appMessageDialog(
Get.context!,
'是否恢复默认人脸识别策略?活体检测将恢复为关闭,相似度阈值恢复为 80%。',
);
if (!confirmed) return;
isSavingRecognitionConfiguration.value = true;
try {
final restored = await FaceDiscernPlugs.resetRecognizeConfiguration();
savedRecognitionConfiguration.value = restored;
recognitionConfiguration.value = restored;
final active = Get.isRegistered<FaceRecognitionSessionService>() &&
Get.find<FaceRecognitionSessionService>().isActive;
Toast.success(
msg: active ? '已恢复默认配置,将在当前识别结束后生效' : '已恢复默认人脸识别配置',
);
} on PlatformException catch (e, stack) {
logger.e('|$_tag|恢复识别策略失败error:|$e|stack:|$stack|');
Toast.error(msg: e.message ?? '恢复默认配置失败');
} catch (e, stack) {
logger.e('|$_tag|恢复识别策略失败error:|$e|stack:|$stack|');
Toast.error(msg: '恢复默认配置失败');
} finally {
isSavingRecognitionConfiguration.value = false;
}
}
void discardRecognitionConfigurationChanges() {
recognitionConfiguration.value = savedRecognitionConfiguration.value;
}
void toggleAdvancedRecognitionConfiguration() {
showAdvancedRecognitionConfiguration.toggle();
}
bool get recognitionConfigurationChanged =>
recognitionConfiguration.value != savedRecognitionConfiguration.value;
Future<void> syncConfig() async {
if (isBusy) return;
if (!AppNetworkTool.isAutoNetworkMsg()) return;
isSyncingConfig.value = true;
errorMessage.value = '';
try {
final setting = await SyncConfigTool.autoSyncSysInfo();
if (setting == null) {
throw Exception('设备配置同步无返回');
}
await Get.find<SettingController>().getSetting();
await refreshStatus(showLoading: false);
Toast.success(msg: '设备配置同步完成');
} catch (e, stack) {
errorMessage.value = '设备配置同步失败,请检查网络和设备绑定状态';
logger.e('|$_tag|同步设备配置失败error:|$e|stack:|$stack|');
Toast.error(msg: errorMessage.value);
} finally {
isSyncingConfig.value = false;
}
}
Future<void> activate() async {
if (isBusy) return;
isActivating.value = true;
errorMessage.value = '';
permissionCanOpenSettings.value = false;
try {
final result = await AppFaceTool.activateSdk();
permissionCanOpenSettings.value = result.canOpenSettings;
if (!result.success) {
errorMessage.value = result.message;
Toast.error(msg: result.message);
return;
}
Toast.success(msg: result.message);
await refreshStatus(showLoading: false);
} catch (e, stack) {
errorMessage.value = '人脸插件激活失败,请稍后重试';
logger.e('|$_tag|激活失败error:|$e|stack:|$stack|');
Toast.error(msg: errorMessage.value);
} finally {
isActivating.value = false;
}
}
Future<void> rebuildLibrary() async {
if (isBusy) return;
final currentStatus = status.value;
if (currentStatus == null || !currentStatus.activated) {
Toast.error(msg: '请先激活人脸插件');
return;
}
if (currentStatus.databaseCount == 0) {
goFaceManage();
return;
}
final confirmed = await appMessageDialog(
Get.context!,
'是否重新注册全部人脸?注册期间可离开此页面,支付暂不能使用人脸识别。',
);
if (!confirmed) return;
isRegistering.value = true;
errorMessage.value = '';
try {
final result = await FaceDiscernPlugs.rebuildFaceLibrary();
lastResult.value = result;
if (result.failedCount > 0) {
errorMessage.value = result.message;
Toast.error(msg: result.message);
} else {
Toast.success(msg: result.message);
}
} on PlatformException catch (e, stack) {
errorMessage.value = e.code == 'REGISTRATION_IN_PROGRESS'
? '人脸库正在注册,请稍候'
: (e.message ?? '人脸库注册失败,请稍后重试');
logger.e('|$_tag|重建人脸库失败error:|$e|stack:|$stack|');
Toast.error(msg: errorMessage.value);
} catch (e, stack) {
errorMessage.value = '人脸库注册失败,请稍后重试';
logger.e('|$_tag|重建人脸库失败error:|$e|stack:|$stack|');
Toast.error(msg: errorMessage.value);
} finally {
isRegistering.value = false;
await refreshStatus(showLoading: false);
}
}
Future<void> openPermissionSettings() async {
await openAppSettings();
}
void goFaceManage() {
Get.find<SettingController>().doMenu(SettingMenuType.faceSetting);
}
void toggleParameterVisibility() {
showFullParameters.toggle();
}
SysSetting? get sysSetting => Get.find<SettingController>().sysSetting.value;
bool get isBusy =>
isLoading.value ||
isActivating.value ||
isRegistering.value ||
isSyncingConfig.value ||
isSavingRecognitionConfiguration.value;
void _handleProgress(FaceRegistrationProgress value) {
progress.value = value;
isRegistering.value = value.inProgress;
if (!value.inProgress && value.phase != 'idle') {
refreshStatus(showLoading: false);
}
}
}