Browse Source

Merge branch 'lxm'

weicu
lxm 2 years ago
parent
commit
54dbdacb8f
  1. 4
      lib/data/models/user_Info.dart
  2. 39
      lib/data/models/user_model.dart
  3. 2
      lib/main.dart
  4. 55
      lib/modules/profile/controllers/profile_controller.dart
  5. 7
      lib/modules/profile/views/profile_view.dart
  6. 8
      lib/modules/settings/controllers/settings_controller.dart
  7. 510
      lib/modules/settings/views/settings_view.dart

4
lib/data/models/user_Info.dart

@ -24,6 +24,7 @@ class User {
String phone; String phone;
String phonemac; String phonemac;
String password; String password;
int membershipLevel=0;//添加会员等级字段,0表示普通用户
// final Int64 lastbettime; // final Int64 lastbettime;
// final Int64 createtime; // final Int64 createtime;
// final String wxopenid; // final String wxopenid;
@ -42,6 +43,7 @@ class User {
required this.phone, required this.phone,
required this.phonemac, required this.phonemac,
required this.password, required this.password,
this.membershipLevel = 0, // 添加默认值
// required this.lastbettime, // required this.lastbettime,
// required this.createtime, // required this.createtime,
// required this.wxopenid, // required this.wxopenid,
@ -66,6 +68,7 @@ class User {
phone: (userData?['phone'] as String?) ?? '', phone: (userData?['phone'] as String?) ?? '',
phonemac: (userData?['phonemac'] as String?) ?? '', phonemac: (userData?['phonemac'] as String?) ?? '',
password: (userData?['password'] as String?) ?? '', password: (userData?['password'] as String?) ?? '',
membershipLevel: (userData?['membershipLevel'] as int?) ?? 0, // 提供默认值
// lastbettime: _parseTimestamp(userData['lastbettime']), // lastbettime: _parseTimestamp(userData['lastbettime']),
// createtime: _parseTimestamp(userData['createtime']), // createtime: _parseTimestamp(userData['createtime']),
// wxopenid: (userData?['wxopenid'] as String?) ?? '', // wxopenid: (userData?['wxopenid'] as String?) ?? '',
@ -111,6 +114,7 @@ class User {
'phone': phone, 'phone': phone,
'phonemac': phonemac, 'phonemac': phonemac,
'password': password, 'password': password,
'membershipLevel': membershipLevel,
// 'lastbettime': lastbettime, // 'lastbettime': lastbettime,
// 'createtime': createtime, // 'createtime': createtime,
// 'wxopenid': wxopenid, // 'wxopenid': wxopenid,

39
lib/data/models/user_model.dart

@ -1,39 +0,0 @@
class UserModel {
String name; // 用户名
String avatar; // 头像
String id;
//final String deviceName;
String membershipLevel; // 会员等级
UserModel({
required this.name,
required this.avatar,
required this.id,
//required this.deviceName,
required this.membershipLevel,
});
Map<String, dynamic> toJson() => {
'name': name,
'avatar': avatar,
'id': id,
//'deviceName': deviceName,
'membershipLevel': membershipLevel,
};
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
name: json['name'] ?? '未设置昵称',
avatar: json['avatar'] ?? '',
id: json['id'] ?? '',
//deviceName: json['deviceName'] ?? '',
membershipLevel: json['membershipLevel'] ?? '普通会员',
);
factory UserModel.defaultUser() => UserModel(
name: '未设置昵称',
avatar: '',
id: 'DeepSound_${DateTime.now().millisecondsSinceEpoch.toString()}',
//deviceName: '',
membershipLevel: '普通会员',
);
}

2
lib/main.dart

@ -65,7 +65,7 @@ class MainApp extends StatelessWidget {
splitScreenMode: true, splitScreenMode: true,
builder: (_, child) { builder: (_, child) {
return GetMaterialApp( return GetMaterialApp(
title: 'Deep Voice', title: 'DeepSound',
theme: AppTheme.lightTheme, theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme, darkTheme: AppTheme.darkTheme,
themeMode: themeMode, // 使用提前获取的主题模式 themeMode: themeMode, // 使用提前获取的主题模式

55
lib/modules/profile/controllers/profile_controller.dart

@ -1,11 +1,13 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
import '../../../data/models/user_model.dart'; import '../../../data/models/user_Info.dart';
import '../../settings/controllers/settings_controller.dart'; import '../../settings/controllers/settings_controller.dart';
import 'dart:io'; import 'dart:io';
import 'dart:convert';
import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart';
class ProfileController extends GetxController { class ProfileController extends GetxController {
@ -20,7 +22,8 @@ class ProfileController extends GetxController {
static const String userKey = 'user_info'; static const String userKey = 'user_info';
final _storage = GetStorage(); final _storage = GetStorage();
final ImagePicker _picker = ImagePicker(); final ImagePicker _picker = ImagePicker();
final Rx<UserModel> userInfo = UserModel.defaultUser().obs; final Rx<User> userInfo = User.instance.obs;
//final RxString localAvatar = ''.obs;
// 使用响应式变量 // 使用响应式变量
final currentLanguage = 'zh'.obs; final currentLanguage = 'zh'.obs;
@ -111,10 +114,48 @@ class ProfileController extends GetxController {
// _isEditing.value = !_isEditing.value; // _isEditing.value = !_isEditing.value;
// } // }
// 更新用户信息到后端
Future<void> _syncWithBackend() async {
try {
// 准备数据
Map<String, dynamic> data = {
"image": "", // 默认空字符串
"name": userInfo.value.name,
"language": currentLanguage.value,
};
// 如果有头像,转换为base64
if (userInfo.value.avatar.isNotEmpty) {
File imageFile = File(userInfo.value.avatar);
List<int> imageBytes = await imageFile.readAsBytes();
String base64Image = base64Encode(imageBytes);
data["image"] = base64Image;
}
// 调用API
final response = await GetConnect().post(
'https://www.deapsound.com:443/api/home/user_setting',
headers: {
'accept': 'application/json',
'Content-Type': 'application/json',
},
data,
);
if (response.statusCode != 200) {
throw '更新失败:${response.body}';
}
} catch (e) {
Logger().e('同步到后端失败: $e');
Get.snackbar('错误','同步到服务器失败,请重试');
throw e;
}
}
void loadUserInfo() { void loadUserInfo() {
final userJson = _storage.read(userKey); final userJson = _storage.read(userKey);
if (userJson != null) { if (userJson != null) {
userInfo.value = UserModel.fromJson(userJson); userInfo.value = User.instance;
} }
} }
@ -162,7 +203,8 @@ class ProfileController extends GetxController {
user.avatar = image.path; user.avatar = image.path;
} }
}); });
await saveUserInfo(); await saveUserInfo();//保存到本地
await _syncWithBackend();//同步到后端
// 通知 SettingsController 更新 // 通知 SettingsController 更新
if (Get.isRegistered<SettingsController>()) { if (Get.isRegistered<SettingsController>()) {
@ -185,7 +227,8 @@ class ProfileController extends GetxController {
} }
}); });
await saveUserInfo(); await saveUserInfo();//保存到本地
await _syncWithBackend();//同步到后端
// 同步更新 SettingsController // 同步更新 SettingsController
if (Get.isRegistered<SettingsController>()) { if (Get.isRegistered<SettingsController>()) {
@ -194,7 +237,7 @@ class ProfileController extends GetxController {
} }
} catch (e) { } catch (e) {
Logger().e('Error updating name: $e'); Logger().e('Error updating name: $e');
Get.snackbar('Error', 'Failed to update user name'); Get.snackbar('错误', 'Failed to update user name');
} }
} }
} }

