15 changed files with 562 additions and 59 deletions
@ -0,0 +1,11 @@ |
|||||
|
import 'package:deep_voice/modules/devices/controllers/devices_controller.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
|
||||
|
class DevicesBinding extends Bindings { |
||||
|
@override |
||||
|
void dependencies() { |
||||
|
Get.lazyPut<DevicesController>( |
||||
|
() => DevicesController(), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
import 'package:deep_voice/core/utils/logger.dart'; |
||||
|
import 'package:deep_voice/data/models/user_Info.dart'; |
||||
|
import 'package:deep_voice/data/services/ble_manager.dart'; |
||||
|
import 'package:deep_voice/data/services/network/api.dart'; |
||||
|
import 'package:deep_voice/routes/app_routes.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
import 'package:get/get_rx/get_rx.dart'; |
||||
|
import 'package:get/get_state_manager/src/simple/get_controllers.dart'; |
||||
|
|
||||
|
/* |
||||
|
设备管理 |
||||
|
*/ |
||||
|
class DevicesController extends GetxController { |
||||
|
late final BleManager _bleManager; |
||||
|
//耳机绑定 |
||||
|
final isearphone = false.obs; |
||||
|
final earphoneName = "".obs; |
||||
|
final earphoneMac = "".obs; |
||||
|
final earphoneCode = "".obs; |
||||
|
|
||||
|
//录音笔 |
||||
|
final isvoicepen = false.obs; |
||||
|
final voicepenName = "".obs; |
||||
|
final voicepenMac = "".obs; |
||||
|
|
||||
|
@override |
||||
|
void onInit() { |
||||
|
super.onInit(); |
||||
|
_bleManager = Get.find<BleManager>(); |
||||
|
earphoneName.value = User.instance.earphonename; |
||||
|
earphoneMac.value = User.instance.earphonemac; |
||||
|
earphoneCode.value = User.instance.earphoneauthcode; |
||||
|
if (earphoneCode.value != "") { |
||||
|
isearphone.value = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
void onClose() { |
||||
|
super.onClose(); |
||||
|
} |
||||
|
|
||||
|
void unbindearphone() async { |
||||
|
final response = await Api.unbindearphone({ |
||||
|
"code": earphoneCode.value, |
||||
|
"earphonname": earphoneMac.value, |
||||
|
}); |
||||
|
if (response != null) { |
||||
|
User.instance.earphonename = ""; |
||||
|
User.instance.earphonemac = ""; |
||||
|
User.instance.earphoneauthcode = ""; |
||||
|
isearphone.value = false; |
||||
|
_bleManager.clearPairedDevices(); |
||||
|
_bleManager.disconnect(); |
||||
|
Get.toNamed(Routes.pairing); |
||||
|
return; |
||||
|
} else { |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,290 @@ |
|||||
|
import 'dart:ui'; |
||||
|
|
||||
|
import 'package:deep_voice/modules/devices/controllers/devices_controller.dart'; |
||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
|
||||
|
class DevicesView extends GetView<DevicesController> { |
||||
|
const DevicesView({Key? key}) : super(key: key); |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
// 直接使用 Theme.of(context) 获取当前主题 |
||||
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
||||
|
|
||||
|
return Scaffold( |
||||
|
backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], |
||||
|
appBar: AppBar( |
||||
|
automaticallyImplyLeading: false, |
||||
|
centerTitle: true, |
||||
|
elevation: 0, |
||||
|
backgroundColor: isDarkMode ? Colors.black : Colors.white, |
||||
|
leading: IconButton( |
||||
|
icon: Icon( |
||||
|
Icons.arrow_back_ios, |
||||
|
size: 20.sp, |
||||
|
color: isDarkMode ? Colors.white : Colors.black, |
||||
|
), |
||||
|
onPressed: () { |
||||
|
Get.back(); // 正常返回 |
||||
|
}, |
||||
|
), |
||||
|
title: Text( |
||||
|
'设备管理'.tr, |
||||
|
style: TextStyle( |
||||
|
fontSize: 20.sp, |
||||
|
color: isDarkMode ? Colors.white : Colors.black, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
body: ListView( |
||||
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), |
||||
|
children: [ |
||||
|
_buildEarphoneCard(isDarkMode), |
||||
|
SizedBox(height: 20.h), |
||||
|
_buildVoiceRecorderCard(isDarkMode), |
||||
|
SizedBox(height: 20.h), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
// 耳机 |
||||
|
Widget _buildEarphoneCard(bool isDarkMode) { |
||||
|
return Column( |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Padding( |
||||
|
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), |
||||
|
child: Text( |
||||
|
'earphone'.tr, // AI设置 |
||||
|
style: TextStyle( |
||||
|
fontSize: 12.sp, |
||||
|
fontWeight: FontWeight.w500, |
||||
|
color: isDarkMode ? Colors.blue[400] : Colors.blue[600], |
||||
|
letterSpacing: 1, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Container( |
||||
|
decoration: BoxDecoration( |
||||
|
color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white, |
||||
|
borderRadius: BorderRadius.circular(16.r), |
||||
|
boxShadow: [ |
||||
|
BoxShadow( |
||||
|
color: isDarkMode |
||||
|
? Colors.black.withOpacity(0.2) |
||||
|
: Colors.black.withOpacity(0.05), |
||||
|
blurRadius: 10, |
||||
|
offset: const Offset(0, 2), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
child: ClipRRect( |
||||
|
borderRadius: BorderRadius.circular(16.r), |
||||
|
child: BackdropFilter( |
||||
|
filter: isDarkMode |
||||
|
? ImageFilter.blur(sigmaX: 5, sigmaY: 5) |
||||
|
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), |
||||
|
child: Column( |
||||
|
children: [ |
||||
|
Obx( |
||||
|
() => |
||||
|
// 耳机列表 |
||||
|
_buildSimpleNavigationSetting( |
||||
|
title: controller.isearphone.value |
||||
|
? controller.earphoneName.value |
||||
|
: "未绑定", |
||||
|
subtitle: controller.isearphone.value |
||||
|
? controller.earphoneMac.value |
||||
|
: "还未绑定设备", |
||||
|
icon: Icons.headphones, |
||||
|
iconBgColor: isDarkMode |
||||
|
? const Color.fromARGB(255, 255, 255, 255)! |
||||
|
.withOpacity(0.3) |
||||
|
: const Color.fromARGB(255, 0, 0, 0)!, |
||||
|
iconColor: isDarkMode |
||||
|
? const Color.fromARGB(255, 0, 0, 0)! |
||||
|
: const Color.fromARGB(255, 255, 255, 255)!, |
||||
|
titleColor: isDarkMode ? Colors.white : null, |
||||
|
subtitleColor: isDarkMode ? Colors.white70 : null, |
||||
|
isDarkMode: isDarkMode, |
||||
|
showbutt: controller.isearphone.value, |
||||
|
onPressed: () { |
||||
|
controller.unbindearphone(); |
||||
|
}, |
||||
|
), |
||||
|
) |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
// 录音笔 |
||||
|
Widget _buildVoiceRecorderCard(bool isDarkMode) { |
||||
|
return Column( |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Padding( |
||||
|
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), |
||||
|
child: Text( |
||||
|
'voicerecorder'.tr, //AI设置 |
||||
|
style: TextStyle( |
||||
|
fontSize: 12.sp, |
||||
|
fontWeight: FontWeight.w500, |
||||
|
color: isDarkMode ? Colors.blue[400] : Colors.blue[600], |
||||
|
letterSpacing: 1, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Container( |
||||
|
decoration: BoxDecoration( |
||||
|
color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white, |
||||
|
borderRadius: BorderRadius.circular(16.r), |
||||
|
boxShadow: [ |
||||
|
BoxShadow( |
||||
|
color: isDarkMode |
||||
|
? Colors.black.withOpacity(0.2) |
||||
|
: Colors.black.withOpacity(0.05), |
||||
|
blurRadius: 10, |
||||
|
offset: const Offset(0, 2), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
child: ClipRRect( |
||||
|
borderRadius: BorderRadius.circular(16.r), |
||||
|
child: BackdropFilter( |
||||
|
filter: isDarkMode |
||||
|
? ImageFilter.blur(sigmaX: 5, sigmaY: 5) |
||||
|
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), |
||||
|
child: Column( |
||||
|
children: [ |
||||
|
// 实时对话入口 |
||||
|
Obx( |
||||
|
() => _buildSimpleNavigationSetting( |
||||
|
title: '未绑定', |
||||
|
subtitle: '还未绑定设备', |
||||
|
icon: Icons.edit, |
||||
|
iconBgColor: isDarkMode |
||||
|
? const Color.fromARGB(255, 255, 255, 255)! |
||||
|
.withOpacity(0.3) |
||||
|
: const Color.fromARGB(255, 0, 0, 0)!, |
||||
|
iconColor: isDarkMode |
||||
|
? const Color.fromARGB(255, 0, 0, 0)! |
||||
|
: const Color.fromARGB(255, 255, 255, 255)!, |
||||
|
titleColor: isDarkMode ? Colors.white : null, |
||||
|
subtitleColor: isDarkMode ? Colors.white70 : null, |
||||
|
isDarkMode: isDarkMode, |
||||
|
showbutt: controller.isvoicepen.value, |
||||
|
onPressed: () {}, |
||||
|
), |
||||
|
) |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
// 简单导航设置项 |
||||
|
Widget _buildSimpleNavigationSetting({ |
||||
|
required String title, |
||||
|
String? subtitle, |
||||
|
required IconData icon, |
||||
|
required Color iconBgColor, |
||||
|
required Color iconColor, |
||||
|
Color? titleColor, |
||||
|
Color? subtitleColor, |
||||
|
required bool isDarkMode, |
||||
|
required bool showbutt, |
||||
|
required VoidCallback onPressed, |
||||
|
}) { |
||||
|
return InkWell( |
||||
|
child: Padding( |
||||
|
padding: EdgeInsets.all(16.w), |
||||
|
child: Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
|
children: [ |
||||
|
Expanded( |
||||
|
child: Row( |
||||
|
children: [ |
||||
|
Container( |
||||
|
width: 32.w, |
||||
|
height: 32.w, |
||||
|
decoration: BoxDecoration( |
||||
|
color: iconBgColor, |
||||
|
borderRadius: BorderRadius.circular(16.r), |
||||
|
), |
||||
|
child: Icon( |
||||
|
icon, |
||||
|
size: 16.w, |
||||
|
color: iconColor, |
||||
|
), |
||||
|
), |
||||
|
SizedBox(width: 12.w), |
||||
|
Flexible( |
||||
|
child: Column( |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Text( |
||||
|
title, |
||||
|
style: TextStyle( |
||||
|
fontSize: 16.sp, |
||||
|
fontWeight: FontWeight.w500, |
||||
|
color: titleColor ?? |
||||
|
(isDarkMode ? Colors.white : Colors.black87), |
||||
|
), |
||||
|
overflow: TextOverflow.ellipsis, |
||||
|
), |
||||
|
if (subtitle != null) SizedBox(height: 2.h), |
||||
|
if (subtitle != null) |
||||
|
Text( |
||||
|
subtitle, |
||||
|
style: TextStyle( |
||||
|
fontSize: 12.sp, |
||||
|
color: subtitleColor ?? |
||||
|
(isDarkMode |
||||
|
? Colors.white70 |
||||
|
: Colors.black54), |
||||
|
), |
||||
|
overflow: TextOverflow.ellipsis, |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
if (showbutt) |
||||
|
Container( |
||||
|
width: 74.w, |
||||
|
height: 40.w, |
||||
|
child: ElevatedButton( |
||||
|
style: ElevatedButton.styleFrom( |
||||
|
backgroundColor: Colors.blue, |
||||
|
shape: RoundedRectangleBorder( |
||||
|
borderRadius: BorderRadius.circular(12), |
||||
|
), |
||||
|
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 2), |
||||
|
), |
||||
|
onPressed: onPressed, |
||||
|
child: const Text( |
||||
|
'解绑', |
||||
|
style: TextStyle( |
||||
|
color: Colors.white, |
||||
|
), |
||||
|
), |
||||
|
)), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue