import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../controllers/settings_controller.dart'; import '../../../core/widgets/common_bottom_nav.dart'; import '../../../core/routes/app_routes.dart'; class SettingsView extends GetView { const SettingsView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[50], appBar: AppBar( backgroundColor: Colors.white, elevation: 0.5, title: Text( '设置', style: TextStyle( fontSize: 17.sp, fontWeight: FontWeight.w600, color: Colors.black, ), ), centerTitle: true, leading: IconButton( icon: const Icon(Icons.arrow_back_ios, color: Colors.black54), onPressed: () => Get.back(), ), ), body: ListView( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), children: [ _buildUserInfoCard(), SizedBox(height: 20.h), _buildHeadphoneSettingsSection(), SizedBox(height: 20.h), _buildAISettingsSection(), SizedBox(height: 20.h), _buildSystemSettingsSection(), SizedBox(height: 20.h), _buildAboutSection(), SizedBox(height: 50.h), ], ), bottomNavigationBar: const CommonBottomNav(currentIndex: 2), ); } // 用户信息卡片 Widget _buildUserInfoCard() { return Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFFE3F2FD), Color(0xFFF3E5F5)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Container( width: 60.w, height: 60.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(30.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(30.r), child: Image.network( 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80', fit: BoxFit.cover, ), ), ), SizedBox(width: 16.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '林美珍', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, color: Colors.black87, ), ), SizedBox(height: 4.h), Row( children: [ Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h), decoration: BoxDecoration( color: Colors.blue[600], borderRadius: BorderRadius.circular(10.r), ), child: Text( '高级会员', style: TextStyle( fontSize: 10.sp, color: Colors.white, ), ), ), SizedBox(width: 8.w), Flexible( child: Text( '已连接设备: DeepVoice Pro', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), overflow: TextOverflow.ellipsis, ), ), ], ), SizedBox(height: 4.h), Text( '账号ID: deepvoice_834291', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: Colors.white.withOpacity(0.7), borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 4, offset: const Offset(0, 1), ), ], ), child: Icon( Icons.edit, size: 16.w, color: Colors.grey[600], ), ), ], ), ); } // 耳机设置部分 Widget _buildHeadphoneSettingsSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 4.w, bottom: 8.h), child: Text( '耳机设置', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w500, color: Colors.blue[600], letterSpacing: 1, ), ), ), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: [ // 噪声消除 Obx(() => _buildToggleSetting( title: '噪声消除', subtitle: '降低周围环境噪音', icon: Icons.volume_off_rounded, iconBgColor: Colors.blue[100]!, iconColor: Colors.blue[600]!, value: controller.noiseReductionEnabled.value, onChanged: controller.toggleNoiseReduction, )), const Divider(height: 1), // 环境音增强 _buildNavigationSetting( title: '环境音增强', subtitle: '增强周围重要声音', icon: Icons.nature, iconBgColor: Colors.green[100]!, iconColor: Colors.green[600]!, value: controller.ambientSoundMode.value, onTap: () { // 弹出环境音增强设置对话框 Get.dialog( Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.r), ), child: Padding( padding: EdgeInsets.all(16.w), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( '环境音增强', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 16.h), ...controller.availableAmbientModes.map((mode) => RadioListTile( title: Text(mode), value: mode, groupValue: controller.ambientSoundMode.value, onChanged: (value) { if (value != null) { controller.updateAmbientSoundMode(value); Get.back(); } }, ), ).toList(), SizedBox(height: 16.h), TextButton( onPressed: () => Get.back(), child: const Text('取消'), ), ], ), ), ), ); }, ), const Divider(height: 1), // 立体声平衡 Padding( padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: Colors.purple[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.balance, size: 16.w, color: Colors.purple[600], ), ), SizedBox(width: 12.w), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '立体声平衡', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.black87, ), ), SizedBox(height: 2.h), Text( '调整左右耳机音量平衡', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ], ), SizedBox(height: 16.h), Obx(() => Column( children: [ SliderTheme( data: SliderThemeData( trackHeight: 4.h, thumbShape: RoundSliderThumbShape(enabledThumbRadius: 8.r), ), child: Slider( value: controller.stereoBalance.value, min: -1.0, max: 1.0, onChanged: controller.updateStereoBalance, ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 8.w), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '左', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), Text( '平衡', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), Text( '右', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ), ], )), ], ), ), ], ), ), ], ); } // AI设置部分 Widget _buildAISettingsSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 4.w, bottom: 8.h), child: Text( 'AI 设置', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w500, color: Colors.blue[600], letterSpacing: 1, ), ), ), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: [ // AI助理默认模式 _buildNavigationSetting( title: 'AI助理默认模式', subtitle: '选择默认的AI互动风格', icon: Icons.android, iconBgColor: Colors.red[100]!, iconColor: Colors.red[600]!, value: controller.aiAssistantMode.value, onTap: () { // 弹出AI助理模式选择对话框 Get.dialog( Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.r), ), child: Padding( padding: EdgeInsets.all(16.w), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'AI助理模式', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 16.h), ...controller.availableAiModes.map((mode) => RadioListTile( title: Text(mode), value: mode, groupValue: controller.aiAssistantMode.value, onChanged: (value) { if (value != null) { controller.updateAiAssistantMode(value); Get.back(); } }, ), ).toList(), SizedBox(height: 16.h), TextButton( onPressed: () => Get.back(), child: const Text('取消'), ), ], ), ), ), ); }, ), const Divider(height: 1), // AI声音选择 _buildNavigationSetting( title: 'AI声音选择', subtitle: '选择AI的声音和音调', icon: Icons.record_voice_over, iconBgColor: Colors.amber[100]!, iconColor: Colors.amber[600]!, value: controller.aiVoice.value, onTap: () { // 弹出AI声音选择对话框 Get.dialog( Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.r), ), child: Padding( padding: EdgeInsets.all(16.w), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'AI声音选择', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 16.h), ...controller.availableVoices.map((voice) => RadioListTile( title: Text(voice), value: voice, groupValue: controller.aiVoice.value, onChanged: (value) { if (value != null) { controller.updateAiVoice(value); Get.back(); } }, ), ).toList(), SizedBox(height: 16.h), TextButton( onPressed: () => Get.back(), child: const Text('取消'), ), ], ), ), ), ); }, ), const Divider(height: 1), // 翻译语言 Padding( padding: EdgeInsets.all(16.w), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // 左侧标题和图标部分 Flexible( child: Row( children: [ Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: Colors.teal[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.translate, size: 16.w, color: Colors.teal[600], ), ), SizedBox(width: 12.w), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '翻译语言', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.black87, ), overflow: TextOverflow.ellipsis, ), SizedBox(height: 2.h), Text( '设置需要翻译的语言', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), overflow: TextOverflow.ellipsis, ), ], ), ), ], ), ), // 右侧语言选择部分 Obx(() => Row( mainAxisSize: MainAxisSize.min, children: [ GestureDetector( onTap: () { _showLanguageSelectionDialog(true); }, child: Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h), decoration: BoxDecoration( color: Colors.blue[600], borderRadius: BorderRadius.circular(8.r), ), child: Text( controller.sourceLanguage.value, style: TextStyle( fontSize: 12.sp, color: Colors.white, ), ), ), ), IconButton( padding: EdgeInsets.zero, constraints: BoxConstraints(), icon: const Icon(Icons.swap_horiz, size: 20), onPressed: controller.swapLanguages, color: Colors.grey[500], ), GestureDetector( onTap: () { _showLanguageSelectionDialog(false); }, child: Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h), decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(8.r), ), child: Text( controller.targetLanguage.value, style: TextStyle( fontSize: 12.sp, color: Colors.grey[700], ), ), ), ), SizedBox(width: 4.w), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.add, size: 16.w, color: Colors.grey[500], ), ), ], )), ], ), ), ], ), ), ], ); } // 系统设置部分 Widget _buildSystemSettingsSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 4.w, bottom: 8.h), child: Text( '系统设置', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w500, color: Colors.blue[600], letterSpacing: 1, ), ), ), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: [ // 通知设置 _buildSimpleNavigationSetting( title: '通知设置', subtitle: '管理应用推送和提醒', icon: Icons.notifications_none, iconBgColor: Colors.indigo[100]!, iconColor: Colors.indigo[600]!, onTap: () { // 打开通知设置页面 }, ), const Divider(height: 1), // 备份与恢复 _buildNavigationSetting( title: '备份与恢复', subtitle: '备份设置和AI互动历史', icon: Icons.cloud_upload_outlined, iconBgColor: Colors.cyan[100]!, iconColor: Colors.cyan[600]!, value: '上次备份: 今天', valueStyle: TextStyle( fontSize: 12.sp, color: Colors.grey[500], ), onTap: () { // 打开备份设置页面 }, ), const Divider(height: 1), // 隐私设置 _buildSimpleNavigationSetting( title: '隐私设置', subtitle: '管理数据收集和权限', icon: Icons.shield_outlined, iconBgColor: Colors.purple[100]!, iconColor: Colors.purple[600]!, onTap: () { // 打开隐私设置页面 }, ), const Divider(height: 1), // 退出登录 _buildSimpleNavigationSetting( title: '退出登录', icon: Icons.logout, iconBgColor: Colors.red[50]!, iconColor: Colors.red[600]!, titleColor: Colors.red[600]!, onTap: () { // 退出登录确认对话框 Get.dialog( AlertDialog( title: const Text('退出登录'), content: const Text('确定要退出当前账号吗?'), actions: [ TextButton( onPressed: () => Get.back(), child: const Text('取消'), ), TextButton( onPressed: () { Get.back(); controller.signOut(); }, child: const Text('确定'), ), ], ), ); }, ), ], ), ), ], ); } // 关于应用部分 Widget _buildAboutSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 4.w, bottom: 8.h), child: Text( '关于应用', style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w500, color: Colors.blue[600], letterSpacing: 1, ), ), ), Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( width: 40.w, height: 40.w, decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF2196F3), Color(0xFF9C27B0)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12.r), ), child: Icon( Icons.headphones, size: 24.w, color: Colors.white, ), ), SizedBox(width: 12.w), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'DeepVoice', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.black87, ), ), SizedBox(height: 2.h), Text( '版本 2.4.1 (Build 87)', style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ], ), Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), decoration: BoxDecoration( color: Colors.blue[100], borderRadius: BorderRadius.circular(16.r), ), child: Text( '检查更新', style: TextStyle( fontSize: 12.sp, color: Colors.blue[600], ), ), ), ], ), ), SizedBox(height: 16.h), Center( child: Column( children: [ Text( '© 2023 DeepVoice Technologies', style: TextStyle( fontSize: 12.sp, color: Colors.grey[500], ), ), SizedBox(height: 4.h), Text( '连接世界,超越声音', style: TextStyle( fontSize: 12.sp, color: Colors.grey[500], ), ), ], ), ), ], ); } // 开关类设置项 Widget _buildToggleSetting({ required String title, String? subtitle, required IconData icon, required Color iconBgColor, required Color iconColor, required bool value, required Function(bool) onChanged, }) { return Padding( padding: EdgeInsets.all(16.w), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 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), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.black87, ), ), if (subtitle != null) SizedBox(height: 2.h), if (subtitle != null) Text( subtitle, style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ], ), Switch( value: value, onChanged: onChanged, activeColor: Colors.blue[600], ), ], ), ); } // 带导航的设置项 Widget _buildNavigationSetting({ required String title, String? subtitle, required IconData icon, required Color iconBgColor, required Color iconColor, required String value, TextStyle? valueStyle, required VoidCallback onTap, }) { return InkWell( onTap: onTap, child: Padding( padding: EdgeInsets.all(16.w), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 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), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.black87, ), ), if (subtitle != null) SizedBox(height: 2.h), if (subtitle != null) Text( subtitle, style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ], ), Row( children: [ Text( value, style: valueStyle ?? TextStyle( fontSize: 14.sp, color: Colors.black87, ), ), SizedBox(width: 8.w), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.chevron_right, size: 16.w, color: Colors.grey[500], ), ), ], ), ], ), ), ); } // 简单导航设置项 Widget _buildSimpleNavigationSetting({ required String title, String? subtitle, required IconData icon, required Color iconBgColor, required Color iconColor, Color? titleColor, required VoidCallback onTap, }) { return InkWell( onTap: onTap, child: Padding( padding: EdgeInsets.all(16.w), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 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), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: titleColor ?? Colors.black87, ), ), if (subtitle != null) SizedBox(height: 2.h), if (subtitle != null) Text( subtitle, style: TextStyle( fontSize: 12.sp, color: Colors.black54, ), ), ], ), ], ), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.chevron_right, size: 16.w, color: Colors.grey[500], ), ), ], ), ), ); } // 显示语言选择对话框 void _showLanguageSelectionDialog(bool isSource) { Get.dialog( Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.r), ), child: Padding( padding: EdgeInsets.all(16.w), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( isSource ? '选择源语言' : '选择目标语言', style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 16.h), SizedBox( height: 300.h, child: ListView( children: controller.availableLanguages.map((language) => RadioListTile( title: Text(language), value: language, groupValue: isSource ? controller.sourceLanguage.value : controller.targetLanguage.value, onChanged: (value) { if (value != null) { if (isSource) { controller.setSourceLanguage(value); } else { controller.setTargetLanguage(value); } Get.back(); } }, ), ).toList(), ), ), SizedBox(height: 16.h), TextButton( onPressed: () => Get.back(), child: const Text('取消'), ), ], ), ), ), ); } }