From 2a356b60abdb8cb01e2ced6434fb4515b017db8e Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Thu, 3 Jul 2025 21:26:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=9A=E8=AE=AE=E5=8A=A9?= =?UTF-8?q?=E6=89=8Bble=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting_connect_controller.dart | 73 ++++++++++- .../meeting/views/meeting_connect_view.dart | 115 +++++++++++++++++- pubspec.yaml | 2 +- 3 files changed, 187 insertions(+), 3 deletions(-) diff --git a/lib/modules/meeting/controllers/meeting_connect_controller.dart b/lib/modules/meeting/controllers/meeting_connect_controller.dart index ff2d95a6b..8a3bbff56 100644 --- a/lib/modules/meeting/controllers/meeting_connect_controller.dart +++ b/lib/modules/meeting/controllers/meeting_connect_controller.dart @@ -1,3 +1,74 @@ +import 'dart:async'; + +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; -class MeetingConnectController extends GetxController {} +class MeetingConnectController extends GetxController { + RxString stateStr = '搜索中...'.obs; + RxBool isRescan = false.obs; + RxBool isImportedFiles = false.obs; + + late StreamSubscription> _scanResultsSubscription; + late StreamSubscription _isScanningSubscription; + BluetoothDevice? _device; + + @override + void onInit() { + super.onInit(); + _scanResultsSubscription = FlutterBluePlus.scanResults.listen((results) { + for (ScanResult item in results) { + _handlerScanResult(item); + } + }); + _isScanningSubscription = FlutterBluePlus.isScanning.listen((state) { + if (!state && _device == null) { + stateStr.value = '未搜索到 AI PEN 设备'; + isRescan.value = true; + } else { + stateStr.value = '搜索中...'; + isRescan.value = false; + } + }); + startScan(); + } + + @override + void onClose() { + _scanResultsSubscription.cancel(); + _isScanningSubscription.cancel(); + _stopScan(); + _disconnect(); + super.onClose(); + } + + Future startScan() async { + await FlutterBluePlus.startScan( + timeout: const Duration(seconds: 15), + withServices: [ + Guid('FFF0'), + ], + withNames: ['AI PEN'], + ); + } + + Future _stopScan() async { + await FlutterBluePlus.stopScan(); + } + + Future _connect() async { + await _device?.connect(); + } + + Future _disconnect() async { + await _device?.disconnect(); + } + + void _handlerScanResult(ScanResult result) async { + if (result.device.platformName == 'AI PEN') { + _device = result.device; + await _stopScan(); + await _connect(); + stateStr.value = '已连接到 AI PEN 设备'; + } + } +} diff --git a/lib/modules/meeting/views/meeting_connect_view.dart b/lib/modules/meeting/views/meeting_connect_view.dart index a864a097a..fbe9ac918 100644 --- a/lib/modules/meeting/views/meeting_connect_view.dart +++ b/lib/modules/meeting/views/meeting_connect_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../controllers/meeting_connect_controller.dart'; @@ -8,6 +9,118 @@ class MeetingConnectView extends GetView { @override Widget build(BuildContext context) { - return const Placeholder(); + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + + return Scaffold( + backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], + appBar: _buildAppBar(isDarkMode), + body: _buildBody(isDarkMode), + ); + } + + PreferredSizeWidget _buildAppBar(bool isDarkMode) { + return AppBar( + backgroundColor: isDarkMode ? Colors.black : Colors.white, + elevation: 0.5, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + color: isDarkMode ? Colors.white : Colors.black, + size: 20.sp, + ), + onPressed: () => Get.back(), + ), + title: Text( + '蓝牙连接', + style: TextStyle( + fontSize: 17.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + centerTitle: true, + ); + } + + Widget _buildBody(bool isDarkMode) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Obx( + () => Text( + controller.stateStr.value, + style: TextStyle( + fontSize: 20.sp, + color: isDarkMode ? Colors.white : Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + Obx( + () => controller.isRescan.value + ? Padding( + padding: EdgeInsets.only(top: 20.w), + child: _button('重新连接', Icons.refresh, onTap: () { + controller.startScan(); + }), + ) + : const SizedBox(), + ), + Obx( + () => controller.isImportedFiles.value + ? Padding( + padding: EdgeInsets.only(top: 30.w), + child: Text( + '检测到有新文件,是否导入', + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.white70 : Colors.black54, + ), + ), + ) + : const SizedBox(), + ), + Obx( + () => controller.isImportedFiles.value + ? _button('导入文件', Icons.file_download, onTap: () {}) + : const SizedBox(), + ), + ], + ), + ); + } + + Widget _button(String text, IconData icon, {Function()? onTap}) { + return GestureDetector( + onTap: onTap, + child: Container( + width: 150.w, + height: 42.w, + margin: EdgeInsets.symmetric(vertical: 10.w), + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(42.w), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icon, + color: Colors.white, + size: 20.sp, + ), + 5.horizontalSpace, + Text( + text, + style: TextStyle( + color: Colors.white, + fontSize: 14.sp, + ), + ), + ], + ), + ), + ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 6262a2de8..e01fc5fb8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,7 +35,7 @@ dependencies: crypto: ^3.0.3 flutter_tts: ^4.2.2 logger: ^2.0.2+1 - flutter_blue_plus: ^1.31.16 + flutter_blue_plus: ^1.35.5 just_audio: ^0.9.36 webview_flutter: ^4.13.0 flutter_easyloading: ^3.0.5