7
lib/modules/profile/views/profile_view.dart

@ -169,10 +169,9 @@ class EditProfileView extends GetView<ProfileController> {
children: [ children: [
Obx(() => CircleAvatar( Obx(() => CircleAvatar(
radius: 50.r, radius: 50.r,
backgroundImage: backgroundImage: controller
controller.userInfo.value.avatar.isNotEmpty .userInfo.value.avatar.isNotEmpty
? FileImage( ? NetworkImage(controller.userInfo.value.avatar)
File(controller.userInfo.value.avatar))
: null, : null,
child: controller.userInfo.value.avatar.isEmpty child: controller.userInfo.value.avatar.isEmpty
? Icon(Icons.person, size: 50.r) ? Icon(Icons.person, size: 50.r)

8
lib/modules/settings/controllers/settings_controller.dart

@ -1,3 +1,4 @@
import 'package:firebase_auth/firebase_auth.dart' as firebase;
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
@ -5,7 +6,8 @@ import 'package:get_storage/get_storage.dart';
import '../../../core/themes/theme_service.dart'; import '../../../core/themes/theme_service.dart';
import '../../../data/services/speech_factory.dart'; import '../../../data/services/speech_factory.dart';
import '../models/language_model.dart'; import '../models/language_model.dart';
import '../../../data/models/user_model.dart'; //import '../../../data/models/user_model.dart';
import '../../../data/models/user_Info.dart';
class SettingsController extends GetxController { class SettingsController extends GetxController {
// 语言设置 // 语言设置
@ -61,7 +63,7 @@ class SettingsController extends GetxController {
static const String userKey='user_info'; static const String userKey='user_info';
//final _storage=GetStorage(); //final _storage=GetStorage();
final ImagePicker _picker=ImagePicker(); final ImagePicker _picker=ImagePicker();
final Rx<UserModel> userInfo=UserModel.defaultUser().obs; final Rx<User> userInfo=User.instance.obs;//使用单例实例
@override @override
void onInit() { void onInit() {
@ -86,7 +88,7 @@ class SettingsController extends GetxController {
void loadUserInfo() { void loadUserInfo() {
final userJson = _storage.read(userKey); final userJson = _storage.read(userKey);
if (userJson != null) { if (userJson != null) {
userInfo.value = UserModel.fromJson(userJson); userInfo.value = User.instance;
} }
} }

510
lib/modules/settings/views/settings_view.dart

@ -1,24 +1,25 @@
import 'package:app_settings/app_settings.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'dart:ui'; import 'dart:ui';
import '../../../core/theme/app_colors.dart';
import '../controllers/settings_controller.dart'; import '../controllers/settings_controller.dart';
import '../../../core/widgets/common_bottom_nav.dart'; import '../../../core/widgets/common_bottom_nav.dart';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
import '../../../data/models/user_Info.dart'; //import '../../../data/models/user_Info.dart';
import 'dart:io';
class SettingsView extends GetView<SettingsController> { class SettingsView extends GetView<SettingsController> {
const SettingsView({Key? key}) : super(key: key); const SettingsView({Key? key}) : super(key: key);
// 正确获取用户名方式 // 正确获取用户名方式
String get userName => User.getname(); // String get userName => User.getname();
String get deviceInfo => User.getdeviceInfo(); // String get deviceInfo => User.getdeviceInfo();
String get userId => User.getuserId(); // String get userId => User.getuserId();
String get standing => User.getstanding(); // String get standing => User.getstanding();
String get avatar => User.getnavatar(); // String get avatar => User.getnavatar();
//String get avatar =>
//"https://lh3.googleusercontent.com/a/ACg8ocJw96pHqo3uceyxyrWziQr8eGS-CZZ_NhRBNC_EvmGkAyf6TQ=s96-c";
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// 直接使用 Theme.of(context) 获取当前主题 // 直接使用 Theme.of(context) 获取当前主题
@ -30,7 +31,7 @@ class SettingsView extends GetView<SettingsController> {
backgroundColor: isDarkMode ? Colors.black : Colors.white, backgroundColor: isDarkMode ? Colors.black : Colors.white,
elevation: 0.5, elevation: 0.5,
title: Text( title: Text(
'设置', 'settings'.tr, // 设置
style: TextStyle( style: TextStyle(
fontSize: 17.sp, fontSize: 17.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -81,6 +82,7 @@ class SettingsView extends GetView<SettingsController> {
], ],
), ),
child: ClipRRect( child: ClipRRect(
//裁剪圆角矩形
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
child: BackdropFilter( child: BackdropFilter(
filter: isDarkMode filter: isDarkMode
@ -88,7 +90,10 @@ class SettingsView extends GetView<SettingsController> {
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Row( child: Row(
children: [ children: [
Container( Obx(() => GestureDetector(
//onTap: ()=>controller.updateUserAvatar(),
child: Container(
//用户头像部分
width: 60.w, width: 60.w,
height: 60.w, height: 60.w,
decoration: BoxDecoration( decoration: BoxDecoration(
@ -102,25 +107,35 @@ class SettingsView extends GetView<SettingsController> {
], ],
), ),
child: ClipRRect( child: ClipRRect(
// 裁剪圆形头像
borderRadius: BorderRadius.circular(30.r), borderRadius: BorderRadius.circular(30.r),
child: Image.network( child: controller.userInfo.value.avatar.isEmpty
avatar, ? Image.network(
fit: BoxFit.cover, 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80',
), fit: BoxFit.cover, // 图片填充方式
), )
), : Image.network(
controller.userInfo.value.avatar,
fit: BoxFit.cover, // 图片填充方式
)),
),
)),
SizedBox(width: 16.w), SizedBox(width: 16.w),
Expanded( Expanded(
child: Column( // 占据剩余空间
crossAxisAlignment: CrossAxisAlignment.start, child: Obx(
() => Column(
crossAxisAlignment: CrossAxisAlignment.start, // 左对齐
children: [ children: [
Text( Text(
userName, //用户名
controller.userInfo.value.name,
style: TextStyle( style: TextStyle(
fontSize: 18.sp, fontSize: 18.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
overflow: TextOverflow.ellipsis,
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Row( Row(
@ -132,22 +147,33 @@ class SettingsView extends GetView<SettingsController> {
color: Colors.blue[600], color: Colors.blue[600],
borderRadius: BorderRadius.circular(10.r), borderRadius: BorderRadius.circular(10.r),
), ),
child: Text( child: Obx(() {
standing, final membershipMap = {
0: 'freeUser', //'免费用户'
1: 'standardUser', //'标准用户'
2: 'proUser', //'专业用户'
};
final membershipString = membershipMap[controller
.userInfo.value.membershipLevel] ??
'Unknown';
return Text(
membershipString,
style: TextStyle( style: TextStyle(
fontSize: 10.sp, fontSize: 10.sp,
color: Colors.white, color: Colors.white,
), ),
), );
}),
), ),
SizedBox(width: 8.w), SizedBox(width: 8.w),
Flexible( Flexible(
child: Text( child: Text(
deviceInfo, '${'joinDevice'.tr} DeepSound Pro', // 已连接设备:
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: color: isDarkMode
isDarkMode ? Colors.white70 : Colors.black54, ? Colors.white70
: Colors.black54,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -156,7 +182,7 @@ class SettingsView extends GetView<SettingsController> {
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Text( Text(
userId, controller.userInfo.value.uid,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
@ -165,7 +191,9 @@ class SettingsView extends GetView<SettingsController> {
], ],
), ),
), ),
),
Container( Container(
// 编辑按钮
width: 32.w, width: 32.w,
height: 32.w, height: 32.w,
decoration: BoxDecoration( decoration: BoxDecoration(
@ -181,12 +209,14 @@ class SettingsView extends GetView<SettingsController> {
), ),
], ],
), ),
child: InkWell(
onTap: () => Get.toNamed(Routes.editProfile),
child: Icon( child: Icon(
Icons.edit, Icons.edit,
size: 16.w, size: 16.w,
color: isDarkMode ? Colors.white70 : Colors.grey[600], color: isDarkMode ? Colors.white70 : Colors.grey[600],
), ),
), )),
], ],
), ),
), ),
@ -202,7 +232,7 @@ class SettingsView extends GetView<SettingsController> {
Padding( Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text( child: Text(
'系统设置', 'systemSetting'.tr, // 系统设置
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -233,23 +263,26 @@ class SettingsView extends GetView<SettingsController> {
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Column( child: Column(
children: [ children: [
// 通知设置 // 语言设置
_buildSimpleNavigationSetting( Obx(
title: '通知设置', () => _buildSimpleNavigationSetting(
subtitle: '管理应用推送和提醒', title: 'languageSetting'.tr, // 语言设置
icon: Icons.notifications_none, subtitle: controller.language.value.name.tr,
icon: Icons.language,
iconBgColor: isDarkMode iconBgColor: isDarkMode
? Colors.indigo[900]!.withOpacity(0.3) ? Colors.indigo[900]!.withOpacity(0.3)
: Colors.indigo[100]!, : Colors.indigo[100]!,
iconColor: iconColor: isDarkMode
isDarkMode ? Colors.indigo[300]! : Colors.indigo[600]!, ? Colors.indigo[300]!
: Colors.indigo[600]!,
titleColor: isDarkMode ? Colors.white : null, titleColor: isDarkMode ? Colors.white : null,
subtitleColor: isDarkMode ? Colors.white70 : null, subtitleColor: isDarkMode ? Colors.white70 : null,
onTap: () { onTap: () {
// 打开通知设置页面 _showLanguageSelectionDialog(isDarkMode);
}, },
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
), ),
),
Divider( Divider(
height: 1, height: 1,
color: isDarkMode color: isDarkMode
@ -258,8 +291,8 @@ class SettingsView extends GetView<SettingsController> {
// 主题设置 // 主题设置
_buildToggleSetting( _buildToggleSetting(
title: '暗黑模式', title: 'darkMode'.tr, // 暗黑模式
subtitle: '切换应用的明暗主题', subtitle: 'darkModeInfo'.tr, // 切换应用的明暗主题
icon: isDarkMode ? Icons.dark_mode : Icons.light_mode, icon: isDarkMode ? Icons.dark_mode : Icons.light_mode,
iconBgColor: isDarkMode iconBgColor: isDarkMode
? Colors.indigo[900]!.withOpacity(0.3) ? Colors.indigo[900]!.withOpacity(0.3)
@ -280,15 +313,15 @@ class SettingsView extends GetView<SettingsController> {
// 备份与恢复 // 备份与恢复
_buildNavigationSetting( _buildNavigationSetting(
title: '备份与恢复', title: 'backups'.tr, // 备份与恢复
subtitle: '备份设置和AI互动历史', subtitle: 'backupsInfo'.tr, // 备份设置和AI互动历史
icon: Icons.cloud_upload_outlined, icon: Icons.cloud_upload_outlined,
iconBgColor: isDarkMode iconBgColor: isDarkMode
? Colors.cyan[900]!.withOpacity(0.3) ? Colors.cyan[900]!.withOpacity(0.3)
: Colors.cyan[100]!, : Colors.cyan[100]!,
iconColor: iconColor:
isDarkMode ? Colors.cyan[300]! : Colors.cyan[600]!, isDarkMode ? Colors.cyan[300]! : Colors.cyan[600]!,
value: '上次备份: 今天', value: '${'lastBackup'.tr} 今天', // 上次备份:
valueStyle: TextStyle( valueStyle: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[500], color: isDarkMode ? Colors.white70 : Colors.grey[500],
@ -304,10 +337,17 @@ class SettingsView extends GetView<SettingsController> {
? Colors.white.withOpacity(0.1) ? Colors.white.withOpacity(0.1)
: Colors.grey[200]), : Colors.grey[200]),
// 语音服务选择
_buildSpeechServiceSetting(isDarkMode),
Divider(
height: 1,
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[200]),
// 隐私设置 // 隐私设置
_buildSimpleNavigationSetting( _buildSimpleNavigationSetting(
title: '隐私设置', title: 'privacySettings'.tr, // 隐私设置
subtitle: '管理数据收集和权限', subtitle: 'privacySettingsInfo'.tr, // 管理数据收集和权限
icon: Icons.shield_outlined, icon: Icons.shield_outlined,
iconBgColor: isDarkMode iconBgColor: isDarkMode
? Colors.purple[900]!.withOpacity(0.3) ? Colors.purple[900]!.withOpacity(0.3)
@ -317,7 +357,7 @@ class SettingsView extends GetView<SettingsController> {
titleColor: isDarkMode ? Colors.white : null, titleColor: isDarkMode ? Colors.white : null,
subtitleColor: isDarkMode ? Colors.white70 : null, subtitleColor: isDarkMode ? Colors.white70 : null,
onTap: () { onTap: () {
// 打开隐私设置页面 AppSettings.openAppSettings();
}, },
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
), ),
@ -329,7 +369,7 @@ class SettingsView extends GetView<SettingsController> {
// 退出登录 // 退出登录
_buildSimpleNavigationSetting( _buildSimpleNavigationSetting(
title: '退出登录', title: 'logout'.tr, // 退出登录
icon: Icons.logout, icon: Icons.logout,
iconBgColor: isDarkMode iconBgColor: isDarkMode
? Colors.red[900]!.withOpacity(0.3) ? Colors.red[900]!.withOpacity(0.3)
@ -344,13 +384,13 @@ class SettingsView extends GetView<SettingsController> {
backgroundColor: backgroundColor:
isDarkMode ? Colors.grey[900] : Colors.white, isDarkMode ? Colors.grey[900] : Colors.white,
title: Text( title: Text(
'退出登录', 'logout'.tr, // 退出登录
style: TextStyle( style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
), ),
content: Text( content: Text(
'确定要退出当前账号吗?', 'logoutTips'.tr, // 确定要退出当前账号吗?
style: TextStyle( style: TextStyle(
color: color:
isDarkMode ? Colors.white70 : Colors.black54, isDarkMode ? Colors.white70 : Colors.black54,
@ -360,7 +400,7 @@ class SettingsView extends GetView<SettingsController> {
TextButton( TextButton(
onPressed: () => Get.back(), onPressed: () => Get.back(),
child: Text( child: Text(
'取消', 'cancel'.tr, // 取消
style: TextStyle( style: TextStyle(
color: isDarkMode color: isDarkMode
? Colors.white70 ? Colors.white70
@ -374,7 +414,7 @@ class SettingsView extends GetView<SettingsController> {
controller.signOut(); controller.signOut();
}, },
child: Text( child: Text(
'确定', 'confirm'.tr, // 确定
style: TextStyle( style: TextStyle(
color: isDarkMode color: isDarkMode
? Colors.red[300] ? Colors.red[300]
@ -405,7 +445,7 @@ class SettingsView extends GetView<SettingsController> {
Padding( Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text( child: Text(
'关于应用', 'aboutApplication'.tr, // 关于应用
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -467,7 +507,7 @@ class SettingsView extends GetView<SettingsController> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'DeepVoice', 'DeepSound',
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -476,7 +516,7 @@ class SettingsView extends GetView<SettingsController> {
), ),
SizedBox(height: 2.h), SizedBox(height: 2.h),
Text( Text(
'版本 2.4.1 (Build 87)', '${'versions'.tr} 2.4.1 (Build 87)', // 版本
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: color:
@ -497,7 +537,7 @@ class SettingsView extends GetView<SettingsController> {
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
child: Text( child: Text(
'检查更新', 'checkUpdates'.tr, // 检查更新
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.blue[300] : Colors.blue[600], color: isDarkMode ? Colors.blue[300] : Colors.blue[600],
@ -514,7 +554,7 @@ class SettingsView extends GetView<SettingsController> {
child: Column( child: Column(
children: [ children: [
Text( Text(
'© 2023 DeepVoice Technologies', '© 2025 DeepSound Technologies',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[500], color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
@ -522,7 +562,7 @@ class SettingsView extends GetView<SettingsController> {
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Text( Text(
'连接世界,超越声音', 'homeSlogan'.tr, // 连接世界,超越声音
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[500], color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
@ -551,7 +591,8 @@ class SettingsView extends GetView<SettingsController> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Expanded(
child: Row(
children: [ children: [
Container( Container(
width: 32.w, width: 32.w,
@ -567,7 +608,8 @@ class SettingsView extends GetView<SettingsController> {
), ),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Column( Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
@ -577,6 +619,7 @@ class SettingsView extends GetView<SettingsController> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
overflow: TextOverflow.ellipsis,
), ),
if (subtitle != null) SizedBox(height: 2.h), if (subtitle != null) SizedBox(height: 2.h),
if (subtitle != null) if (subtitle != null)
@ -586,11 +629,14 @@ class SettingsView extends GetView<SettingsController> {
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
overflow: TextOverflow.ellipsis,
), ),
], ],
), ),
),
], ],
), ),
),
Switch( Switch(
value: value, value: value,
onChanged: onChanged, onChanged: onChanged,
@ -620,7 +666,8 @@ class SettingsView extends GetView<SettingsController> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Expanded(
child: Row(
children: [ children: [
Container( Container(
width: 32.w, width: 32.w,
@ -636,7 +683,8 @@ class SettingsView extends GetView<SettingsController> {
), ),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Column( Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
@ -646,6 +694,7 @@ class SettingsView extends GetView<SettingsController> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
overflow: TextOverflow.ellipsis,
), ),
if (subtitle != null) SizedBox(height: 2.h), if (subtitle != null) SizedBox(height: 2.h),
if (subtitle != null) if (subtitle != null)
@ -653,22 +702,30 @@ class SettingsView extends GetView<SettingsController> {
subtitle, subtitle,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54, color:
isDarkMode ? Colors.white70 : Colors.black54,
), ),
overflow: TextOverflow.ellipsis,
), ),
], ],
), ),
),
], ],
), ),
),
Row( Row(
mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Flexible(
child: Text(
value, value,
style: valueStyle ?? style: valueStyle ??
TextStyle( TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
overflow: TextOverflow.ellipsis,
),
), ),
SizedBox(width: 8.w), SizedBox(width: 8.w),
Container( Container(
@ -713,7 +770,8 @@ class SettingsView extends GetView<SettingsController> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Expanded(
child: Row(
children: [ children: [
Container( Container(
width: 32.w, width: 32.w,
@ -729,7 +787,8 @@ class SettingsView extends GetView<SettingsController> {
), ),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Column( Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
@ -740,6 +799,7 @@ class SettingsView extends GetView<SettingsController> {
color: titleColor ?? color: titleColor ??
(isDarkMode ? Colors.white : Colors.black87), (isDarkMode ? Colors.white : Colors.black87),
), ),
overflow: TextOverflow.ellipsis,
), ),
if (subtitle != null) SizedBox(height: 2.h), if (subtitle != null) SizedBox(height: 2.h),
if (subtitle != null) if (subtitle != null)
@ -748,13 +808,116 @@ class SettingsView extends GetView<SettingsController> {
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: subtitleColor ?? color: subtitleColor ??
(isDarkMode ? Colors.white70 : Colors.black54), (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],
),
),
],
),
),
);
}
// 语音服务设置项
Widget _buildSpeechServiceSetting(bool isDarkMode) {
return InkWell(
onTap: () {
_showSpeechServiceSelectionDialog(isDarkMode);
},
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: isDarkMode
? Colors.teal[900]!.withOpacity(0.3)
: Colors.teal[100]!,
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
Icons.record_voice_over,
size: 16.w,
color: isDarkMode ? Colors.teal[300]! : Colors.teal[600]!,
),
),
SizedBox(width: 12.w),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'voiceService'.tr, // 语音服务
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
SizedBox(height: 2.h),
Text(
'voiceServiceInfo'.tr, // 选择语音识别和合成服务
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54,
),
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Obx(() {
final serviceType = controller.speechServiceType.value;
final serviceName = controller.availableSpeechServices
.firstWhere(
(service) => service['type'] == serviceType)['name'];
return Flexible(
child: Text(
'$serviceName'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
),
overflow: TextOverflow.ellipsis,
),
);
}),
SizedBox(width: 8.w),
Container( Container(
width: 32.w, width: 32.w,
height: 32.w, height: 32.w,
@ -772,6 +935,225 @@ class SettingsView extends GetView<SettingsController> {
), ),
], ],
), ),
],
),
),
);
}
// 显示语音服务选择对话框
void _showSpeechServiceSelectionDialog(bool isDarkMode) {
Get.dialog(
Dialog(
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
child: Padding(
padding: EdgeInsets.all(16.w),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'selectVoiceService'.tr, // 选择语音服务
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
SizedBox(height: 16.h),
...controller.availableSpeechServices.map((service) {
return Obx(() {
final isSelected =
controller.speechServiceType.value == service['type'];
return InkWell(
onTap: () {
controller.setSpeechServiceType(service['type']);
Get.back();
},
child: Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: isSelected
? (isDarkMode
? Colors.teal[900]!.withOpacity(0.3)
: Colors.teal[50]!)
: (isDarkMode
? Colors.white.withOpacity(0.05)
: Colors.grey[100]!),
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: isSelected
? (isDarkMode
? Colors.teal[300]!
: Colors.teal[600]!)
: Colors.transparent,
width: 1,
),
),
child: Row(
children: [
Container(
width: 24.w,
height: 24.w,
decoration: BoxDecoration(
color: isSelected
? (isDarkMode
? Colors.teal[300]
: Colors.teal[600])
: (isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[300]),
shape: BoxShape.circle,
),
child: isSelected
? Icon(
Icons.check,
size: 16.w,
color: Colors.white,
)
: null,
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${service['name']}'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode
? Colors.white
: Colors.black87,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 4.h),
Text(
'${service['description']}'.tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode
? Colors.white70
: Colors.black54,
),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
],
),
),
],
),
),
);
});
}).toList(),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'cancel'.tr, // 取消
style: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.black54,
),
),
),
],
),
],
),
),
),
);
}
// 显示语言选择对话框
void _showLanguageSelectionDialog(bool isDarkMode) {
Get.dialog(
Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24.r),
),
insetPadding: EdgeInsets.symmetric(horizontal: 20.w),
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
child: Container(
width: 0.9.sw,
padding: EdgeInsets.only(top: 32.h, bottom: 16.h),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 24.w),
child: Text(
'selectLanguage'.tr, // 选择语言
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.white : Colors.black,
),
),
),
SizedBox(height: 16.h),
Container(
constraints: BoxConstraints(maxHeight: 0.5.sh),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: controller.languageList.map((language) {
return ListTile(
title: Text(
language.name.tr,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
),
),
trailing:
controller.language.value.value == language.value
? Icon(
Icons.check_circle,
color: isDarkMode
? AppColors.primary
: Colors.blue,
)
: const SizedBox.shrink(),
onTap: () {
controller.setLanguage(language);
},
);
}).toList(),
),
),
),
SizedBox(height: 16.h),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.only(right: 24.w),
child: TextButton(
onPressed: () => Get.back(),
child: Text(
'cancel'.tr, // 取消
style: TextStyle(
color: isDarkMode ? AppColors.primary : Colors.blue,
fontSize: 16.sp,
),
),
),
),
),
],
),
),
), ),
); );
} }

Loading…
Cancel
Save