From da712a9a6253889bf11bebde4ad5b9cc5d4c8838 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 18 Nov 2025 15:20:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=BE=E5=A4=87=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/devices/views/devices_view.dart | 171 ++++++------- .../controllers/eq_settings_controller.dart | 84 ++++++- .../eq_settings/views/eq_settings_view.dart | 84 ++++++- .../views/widgets/row_confirm_widget.dart | 96 ++++++++ .../views/widgets/row_input_widget.dart | 231 ++++++++++++++++++ 5 files changed, 581 insertions(+), 85 deletions(-) create mode 100644 lib/modules/eq_settings/views/widgets/row_confirm_widget.dart create mode 100644 lib/modules/eq_settings/views/widgets/row_input_widget.dart diff --git a/lib/modules/devices/views/devices_view.dart b/lib/modules/devices/views/devices_view.dart index 846004a4e..7a69dd5b0 100644 --- a/lib/modules/devices/views/devices_view.dart +++ b/lib/modules/devices/views/devices_view.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import '../../../routes/app_routes.dart'; import '/modules/devices/controllers/devices_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -201,103 +202,107 @@ class DevicesView extends GetView { required DeviceType deviceType, required bool isDarkMode, }) { - return Container( - margin: EdgeInsets.only(bottom: 12.h), - padding: EdgeInsets.all(16.w), - decoration: BoxDecoration( - color: isDarkMode ? AppColors.cardBackground : Colors.white, - borderRadius: BorderRadius.circular(12.r), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.05), - blurRadius: 8, - offset: const Offset(0, 2), - ), - ], - ), - child: Row( - children: [ - // 设备图标 - Container( - width: 48.w, - height: 48.w, - decoration: BoxDecoration( - color: - isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[100], - borderRadius: BorderRadius.circular(12.r), + return GestureDetector( + onTap: () => Get.toNamed(Routes.eqSettings), + child: Container( + margin: EdgeInsets.only(bottom: 12.h), + padding: EdgeInsets.all(16.w), + decoration: BoxDecoration( + color: isDarkMode ? AppColors.cardBackground : Colors.white, + borderRadius: BorderRadius.circular(12.r), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 8, + offset: const Offset(0, 2), ), - child: Icon( - deviceType.icon, - color: isDarkMode ? Colors.white : Colors.black87, - size: 24.sp, + ], + ), + child: Row( + children: [ + // 设备图标 + Container( + width: 48.w, + height: 48.w, + decoration: BoxDecoration( + color: isDarkMode + ? Colors.white.withOpacity(0.1) + : Colors.grey[100], + borderRadius: BorderRadius.circular(12.r), + ), + child: Icon( + deviceType.icon, + color: isDarkMode ? Colors.white : Colors.black87, + size: 24.sp, + ), ), - ), - SizedBox(width: 16.w), - // 设备信息 - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - device.devicename.isNotEmpty - ? device.devicename - : "deviceTypeUnknown".tr, - style: TextStyle( - fontSize: 16.sp, - fontWeight: FontWeight.w500, - color: isDarkMode ? Colors.white : Colors.black87, - ), - ), - SizedBox(height: 4.h), - Text( - device.devicemac.isNotEmpty - ? device.devicemac - : "noMacAddress".tr, - style: TextStyle( - fontSize: 14.sp, - color: isDarkMode ? Colors.white70 : Colors.grey[600], + SizedBox(width: 16.w), + // 设备信息 + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + device.devicename.isNotEmpty + ? device.devicename + : "deviceTypeUnknown".tr, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w500, + color: isDarkMode ? Colors.white : Colors.black87, + ), ), - ), - if (device.license.isNotEmpty) ...[ SizedBox(height: 4.h), Text( - "${"licenseCode".tr}: ${device.license}", + device.devicemac.isNotEmpty + ? device.devicemac + : "noMacAddress".tr, style: TextStyle( - fontSize: 12.sp, - color: isDarkMode ? Colors.white54 : Colors.grey[500], + fontSize: 14.sp, + color: isDarkMode ? Colors.white70 : Colors.grey[600], ), ), + if (device.license.isNotEmpty) ...[ + SizedBox(height: 4.h), + Text( + "${"licenseCode".tr}: ${device.license}", + style: TextStyle( + fontSize: 12.sp, + color: isDarkMode ? Colors.white54 : Colors.grey[500], + ), + ), + ], ], - ], - ), - ), - // 解绑按钮 - GestureDetector( - onTap: () => _showUnbindDialog(device, isDarkMode), - child: Container( - padding: EdgeInsets.symmetric( - horizontal: 12.w, - vertical: 6.h, ), - decoration: BoxDecoration( - color: Colors.red.withOpacity(0.1), - borderRadius: BorderRadius.circular(6.r), - border: Border.all( - color: Colors.red.withOpacity(0.3), - width: 1, + ), + // 解绑按钮 + GestureDetector( + onTap: () => _showUnbindDialog(device, isDarkMode), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 12.w, + vertical: 6.h, ), - ), - child: Text( - "unbind".tr, - style: TextStyle( - fontSize: 12.sp, - color: Colors.red, - fontWeight: FontWeight.w500, + decoration: BoxDecoration( + color: Colors.red.withOpacity(0.1), + borderRadius: BorderRadius.circular(6.r), + border: Border.all( + color: Colors.red.withOpacity(0.3), + width: 1, + ), + ), + child: Text( + "unbind".tr, + style: TextStyle( + fontSize: 12.sp, + color: Colors.red, + fontWeight: FontWeight.w500, + ), ), ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/modules/eq_settings/controllers/eq_settings_controller.dart b/lib/modules/eq_settings/controllers/eq_settings_controller.dart index ef5daae05..a0857a5a1 100644 --- a/lib/modules/eq_settings/controllers/eq_settings_controller.dart +++ b/lib/modules/eq_settings/controllers/eq_settings_controller.dart @@ -1,3 +1,85 @@ +import 'package:flutter/widgets.dart'; import 'package:get/get.dart'; -class EqSettingsController extends GetxController {} +import '../../../core/utils/logger.dart'; +import '../../../routes/app_routes.dart'; +import '../views/widgets/row_confirm_widget.dart'; +import '../views/widgets/row_input_widget.dart'; + +class EqSettingsController extends GetxController { + final RxList uiList = [ + { + 'title': '音效', + 'templates': [], + }, + { + 'title': '按键功能', + 'templates': [], + }, + { + 'title': '耳机功能', + 'templates': [ + { + 'type': 'input', + 'name': '修改名称', + 'value': 'voitrans', + 'onCallback': (String value) { + Logger.d('input', '修改名称:$value'); + }, + }, + { + 'type': 'input', + 'name': '工作模式', + 'value': '', + 'onCallback': () {}, + }, + { + 'type': 'switch', + 'name': '闪灯开关', + 'value': false, + 'onCallback': () {}, + }, + { + 'type': 'switch', + 'name': '查找设备', + 'value': false, + 'description': '在设备上播放声音', + 'onCallback': () {}, + }, + ], + }, + { + 'templates': [ + { + 'type': 'confirm', + 'name': '升级耳机固件', + 'onCallback': () => Get.toNamed(Routes.OTA_UPGRADE), + }, + { + 'type': 'confirm', + 'name': '恢复出厂设置', + 'tips': '确定要恢复出厂设置吗?', + 'onCallback': () { + Logger.d('confirm', '恢复出厂设置'); + }, + }, + { + 'type': 'confirm', + 'name': '清除配对记录', + 'tips': '确定要清除配对记录吗?', + 'onCallback': () { + Logger.d('confirm', '清除配对记录'); + }, + }, + ], + } + ].obs; + + Widget getTemplate(Map data) { + return switch (data['type']) { + 'input' => RowInputWidget(data), + 'confirm' => RowConfirmWidget(data), + _ => const SizedBox.shrink(), + }; + } +} diff --git a/lib/modules/eq_settings/views/eq_settings_view.dart b/lib/modules/eq_settings/views/eq_settings_view.dart index 32c26179f..67f0403e9 100644 --- a/lib/modules/eq_settings/views/eq_settings_view.dart +++ b/lib/modules/eq_settings/views/eq_settings_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/eq_settings_controller.dart'; @@ -8,6 +9,87 @@ class EqSettingsView 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, + surfaceTintColor: Colors.transparent, + 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 Obx( + () => ListView.builder( + itemCount: controller.uiList.length, + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 5.w), + itemBuilder: (BuildContext context, int index) { + Map data = controller.uiList[index]; + return _item(isDarkMode, data); + }, + ), + ); + } + + Widget _item(bool isDarkMode, Map data) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 10.w), + margin: EdgeInsets.symmetric(vertical: 5.w), + decoration: BoxDecoration( + color: isDarkMode ? Colors.white.withValues(alpha: 0.05) : Colors.white, + borderRadius: BorderRadius.circular(8.w), + boxShadow: [ + BoxShadow( + color: isDarkMode + ? Colors.black.withValues(alpha: 0.2) + : Colors.black.withValues(alpha: 0.05), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (data['title'] != null) + Text( + data['title'], + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + ...data['templates'].map((e) => controller.getTemplate(e)).toList(), + ], + ), + ); } } diff --git a/lib/modules/eq_settings/views/widgets/row_confirm_widget.dart b/lib/modules/eq_settings/views/widgets/row_confirm_widget.dart new file mode 100644 index 000000000..ce680b1d0 --- /dev/null +++ b/lib/modules/eq_settings/views/widgets/row_confirm_widget.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +class RowConfirmWidget extends StatefulWidget { + final Map templateData; + + const RowConfirmWidget(this.templateData, {super.key}); + + @override + State createState() => _RowConfirmWidgetState(); +} + +class _RowConfirmWidgetState extends State { + Map get _templateData => widget.templateData; + + @override + Widget build(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + + return GestureDetector( + onTap: () { + if (_templateData['tips'] != null) { + _alertDialog(isDarkMode); + } else { + _templateData['onCallback'](); + } + }, + behavior: HitTestBehavior.translucent, + child: Padding( + padding: EdgeInsets.fromLTRB(10.w, 10.w, 0, 10.w), + child: Row( + children: [ + Expanded( + child: Text( + _templateData['name'], + style: TextStyle( + fontSize: 14.sp, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + ), + Icon( + Icons.chevron_right, + size: 26.w, + color: Colors.blue, + ), + ], + ), + ), + ); + } + + void _alertDialog(bool isDarkMode) { + Get.dialog( + AlertDialog( + backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, + title: Text( + _templateData['name'], + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + ), + ), + content: Text( + _templateData['tips'], + style: TextStyle( + color: isDarkMode ? Colors.white70 : Colors.black54, + ), + ), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text( + 'cancel'.tr, // 取消 + style: TextStyle( + color: isDarkMode ? Colors.white70 : Colors.black54, + ), + ), + ), + TextButton( + onPressed: () { + _templateData['onCallback'](); + Get.back(); + }, + child: Text( + 'confirm'.tr, // 确定 + style: TextStyle( + color: isDarkMode ? Colors.red[300] : Colors.red[600], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/modules/eq_settings/views/widgets/row_input_widget.dart b/lib/modules/eq_settings/views/widgets/row_input_widget.dart new file mode 100644 index 000000000..2409e644e --- /dev/null +++ b/lib/modules/eq_settings/views/widgets/row_input_widget.dart @@ -0,0 +1,231 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +class RowInputWidget extends StatefulWidget { + final Map templateData; + + const RowInputWidget(this.templateData, {super.key}); + + @override + State createState() => _RowInputWidgetState(); +} + +class _RowInputWidgetState extends State { + Map get _templateData => widget.templateData; + + @override + Widget build(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + + return GestureDetector( + onTap: () => _inputBottomSheet(isDarkMode), + behavior: HitTestBehavior.translucent, + child: Padding( + padding: EdgeInsets.fromLTRB(10.w, 10.w, 0, 10.w), + child: Row( + children: [ + Expanded( + child: Text( + _templateData['name'], + style: TextStyle( + fontSize: 14.sp, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + ), + Text( + _templateData['value'], + style: TextStyle( + fontSize: 12.sp, + color: isDarkMode ? Colors.white : Colors.grey, + ), + ), + Icon( + Icons.chevron_right, + size: 26.w, + color: Colors.blue, + ), + ], + ), + ), + ); + } + + void _inputBottomSheet(bool isDarkMode) { + Get.bottomSheet( + InputBox(_templateData['name'], _templateData['value']), + isScrollControlled: true, + backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[100], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(12.r), + ), + ), + ).then((value) { + if (value != null) { + setState(() { + _templateData['value'] = value; + }); + _templateData['onCallback'](value); + } + }); + } +} + +class InputBox extends StatefulWidget { + final String title; + final String inputText; + + const InputBox(this.title, this.inputText, {super.key}); + + @override + State createState() => _InputBoxState(); +} + +class _InputBoxState extends State { + final TextEditingController _inputController = TextEditingController(); + + @override + void initState() { + super.initState(); + _inputController.text = widget.inputText; + } + + @override + void dispose() { + _inputController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 10.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + fontSize: 16.sp, + color: Colors.black87, + fontWeight: FontWeight.bold, + ), + ), + GestureDetector( + onTap: () => Get.back(), + child: Container( + width: 26.w, + height: 26.w, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(26.r), + ), + child: Icon( + Icons.close, + size: 18.w, + color: Colors.grey[400], + ), + ), + ) + ], + ), + ), + Divider( + height: 1, + color: Colors.grey[300], + ), + Container( + margin: EdgeInsets.symmetric(vertical: 20.w), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.w), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: TextField( + controller: _inputController, + style: TextStyle( + color: Colors.black87, + fontSize: 16.sp, + ), + decoration: InputDecoration( + hintText: 'maxCharacters'.tr, + hintStyle: TextStyle( + color: Colors.black54, + fontSize: 16.sp, + ), + isDense: true, + fillColor: Colors.transparent, + border: InputBorder.none, + contentPadding: EdgeInsets.all(10.w), + ), + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 20.w), + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () => Get.back(), + child: Container( + height: 48.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(12.r), + ), + child: Text( + 'cancel'.tr, // 取消 + style: TextStyle( + fontSize: 16.sp, + color: Colors.black, + ), + ), + ), + ), + ), + 10.horizontalSpace, + Expanded( + child: GestureDetector( + onTap: () { + Get.back(result: _inputController.text); + }, + child: Container( + height: 48.w, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(12.r), + ), + child: Text( + 'confirm'.tr, // 确认 + style: TextStyle( + fontSize: 16.sp, + color: Colors.white, + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ); + } +}