From 388c832f794a1c1739541e496ae5f460aed6ce7e Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Wed, 16 Jul 2025 13:07:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(profile):=20=E6=B7=BB=E5=8A=A0=E4=BC=9A?= =?UTF-8?q?=E8=AE=AE=E6=A8=A1=E5=9D=97=E8=B7=B3=E8=BD=AC=E7=9A=84=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E4=BF=A1=E6=81=AF=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 profile_meeting 路由和视图 - 在会议模块中集成个人信息控制器 - 统一头像显示逻辑 - 移除 SettingsController 中的冗余用户信息管理 --- .../meeting/bindings/meeting_binding.dart | 2 + .../meeting/views/meeting_mine_view.dart | 61 ++- .../controllers/profile_controller.dart | 13 +- .../profile/views/profile_meeting_view.dart | 477 ++++++++++++++++++ .../settings/bindings/settings_binding.dart | 8 +- .../controllers/settings_controller.dart | 150 +++--- lib/modules/settings/views/settings_view.dart | 84 ++- lib/routes/app_pages.dart | 8 + lib/routes/app_routes.dart | 1 + 9 files changed, 639 insertions(+), 165 deletions(-) create mode 100644 lib/modules/profile/views/profile_meeting_view.dart diff --git a/lib/modules/meeting/bindings/meeting_binding.dart b/lib/modules/meeting/bindings/meeting_binding.dart index e555c1194..0edd89e9b 100644 --- a/lib/modules/meeting/bindings/meeting_binding.dart +++ b/lib/modules/meeting/bindings/meeting_binding.dart @@ -2,6 +2,7 @@ import 'package:get/get.dart'; import '../controllers/meeting_controller.dart'; import '../controllers/meeting_home_controller.dart'; import '../controllers/meeting_mine_controller.dart'; +import '../../profile/controllers/profile_controller.dart'; class MeetingBinding extends Bindings { @override @@ -10,5 +11,6 @@ class MeetingBinding extends Bindings { Get.lazyPut(() => MeetingController()); Get.lazyPut(() => MeetingHomeController()); Get.lazyPut(() => MeetingMineController()); + Get.lazyPut(() => ProfileController()); } } diff --git a/lib/modules/meeting/views/meeting_mine_view.dart b/lib/modules/meeting/views/meeting_mine_view.dart index cceb7b243..77c9d0f43 100644 --- a/lib/modules/meeting/views/meeting_mine_view.dart +++ b/lib/modules/meeting/views/meeting_mine_view.dart @@ -1,5 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'dart:io'; +import '../../../routes/app_routes.dart'; +import '../../profile/controllers/profile_controller.dart'; class MeetingMineView extends StatefulWidget { const MeetingMineView({super.key}); @@ -93,32 +97,49 @@ class _MeetingMineViewState extends State { } Widget _head() { + final ProfileController profileCtrl = + Get.find(); // 从GetX中获取ProfileController实例 return Padding( padding: EdgeInsets.symmetric(vertical: 20.w), child: GestureDetector( - onTap: () {}, + onTap: () => Get.toNamed(Routes.profileMeeting), // 跳转到个人信息页面 child: Row( children: [ - Container( - width: 50.w, - height: 50.w, - margin: EdgeInsets.only(right: 10.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(50.w), - image: const DecorationImage( - image: NetworkImage( - 'https://pic8.iqiyipic.com/image/20250403/ed/a7/a_100013977_m_601_m75_318_424.avif'), - fit: BoxFit.cover, - ), - ), - ), + // 统一头像显示逻辑:本地头像 > 网络头像 > 默认图标 + Obx(() => Container( + width: 50.w, + height: 50.w, + margin: EdgeInsets.only(right: 10.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50.w), + ), + child: CircleAvatar( + radius: 25.w, + backgroundImage: profileCtrl.localAvatar.value.isNotEmpty + ? FileImage(File(profileCtrl.localAvatar.value)) + : (profileCtrl.userInfo.value.avatar.isNotEmpty + ? NetworkImage(profileCtrl.userInfo.value.avatar) + : null) as ImageProvider?, + backgroundColor: Colors.grey[200], + child: (profileCtrl.localAvatar.value.isEmpty && + profileCtrl.userInfo.value.avatar.isEmpty) + ? Icon( + Icons.person, + size: 25.r, + color: Colors.grey[600], + ) + : null, + ), + )), Expanded( - child: Text( - 'tianming liu', - style: TextStyle( - color: Colors.black87, - fontSize: 20.sp, - fontWeight: FontWeight.bold, + child: Obx( + () => Text( + profileCtrl.userInfo.value.name, + style: TextStyle( + color: Colors.black87, + fontSize: 20.sp, + fontWeight: FontWeight.bold, + ), ), ), ), diff --git a/lib/modules/profile/controllers/profile_controller.dart b/lib/modules/profile/controllers/profile_controller.dart index 3dd9b3864..ae71fea8b 100644 --- a/lib/modules/profile/controllers/profile_controller.dart +++ b/lib/modules/profile/controllers/profile_controller.dart @@ -91,7 +91,7 @@ class ProfileController extends GetxController { currentLanguage.value = languageCode; } } catch (e) { - print('Failed to load language preference: $e'); + Logger().e('Failed to load language preference: $e'); } } @@ -101,7 +101,7 @@ class ProfileController extends GetxController { await _storage.write('languageCode', locale.languageCode); await _storage.write('countryCode', locale.countryCode); } catch (e) { - print('Failed to save language preference: $e'); + Logger().e('Failed to save language preference: $e'); } } @@ -577,15 +577,6 @@ class ProfileController extends GetxController { _saveOriginalState(); await _syncLocalStorage(); - // 同步更新 SettingsController - if (Get.isRegistered()) { - final settingsController = Get.find(); - settingsController.userInfo.value.name = userInfo.value.name; - settingsController.userInfo.value.avatar = - '${userInfo.value.avatar}?time=${DateTime.now().millisecondsSinceEpoch}'; - settingsController.userInfo.refresh(); - } - // 重置编辑状态 hasEdits.value = false; diff --git a/lib/modules/profile/views/profile_meeting_view.dart b/lib/modules/profile/views/profile_meeting_view.dart new file mode 100644 index 000000000..a2bcad1c1 --- /dev/null +++ b/lib/modules/profile/views/profile_meeting_view.dart @@ -0,0 +1,477 @@ +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import '../controllers/profile_controller.dart'; + +class ProfileMeetingView extends GetView { + ProfileMeetingView({super.key}); + + // 昵称编辑控制器 - 与 profile_view.dart 保持一致 + final TextEditingController nameController = TextEditingController(); + + @override + Widget build(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + + return Scaffold( + backgroundColor: isDarkMode ? Colors.black : Colors.white, + appBar: _buildAppBar(isDarkMode), + body: _buildBody(isDarkMode), + ); + } + + PreferredSizeWidget _buildAppBar(bool isDarkMode) { + // 初始化 nameController 的文本内容 + nameController.text = controller.userInfo.value.name; + return AppBar( + backgroundColor: isDarkMode ? Colors.black : Colors.white, + elevation: 0, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + color: isDarkMode ? Colors.white : Colors.black87, + size: 20.w, + ), + onPressed: () => Get.back(), + ), + title: Text( + '账号和资料', + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + fontSize: 18.sp, + fontWeight: FontWeight.w600, + ), + ), + centerTitle: true, + 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, + ), + ), + ), + )) + ], + ); + } + + Widget _buildBody(bool isDarkMode) { + return SafeArea( + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 16.w), + children: [ + SizedBox(height: 4.h), + _buildAvatarSection(isDarkMode), + SizedBox(height: 16.h), + _buildNicknameItem(isDarkMode), + Divider( + height: 1.h, + color: isDarkMode ? Colors.grey[800] : Colors.grey[200]), + _buildLoginMethodItem(isDarkMode), + Divider( + height: 1.h, + color: isDarkMode ? Colors.grey[800] : Colors.grey[200]), + _buildManageLoginItem(isDarkMode), + Divider( + height: 1.h, + color: isDarkMode ? Colors.grey[800] : Colors.grey[200]), + SizedBox(height: 32.h), + _buildLogoutButton(isDarkMode), + SizedBox(height: 16.h), + _buildDeleteAccountButton(isDarkMode), + SizedBox(height: 8.h), + _buildWarningText(), + SizedBox(height: 32.h), + ], + ), + ); + } + + Widget _buildAvatarSection(bool isDarkMode) { + return Center( + child: Column( + children: [ + Obx(() => GestureDetector( + onTap: () => controller.updateUserAvatar(), + child: Stack( + children: [ + CircleAvatar( + radius: 40.r, + backgroundImage: controller.localAvatar.value.isNotEmpty + ? FileImage(File(controller.localAvatar.value)) + : (controller.userInfo.value.avatar.isNotEmpty + ? NetworkImage(controller.userInfo.value.avatar) + : null) as ImageProvider?, + backgroundColor: + isDarkMode ? Colors.grey[800] : Colors.grey[200], + child: (controller.localAvatar.value.isEmpty && + controller.userInfo.value.avatar.isEmpty) + ? Icon( + Icons.person, + size: 30.r, + color: isDarkMode + ? Colors.grey[400] + : Colors.grey[600], + ) + : null, + ), + Positioned( + bottom: 0, + right: 0, + child: Container( + width: 22.w, + height: 22.w, + decoration: BoxDecoration( + color: + isDarkMode ? Colors.grey[600] : Colors.grey[350], + shape: BoxShape.circle, + border: Border.all( + color: isDarkMode ? Colors.black : Colors.white, + width: 0.w, + ), + ), + child: Icon( + Icons.camera_alt, + size: 14.w, + color: Colors.black, + ), + ), + ), + ], + ), + )), + ], + ), + ); + } + + // 昵称设置项(双模式内联编辑)- 与 profile_view.dart 完全相同的逻辑 + Widget _buildNicknameItem(bool isDarkMode) { + return Obx(() { + // 根据编辑状态显示不同的UI + if (controller.isEditingNickname.value) { + return _buildNicknameEditingMode(isDarkMode, nameController); + } else { + return _buildNicknameDisplayMode(isDarkMode, nameController); + } + }); + } + + // 构建昵称显示模式 - 适配 profile_meeting_view 的 ListTile 样式 + Widget _buildNicknameDisplayMode( + bool isDarkMode, TextEditingController nameController) { + return ListTile( + onTap: () { + // 开始内联编辑 + nameController.text = controller.userInfo.value.name; + controller.startEditingNickname(); + }, + // 禁用水波纹效果 + splashColor: Colors.transparent, + title: Text( + 'nickname'.tr, + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Obx(() => Text( + controller.userInfo.value.name.isNotEmpty + ? controller.userInfo.value.name + : '未设置昵称', + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.white : Colors.grey[600], + ), + )), + SizedBox(width: 8.w), + Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ], + ), + ); + } + + // 构建昵称编辑模式 - 适配 profile_meeting_view 的 ListTile 样式 + Widget _buildNicknameEditingMode( + bool isDarkMode, TextEditingController nameController) { + return ListTile( + title: Text( + 'nickname'.tr, + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + // 编辑输入框 - 替换原来的昵称文本显示区域 + Container( + constraints: BoxConstraints( + minWidth: 80.w, // 确保有足够的编辑空间 + maxWidth: 120.w, // 限制最大宽度保持布局稳定 + ), + child: TextField( + controller: nameController, + autofocus: true, + textAlign: TextAlign.right, // 右对齐,与原昵称显示保持一致 + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.white : Colors.grey[600], + ), + decoration: InputDecoration( + hintText: '输入昵称', + hintStyle: TextStyle( + color: isDarkMode ? Colors.grey[500] : Colors.grey[400], + fontSize: 16.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), + // 保持原有的箭头图标位置,但在编辑模式下可以考虑隐藏或改变 + Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ], + ), + ); + } + + Widget _buildLoginMethodItem(bool isDarkMode) { + return ListTile( + title: Text( + '登录方式', + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + trailing: Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ); + } + + Widget _buildManageLoginItem(bool isDarkMode) { + return ListTile( + title: Text( + '管理我的登录', + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + trailing: Icon( + Icons.arrow_forward_ios, + size: 16.w, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ); + } + + Widget _buildLogoutButton(bool isDarkMode) { + return SizedBox( + width: double.infinity, + height: 48.h, + child: OutlinedButton( + onPressed: () => _showLogoutDialog(isDarkMode), + style: OutlinedButton.styleFrom( + backgroundColor: isDarkMode ? Colors.grey[900] : Colors.grey[50], + side: BorderSide( + color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.r), + ), + ), + child: Text( + '退出登录', + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.white : Colors.black87, + ), + ), + ), + ); + } + + Widget _buildDeleteAccountButton(bool isDarkMode) { + return SizedBox( + width: double.infinity, + height: 48.h, + child: ElevatedButton( + onPressed: () => _showDeleteAccountDialog(isDarkMode), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.r), + ), + ), + child: Text( + '删除账号', + style: TextStyle( + fontSize: 16.sp, + color: Colors.white, + ), + ), + ), + ); + } + + Widget _buildWarningText() { + return Text( + '警告:您的账号信息和所有文件将被永久删除。', + style: TextStyle( + fontSize: 12.sp, + color: Colors.red, + ), + textAlign: TextAlign.center, + ); + } + +//退出登录提示窗 + void _showLogoutDialog(bool isDarkMode) { + Get.dialog( + AlertDialog( + backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, + title: Text( + '退出登录', + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + ), + ), + content: Text( + '确定要退出当前账号吗?\n请确认所有转写任务已完成。', + style: TextStyle( + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text( + 'cancel'.tr, + style: TextStyle( + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + ), + TextButton( + onPressed: () { + Get.back(); + controller.signOut(); + }, + child: Text( + 'confirm'.tr, + style: const TextStyle( + color: Colors.red, + ), + ), + ), + ], + ), + ); + } + + void _showDeleteAccountDialog(bool isDarkMode) { + Get.dialog( + AlertDialog( + backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, + title: Text( + '删除账号', + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + ), + ), + content: Text( + '警告:您的账号信息和所有文件将被永久删除。', + style: TextStyle( + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text( + '取消', + style: TextStyle( + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], + ), + ), + ), + TextButton( + onPressed: () { + Get.back(); + controller.deleteAccount(); + }, + child: Text( + 'comfirm'.tr, + style: const TextStyle( + color: Colors.red, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/modules/settings/bindings/settings_binding.dart b/lib/modules/settings/bindings/settings_binding.dart index f8ff3eb08..dae35e08d 100644 --- a/lib/modules/settings/bindings/settings_binding.dart +++ b/lib/modules/settings/bindings/settings_binding.dart @@ -1,11 +1,11 @@ import 'package:get/get.dart'; +import '../../profile/controllers/profile_controller.dart'; import '../controllers/settings_controller.dart'; class SettingsBinding extends Bindings { @override void dependencies() { - Get.lazyPut( - () => SettingsController(), - ); + Get.lazyPut(() => SettingsController()); + Get.lazyPut(() => ProfileController()); } -} \ No newline at end of file +} diff --git a/lib/modules/settings/controllers/settings_controller.dart b/lib/modules/settings/controllers/settings_controller.dart index 40fb97440..5b92b5474 100644 --- a/lib/modules/settings/controllers/settings_controller.dart +++ b/lib/modules/settings/controllers/settings_controller.dart @@ -121,8 +121,8 @@ class SettingsController extends GetxController { RxString timbreName = 'defaultTimbre'.obs; //用户信息 - static const String userKey = 'user_info'; - final Rx userInfo = User.instance.obs; //使用单例实例 + // static const String userKey = 'user_info'; + // final Rx userInfo = User.instance.obs; //使用单例实例 // 添加版本信息变量 final appVersion = ''.obs; @@ -234,7 +234,7 @@ class SettingsController extends GetxController { _loadCurrentSpeechServiceType(); //获取用户信息 - loadUserInfo(); + // loadUserInfo(); // 获取应用版本信息 getAppVersion(); @@ -254,71 +254,71 @@ class SettingsController extends GetxController { } } - void loadUserInfo() { - final userJson = _storage.read(userKey); - Logger().d('加载用户信息: $userJson'); - - if (userJson != null) { - userInfo.value = User.instance; - Logger().d('用户信息已加载: ${userInfo.value.toJson()}'); - - if (userInfo.value.avatar.isNotEmpty) { - Logger().d('开始下载头像'); - _downloadAndSaveAvatar(userInfo.value.avatar); - } else { - Logger().d('用户没有头像'); - } - } else { - Logger().d('没有找到用户信息'); - } - } + // void loadUserInfo() { + // final userJson = _storage.read(userKey); + // Logger().d('加载用户信息: $userJson'); + + // if (userJson != null) { + // userInfo.value = User.instance; + // Logger().d('用户信息已加载: ${userInfo.value.toJson()}'); + + // if (userInfo.value.avatar.isNotEmpty) { + // Logger().d('开始下载头像'); + // _downloadAndSaveAvatar(userInfo.value.avatar); + // } else { + // Logger().d('用户没有头像'); + // } + // } else { + // Logger().d('没有找到用户信息'); + // } + // } - Future saveUserInfo() async { - await _storage.write(userKey, userInfo.value.toJson()); - } + // Future saveUserInfo() async { + // await _storage.write(userKey, userInfo.value.toJson()); + // } // 下载并保存远程头像 - Future _downloadAndSaveAvatar(String url) async { - try { - Logger().d('开始下载头像: $url'); - - final dio = Dio(BaseOptions( - headers: { - 'accept': '*/*', - 'Authorization': _storage.read("logintoken"), - }, - )); - - final response = await dio.get( - url, - options: Options(responseType: ResponseType.bytes), - ); - - Logger().d('下载状态: ${response.statusCode}'); - - if (response.statusCode == 200) { - // 保存到应用文档目录 - final appDir = await getApplicationSupportDirectory(); - final fileName = - '/UserAvatar/avatar_${DateTime.now().millisecondsSinceEpoch}.jpg'; - final localPath = '${appDir.path}/$fileName'; - -// 确保目录存在 - final file = File(localPath); - await file.parent.create(recursive: true); - - await file.writeAsBytes(response.data); - - // 更新本地头像路径 - //localAvatar.value = localPath; - await _storage.write('local_avatar', localPath); - Logger().d('头像已下载到本地: $localPath'); - //Get.snackbar('头像', '头像已下载到本地'); - } - } catch (e) { - Logger().e('下载头像失败: $e'); - } - } +// Future _downloadAndSaveAvatar(String url) async { +// try { +// Logger().d('开始下载头像: $url'); + +// final dio = Dio(BaseOptions( +// headers: { +// 'accept': '*/*', +// 'Authorization': _storage.read("logintoken"), +// }, +// )); + +// final response = await dio.get( +// url, +// options: Options(responseType: ResponseType.bytes), +// ); + +// Logger().d('下载状态: ${response.statusCode}'); + +// if (response.statusCode == 200) { +// // 保存到应用文档目录 +// final appDir = await getApplicationSupportDirectory(); +// final fileName = +// '/UserAvatar/avatar_${DateTime.now().millisecondsSinceEpoch}.jpg'; +// final localPath = '${appDir.path}/$fileName'; + +// // 确保目录存在 +// final file = File(localPath); +// await file.parent.create(recursive: true); + +// await file.writeAsBytes(response.data); + +// // 更新本地头像路径 +// //localAvatar.value = localPath; +// await _storage.write('local_avatar', localPath); +// Logger().d('头像已下载到本地: $localPath'); +// //Get.snackbar('头像', '头像已下载到本地'); +// } +// } catch (e) { +// Logger().e('下载头像失败: $e'); +// } +// } // Future updateUserAvatar() async { // final XFile? image = await _picker.pickImage( @@ -338,16 +338,16 @@ class SettingsController extends GetxController { // } // } - Future updateUserName(String name) async { - if (name.trim().isNotEmpty) { - userInfo.update((user) { - if (user != null) { - user.name = name.trim(); - } - }); - await saveUserInfo(); - } - } + // Future updateUserName(String name) async { + // if (name.trim().isNotEmpty) { + // userInfo.update((user) { + // if (user != null) { + // user.name = name.trim(); + // } + // }); + // await saveUserInfo(); + // } + // } // Future updateDeviceName(String deviceName) async { // userInfo.update((user) { diff --git a/lib/modules/settings/views/settings_view.dart b/lib/modules/settings/views/settings_view.dart index 7f72efe65..f3beae7e6 100644 --- a/lib/modules/settings/views/settings_view.dart +++ b/lib/modules/settings/views/settings_view.dart @@ -10,6 +10,7 @@ import '../../../routes/app_routes.dart'; //import '../../../data/models/user_Info.dart'; import 'dart:io'; import '../../common/webview_page.dart'; +import '../../../modules/profile/controllers/profile_controller.dart'; class SettingsView extends GetView { const SettingsView({Key? key}) : super(key: key); @@ -60,6 +61,8 @@ class SettingsView extends GetView { // 用户信息卡片 Widget _buildUserInfoCard(bool isDarkMode) { + final ProfileController profileCtrl = + Get.find(); // 从GetX中获取ProfileController实例 return GestureDetector( onTap: () => Get.toNamed(Routes.editProfile), child: Container( @@ -112,58 +115,27 @@ class SettingsView extends GetView { ], ), child: ClipRRect( - // 裁剪圆形头像 - borderRadius: BorderRadius.circular(30.r), - child: controller.userInfo.value.avatar.isEmpty - ? Container( - decoration: BoxDecoration( - color: Colors.blue[600], - borderRadius: BorderRadius.circular(30.r), - ), - child: Center( - child: Text( - controller - .userInfo.value.name.isNotEmpty - ? controller.userInfo.value.name[0] - .toUpperCase() - : '?', - style: TextStyle( - color: Colors.white, - fontSize: 24.sp, - fontWeight: FontWeight.bold, - ), - ), - ), + // 裁剪圆形头像 + borderRadius: BorderRadius.circular(30.r), + child: CircleAvatar( + radius: 30.r, + // 统一头像显示优先级:本地头像 > 网络头像 > 默认图标 + backgroundImage: profileCtrl.localAvatar.value.isNotEmpty + ? FileImage(File(profileCtrl.localAvatar.value)) + : (profileCtrl.userInfo.value.avatar.isNotEmpty + ? NetworkImage(profileCtrl.userInfo.value.avatar) + : null) as ImageProvider?, + backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[200], + child: (profileCtrl.localAvatar.value.isEmpty && + profileCtrl.userInfo.value.avatar.isEmpty) + ? Icon( + Icons.person, + size: 30.r, + color: isDarkMode ? Colors.grey[400] : Colors.grey[600], ) - : Image.network( - controller.userInfo.value.avatar, - fit: BoxFit.cover, - errorBuilder: (context, error, stackTrace) { - // 当图片加载失败时显示用户名首字母 - return Container( - decoration: BoxDecoration( - color: Colors.blue[600], - borderRadius: - BorderRadius.circular(30.r), - ), - child: Center( - child: Text( - controller.userInfo.value.name - .isNotEmpty - ? controller - .userInfo.value.name[0] - .toUpperCase() - : '?', - style: TextStyle( - color: Colors.white, - fontSize: 24.sp, - fontWeight: FontWeight.bold, - ), - ), - ), - ); - }, - )), + : null, + ), + ), ), )), SizedBox(width: 16.w), @@ -175,7 +147,7 @@ class SettingsView extends GetView { children: [ Text( //用户名 - controller.userInfo.value.name, + profileCtrl.userInfo.value.name, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, @@ -200,7 +172,7 @@ class SettingsView extends GetView { 2: 'proUser', //'专业用户' }; final membershipString = membershipMap[ - controller.userInfo.value.viplv] ?? + profileCtrl.userInfo.value.viplv] ?? 'Unknown'; return Text( membershipString.tr, // 会员等级 @@ -228,7 +200,7 @@ class SettingsView extends GetView { ), SizedBox(height: 4.h), Text( - 'ID:${controller.userInfo.value.uid}', + 'ID:${profileCtrl.userInfo.value.uid}', style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.black54, @@ -802,7 +774,9 @@ class SettingsView extends GetView { 'checkUpdates'.tr, // 检查更新 style: TextStyle( fontSize: 12.sp, - color: isDarkMode ? Colors.blue[300] : Colors.blue[600], + color: isDarkMode + ? Colors.blue[300] + : Colors.blue[600], height: 1.2, // 稍微减少行高,适应FittedBox ), textAlign: TextAlign.center, diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index 88f7f07c6..10d791d6c 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -18,6 +18,7 @@ import '../modules/meeting/views/meeting_view.dart'; import '../modules/opus_test/bindings/opus_test_binding.dart'; import '../modules/opus_test/views/opus_test_view.dart'; import '../modules/profile/views/profile_view.dart'; +import '../modules/profile/views/profile_meeting_view.dart'; import '../modules/profile/bindings/profile_binding.dart'; // import '../modules/chat/bindings/chat_binding.dart'; //import '../modules/chat/views/chat_view.dart'; @@ -126,6 +127,13 @@ abstract class AppPages { transition: Transition.rightToLeft, transitionDuration: Duration(milliseconds: 250), ), + GetPage( + name: Routes.profileMeeting, + page: () => ProfileMeetingView(), + binding: ProfileBinding(), + transition: Transition.rightToLeft, + transitionDuration: Duration(milliseconds: 250), + ), GetPage( name: Routes.translation, page: () => const TranslationView(), diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index 7942bfd73..e700acb92 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -11,6 +11,7 @@ abstract class Routes { static const chat = '/chat'; static const profile = '/profile'; static const editProfile = '/edit_profile'; + static const profileMeeting = '/profile_meeting'; // 个人信息页面(从会议模块跳转) // 设备管理 static const OTA_UPGRADE = '/ota_upgrade'; // OTA升级