feat:添加识别策略
This commit is contained in:
1 parent
0d0924c314
commit
1c348fc18e
20 files changed
+1500
-74
No files matched your search
@@ -2,6 +2,8 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../models/face_recognition_display_models.dart';
|
||||
import '../models/reservation_query_display_models.dart';
|
||||
import 'customer_display_coordinator.dart';
|
||||
import 'face_recognition_coordinator.dart';
|
||||
import 'reservation_query_coordinator.dart';
|
||||
@@ -27,6 +29,7 @@ class SubDisplayCoordinator extends ChangeNotifier {
|
||||
|
||||
static const _reservationUpdate = 'reservationQueryUpdate';
|
||||
static const _reservationClear = 'reservationQueryClear';
|
||||
static const _faceStart = 'faceRecognitionStart';
|
||||
static const _settlementActions = {
|
||||
'updateCard',
|
||||
'jumpSubPage',
|
||||
@@ -43,6 +46,10 @@ class SubDisplayCoordinator extends ChangeNotifier {
|
||||
SubDisplayMode _mode = SubDisplayMode.settlement;
|
||||
SubDisplayMode _modeBeforeFace = SubDisplayMode.settlement;
|
||||
Timer? _faceRestoreTimer;
|
||||
String? _reservationSessionAtFaceStart;
|
||||
int _reservationRevisionAtFaceStart = -1;
|
||||
bool _reservationSuccessDelayPassed = false;
|
||||
bool _reservationResultReady = false;
|
||||
bool _disposed = false;
|
||||
|
||||
SubDisplayMode get mode => _mode;
|
||||
@@ -52,21 +59,42 @@ class SubDisplayCoordinator extends ChangeNotifier {
|
||||
if (action.startsWith('faceRecognition')) {
|
||||
final result = faceRecognitionCoordinator.handleAction(action, arguments);
|
||||
if (!result.accepted) return false;
|
||||
final faceState = faceRecognitionCoordinator.state;
|
||||
switch (result.transition) {
|
||||
case FaceRecognitionDisplayTransition.show:
|
||||
_faceRestoreTimer?.cancel();
|
||||
if (action == _faceStart) {
|
||||
_resetReservationFaceHandoff();
|
||||
if (faceState?.scene == FaceRecognitionDisplayScene.reservation) {
|
||||
_beginReservationFaceHandoff();
|
||||
}
|
||||
}
|
||||
if (_mode != SubDisplayMode.faceRecognition) _modeBeforeFace = _mode;
|
||||
_replaceMode(SubDisplayMode.faceRecognition);
|
||||
break;
|
||||
case FaceRecognitionDisplayTransition.restoreNow:
|
||||
_faceRestoreTimer?.cancel();
|
||||
_resetReservationFaceHandoff();
|
||||
_replaceMode(_modeBeforeFace);
|
||||
break;
|
||||
case FaceRecognitionDisplayTransition.restoreAfterSuccess:
|
||||
_faceRestoreTimer?.cancel();
|
||||
_faceRestoreTimer = Timer(const Duration(milliseconds: 700), () {
|
||||
if (!_disposed) _replaceMode(_modeBeforeFace);
|
||||
});
|
||||
if (faceState?.scene == FaceRecognitionDisplayScene.reservation) {
|
||||
// 预约查询必须在人脸成功提示展示满 700ms 且查询拿到最终结果后再恢复,
|
||||
// 否则慢网络会先露出中间 loading,顾客看不到“人脸 -> 本人菜单”的完整顺序。
|
||||
_reservationSuccessDelayPassed = false;
|
||||
_reservationResultReady = _hasNewReservationTerminalState();
|
||||
_faceRestoreTimer = Timer(const Duration(milliseconds: 700), () {
|
||||
if (_disposed) return;
|
||||
_reservationSuccessDelayPassed = true;
|
||||
_restoreReservationAfterFaceIfReady();
|
||||
});
|
||||
} else {
|
||||
_resetReservationFaceHandoff();
|
||||
_faceRestoreTimer = Timer(const Duration(milliseconds: 700), () {
|
||||
if (!_disposed) _replaceMode(_modeBeforeFace);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case FaceRecognitionDisplayTransition.none:
|
||||
break;
|
||||
@@ -75,12 +103,18 @@ class SubDisplayCoordinator extends ChangeNotifier {
|
||||
}
|
||||
if (action == _reservationUpdate) {
|
||||
final accepted = reservationCoordinator.handleUpdate(arguments);
|
||||
if (accepted) _showOrRememberMode(SubDisplayMode.reservationQuery);
|
||||
if (accepted) {
|
||||
_showOrRememberMode(SubDisplayMode.reservationQuery);
|
||||
_handleReservationUpdateDuringFace();
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
if (action == _reservationClear) {
|
||||
final accepted = reservationCoordinator.handleClear(arguments);
|
||||
if (accepted) _showOrRememberMode(SubDisplayMode.reservationQuery);
|
||||
if (accepted) {
|
||||
_showOrRememberMode(SubDisplayMode.reservationQuery);
|
||||
_handleReservationClearDuringFace();
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
if (_settlementActions.contains(action)) {
|
||||
@@ -98,6 +132,73 @@ class SubDisplayCoordinator extends ChangeNotifier {
|
||||
return true;
|
||||
}
|
||||
|
||||
void _beginReservationFaceHandoff() {
|
||||
final reservationState = reservationCoordinator.state;
|
||||
_reservationSessionAtFaceStart = reservationState.sessionId;
|
||||
_reservationRevisionAtFaceStart = reservationState.revision;
|
||||
_reservationSuccessDelayPassed = false;
|
||||
_reservationResultReady = false;
|
||||
}
|
||||
|
||||
void _handleReservationUpdateDuringFace() {
|
||||
if (_mode != SubDisplayMode.faceRecognition) return;
|
||||
final faceState = faceRecognitionCoordinator.state;
|
||||
if (faceState?.scene != FaceRecognitionDisplayScene.reservation) return;
|
||||
if (faceState?.status != FaceRecognitionDisplayStatus.success &&
|
||||
faceState?.status != FaceRecognitionDisplayStatus.failed) {
|
||||
return;
|
||||
}
|
||||
if (!_hasNewReservationTerminalState()) return;
|
||||
_reservationResultReady = true;
|
||||
if (faceState?.status == FaceRecognitionDisplayStatus.failed) {
|
||||
// 可重试的人脸失败不会产生预约结果;只有业务已收口为 error 时才离开人脸页。
|
||||
_faceRestoreTimer?.cancel();
|
||||
_restoreReservationAfterFace();
|
||||
return;
|
||||
}
|
||||
_restoreReservationAfterFaceIfReady();
|
||||
}
|
||||
|
||||
void _handleReservationClearDuringFace() {
|
||||
if (_mode != SubDisplayMode.faceRecognition) return;
|
||||
final faceState = faceRecognitionCoordinator.state;
|
||||
if (faceState?.scene != FaceRecognitionDisplayScene.reservation) return;
|
||||
if (faceState?.status != FaceRecognitionDisplayStatus.success &&
|
||||
faceState?.status != FaceRecognitionDisplayStatus.failed) {
|
||||
return;
|
||||
}
|
||||
// 页面退出或隐私清屏不再等待查询结果,避免副屏停留在已结束的人脸成功页。
|
||||
_restoreReservationAfterFace();
|
||||
}
|
||||
|
||||
bool _hasNewReservationTerminalState() {
|
||||
final state = reservationCoordinator.state;
|
||||
final isNewer = state.sessionId != _reservationSessionAtFaceStart ||
|
||||
state.revision > _reservationRevisionAtFaceStart;
|
||||
if (!isNewer) return false;
|
||||
return state.scenario == ReservationQueryDisplayScenario.success ||
|
||||
state.scenario == ReservationQueryDisplayScenario.empty ||
|
||||
state.scenario == ReservationQueryDisplayScenario.error;
|
||||
}
|
||||
|
||||
void _restoreReservationAfterFaceIfReady() {
|
||||
if (!_reservationSuccessDelayPassed || !_reservationResultReady) return;
|
||||
_restoreReservationAfterFace();
|
||||
}
|
||||
|
||||
void _restoreReservationAfterFace() {
|
||||
_faceRestoreTimer?.cancel();
|
||||
_replaceMode(SubDisplayMode.reservationQuery);
|
||||
_resetReservationFaceHandoff();
|
||||
}
|
||||
|
||||
void _resetReservationFaceHandoff() {
|
||||
_reservationSessionAtFaceStart = null;
|
||||
_reservationRevisionAtFaceStart = -1;
|
||||
_reservationSuccessDelayPassed = false;
|
||||
_reservationResultReady = false;
|
||||
}
|
||||
|
||||
/// 人脸页显示期间,普通业务消息仍更新各自 Coordinator,但只修改待恢复页面。
|
||||
/// 这样 success 的 700ms 提示和 failed 的重试引导不会被金额或查询消息提前顶掉。
|
||||
bool _showOrRememberMode(SubDisplayMode next) {
|
||||
@@ -118,6 +219,7 @@ class SubDisplayCoordinator extends ChangeNotifier {
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
_faceRestoreTimer?.cancel();
|
||||
_resetReservationFaceHandoff();
|
||||
customerCoordinator.removeListener(_notifyFromChild);
|
||||
reservationCoordinator.removeListener(_notifyFromChild);
|
||||
faceRecognitionCoordinator.removeListener(_notifyFromChild);
|
||||
|
||||
Reference in new issue
Block a user