import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../controllers/profile_controller.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../../core/widgets/common_bottom_nav.dart'; import '../../../routes/app_routes.dart'; import 'dart:io'; import 'dart:ui'; import '../../common/webview_page.dart'; import '../../../core/utils/doc_url_helper.dart'; import 'unified_avatar.dart'; // ProfileView: 用户设置页面 // class ProfileView extends GetView { // const ProfileView({Key? key}) : super(key: key); // Widget _buildMenuItem({ // required String title, // required IconData icon, // String? subtitle, // required VoidCallback onTap, // }) { // return ListTile( // leading: Icon(icon, size: 24.sp, color: Colors.grey[700]), // title: Text( // title, // style: TextStyle( // fontSize: 16.sp, // fontWeight: FontWeight.w500, // ), // ), // subtitle: subtitle != null // ? Text( // subtitle, // style: TextStyle( // fontSize: 14.sp, // color: Colors.grey[600], // ), // ) // : null, // trailing: Icon( // Icons.chevron_right, // size: 24.sp, // color: Colors.grey[400], // ), // onTap: onTap, // ); // } // @override // Widget build(BuildContext context) { // return Scaffold( // backgroundColor: Colors.white, // appBar: AppBar( // backgroundColor: Colors.white, // elevation: 0, // title: Text( // '设置'.tr, // style: TextStyle( // fontSize: 17.sp, // fontWeight: FontWeight.w600, // color: Colors.black, // ), // ), // centerTitle: true, // ), // body: ListView( // children: [ // SizedBox(height: 12.h), // const Divider(), // _buildMenuItem( // title: '关于'.tr, // icon: Icons.info_outline, // onTap: () { // // TODO: 实现关于页面 // }, // ), // const Divider(), // _buildMenuItem( // title: '火山语音合成测试'.tr, // icon: Icons.record_voice_over, // subtitle: '测试火山语音TTS功能', // onTap: () { // Get.toNamed(Routes.TTS_TEST); // }, // ), // const Divider(), // _buildMenuItem( // title: '火山语音识别测试'.tr, // icon: Icons.mic_external_on, // subtitle: '测试火山语音ASR功能', // onTap: () { // Get.toNamed(Routes.VOLCANO_ASR_TEST); // }, // ), // const Divider(), // _buildMenuItem( // title: 'Azure语音识别测试'.tr, // icon: Icons.mic, // subtitle: '测试Azure语音ASR功能', // onTap: () { // Get.toNamed(Routes.AZURE_ASR_TEST); // }, // ), // const Divider(), // _buildMenuItem( // title: 'Azure语音合成测试'.tr, // icon: Icons.record_voice_over, // subtitle: '测试Azure语音TTS功能', // onTap: () { // Get.toNamed(Routes.AZURE_TTS_TEST); // }, // ), // const Divider(), // _buildMenuItem( // title: '本地语音合成测试'.tr, // icon: Icons.speaker_phone, // subtitle: '测试Flutter TTS本地语音合成功能', // onTap: () { // Get.toNamed(Routes.FLUTTER_TTS_TEST); // }, // ), // const Divider(), // _buildMenuItem( // title: '本地语音识别测试'.tr, // icon: Icons.mic_none, // subtitle: '测试Flutter本地语音识别功能', // onTap: () { // Get.toNamed(Routes.FLUTTER_ASR_TEST); // }, // ), // ], // ), // bottomNavigationBar: const CommonBottomNav(currentIndex: 2), // ); // } // } // EditProfileView: 编辑个人资料页面 class EditProfileView extends GetView { const EditProfileView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; final nameController = TextEditingController(text: controller.userInfo.value.name); return Scaffold( resizeToAvoidBottomInset: false, // 添加这一行,防止键盘挤压内容 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: () { controller.forceRollbackIfUnsaved(); Get.back(); }, ), // title: Text( // 'editProfile'.tr, // style: TextStyle( // fontSize: 17.sp, // fontWeight: FontWeight.w600, // color: isDarkMode ? Colors.white : Colors.black, // ), // ), actions: [ Obx(() => Visibility( visible: controller.hasEdits.value, child: controller.isUpdating.value ? Padding( padding: EdgeInsets.all(16.w), child: SizedBox( width: 20.w, height: 20.w, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( isDarkMode ? Colors.blue[300]! : Colors.blue, ), ), ), ) : TextButton( onPressed: () async { // 保存用户名和头像 await controller .updateUserNameAndAvatar(nameController.text); // 如果保存成功(没有编辑状态),延迟返回上一级页面让用户看到成功提示 if (!controller.hasEdits.value) { // 延迟跳转,让用户看到成功提示 Future.delayed(const Duration(milliseconds: 500), () { if (Get.isRegistered()) { Get.back(); } }); } }, child: Text( 'save'.tr, style: TextStyle( fontSize: 16.sp, color: isDarkMode ? Colors.blue[300] : Colors.blue, fontWeight: FontWeight.w500, ), ), ), )) ], ), // ignore: deprecated_member_use body: WillPopScope( onWillPop: () async { ProfileController.to.forceRollbackIfUnsaved(); return true; }, child: Padding( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildEditProfileSection( context, isDarkMode, nameController), SizedBox(height: 16.h), _buildAccountSettings(isDarkMode), SizedBox(height: 16.h), ])))); } // 新增:构建编辑资料区域的方法 Widget _buildEditProfileSection(BuildContext context, bool isDarkMode, TextEditingController nameController) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 4.w, bottom: 8.h), child: Text( 'editProfile'.tr, // 编辑个人信息 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: [ // 头像设置项 _buildAvatarSetting(isDarkMode), Divider( height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]), // 昵称设置项 _buildNicknameSetting(context, isDarkMode, nameController), ], ), ), ), ), ], ); } // 新增:构建头像设置项 Widget _buildAvatarSetting(bool isDarkMode) { return InkWell( onTap: () => controller.updateUserAvatar(), child: Padding( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 4.h), // 调整垂直间距 child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // 移除,让内容自然排列 children: [ // --- 添加图标 --- Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.blue[900]!.withOpacity(0.3) // 使用示例颜色 : Colors.blue[50]!, // 使用示例颜色 borderRadius: BorderRadius.circular(16.r), // 图标背景圆角 ), child: Icon( Icons.account_circle_outlined, // 头像图标 size: 18.w, color: isDarkMode ? Colors.blue[300]! : Colors.blue[600]!, // 图标颜色 ), ), SizedBox(width: 12.w), // 图标和文字间距 // --- --- Expanded( // 让文字占据剩余空间 child: Text( 'avatar'.tr, // 头像 style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: isDarkMode ? Colors.white : Colors.black87, ), ), ), // --- 右侧内容保持不变 --- Row( children: [ // 使用统一头像组件,避免闪烁问题 UnifiedAvatar( radius: 26.r, backgroundColor: Colors.grey[200], iconColor: Colors.grey, iconSize: 20.r, isDarkMode: isDarkMode, ), SizedBox(width: 8.w), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.chevron_right, size: 16.w, color: isDarkMode ? Colors.white70 : Colors.grey[500], ), ), ], ), // --- --- ], ), ), ); } // 新增:构建昵称设置项(双模式内联编辑) Widget _buildNicknameSetting(BuildContext context, bool isDarkMode, TextEditingController nameController) { return Obx(() { // 根据编辑状态显示不同的UI if (controller.isEditingNickname.value) { return _buildNicknameEditingMode(context, isDarkMode, nameController); } else { return _buildNicknameDisplayMode(context, isDarkMode, nameController); } }); } // 构建昵称显示模式 Widget _buildNicknameDisplayMode(BuildContext context, bool isDarkMode, TextEditingController nameController) { return InkWell( key: Key('nickname_edit_button'), // 添加测试Key onTap: () { // 开始内联编辑 nameController.text = controller.userInfo.value.name; controller.startEditingNickname(); }, child: Padding( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), child: Row( children: [ // 图标 Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.green[900]!.withOpacity(0.3) : Colors.green[50]!, borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.edit_outlined, size: 18.w, color: isDarkMode ? Colors.green[300]! : Colors.green[600]!, ), ), SizedBox(width: 12.w), // 标签 Expanded( child: Text( 'nickname'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: isDarkMode ? Colors.white : Colors.black87, ), ), ), // 右侧内容 Row( children: [ Obx(() => Text( controller.userInfo.value.name.isNotEmpty ? controller.userInfo.value.name : 'notSet'.tr, style: TextStyle( fontSize: 14.sp, color: isDarkMode ? Colors.white70 : Colors.grey[600], ), overflow: TextOverflow.ellipsis, )), SizedBox(width: 8.w), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.chevron_right, size: 16.w, color: isDarkMode ? Colors.white70 : Colors.grey[500], ), ), ], ), ], ), ), ); } // 构建昵称编辑模式 Widget _buildNicknameEditingMode(BuildContext context, bool isDarkMode, TextEditingController nameController) { return Padding( padding: EdgeInsets.symmetric( horizontal: 16.w, vertical: 16.h), // 与显示模式保持一致的padding child: Row( children: [ // 图标 - 保持与显示模式相同的绿色主题 Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.green[900]!.withOpacity(0.3) : Colors.green[50]!, borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.edit_outlined, // 保持与显示模式相同的图标 size: 18.w, color: isDarkMode ? Colors.green[300]! : Colors.green[600]!, ), ), SizedBox(width: 12.w), // 标签 - 保持与显示模式相同的布局 Expanded( child: Text( 'nickname'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: isDarkMode ? Colors.white : Colors.black87, ), ), ), // 右侧内容区域 - 与显示模式布局保持一致 Row( children: [ // 编辑输入框 - 替换原来的昵称文本显示区域 Container( constraints: BoxConstraints( minWidth: 80.w, // 确保有足够的编辑空间 maxWidth: 120.w, // 限制最大宽度保持布局稳定 ), child: TextField( controller: nameController, autofocus: true, textAlign: TextAlign.center, // 右对齐,与原昵称显示保持一致 style: TextStyle( fontSize: 14.sp, color: isDarkMode ? Colors.white70 : Colors.grey[600], ), decoration: InputDecoration( hintText: 'enterNickname'.tr, hintStyle: TextStyle( color: isDarkMode ? Colors.white54 : Colors.grey[500], fontSize: 14.sp, ), border: InputBorder.none, // 移除边框,保持简洁 enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, contentPadding: EdgeInsets.zero, // 移除内边距 isDense: true, ), onSubmitted: (value) { // 按回车确认编辑 controller.finishEditingNickname(value); }, onTapOutside: (event) { // 点击外部区域确认编辑 controller.finishEditingNickname(nameController.text); }, ), ), SizedBox(width: 8.w), // 右侧箭头图标 - 保持与显示模式完全相同 Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.chevron_right, size: 16.w, color: isDarkMode ? Colors.white70 : Colors.grey[500], ), ), ], ), ], ), ); } // _buildEditProfile(bool isDarkMode, TextEditingController nameController) { // return // //Padding( // //padding: EdgeInsets.all(16.w), // //child: // Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // Padding( // padding: EdgeInsets.only(left: 4.w, bottom: 8.h), // child: Text( // 'editProfile'.tr, // 账号设置 // style: TextStyle( // fontSize: 12.sp, // fontWeight: FontWeight.w500, // color: isDarkMode ? Colors.blue[400] : Colors.blue[600], // letterSpacing: 1, // ), // ), // ), // // 头像编辑 // Center( // child: GestureDetector( // onTap: () => controller.updateUserAvatar(), // child: Stack( // children: [ // Obx(() => CircleAvatar( // radius: 50.r, // backgroundImage: controller.localAvatar.value.isNotEmpty // ? FileImage(File(controller.localAvatar.value)) // : (controller.userInfo.value.avatar.isNotEmpty // ? NetworkImage(controller.userInfo.value.avatar) // : null) as ImageProvider?, // child: controller.userInfo.value.avatar.isEmpty // ? Icon(Icons.person, size: 50.r) // : null, // )), // Positioned( // right: 0, // bottom: 0, // child: Container( // padding: EdgeInsets.all(4.w), // decoration: const BoxDecoration( // color: Colors.blue, // shape: BoxShape.circle, // ), // child: Icon( // Icons.camera_alt, // size: 20.w, // color: Colors.white, // )), // ) // ], // )), // ), // SizedBox(height: 20.h), // // 昵称编辑 - 使用外部定义的controller而不是每次重建 // Row( // children: [ // Expanded( // child: TextField( // controller: nameController, // decoration: InputDecoration( // labelText: 'nickname'.tr, // border: const OutlineInputBorder(), // suffixIcon: nameController.text.isNotEmpty // ? IconButton( // icon: const Icon(Icons.clear), // onPressed: () { // nameController.clear(); // }, // ) // : null, // ), // ), // ), // ], // ), // ], // //), // ); // } Widget _buildAccountSettings(bool isDarkMode) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 4.w, bottom: 8.h), child: Text( 'accountSetting'.tr, // 账号设置 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: [ // 用户协议 _buildSimpleNavigationSetting( title: 'userAgreement'.tr, // 用户协议 icon: Icons.description_outlined, iconBgColor: isDarkMode ? Colors.purple[900]!.withOpacity(0.3) : Colors.purple[50]!, iconColor: isDarkMode ? Colors.purple[300]! : Colors.purple[600]!, titleColor: isDarkMode ? Colors.white : Colors.black87, onTap: () { Get.to(() => WebViewPage( url: userAgreementUrl(), title: 'userAgreement'.tr, )); }, isDarkMode: isDarkMode, ), Divider( height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]), // 隐私政策 _buildSimpleNavigationSetting( title: 'privacyPolicy'.tr, // 隐私政策 icon: Icons.privacy_tip_outlined, iconBgColor: isDarkMode ? Colors.purple[900]!.withOpacity(0.3) : Colors.purple[50]!, iconColor: isDarkMode ? Colors.purple[300]! : Colors.purple[600]!, titleColor: isDarkMode ? Colors.white : Colors.black87, onTap: () { Get.to(() => WebViewPage( url: privacyPolicyUrl(), title: 'privacyPolicy'.tr, )); }, isDarkMode: isDarkMode, ), Divider( height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]), // 清理缓存 _buildSimpleNavigationSetting( title: 'clean'.tr, // 清理缓存 icon: Icons.cleaning_services, iconBgColor: isDarkMode ? Colors.blue[900]!.withOpacity(0.3) : Colors.blue[50]!, iconColor: isDarkMode ? Colors.blue[300]! : Colors.blue[600]!, titleColor: isDarkMode ? Colors.white : Colors.black87, onTap: () { // 退出登录确认对话框 Get.dialog( AlertDialog( backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, title: Text( 'clean'.tr, // 清除缓存 style: TextStyle( color: isDarkMode ? Colors.white : Colors.black87, ), ), content: Text( 'cleanTips'.tr, // 确定要清除个人缓存吗? 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: () { Get.back(); controller.clean(); }, child: Text( 'confirm'.tr, // 确定 style: TextStyle( color: isDarkMode ? Colors.red[300] : Colors.red[600], ), ), ), ], ), ); }, isDarkMode: isDarkMode, ), Divider( height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]), // 退出登录 _buildSimpleNavigationSetting( title: 'logout'.tr, // 退出登录 icon: Icons.logout, iconBgColor: isDarkMode ? Colors.orange[900]!.withOpacity(0.3) : Colors.orange[50]!, iconColor: isDarkMode ? Colors.orange[300]! : Colors.orange[600]!, titleColor: isDarkMode ? Colors.orange[300]! : Colors.orange[600]!, onTap: () { // 退出登录确认对话框 Get.dialog( AlertDialog( backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, title: Text( 'logout'.tr, // 退出登录 style: TextStyle( color: isDarkMode ? Colors.white : Colors.black87, ), ), content: Text( 'logoutTips'.tr, // 确定要退出当前账号吗? 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: () { Get.back(); controller.signOut(); }, child: Text( 'confirm'.tr, // 确定 style: TextStyle( color: isDarkMode ? Colors.red[300] : Colors.red[600], ), ), ), ], ), ); }, isDarkMode: isDarkMode, ), Divider( height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]), // 注销账号 _buildSimpleNavigationSetting( title: 'deleteAccount'.tr, // 注销账号 icon: Icons.delete_forever, iconBgColor: isDarkMode ? Colors.red[900]!.withOpacity(0.3) : Colors.red[50]!, iconColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!, titleColor: isDarkMode ? Colors.red[300]! : Colors.red[600]!, onTap: () { // 注销账号确认对话框 Get.dialog( AlertDialog( backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, title: Text( 'deleteAccount'.tr, // 注销账号 style: TextStyle( color: isDarkMode ? Colors.white : Colors.black87, ), ), content: Text( 'deleteAccountTips'.tr, // 确定要永久删除您的账号吗?此操作不可撤销 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: () { Get.back(); controller.deleteAccount(); }, child: Text( 'confirm'.tr, // 确定 style: TextStyle( color: isDarkMode ? Colors.red[300] : Colors.red[600], ), ), ), ], ), ); }, isDarkMode: isDarkMode, ), ], ), ), ), ), ], ); } // 简单导航设置项 Widget _buildSimpleNavigationSetting({ required String title, String? subtitle, required IconData icon, required Color iconBgColor, required Color iconColor, Color? titleColor, Color? subtitleColor, required VoidCallback onTap, required bool isDarkMode, }) { return InkWell( onTap: onTap, 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, ), ], ), ), ], ), ), Container( width: 32.w, height: 32.w, decoration: BoxDecoration( color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100], borderRadius: BorderRadius.circular(16.r), ), child: Icon( Icons.chevron_right, size: 16.w, color: isDarkMode ? Colors.white70 : Colors.grey[500], ), ), ], ), ), ); } }