From f2a49b995670de6b9d304f7f2a7ae8708f203864 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Thu, 12 Jun 2025 14:52:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=85=8D=E5=AF=B9):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E9=85=8D=E5=AF=B9=E6=A8=A1=E5=BC=8F=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增手动配对模式控制变量 isManualMode 和 isReadyToStart - 添加手动开始配对方法 startManualPairing 和重置方法 resetToManualMode - 分离初始化逻辑到 _executeInitFlow 方法 - 更新配对视图以支持手动模式UI展示 - 添加开始配对按钮和重置按钮 --- .../controllers/pairing_controller.dart | 58 ++++++-- lib/modules/pairing/views/pairing_view.dart | 132 ++++++++++++++++-- 2 files changed, 165 insertions(+), 25 deletions(-) diff --git a/lib/modules/pairing/controllers/pairing_controller.dart b/lib/modules/pairing/controllers/pairing_controller.dart index 2c7debbe5..35a858a4f 100644 --- a/lib/modules/pairing/controllers/pairing_controller.dart +++ b/lib/modules/pairing/controllers/pairing_controller.dart @@ -36,6 +36,10 @@ class PairingController extends GetxController { final _state = PairingState.init.obs; PairingState get state => _state.value; + // ==================== 手动模式控制 ==================== + final isManualMode = true.obs; + final isReadyToStart = false.obs; + // ==================== 状态数据 ==================== final statusDescription = ''.obs; final actionButtonText = ''.obs; @@ -78,12 +82,32 @@ class PairingController extends GetxController { _transition(PairingState.init); } + /// 手动开始配对 + Future startManualPairing() async { + if (!isReadyToStart.value) return; + + Logger.i(_tag, '用户手动启动配对流程'); + isManualMode.value = false; + isReadyToStart.value = false; + + // 开始执行配对流程 + await _executeInitFlow(); + } + /// 重新开始配对流程 Future restart() async { _cancelAllOperations(); _transition(PairingState.init); } + /// 重置到手动模式 + void resetToManualMode() { + _cancelAllOperations(); + isManualMode.value = true; + isReadyToStart.value = true; + _transition(PairingState.init); + } + /// 处理按钮点击 void handleActionButtonTap() { switch (state) { @@ -174,10 +198,24 @@ class PairingController extends GetxController { // ==================== 状态处理方法 ==================== - /// INIT: 初始化,检查权限 + /// INIT: 初始化状态 Future _enterInit() async { - Logger.i(_tag, '开始执行初始化流程'); + Logger.i(_tag, '进入初始化状态'); + if (isManualMode.value) { + // 手动模式:仅显示待机状态,不执行任何操作 + isLoading.value = false; + statusDescription.value = '准备就绪'; + isReadyToStart.value = true; + return; + } + + // 自动模式:执行原有的初始化逻辑 + await _executeInitFlow(); + } + + /// 执行初始化流程 + Future _executeInitFlow() async { isLoading.value = true; statusDescription.value = '正在初始化...'; @@ -529,12 +567,6 @@ class PairingController extends GetxController { } // Android权限检查 - 使用 PermissionUtil - // final context = Get.context; - // if (context == null) { - // Logger.e(_tag, '无法获取有效上下文,跳过权限请求'); - // return false; - // } - // 根据 Android 版本确定需要的权限 List requiredPermissions = [ Permission.locationWhenInUse, @@ -551,7 +583,6 @@ class PairingController extends GetxController { Logger.d(_tag, '正在请求 $permissionName 权限'); final granted = await PermissionUtil.instance.requestPermission( - // context: context, permissionType: permission, permissionName: permissionName, explanationText: _getExplanationText(permission), @@ -646,7 +677,11 @@ class PairingController extends GetxController { // 根据状态更新UI文本 switch (state) { case PairingState.init: - statusDescription.value = '初始化中...'; + if (isManualMode.value && isReadyToStart.value) { + statusDescription.value = '准备就绪'; + } else { + statusDescription.value = '初始化中...'; + } break; case PairingState.btReady: statusDescription.value = '蓝牙已就绪'; @@ -718,7 +753,8 @@ class PairingController extends GetxController { /// 是否可以跳过配对 bool get canSkip => !isLoading.value && - (state == PairingState.exitNoClassic || + ((isManualMode.value && isReadyToStart.value) || // 手动模式待机状态可以跳过 + state == PairingState.exitNoClassic || state == PairingState.exitNotMatch || state == PairingState.exitTimeout); diff --git a/lib/modules/pairing/views/pairing_view.dart b/lib/modules/pairing/views/pairing_view.dart index f15cf8f34..abc48189e 100644 --- a/lib/modules/pairing/views/pairing_view.dart +++ b/lib/modules/pairing/views/pairing_view.dart @@ -99,11 +99,13 @@ class PairingView extends GetView { return Obx(() { final state = controller.state; final isLoading = controller.isLoading.value; - + final isReadyToStart = controller.isReadyToStart.value; + final isManualMode = controller.isManualMode.value; + // 根据状态决定动画颜色 Color primaryColor = Color(0xFF0066CC); Color secondaryColor = Color(0xFF5E5CE6); - + // 错误状态使用红色 if (state.name.startsWith('exit')) { primaryColor = Colors.red; @@ -114,7 +116,54 @@ class PairingView extends GetView { primaryColor = Colors.green; secondaryColor = Colors.greenAccent; } - + + // 手动模式待机状态的特殊处理 + if (isManualMode && isReadyToStart) { + return Container( + width: 240.w, + height: 240.w, + child: Stack( + alignment: Alignment.center, + children: [ + // 静态背景圆圈 + Container( + width: 200.w, + height: 200.w, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + primaryColor.withOpacity(0.1), + secondaryColor.withOpacity(0.1), + ], + ), + shape: BoxShape.circle, + ), + ), + // 设备图标 + Container( + width: 120.w, + height: 120.w, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [primaryColor, secondaryColor], + ), + shape: BoxShape.circle, + ), + child: Icon( + Icons.headphones, + color: Colors.white, + size: 60.w, + ), + ), + ], + ), + ); + } + return Container( width: 240.w, height: 240.w, @@ -239,11 +288,11 @@ class PairingView extends GetView { ), // 当前连接设备(有设备时才显示) - if (device != null && - (state == PairingState.classicOk || - state == PairingState.serverVerify || - state == PairingState.pairing || - state == PairingState.paired)) ...[ + if (device != null && + (state == PairingState.classicOk || + state == PairingState.serverVerify || + state == PairingState.pairing || + state == PairingState.paired)) ...[ SizedBox(height: 24.h), _buildConnectedDevice(device, isDarkMode), ], @@ -254,10 +303,14 @@ class PairingView extends GetView { // 根据状态获取副标题 String _getSubtitleForState(PairingState state) { + if (controller.isManualMode.value && controller.isReadyToStart.value) { + return '点击下方按钮开始配对您的DeapSound设备'; + } + switch (state) { case PairingState.init: case PairingState.btReady: - return '正在准备配对环境...'; + return controller.isManualMode.value ? '准备开始配对' : '正在准备配对环境...'; case PairingState.classicOk: return '请先通过系统蓝牙连接DeapSound设备'; case PairingState.serverVerify: @@ -364,17 +417,50 @@ class PairingView extends GetView { final showActionButton = controller.showActionButton; final canSkip = controller.canSkip; final actionButtonText = controller.actionButtonText.value; - + final isReadyToStart = controller.isReadyToStart.value; + final isManualMode = controller.isManualMode.value; + return Container( width: double.infinity, child: Column( children: [ - // 主按钮 - 根据状态显示不同的按钮 - if (showActionButton) + // 手动模式:显示开始配对按钮 + if (isManualMode && isReadyToStart) + ElevatedButton( + onPressed: () => controller.startManualPairing(), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF0066CC), + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric(vertical: 16.h), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.r), + ), + elevation: 0, + minimumSize: Size(double.infinity, 56.h), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.bluetooth_searching, size: 20.w), + SizedBox(width: 8.w), + Text( + '开始配对设备', + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + + // 原有的状态按钮(错误处理等) + if (showActionButton && !isManualMode) ElevatedButton( onPressed: () => controller.handleActionButtonTap(), style: ElevatedButton.styleFrom( - backgroundColor: _getButtonColor(controller.state, isDarkMode), + backgroundColor: + _getButtonColor(controller.state, isDarkMode), foregroundColor: Colors.white, padding: EdgeInsets.symmetric(vertical: 16.h), shape: RoundedRectangleBorder( @@ -392,7 +478,7 @@ class PairingView extends GetView { ), ), - // 只在可以跳过时显示跳过按钮 + // 跳过按钮和重置按钮 if (canSkip) ...[ SizedBox(height: 12.h), TextButton( @@ -411,6 +497,24 @@ class PairingView extends GetView { ), ), ], + + // 添加重置按钮(在错误状态下) + if (!isManualMode && + !controller.isLoading.value && + controller.state.name.startsWith('exit')) ...[ + SizedBox(height: 8.h), + TextButton( + onPressed: () => controller.resetToManualMode(), + style: TextButton.styleFrom( + foregroundColor: Colors.grey, + padding: EdgeInsets.symmetric(vertical: 8.h), + ), + child: Text( + '重新配对', + style: TextStyle(fontSize: 14.sp), + ), + ), + ], ], ), );