Browse Source

add dark light skin

newdev_shunjiawei
wolfplus 2 years ago
parent
commit
d70bcfb68c
  1. 114
      android/app/src/main/kotlin/com/example/deep_voice/AzureAsrHelper.kt
  2. 65
      android/app/src/main/kotlin/com/example/deep_voice/VoiceInteractionService.kt
  3. BIN
      assets/images/headphone_light.png
  4. 29
      lib/app/theme/theme_service.dart
  5. 10
      lib/core/widgets/common_bottom_nav.dart
  6. 6
      lib/main.dart
  7. 52
      lib/modules/explore/controllers/explore_controller.dart
  8. 108
      lib/modules/explore/views/explore_view.dart
  9. 467
      lib/modules/home/views/home_view.dart
  10. 20
      lib/modules/login/controllers/login_controller.dart
  11. 250
      lib/modules/login/views/login_view.dart
  12. 63
      lib/modules/pairing/views/pairing_view.dart
  13. 19
      lib/modules/settings/controllers/settings_controller.dart
  14. 581
      lib/modules/settings/views/settings_view.dart
  15. 18
      lib/modules/splash/controllers/splash_controller.dart
  16. 76
      lib/modules/splash/views/splash_view.dart
  17. 28
      macos/Podfile.lock

114
android/app/src/main/kotlin/com/example/deep_voice/AzureAsrHelper.kt

@ -169,21 +169,46 @@ class AzureAsrHelper {
} }
try { try {
// 重新创建识别器 Log.d(TAG, "开始重置识别器和音频资源")
Log.d(TAG, "重新创建识别器")
recognizer?.close()
// 完全释放所有资源,确保干净的状态
try {
// 释放识别器
recognizer?.close()
recognizer = null
// 释放音频资源
releaseAudioResources()
// 确保状态标志正确
isContinuousRecognitionActive = false
isRecording = false
Log.d(TAG, "资源释放完成,准备重新创建")
} catch (e: Exception) {
Log.e(TAG, "释放资源失败: ${e.message}", e)
// 继续执行,尝试重新创建
}
// 重新创建音频配置
try { try {
// 重新设置音频输入
setupAudioInput() setupAudioInput()
Log.d(TAG, "重新创建音频配置成功") Log.d(TAG, "音频配置创建成功")
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "重新创建音频配置失败: ${e.message}", e) Log.e(TAG, "创建音频配置失败: ${e.message}", e)
callback.onError("创建音频配置失败: ${e.message}") callback.onError("创建音频配置失败: ${e.message}")
return false return false
} }
recognizer = SpeechRecognizer(speechConfig, audioConfig) // 重新创建识别器
try {
Log.d(TAG, "创建新的语音识别器")
recognizer = SpeechRecognizer(speechConfig, audioConfig)
} catch (e: Exception) {
Log.e(TAG, "创建识别器失败: ${e.message}", e)
callback.onError("创建识别器失败: ${e.message}")
return false
}
// 设置识别事件处理 // 设置识别事件处理
recognizer?.let { recognizer -> recognizer?.let { recognizer ->
@ -341,21 +366,45 @@ class AzureAsrHelper {
// 释放资源 // 释放资源
fun dispose() { fun dispose() {
try { try {
// 添加标志,避免重复释放
if (recognizer == null && audioRecord == null && pushStream == null) {
Log.d(TAG, "资源已经释放,跳过重复释放")
return
}
Log.d(TAG, "开始释放资源")
if (isContinuousRecognitionActive && recognizer != null) { if (isContinuousRecognitionActive && recognizer != null) {
recognizer?.stopContinuousRecognitionAsync()?.get() try {
recognizer?.stopContinuousRecognitionAsync()?.get()
Log.d(TAG, "连续识别已停止")
} catch (e: Exception) {
Log.e(TAG, "停止连续识别失败: ${e.message}", e)
}
} }
recognizer?.close() try {
recognizer = null recognizer?.close()
recognizer = null
Log.d(TAG, "识别器已关闭")
} catch (e: Exception) {
Log.e(TAG, "关闭识别器失败: ${e.message}", e)
}
releaseAudioResources() releaseAudioResources()
speechConfig?.close() try {
speechConfig = null speechConfig?.close()
speechConfig = null
Log.d(TAG, "语音配置已关闭")
} catch (e: Exception) {
Log.e(TAG, "关闭语音配置失败: ${e.message}", e)
}
isContinuousRecognitionActive = false isContinuousRecognitionActive = false
Log.d(TAG, "所有资源已释放")
} catch (e: Exception) { } catch (e: Exception) {
// 忽略异常 Log.e(TAG, "释放资源时出错: ${e.message}", e)
} }
} }
@ -365,27 +414,36 @@ class AzureAsrHelper {
stopRecording() stopRecording()
// 释放 AudioRecord // 释放 AudioRecord
try { if (audioRecord != null) {
audioRecord?.release() try {
audioRecord = null Log.d(TAG, "释放 AudioRecord")
} catch (e: Exception) { audioRecord?.release()
Log.e(TAG, "释放 AudioRecord 失败: ${e.message}", e) audioRecord = null
} catch (e: Exception) {
Log.e(TAG, "释放 AudioRecord 失败: ${e.message}", e)
}
} }
// 释放 AudioConfig // 释放 AudioConfig
try { if (audioConfig != null) {
audioConfig?.close() try {
audioConfig = null Log.d(TAG, "释放 AudioConfig")
} catch (e: Exception) { audioConfig?.close()
Log.e(TAG, "释放 AudioConfig 失败: ${e.message}", e) audioConfig = null
} catch (e: Exception) {
Log.e(TAG, "释放 AudioConfig 失败: ${e.message}", e)
}
} }
// 释放 PushStream // 释放 PushStream
try { if (pushStream != null) {
pushStream?.close() try {
pushStream = null Log.d(TAG, "释放 PushStream")
} catch (e: Exception) { pushStream?.close()
Log.e(TAG, "释放 PushStream 失败: ${e.message}", e) pushStream = null
} catch (e: Exception) {
Log.e(TAG, "释放 PushStream 失败: ${e.message}", e)
}
} }
// 释放回音消除资源 // 释放回音消除资源

65
android/app/src/main/kotlin/com/example/deep_voice/VoiceInteractionService.kt

@ -319,9 +319,16 @@ class VoiceInteractionService : Service() {
// 如果超过5秒没有检测到语音,且不在TTS播放中,暂停语音识别 // 如果超过5秒没有检测到语音,且不在TTS播放中,暂停语音识别
if (!hasSpeechDetected && !isTtsSpeaking && elapsedTime >= RECOGNITION_TIMEOUT) { if (!hasSpeechDetected && !isTtsSpeaking && elapsedTime >= RECOGNITION_TIMEOUT) {
Log.d(TAG, "超过${RECOGNITION_TIMEOUT/1000}秒未检测到语音,停止识别")
isTimeoutPaused = true isTimeoutPaused = true
playNotification("没有听到您说话,已暂停语音识别。双击耳机按钮可重新开始。") playNotification("没有听到您说话,已暂停语音识别。双击耳机按钮可重新开始。")
// 停止语音识别并确保资源完全释放
stopVoiceRecognition() stopVoiceRecognition()
// 清理识别状态
isRecognitionActive = false
hasSpeechDetected = false
} }
} }
} }
@ -339,7 +346,8 @@ class VoiceInteractionService : Service() {
Log.d(TAG, "短时间重复响应,忽略") Log.d(TAG, "短时间重复响应,忽略")
return return
} }
lastKeyEventTime = currentTime
// 停止当前TTS播放 // 停止当前TTS播放
stopCurrentTTS() stopCurrentTTS()
@ -355,6 +363,28 @@ class VoiceInteractionService : Service() {
// 启动或重置语音识别 // 启动或重置语音识别
if (!isRecognitionActive) { if (!isRecognitionActive) {
Log.d(TAG, "语音识别未激活,开始启动") Log.d(TAG, "语音识别未激活,开始启动")
// 如果之前是因为超时暂停,重新初始化语音识别组件
if (isTimeoutPaused) {
Log.d(TAG, "之前因超时暂停,重新初始化Azure服务")
// 释放旧的实例
try {
azureAsrHelper.dispose()
} catch (e: Exception) {
Log.e(TAG, "释放旧的Azure ASR实例失败: ${e.message}", e)
}
// 创建新的实例
azureAsrHelper = AzureAsrHelper()
// 重新初始化
val subscriptionKey = MainActivity.azureSpeechKey
val serviceRegion = MainActivity.azureSpeechRegion
if (subscriptionKey.isNotEmpty() && serviceRegion.isNotEmpty()) {
azureAsrHelper.initialize(subscriptionKey, serviceRegion, "zh-CN")
}
}
startVoiceRecognition() startVoiceRecognition()
} else { } else {
Log.d(TAG, "语音识别已激活,更新活动时间") Log.d(TAG, "语音识别已激活,更新活动时间")
@ -466,14 +496,31 @@ class VoiceInteractionService : Service() {
private fun stopVoiceRecognition() { private fun stopVoiceRecognition() {
if (!isRecognitionActive) return if (!isRecognitionActive) return
azureAsrHelper.stopContinuousRecognition(object : AzureAsrHelper.ContinuousRecognizeCallback { Log.d(TAG, "停止语音识别")
override fun onResult(result: String) {}
override fun onRecognizing(recognizing: String) {} try {
override fun onSessionStarted() {} azureAsrHelper.stopContinuousRecognition(object : AzureAsrHelper.ContinuousRecognizeCallback {
override fun onSessionStopped() { isRecognitionActive = false } override fun onResult(result: String) {}
override fun onCanceled(reason: String, errorDetails: String) { isRecognitionActive = false } override fun onRecognizing(recognizing: String) {}
override fun onError(error: String) { isRecognitionActive = false } override fun onSessionStarted() {}
}) override fun onSessionStopped() {
isRecognitionActive = false
Log.d(TAG, "语音识别会话已停止")
}
override fun onCanceled(reason: String, errorDetails: String) {
isRecognitionActive = false
Log.d(TAG, "语音识别已取消: $reason")
}
override fun onError(error: String) {
isRecognitionActive = false
Log.e(TAG, "停止语音识别时出错: $error")
}
})
} catch (e: Exception) {
Log.e(TAG, "停止语音识别异常: ${e.message}", e)
// 确保状态一致性
isRecognitionActive = false
}
setPlaybackState(PlaybackStateCompat.STATE_PAUSED) setPlaybackState(PlaybackStateCompat.STATE_PAUSED)
isRecognitionActive = false isRecognitionActive = false

BIN
assets/images/headphone_light.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 98 KiB

29
lib/app/theme/theme_service.dart

@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
class ThemeService {
final _box = GetStorage();
final _key = 'isDarkMode';
/// 获取主题模式 - 如果没有保存过,则默认为系统主题
ThemeMode getThemeMode() {
return isSavedDarkMode() ? ThemeMode.dark : ThemeMode.light;
}
/// 是否是暗黑模式
bool isSavedDarkMode() {
return _box.read(_key) ?? false;
}
/// 保存主题模式到本地存储
void saveThemeMode(bool isDarkMode) {
_box.write(_key, isDarkMode);
}
/// 切换主题
void changeThemeMode() {
Get.changeThemeMode(isSavedDarkMode() ? ThemeMode.light : ThemeMode.dark);
saveThemeMode(!isSavedDarkMode());
}
}

10
lib/core/widgets/common_bottom_nav.dart

@ -12,6 +12,8 @@ class CommonBottomNav extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return BottomNavigationBar( return BottomNavigationBar(
currentIndex: currentIndex, currentIndex: currentIndex,
onTap: (index) { onTap: (index) {
@ -28,10 +30,10 @@ class CommonBottomNav extends StatelessWidget {
break; break;
} }
}, },
backgroundColor: const Color(0xFFF9FAFB), // 浅灰色背景 #F9FAFB backgroundColor: isDarkMode ? Colors.black : const Color(0xFFF9FAFB), // 暗黑模式黑色背景,浅色模式浅灰色背景
selectedItemColor: const Color(0xFF3B82F6), // 蓝色选中项 #3B82F6 selectedItemColor: const Color(0xFF3B82F6), // 蓝色选中项保持不变
unselectedItemColor: const Color(0xFF6B7280), // 灰色未选中项 #6B7280 unselectedItemColor: isDarkMode ? Colors.grey[500] : const Color(0xFF6B7280), // 暗黑模式灰色调整
elevation: 8, // 添加阴影 elevation: isDarkMode ? 0 : 8, // 暗黑模式无阴影,浅色模式保持阴影
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
items: [ items: [
BottomNavigationBarItem( BottomNavigationBarItem(

6
lib/main.dart

@ -11,6 +11,7 @@ import 'package:window_size/window_size.dart';
import 'app/translations/app_translations.dart'; import 'app/translations/app_translations.dart';
import 'data/services/voice_interaction_service.dart'; import 'data/services/voice_interaction_service.dart';
import 'app/theme/app_theme.dart'; import 'app/theme/app_theme.dart';
import 'app/theme/theme_service.dart';
void main() async { void main() async {
// 确保Flutter绑定初始化 // 确保Flutter绑定初始化
@ -53,6 +54,9 @@ Future<void> _initializeApp() async {
// 初始化存储 // 初始化存储
await GetStorage.init(); await GetStorage.init();
// 注意:应用启动时会在 SplashController 中检查上次保存的皮肤模式
// 并自动应用保存的主题(暗黑/浅色)
// AudioService 将在 AudioServiceManager 中初始化 // AudioService 将在 AudioServiceManager 中初始化
// 不再需要在这里调用 AudioService.init // 不再需要在这里调用 AudioService.init
@ -74,7 +78,7 @@ class MainApp extends StatelessWidget {
title: 'Deep Voice', title: 'Deep Voice',
theme: AppTheme.lightTheme, theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme, darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.dark, themeMode: ThemeService().getThemeMode(), // 初始主题模式,将在 SplashController 中再次检查
initialBinding: InitialBinding(), initialBinding: InitialBinding(),
initialRoute: Routes.splash, initialRoute: Routes.splash,
getPages: AppPages.pages, getPages: AppPages.pages,

52
lib/modules/explore/controllers/explore_controller.dart

@ -55,21 +55,21 @@ class ExploreController extends GetxController {
title: '全能助理', title: '全能助理',
description: '帮你解决各类问题', description: '帮你解决各类问题',
icon: Icons.assistant, icon: Icons.assistant,
startColor: Colors.blue.shade100, startColor: const Color(0xFF0066CC),
endColor: Colors.blue.shade200, endColor: const Color(0xFF5E5CE6),
iconBgColor: Colors.blue.withOpacity(0.2), iconBgColor: const Color(0xFF0066CC).withOpacity(0.2),
iconColor: Colors.blue.shade600, iconColor: const Color(0xFF0066CC),
agentId: 'personal_assistant', agentId: 'personal_assistant',
targetRoute: Routes.chat, targetRoute: Routes.chat,
), ),
AIFeature( AIFeature(
title: '同声传译', title: '同声翻译',
description: '实时翻译80+种语言', description: '实时翻译80+种语言',
icon: Icons.translate, icon: Icons.translate,
startColor: Colors.green.shade100, startColor: const Color(0xFF4CAF50),
endColor: Colors.green.shade200, endColor: const Color(0xFF009688),
iconBgColor: Colors.green.withOpacity(0.2), iconBgColor: const Color(0xFF4CAF50).withOpacity(0.2),
iconColor: Colors.green.shade600, iconColor: const Color(0xFF4CAF50),
agentId: 'simultaneous_interpreter', agentId: 'simultaneous_interpreter',
targetRoute: Routes.translation, targetRoute: Routes.translation,
), ),
@ -77,10 +77,10 @@ class ExploreController extends GetxController {
title: 'AI女友', title: 'AI女友',
description: '智能陪伴,随时聊天', description: '智能陪伴,随时聊天',
icon: Icons.favorite, icon: Icons.favorite,
startColor: Colors.pink.shade100, startColor: const Color(0xFFE91E63),
endColor: Colors.pink.shade200, endColor: const Color(0xFFFF5252),
iconBgColor: Colors.pink.withOpacity(0.2), iconBgColor: const Color(0xFFE91E63).withOpacity(0.2),
iconColor: Colors.pink.shade600, iconColor: const Color(0xFFE91E63),
agentId: 'cyber_girlfriend', agentId: 'cyber_girlfriend',
targetRoute: Routes.chat, targetRoute: Routes.chat,
), ),
@ -88,10 +88,10 @@ class ExploreController extends GetxController {
title: '健康顾问', title: '健康顾问',
description: '提供科学健康建议', description: '提供科学健康建议',
icon: Icons.healing, icon: Icons.healing,
startColor: Colors.amber.shade100, startColor: const Color(0xFFFFC107),
endColor: Colors.amber.shade200, endColor: const Color(0xFFFF9800),
iconBgColor: Colors.amber.withOpacity(0.2), iconBgColor: const Color(0xFFFFC107).withOpacity(0.2),
iconColor: Colors.amber.shade600, iconColor: const Color(0xFFFFC107),
agentId: 'health_advisor', agentId: 'health_advisor',
targetRoute: Routes.chat, targetRoute: Routes.chat,
), ),
@ -103,25 +103,25 @@ class ExploreController extends GetxController {
title: '商务会议助手', title: '商务会议助手',
description: '实时记录会议纪要,多语言翻译', description: '实时记录会议纪要,多语言翻译',
icon: Icons.people, icon: Icons.people,
startColor: Colors.blue.shade200, startColor: const Color(0xFF3F51B5),
endColor: Colors.blue.shade300, endColor: const Color(0xFF673AB7),
iconColor: Colors.blue.shade600, iconColor: const Color(0xFF3F51B5),
), ),
FunctionScene( FunctionScene(
title: '语言学习助手', title: '语言学习助手',
description: '发音纠正,实时练习口语', description: '发音纠正,实时练习口语',
icon: Icons.school, icon: Icons.school,
startColor: Colors.green.shade200, startColor: const Color(0xFF4CAF50),
endColor: Colors.green.shade300, endColor: const Color(0xFF009688),
iconColor: Colors.green.shade600, iconColor: const Color(0xFF4CAF50),
), ),
FunctionScene( FunctionScene(
title: '旅行翻译助手', title: '旅行翻译助手',
description: '实时语音翻译,旅游景点介绍', description: '实时语音翻译,旅游景点介绍',
icon: Icons.language, icon: Icons.language,
startColor: Colors.amber.shade200, startColor: const Color(0xFFFFC107),
endColor: Colors.amber.shade300, endColor: const Color(0xFFFF9800),
iconColor: Colors.amber.shade600, iconColor: const Color(0xFFFFC107),
), ),
]; ];

108
lib/modules/explore/views/explore_view.dart

@ -10,13 +10,15 @@ class ExploreView extends GetView<ExploreController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
backgroundColor: Colors.grey[50], backgroundColor: isDarkMode ? Colors.black : Colors.grey[50],
body: SafeArea( body: SafeArea(
child: Column( child: Column(
children: [ children: [
// 标题和搜索 // 标题和搜索
_buildHeaderAndSearch(), _buildHeaderAndSearch(isDarkMode),
// 主要内容(可滚动) // 主要内容(可滚动)
Expanded( Expanded(
@ -32,15 +34,15 @@ class ExploreView extends GetView<ExploreController> {
// AI功能列表 // AI功能列表
SizedBox(height: 24.h), SizedBox(height: 24.h),
_buildAIFeaturesSection(), _buildAIFeaturesSection(isDarkMode),
// 热门功能场景 // 热门功能场景
SizedBox(height: 24.h), SizedBox(height: 24.h),
_buildFunctionScenesSection(), _buildFunctionScenesSection(isDarkMode),
// 新功能推荐 // 新功能推荐
SizedBox(height: 24.h), SizedBox(height: 24.h),
_buildNewFeatureSection(), _buildNewFeatureSection(isDarkMode),
], ],
), ),
), ),
@ -54,7 +56,7 @@ class ExploreView extends GetView<ExploreController> {
} }
// 标题和搜索 // 标题和搜索
Widget _buildHeaderAndSearch() { Widget _buildHeaderAndSearch(bool isDarkMode) {
return Padding( return Padding(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
child: Column( child: Column(
@ -68,18 +70,22 @@ class ExploreView extends GetView<ExploreController> {
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
Container( Container(
width: 32.w, width: 32.w,
height: 32.w, height: 32.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[200], color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200],
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
child: IconButton( child: IconButton(
icon: Icon(Icons.more_vert, size: 16.sp), icon: Icon(
Icons.more_vert,
size: 16.sp,
color: isDarkMode ? Colors.white : Colors.grey[700],
),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () {}, onPressed: () {},
), ),
@ -91,7 +97,7 @@ class ExploreView extends GetView<ExploreController> {
SizedBox(height: 16.h), SizedBox(height: 16.h),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[100], color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[100],
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
), ),
child: TextField( child: TextField(
@ -100,18 +106,21 @@ class ExploreView extends GetView<ExploreController> {
hintText: '搜索AI功能...', hintText: '搜索AI功能...',
hintStyle: TextStyle( hintStyle: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.grey[400], color: isDarkMode ? Colors.grey[400] : Colors.grey[400],
), ),
prefixIcon: Icon( prefixIcon: Icon(
Icons.search, Icons.search,
size: 20.sp, size: 20.sp,
color: Colors.grey[400], color: isDarkMode ? Colors.grey[400] : Colors.grey[400],
), ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 12.h), contentPadding: EdgeInsets.symmetric(vertical: 12.h),
), ),
textInputAction: TextInputAction.search, textInputAction: TextInputAction.search,
onSubmitted: (_) => controller.search(), onSubmitted: (_) => controller.search(),
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
),
), ),
), ),
], ],
@ -127,7 +136,7 @@ class ExploreView extends GetView<ExploreController> {
borderRadius: BorderRadius.circular(24.r), borderRadius: BorderRadius.circular(24.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.2), color: Colors.black.withOpacity(0.2),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@ -208,7 +217,7 @@ class ExploreView extends GetView<ExploreController> {
} }
// AI功能部分 // AI功能部分
Widget _buildAIFeaturesSection() { Widget _buildAIFeaturesSection(bool isDarkMode) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -217,7 +226,7 @@ class ExploreView extends GetView<ExploreController> {
style: TextStyle( style: TextStyle(
fontSize: 18.sp, fontSize: 18.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -233,7 +242,7 @@ class ExploreView extends GetView<ExploreController> {
itemCount: controller.aiFeatures.length, itemCount: controller.aiFeatures.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final feature = controller.aiFeatures[index]; final feature = controller.aiFeatures[index];
return _buildAIFeatureItem(feature, index); return _buildAIFeatureItem(feature, index, isDarkMode);
}, },
), ),
], ],
@ -241,7 +250,7 @@ class ExploreView extends GetView<ExploreController> {
} }
// AI功能项 // AI功能项
Widget _buildAIFeatureItem(AIFeature feature, int index) { Widget _buildAIFeatureItem(AIFeature feature, int index, bool isDarkMode) {
return GestureDetector( return GestureDetector(
onTap: () => controller.onAIFeatureTap(index), onTap: () => controller.onAIFeatureTap(index),
child: Container( child: Container(
@ -251,16 +260,18 @@ class ExploreView extends GetView<ExploreController> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
feature.startColor, feature.startColor.withOpacity(isDarkMode ? 0.3 : 0.3),
feature.endColor, feature.endColor.withOpacity(isDarkMode ? 0.3 : 0.3),
], ],
), ),
borderRadius: BorderRadius.circular(20.r), borderRadius: BorderRadius.circular(20.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.1), color: isDarkMode
blurRadius: 4, ? Colors.black.withOpacity(0.2)
offset: const Offset(0, 2), : Colors.grey.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
), ),
], ],
), ),
@ -294,9 +305,9 @@ class ExploreView extends GetView<ExploreController> {
Text( Text(
feature.title, feature.title,
style: TextStyle( style: TextStyle(
fontSize: 18.sp, fontSize: 16.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -306,8 +317,8 @@ class ExploreView extends GetView<ExploreController> {
Text( Text(
feature.description, feature.description,
style: TextStyle( style: TextStyle(
fontSize: 13.sp, fontSize: 12.sp,
color: Colors.grey[600], color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
), ),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -322,7 +333,7 @@ class ExploreView extends GetView<ExploreController> {
} }
// 热门功能场景部分 // 热门功能场景部分
Widget _buildFunctionScenesSection() { Widget _buildFunctionScenesSection(bool isDarkMode) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -331,7 +342,7 @@ class ExploreView extends GetView<ExploreController> {
style: TextStyle( style: TextStyle(
fontSize: 18.sp, fontSize: 18.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -343,7 +354,7 @@ class ExploreView extends GetView<ExploreController> {
final scene = controller.functionScenes[index]; final scene = controller.functionScenes[index];
return Padding( return Padding(
padding: EdgeInsets.only(bottom: 16.h), padding: EdgeInsets.only(bottom: 16.h),
child: _buildFunctionSceneItem(scene, index), child: _buildFunctionSceneItem(scene, index, isDarkMode),
); );
}, },
), ),
@ -352,17 +363,19 @@ class ExploreView extends GetView<ExploreController> {
} }
// 功能场景项 // 功能场景项
Widget _buildFunctionSceneItem(FunctionScene scene, int index) { Widget _buildFunctionSceneItem(FunctionScene scene, int index, bool isDarkMode) {
return GestureDetector( return GestureDetector(
onTap: () => controller.onFunctionSceneTap(index), onTap: () => controller.onFunctionSceneTap(index),
child: Container( child: Container(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[100], color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100],
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.1), color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.grey.withOpacity(0.1),
blurRadius: 4, blurRadius: 4,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
@ -379,8 +392,8 @@ class ExploreView extends GetView<ExploreController> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
scene.startColor, scene.startColor.withOpacity(isDarkMode ? 0.3 : 0.3),
scene.endColor, scene.endColor.withOpacity(isDarkMode ? 0.3 : 0.3),
], ],
), ),
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
@ -403,7 +416,7 @@ class ExploreView extends GetView<ExploreController> {
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
@ -411,7 +424,7 @@ class ExploreView extends GetView<ExploreController> {
scene.description, scene.description,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.grey[600], color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
), ),
), ),
], ],
@ -424,7 +437,7 @@ class ExploreView extends GetView<ExploreController> {
} }
// 新功能推荐部分 // 新功能推荐部分
Widget _buildNewFeatureSection() { Widget _buildNewFeatureSection(bool isDarkMode) {
return Container( return Container(
padding: EdgeInsets.all(20.w), padding: EdgeInsets.all(20.w),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -432,14 +445,16 @@ class ExploreView extends GetView<ExploreController> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Colors.purple.shade100, const Color(0xFF9C27B0).withOpacity(isDarkMode ? 0.3 : 0.3),
Colors.purple.shade200, const Color(0xFFE91E63).withOpacity(isDarkMode ? 0.3 : 0.3),
], ],
), ),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.1), color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.grey.withOpacity(0.1),
blurRadius: 8, blurRadius: 8,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@ -453,13 +468,13 @@ class ExploreView extends GetView<ExploreController> {
width: 48.w, width: 48.w,
height: 48.w, height: 48.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.purple.shade200, color: const Color(0xFF9C27B0).withOpacity(0.2),
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
), ),
child: Icon( child: Icon(
Icons.lightbulb_outline, Icons.lightbulb_outline,
size: 24.sp, size: 24.sp,
color: Colors.purple.shade600, color: const Color(0xFF9C27B0),
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -470,7 +485,7 @@ class ExploreView extends GetView<ExploreController> {
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 20.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -480,7 +495,7 @@ class ExploreView extends GetView<ExploreController> {
'用你喜欢的歌手声音演唱任何歌曲,甚至是你自己创作的歌曲', '用你喜欢的歌手声音演唱任何歌曲,甚至是你自己创作的歌曲',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.grey[600], color: isDarkMode ? Colors.grey[300] : Colors.grey[600],
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -489,7 +504,9 @@ class ExploreView extends GetView<ExploreController> {
ElevatedButton( ElevatedButton(
onPressed: controller.tryNewFeature, onPressed: controller.tryNewFeature,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple.shade500, backgroundColor: isDarkMode
? const Color(0xFF9C27B0)
: Colors.white.withOpacity(0.2),
foregroundColor: Colors.white, foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h), padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -501,6 +518,7 @@ class ExploreView extends GetView<ExploreController> {
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
), ),

467
lib/modules/home/views/home_view.dart

@ -1,6 +1,7 @@
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 '../controllers/home_controller.dart'; import '../controllers/home_controller.dart';
import '../../../core/routes/app_pages.dart'; import '../../../core/routes/app_pages.dart';
import '../../../core/routes/app_routes.dart'; import '../../../core/routes/app_routes.dart';
@ -72,34 +73,19 @@ class HomeView extends GetView<HomeController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
backgroundColor: Color(0xFFF9FAFC), backgroundColor: isDarkMode ? Colors.black : Color(0xFFF9FAFC),
appBar: AppBar(
elevation: 0,
backgroundColor: Color(0xFFF9FAFC),
title: Text(
'智能耳机',
style: TextStyle(
color: Colors.black87,
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
),
actions: [
IconButton(
icon: Icon(Icons.settings_outlined, color: Colors.black54),
onPressed: () {
Get.toNamed(Routes.settings);
},
),
],
),
body: SafeArea( body: SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// 顶部标题栏
_buildAppBar(isDarkMode),
// 顶部图片 // 顶部图片
Center( Center(
child: _buildEarbudsImage(), child: _buildEarbudsImage(),
@ -107,28 +93,11 @@ class HomeView extends GetView<HomeController> {
SizedBox(height: 20.h), SizedBox(height: 20.h),
// 设备状态卡片 // 设备状态卡片
_buildDeviceStatusCard(), _buildDeviceStatusCard(isDarkMode),
SizedBox(height: 20.h), SizedBox(height: 20.h),
// 热门AI体验 // 热门AI体验
Row( _buildSectionTitle(isDarkMode),
children: [
Text(
'热门AI体验',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
),
),
SizedBox(width: 8.w),
Icon(
Icons.star,
color: Colors.amber,
size: 20.w,
),
],
),
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildPremiumAILayout(), _buildPremiumAILayout(),
], ],
@ -139,31 +108,24 @@ class HomeView extends GetView<HomeController> {
); );
} }
// 页面顶部:状态栏和标题 // 顶部标题栏
Widget _buildHeader() { Widget _buildAppBar(bool isDarkMode) {
return Container( return Row(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
child: Column(
children: [
// 删除状态栏
// 标题区域
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
'DeepVoice Pro', 'DeepVoice',
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 20.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
Container( Container(
width: 32.w, width: 32.w,
height: 32.w, height: 32.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[200], color: isDarkMode ? Colors.grey[800] : Colors.grey[200],
shape: BoxShape.circle, shape: BoxShape.circle,
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
@ -174,87 +136,44 @@ class HomeView extends GetView<HomeController> {
], ],
), ),
child: IconButton( child: IconButton(
icon: Icon(Icons.more_horiz, size: 16.sp, color: Colors.grey[600]), icon: Icon(
Icons.settings_outlined,
size: 16.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600]
),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
// 打开更多选项菜单 Get.toNamed(Routes.settings);
}, },
), ),
), ),
], ],
),
],
),
); );
} }
// 耳机图片 // 耳机图片
Widget _buildEarbudsImage() { Widget _buildEarbudsImage() {
final bool isDarkMode = Get.isDarkMode;
return Container( return Container(
height: 180.h, height: 220.h,
alignment: Alignment.center, alignment: Alignment.center,
child: Container( child: Image.asset(
decoration: BoxDecoration( isDarkMode ? 'assets/images/headphone_dark.png' : 'assets/images/headphone_light.png',
borderRadius: BorderRadius.circular(20.r), height: 180.h,
boxShadow: [ fit: BoxFit.contain,
BoxShadow(
color: Colors.grey.withOpacity(0.15),
blurRadius: 15,
offset: const Offset(0, 5),
),
BoxShadow(
color: Colors.blue.withOpacity(0.05),
blurRadius: 20,
offset: const Offset(0, -2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.r),
child: Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
child: Stack(
alignment: Alignment.center,
children: [
// 背景光效
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [
Colors.blue.withOpacity(0.05),
Colors.white,
],
center: Alignment.topRight,
radius: 0.8,
),
),
),
),
// 耳机图片
Image.asset(
'assets/images/headphone_light.png',
height: 150.h,
fit: BoxFit.contain,
),
],
),
),
),
), ),
); );
} }
// 设备状态卡片 // 设备状态卡片
Widget _buildDeviceStatusCard() { Widget _buildDeviceStatusCard(bool isDarkMode) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: isDarkMode ? Color(0xFF1A1A1A) : Colors.white,
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.1), color: Colors.grey.withOpacity(isDarkMode ? 0.05 : 0.1),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 4), offset: const Offset(0, 4),
), ),
@ -272,7 +191,7 @@ class HomeView extends GetView<HomeController> {
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.grey[700], color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
), ),
), ),
Obx(() => Row( Obx(() => Row(
@ -300,7 +219,7 @@ class HomeView extends GetView<HomeController> {
child: Icon( child: Icon(
Icons.refresh, Icons.refresh,
size: 16.sp, size: 16.sp,
color: Colors.grey[600], color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
), ),
), ),
], ],
@ -319,9 +238,9 @@ class HomeView extends GetView<HomeController> {
Container( Container(
padding: EdgeInsets.all(8.w), padding: EdgeInsets.all(8.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.red[50], color: isDarkMode ? Colors.red[900]!.withOpacity(0.2) : Colors.red[50],
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
border: Border.all(color: Colors.red[200]!), border: Border.all(color: isDarkMode ? Colors.red[800]! : Colors.red[200]!),
), ),
child: Row( child: Row(
children: [ children: [
@ -336,7 +255,7 @@ class HomeView extends GetView<HomeController> {
controller.connectionErrorMsg, controller.connectionErrorMsg,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.red[800], color: isDarkMode ? Colors.red[300] : Colors.red[800],
), ),
), ),
), ),
@ -403,7 +322,7 @@ class HomeView extends GetView<HomeController> {
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.grey[700], color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -428,7 +347,7 @@ class HomeView extends GetView<HomeController> {
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h), padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[50], color: isDarkMode ? Colors.grey[900] : Colors.grey[50],
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
), ),
child: Column( child: Column(
@ -438,7 +357,7 @@ class HomeView extends GetView<HomeController> {
'设备ID:${controller.getDeviceId()}', '设备ID:${controller.getDeviceId()}',
style: TextStyle( style: TextStyle(
fontSize: 10.sp, fontSize: 10.sp,
color: Colors.grey[500], color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
@ -446,7 +365,7 @@ class HomeView extends GetView<HomeController> {
'固件版本:${controller.firmwareVersion}', '固件版本:${controller.firmwareVersion}',
style: TextStyle( style: TextStyle(
fontSize: 10.sp, fontSize: 10.sp,
color: Colors.grey[500], color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
), ),
), ),
], ],
@ -458,7 +377,7 @@ class HomeView extends GetView<HomeController> {
padding: EdgeInsets.symmetric(vertical: 8.h), padding: EdgeInsets.symmetric(vertical: 8.h),
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[100], color: isDarkMode ? Colors.grey[900] : Colors.grey[100],
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
), ),
child: Row( child: Row(
@ -467,14 +386,14 @@ class HomeView extends GetView<HomeController> {
Icon( Icon(
Icons.bluetooth_disabled, Icons.bluetooth_disabled,
size: 14.sp, size: 14.sp,
color: Colors.grey[700], color: isDarkMode ? Colors.grey[400] : Colors.grey[700],
), ),
SizedBox(width: 4.w), SizedBox(width: 4.w),
Text( Text(
'未连接设备,点击下方按钮连接', '未连接设备,点击下方按钮连接',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.grey[700], color: isDarkMode ? Colors.grey[400] : Colors.grey[700],
), ),
), ),
], ],
@ -507,51 +426,54 @@ class HomeView extends GetView<HomeController> {
); );
} }
// 热门AI体验标题
Widget _buildSectionTitle(bool isDarkMode) {
return Row(
children: [
Text(
'热门AI体验',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.white : Colors.grey[800],
),
),
SizedBox(width: 8.w),
Icon(
Icons.star,
color: Colors.amber,
size: 20.w,
),
],
);
}
// 优质AI体验布局(左1右2) // 优质AI体验布局(左1右2)
Widget _buildPremiumAILayout() { Widget _buildPremiumAILayout() {
final bool isDarkMode = Get.isDarkMode;
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// 左侧大卡片 - AI助理 // 左侧大卡片 - AI助理
Expanded( Expanded(
flex: 1, flex: 1,
child: Stack( child: _buildFeatureCard(
children: [ title: 'AI全能助手',
// 呼吸光效果 description: '24小时专属顾问,解答问题、提供建议',
Positioned.fill( icon: Icons.assistant,
child: Container( gradient: LinearGradient(
decoration: BoxDecoration( begin: Alignment.topLeft,
borderRadius: BorderRadius.circular(16.r), end: Alignment.bottomRight,
gradient: RadialGradient( colors: [
colors: [ Color(0xFF0066CC).withOpacity(0.3),
Color(0xFF4ECDC4).withOpacity(0.6), Color(0xFF5E5CE6).withOpacity(0.3),
Colors.transparent, ],
], ),
center: Alignment.topRight, onTap: controller.exploreAIFeatures,
radius: 1.0, iconOnTop: true,
), height: 175.h, // 增加高度
), isDarkMode: isDarkMode,
child: AnimatedPulsing(), iconColor: const Color(0xFF0066CC),
),
),
// 卡片内容
_buildFeatureCard(
title: 'AI全能助手',
description: '24小时专属顾问,解答问题、提供建议',
icon: Icons.smart_toy,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF4ECDC4),
Color(0xFF556270),
],
),
onTap: controller.exploreAIFeatures,
iconOnTop: true,
height: 175.h, // 增加高度
),
],
), ),
), ),
@ -571,12 +493,14 @@ class HomeView extends GetView<HomeController> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Color(0xFF5E72EB), Color(0xFF4CAF50).withOpacity(0.3),
Color(0xFF4776E6), Color(0xFF009688).withOpacity(0.3),
], ],
), ),
onTap: controller.openTranslation, onTap: controller.openTranslation,
height: 83.h, // 增加高度 height: 83.h, // 增加高度
isDarkMode: isDarkMode,
iconColor: const Color(0xFF4CAF50),
), ),
SizedBox(height: 5.h), // 减少间距 SizedBox(height: 5.h), // 减少间距
@ -590,12 +514,14 @@ class HomeView extends GetView<HomeController> {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
colors: [ colors: [
Color(0xFFFF758C), Color(0xFFE91E63).withOpacity(0.3),
Color(0xFFFF7EB3), Color(0xFFFF5252).withOpacity(0.3),
], ],
), ),
onTap: controller.openAIGirlfriend, onTap: controller.openAIGirlfriend,
height: 85.h, // 增加高度 height: 85.h, // 增加高度
isDarkMode: isDarkMode,
iconColor: const Color(0xFFE91E63),
), ),
], ],
), ),
@ -613,8 +539,10 @@ class HomeView extends GetView<HomeController> {
required VoidCallback onTap, required VoidCallback onTap,
double? height, double? height,
bool iconOnTop = false, bool iconOnTop = false,
bool isDarkMode = false,
Color iconColor = Colors.white,
}) { }) {
return InkWell( return GestureDetector(
onTap: onTap, onTap: onTap,
child: Container( child: Container(
height: height ?? 175.h, height: height ?? 175.h,
@ -624,132 +552,119 @@ class HomeView extends GetView<HomeController> {
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: isDarkMode
blurRadius: 5, ? Colors.black.withOpacity(0.2)
offset: Offset(0, 2), : Colors.grey.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
), ),
], ],
), ),
child: iconOnTop child: Stack(
? Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, // 图标
children: [ if (iconOnTop)
// 图标靠左而不是居中 // 大卡片布局
Container( Align(
width: 45.w, alignment: Alignment.topLeft,
height: 45.w, child: Container(
decoration: BoxDecoration( width: 45.w,
color: Colors.white.withOpacity(0.2), height: 45.w,
borderRadius: BorderRadius.circular(12.r), decoration: BoxDecoration(
), color: iconColor.withOpacity(0.2),
child: Icon( shape: BoxShape.circle,
icon,
color: Colors.white,
size: 24.w,
),
), ),
SizedBox(height: 8.h), child: Icon(
// 标题 icon,
Text( color: iconColor,
title, size: 24.w,
style: TextStyle( ),
color: Colors.white, ),
fontSize: 16.sp, )
fontWeight: FontWeight.bold, else
shadows: [ // 小卡片布局 - 图标
Shadow( Align(
offset: Offset(0, 1), alignment: Alignment.topLeft,
blurRadius: 3.0, child: Container(
color: Colors.black.withOpacity(0.3), width: 34.w,
), height: 34.w,
], decoration: BoxDecoration(
), color: iconColor.withOpacity(0.2),
shape: BoxShape.circle,
), ),
SizedBox(height: 4.h), child: Icon(
// 描述 icon,
Expanded( color: iconColor,
child: Text( size: 18.w,
),
),
),
// 文本内容
if (iconOnTop)
// 大卡片布局 - 文本
Padding(
padding: EdgeInsets.only(top: 55.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.grey[800],
fontSize: 16.sp,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 4.h),
Text(
description, description,
style: TextStyle( style: TextStyle(
color: Colors.white, color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
fontSize: 12.sp, fontSize: 12.sp,
shadows: [
Shadow(
offset: Offset(0, 1),
blurRadius: 2.0,
color: Colors.black.withOpacity(0.2),
),
],
), ),
maxLines: 3, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ],
], ),
) )
: Row( else
crossAxisAlignment: CrossAxisAlignment.start, // 小卡片布局 - 文本
children: [ Padding(
// 图标 padding: EdgeInsets.only(left: 44.w),
Container( child: Column(
width: 34.w, crossAxisAlignment: CrossAxisAlignment.start,
height: 34.w, mainAxisSize: MainAxisSize.min,
decoration: BoxDecoration( children: [
color: Colors.white.withOpacity(0.2), Text(
borderRadius: BorderRadius.circular(8.r), title,
), style: TextStyle(
child: Icon( color: isDarkMode ? Colors.white : Colors.grey[800],
icon, fontSize: 14.sp,
color: Colors.white, fontWeight: FontWeight.bold,
size: 18.w, ),
maxLines: 1,
overflow: TextOverflow.ellipsis,
), ),
), SizedBox(height: 2.h),
SizedBox(width: 10.w), Text(
// 文本内容 description,
Expanded( style: TextStyle(
child: Column( color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
crossAxisAlignment: CrossAxisAlignment.start, fontSize: 10.sp,
mainAxisSize: MainAxisSize.min, ),
children: [ maxLines: 2,
// 标题 overflow: TextOverflow.ellipsis,
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.bold,
shadows: [
Shadow(
offset: Offset(0, 1),
blurRadius: 3.0,
color: Colors.black.withOpacity(0.3),
),
],
),
),
SizedBox(height: 2.h),
// 描述
Text(
description,
style: TextStyle(
color: Colors.white,
fontSize: 10.sp,
shadows: [
Shadow(
offset: Offset(0, 1),
blurRadius: 2.0,
color: Colors.black.withOpacity(0.2),
),
],
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
), ),
), ],
], ),
), ),
],
),
), ),
); );
} }

20
lib/modules/login/controllers/login_controller.dart

@ -200,16 +200,16 @@ class LoginController extends GetxController {
// 登录 // 登录
Future<void> login() async { Future<void> login() async {
// 暂时关闭验证码验证 // 暂时关闭验证码验证
if (!isVerificationCodeComplete()) { // if (!isVerificationCodeComplete()) {
Get.snackbar( // Get.snackbar(
'提示', // '提示',
'请输入完整的验证码', // '请输入完整的验证码',
snackPosition: SnackPosition.TOP, // snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.1), // backgroundColor: Colors.red.withOpacity(0.1),
colorText: Colors.red, // colorText: Colors.red,
); // );
return; // return;
} // }
_isLoading.value = true; _isLoading.value = true;

250
lib/modules/login/views/login_view.dart

@ -10,53 +10,49 @@ class LoginView extends GetView<LoginController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// 使用浅色主题 final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Theme(
data: AppTheme.lightTheme, return Scaffold(
child: Scaffold( backgroundColor: isDarkMode ? Colors.black : Colors.grey[50],
body: SafeArea( body: SafeArea(
child: Obx(() => controller.viewState == LoginViewState.welcome child: Obx(() => controller.viewState == LoginViewState.welcome
? _buildWelcomeView() ? _buildWelcomeView(isDarkMode)
: _buildVerificationView(context)), : _buildVerificationView(context, isDarkMode)),
),
), ),
); );
} }
// 欢迎页面 // 欢迎页面
Widget _buildWelcomeView() { Widget _buildWelcomeView(bool isDarkMode) {
return Padding( return Padding(
padding: EdgeInsets.all(24.w), padding: EdgeInsets.all(24.w),
child: SingleChildScrollView( child: SingleChildScrollView(
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
child: Column( child: Column(
children: [ children: [
// 状态栏
_buildStatusBar(),
// 应用标志和标题 // 应用标志和标题
SizedBox(height: 32.h), SizedBox(height: 32.h),
_buildAppLogo(), _buildAppLogo(isDarkMode),
// 欢迎文本 // 欢迎文本
SizedBox(height: 32.h), SizedBox(height: 32.h),
_buildWelcomeText(), _buildWelcomeText(isDarkMode),
// 输入框和继续按钮 // 输入框和继续按钮
SizedBox(height: 24.h), SizedBox(height: 24.h),
_buildInputField(), _buildInputField(isDarkMode),
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildVerificationInputField(), _buildVerificationInputField(isDarkMode),
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildContinueButton(), _buildContinueButton(isDarkMode),
// 社交媒体登录 // 社交媒体登录
SizedBox(height: 32.h), SizedBox(height: 32.h),
_buildSocialLoginSection(), _buildSocialLoginSection(isDarkMode),
// 用户协议 // 用户协议
SizedBox(height: 40.h), SizedBox(height: 40.h),
_buildTermsAndPrivacy(), _buildTermsAndPrivacy(isDarkMode),
SizedBox(height: 24.h), SizedBox(height: 24.h),
], ],
), ),
@ -65,7 +61,7 @@ class LoginView extends GetView<LoginController> {
} }
// 验证码页面 // 验证码页面
Widget _buildVerificationView(BuildContext context) { Widget _buildVerificationView(BuildContext context, bool isDarkMode) {
return Padding( return Padding(
padding: EdgeInsets.all(24.w), padding: EdgeInsets.all(24.w),
child: SingleChildScrollView( child: SingleChildScrollView(
@ -74,27 +70,27 @@ class LoginView extends GetView<LoginController> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// 返回按钮 // 返回按钮
_buildBackButton(), _buildBackButton(isDarkMode),
// 验证码标题 // 验证码标题
SizedBox(height: 24.h), SizedBox(height: 24.h),
_buildVerificationTitle(), _buildVerificationTitle(isDarkMode),
// 验证码输入框 // 验证码输入框
SizedBox(height: 32.h), SizedBox(height: 32.h),
_buildVerificationInputs(context), _buildVerificationInputs(context, isDarkMode),
// 重新发送验证码 // 重新发送验证码
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildResendButton(), _buildResendButton(isDarkMode),
// 登录按钮 // 登录按钮
SizedBox(height: 32.h), SizedBox(height: 32.h),
_buildLoginButton(), _buildLoginButton(isDarkMode),
// 使用密码登录 // 使用密码登录
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildUsePasswordButton(), _buildUsePasswordButton(isDarkMode),
SizedBox(height: 24.h), SizedBox(height: 24.h),
], ],
), ),
@ -102,33 +98,8 @@ class LoginView extends GetView<LoginController> {
); );
} }
// 状态栏
Widget _buildStatusBar() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'9:41',
style: TextStyle(
fontSize: 12.sp,
color: Colors.black54,
),
),
Row(
children: [
Icon(Icons.signal_cellular_4_bar, size: 12.sp, color: Colors.black54),
SizedBox(width: 4.w),
Icon(Icons.wifi, size: 12.sp, color: Colors.black54),
SizedBox(width: 4.w),
Icon(Icons.battery_full, size: 12.sp, color: Colors.black54),
],
),
],
);
}
// 应用标志和标题 // 应用标志和标题
Widget _buildAppLogo() { Widget _buildAppLogo(bool isDarkMode) {
return Column( return Column(
children: [ children: [
Container( Container(
@ -161,7 +132,7 @@ class LoginView extends GetView<LoginController> {
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -169,7 +140,7 @@ class LoginView extends GetView<LoginController> {
'连接世界,超越声音', '连接世界,超越声音',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.grey[400] : Colors.black54,
), ),
), ),
], ],
@ -177,7 +148,7 @@ class LoginView extends GetView<LoginController> {
} }
// 欢迎文本 // 欢迎文本
Widget _buildWelcomeText() { Widget _buildWelcomeText(bool isDarkMode) {
return Column( return Column(
children: [ children: [
Text( Text(
@ -185,7 +156,7 @@ class LoginView extends GetView<LoginController> {
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 20.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
@ -193,7 +164,7 @@ class LoginView extends GetView<LoginController> {
'请使用手机号或邮箱登录/注册', '请使用手机号或邮箱登录/注册',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.grey[400] : Colors.black54,
), ),
), ),
], ],
@ -201,10 +172,10 @@ class LoginView extends GetView<LoginController> {
} }
// 输入框 // 输入框
Widget _buildInputField() { Widget _buildInputField(bool isDarkMode) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1), color: isDarkMode ? Colors.grey[900]!.withOpacity(0.4) : Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
child: Padding( child: Padding(
@ -213,7 +184,7 @@ class LoginView extends GetView<LoginController> {
children: [ children: [
Icon( Icon(
Icons.person_outline, Icons.person_outline,
color: Colors.black54, color: isDarkMode ? Colors.grey[400] : Colors.black54,
size: 20.sp, size: 20.sp,
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
@ -224,13 +195,15 @@ class LoginView extends GetView<LoginController> {
hintText: '手机号码或邮箱', hintText: '手机号码或邮箱',
hintStyle: TextStyle( hintStyle: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black38, color: isDarkMode ? Colors.grey[600] : Colors.black38,
), ),
border: InputBorder.none, border: InputBorder.none,
fillColor: Colors.transparent,
filled: true,
), ),
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
), ),
@ -241,10 +214,10 @@ class LoginView extends GetView<LoginController> {
} }
// 验证码输入框 // 验证码输入框
Widget _buildVerificationInputField() { Widget _buildVerificationInputField(bool isDarkMode) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1), color: isDarkMode ? Colors.grey[900]!.withOpacity(0.4) : Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
child: Padding( child: Padding(
@ -253,7 +226,7 @@ class LoginView extends GetView<LoginController> {
children: [ children: [
Icon( Icon(
Icons.lock_outline, Icons.lock_outline,
color: Colors.black54, color: isDarkMode ? Colors.grey[400] : Colors.black54,
size: 20.sp, size: 20.sp,
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
@ -266,14 +239,16 @@ class LoginView extends GetView<LoginController> {
hintText: '验证码', hintText: '验证码',
hintStyle: TextStyle( hintStyle: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black38, color: isDarkMode ? Colors.grey[600] : Colors.black38,
), ),
border: InputBorder.none, border: InputBorder.none,
counterText: '', counterText: '',
fillColor: Colors.transparent,
filled: true,
), ),
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
), ),
@ -283,9 +258,9 @@ class LoginView extends GetView<LoginController> {
: controller.getVerificationCode, : controller.getVerificationCode,
style: TextButton.styleFrom( style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 16.w), padding: EdgeInsets.symmetric(horizontal: 16.w),
foregroundColor: const Color(0xFF0066CC), foregroundColor: const Color(0xFF3B82F6),
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
disabledForegroundColor: Colors.black38, disabledForegroundColor: isDarkMode ? Colors.grey[600] : Colors.grey[400],
), ),
child: Text( child: Text(
controller.countdownSeconds > 0 controller.countdownSeconds > 0
@ -304,34 +279,36 @@ class LoginView extends GetView<LoginController> {
} }
// 继续按钮 // 继续按钮
Widget _buildContinueButton() { Widget _buildContinueButton(bool isDarkMode) {
return SizedBox( return SizedBox(
width: double.infinity, width: double.infinity,
child: Obx(() => ElevatedButton( child: Obx(() => ElevatedButton(
onPressed: controller.isLoading ? null : controller.loginWithVerificationCode, onPressed: controller.isLoading ? null : () => controller.login(),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF0066CC), backgroundColor: const Color(0xFF0066CC),
padding: EdgeInsets.symmetric(vertical: 16.h), foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 14.h),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
elevation: 0, elevation: 0,
disabledBackgroundColor: const Color(0xFF0066CC).withOpacity(0.7),
disabledForegroundColor: Colors.white,
), ),
child: controller.isLoading child: controller.isLoading
? SizedBox( ? SizedBox(
width: 20.w, height: 20.h,
height: 20.w, width: 20.h,
child: const CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2, strokeWidth: 2.w,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white), valueColor: const AlwaysStoppedAnimation<Color>(Colors.white),
), ),
) )
: Text( : Text(
'登录', '继续',
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w600,
color: Colors.white,
), ),
), ),
)), )),
@ -339,32 +316,32 @@ class LoginView extends GetView<LoginController> {
} }
// 社交媒体登录部分 // 社交媒体登录部分
Widget _buildSocialLoginSection() { Widget _buildSocialLoginSection(bool isDarkMode) {
return Column( return Column(
children: [ children: [
Row( Row(
children: [ children: [
Expanded(child: Divider(color: Colors.black12)), Expanded(child: Divider(color: isDarkMode ? Colors.grey[800] : Colors.grey[300])),
Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w), padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Text( child: Text(
'或使用以下方式登录', '或使用以下方式登录',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.black45, color: isDarkMode ? Colors.grey[500] : Colors.grey[600],
), ),
), ),
), ),
Expanded(child: Divider(color: Colors.black12)), Expanded(child: Divider(color: isDarkMode ? Colors.grey[800] : Colors.grey[300])),
], ],
), ),
SizedBox(height: 24.h), SizedBox(height: 24.h),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
_buildSocialButton(FontAwesomeIcons.google, Colors.red), _buildSocialButton(FontAwesomeIcons.google, Colors.red, isDarkMode),
SizedBox(width: 24.w), SizedBox(width: 24.w),
_buildSocialButton(FontAwesomeIcons.weixin, Colors.green), _buildSocialButton(FontAwesomeIcons.weixin, Colors.green, isDarkMode),
], ],
), ),
], ],
@ -372,30 +349,41 @@ class LoginView extends GetView<LoginController> {
} }
// 社交媒体按钮 // 社交媒体按钮
Widget _buildSocialButton(IconData icon, Color color) { Widget _buildSocialButton(IconData icon, Color color, bool isDarkMode) {
return Container( return Container(
width: 48.w, width: 48.w,
height: 48.w, height: 48.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1), color: isDarkMode ? Colors.grey[800] : Colors.white,
borderRadius: BorderRadius.circular(24.r), borderRadius: BorderRadius.circular(24.r),
boxShadow: isDarkMode ? [] : [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
), ),
child: IconButton( child: IconButton(
icon: Icon(icon, color: color, size: 20.sp), icon: FaIcon(
icon,
color: color,
size: 20.sp,
),
onPressed: () {}, onPressed: () {},
), ),
); );
} }
// 用户协议和隐私政策 // 用户协议和隐私政策
Widget _buildTermsAndPrivacy() { Widget _buildTermsAndPrivacy(bool isDarkMode) {
return Column( return Column(
children: [ children: [
Text( Text(
'登录/注册即表示你同意', '登录/注册即表示你同意',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.black45, color: isDarkMode ? Colors.grey[500] : Colors.grey[600],
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
@ -408,7 +396,7 @@ class LoginView extends GetView<LoginController> {
'《用户协议》', '《用户协议》',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: const Color(0xFF0066CC), color: const Color(0xFF3B82F6),
), ),
), ),
), ),
@ -416,7 +404,7 @@ class LoginView extends GetView<LoginController> {
' 和 ', ' 和 ',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.black45, color: isDarkMode ? Colors.grey[500] : Colors.grey[600],
), ),
), ),
GestureDetector( GestureDetector(
@ -425,7 +413,7 @@ class LoginView extends GetView<LoginController> {
'《隐私政策》', '《隐私政策》',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: const Color(0xFF0066CC), color: const Color(0xFF3B82F6),
), ),
), ),
), ),
@ -436,23 +424,27 @@ class LoginView extends GetView<LoginController> {
} }
// 返回按钮 // 返回按钮
Widget _buildBackButton() { Widget _buildBackButton(bool isDarkMode) {
return Container( return Container(
width: 40.w, width: 40.w,
height: 40.w, height: 40.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1), color: isDarkMode ? Colors.grey[800] : Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(20.r), borderRadius: BorderRadius.circular(20.r),
), ),
child: IconButton( child: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.black54, size: 20.sp), icon: Icon(
onPressed: controller.showWelcomeView, Icons.arrow_back,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
size: 20.sp,
),
onPressed: () => controller.showWelcomeView(),
), ),
); );
} }
// 验证码标题 // 验证码标题
Widget _buildVerificationTitle() { Widget _buildVerificationTitle(bool isDarkMode) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -461,7 +453,7 @@ class LoginView extends GetView<LoginController> {
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 20.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -469,7 +461,7 @@ class LoginView extends GetView<LoginController> {
'验证码已发送至 ${controller.displayContact}', '验证码已发送至 ${controller.displayContact}',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
), ),
)), )),
], ],
@ -477,23 +469,23 @@ class LoginView extends GetView<LoginController> {
} }
// 验证码输入框 // 验证码输入框
Widget _buildVerificationInputs(BuildContext context) { Widget _buildVerificationInputs(BuildContext context, bool isDarkMode) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(4, (index) => _buildVerificationInput(index, context)), children: List.generate(4, (index) => _buildVerificationInput(index, context, isDarkMode)),
); );
} }
// 单个验证码输入框 // 单个验证码输入框
Widget _buildVerificationInput(int index, BuildContext context) { Widget _buildVerificationInput(int index, BuildContext context, bool isDarkMode) {
return Container( return Container(
width: 60.w, width: 60.w,
height: 60.w, height: 60.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1), color: isDarkMode ? Colors.grey[900]!.withOpacity(0.3) : Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(12.r),
border: Border.all( border: Border.all(
color: Colors.black12, color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!,
width: 1, width: 1,
), ),
), ),
@ -508,14 +500,16 @@ class LoginView extends GetView<LoginController> {
FocusScope.of(context).nextFocus(); FocusScope.of(context).nextFocus();
} }
}, },
decoration: const InputDecoration( decoration: InputDecoration(
counterText: '', counterText: '',
border: InputBorder.none, border: InputBorder.none,
fillColor: Colors.transparent,
filled: true,
), ),
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
), ),
@ -523,7 +517,7 @@ class LoginView extends GetView<LoginController> {
} }
// 重新发送验证码按钮 // 重新发送验证码按钮
Widget _buildResendButton() { Widget _buildResendButton(bool isDarkMode) {
return Center( return Center(
child: Obx(() => TextButton.icon( child: Obx(() => TextButton.icon(
onPressed: controller.countdownSeconds > 0 onPressed: controller.countdownSeconds > 0
@ -533,8 +527,8 @@ class LoginView extends GetView<LoginController> {
Icons.refresh, Icons.refresh,
size: 14.sp, size: 14.sp,
color: controller.countdownSeconds > 0 color: controller.countdownSeconds > 0
? Colors.black38 ? (isDarkMode ? Colors.grey[600] : Colors.grey[500])
: const Color(0xFF0066CC), : const Color(0xFF3B82F6),
), ),
label: Text( label: Text(
controller.countdownSeconds > 0 controller.countdownSeconds > 0
@ -543,8 +537,8 @@ class LoginView extends GetView<LoginController> {
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: controller.countdownSeconds > 0 color: controller.countdownSeconds > 0
? Colors.black38 ? (isDarkMode ? Colors.grey[600] : Colors.grey[500])
: const Color(0xFF0066CC), : const Color(0xFF3B82F6),
), ),
), ),
)), )),
@ -552,34 +546,36 @@ class LoginView extends GetView<LoginController> {
} }
// 登录按钮 // 登录按钮
Widget _buildLoginButton() { Widget _buildLoginButton(bool isDarkMode) {
return SizedBox( return SizedBox(
width: double.infinity, width: double.infinity,
child: Obx(() => ElevatedButton( child: Obx(() => ElevatedButton(
onPressed: controller.isLoading ? null : controller.login, onPressed: controller.isLoading ? null : controller.login,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF0066CC), backgroundColor: const Color(0xFF3B82F6),
padding: EdgeInsets.symmetric(vertical: 16.h), foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 14.h),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
elevation: 0, elevation: 0,
disabledBackgroundColor: const Color(0xFF3B82F6).withOpacity(0.7),
disabledForegroundColor: Colors.white,
), ),
child: controller.isLoading child: controller.isLoading
? SizedBox( ? SizedBox(
width: 20.w, height: 20.h,
height: 20.w, width: 20.h,
child: const CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2, strokeWidth: 2.w,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white), valueColor: const AlwaysStoppedAnimation<Color>(Colors.white),
), ),
) )
: Text( : Text(
'登录', '登录',
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w600,
color: Colors.white,
), ),
), ),
)), )),
@ -587,7 +583,7 @@ class LoginView extends GetView<LoginController> {
} }
// 使用密码登录按钮 // 使用密码登录按钮
Widget _buildUsePasswordButton() { Widget _buildUsePasswordButton(bool isDarkMode) {
return Center( return Center(
child: TextButton( child: TextButton(
onPressed: controller.usePasswordLogin, onPressed: controller.usePasswordLogin,
@ -595,7 +591,7 @@ class LoginView extends GetView<LoginController> {
'使用密码登录', '使用密码登录',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: const Color(0xFF0066CC), color: isDarkMode ? const Color(0xFF3B82F6) : const Color(0xFF3B82F6),
), ),
), ),
), ),

63
lib/modules/pairing/views/pairing_view.dart

@ -10,35 +10,34 @@ class PairingView extends GetView<PairingController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// 使用浅色主题 final bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Theme(
data: AppTheme.lightTheme, return Scaffold(
child: Scaffold( backgroundColor: isDarkMode ? Colors.black : Colors.white,
body: SafeArea( body: SafeArea(
child: Stack( child: Stack(
children: [ children: [
// 主要内容 // 主要内容
_buildMainContent(), _buildMainContent(isDarkMode),
], ],
),
),
bottomNavigationBar: Opacity(
opacity: 0.5, // 保持半透明效果
child: const CommonBottomNav(currentIndex: 0),
), ),
), ),
bottomNavigationBar: Opacity(
opacity: 0.5, // 保持半透明效果
child: const CommonBottomNav(currentIndex: 0),
),
); );
} }
// 主要内容 // 主要内容
Widget _buildMainContent() { Widget _buildMainContent(bool isDarkMode) {
return Padding( return Padding(
padding: EdgeInsets.fromLTRB(24.w, 40.h, 24.w, 24.h), padding: EdgeInsets.fromLTRB(24.w, 40.h, 24.w, 24.h),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
// 标题部分 // 标题部分
_buildHeader(), _buildHeader(isDarkMode),
// 设备动画 // 设备动画
SizedBox(height: 40.h), SizedBox(height: 40.h),
@ -46,11 +45,11 @@ class PairingView extends GetView<PairingController> {
// 搜索状态 // 搜索状态
SizedBox(height: 40.h), SizedBox(height: 40.h),
_buildSearchStatus(), _buildSearchStatus(isDarkMode),
// 底部按钮 // 底部按钮
SizedBox(height: 60.h), SizedBox(height: 60.h),
_buildBottomButtons(), _buildBottomButtons(isDarkMode),
SizedBox(height: 80.h), // 留出底部导航的空间 SizedBox(height: 80.h), // 留出底部导航的空间
], ],
), ),
@ -59,7 +58,7 @@ class PairingView extends GetView<PairingController> {
} }
// 标题部分 // 标题部分
Widget _buildHeader() { Widget _buildHeader(bool isDarkMode) {
return Column( return Column(
children: [ children: [
Text( Text(
@ -67,7 +66,7 @@ class PairingView extends GetView<PairingController> {
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -75,7 +74,7 @@ class PairingView extends GetView<PairingController> {
'连接世界,超越声音', '连接世界,超越声音',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
), ),
], ],
@ -170,7 +169,7 @@ class PairingView extends GetView<PairingController> {
} }
// 搜索状态 // 搜索状态
Widget _buildSearchStatus() { Widget _buildSearchStatus(bool isDarkMode) {
return Obx(() { return Obx(() {
switch (controller.searchStatus) { switch (controller.searchStatus) {
case SearchStatus.searching: case SearchStatus.searching:
@ -181,7 +180,7 @@ class PairingView extends GetView<PairingController> {
style: TextStyle( style: TextStyle(
fontSize: 18.sp, fontSize: 18.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
SizedBox(height: 8.h), SizedBox(height: 8.h),
@ -189,7 +188,7 @@ class PairingView extends GetView<PairingController> {
'请打开耳机充电盒,将耳机放入您的耳朵', '请打开耳机充电盒,将耳机放入您的耳朵',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
), ),
], ],
@ -217,7 +216,7 @@ class PairingView extends GetView<PairingController> {
'正在跳转到主页...', '正在跳转到主页...',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
), ),
], ],
@ -245,7 +244,7 @@ class PairingView extends GetView<PairingController> {
controller.errorMessage, controller.errorMessage,
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -288,7 +287,7 @@ class PairingView extends GetView<PairingController> {
'请确保耳机已开机并在附近' : controller.errorMessage, '请确保耳机已开机并在附近' : controller.errorMessage,
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -318,7 +317,7 @@ class PairingView extends GetView<PairingController> {
'请在系统设置中配对您的设备' : controller.errorMessage, '请在系统设置中配对您的设备' : controller.errorMessage,
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -344,7 +343,7 @@ class PairingView extends GetView<PairingController> {
} }
// 底部按钮 // 底部按钮
Widget _buildBottomButtons() { Widget _buildBottomButtons(bool isDarkMode) {
return Column( return Column(
children: [ children: [
SizedBox( SizedBox(
@ -352,8 +351,8 @@ class PairingView extends GetView<PairingController> {
child: ElevatedButton( child: ElevatedButton(
onPressed: controller.refreshSearch, onPressed: controller.refreshSearch,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey.withOpacity(0.1), backgroundColor: isDarkMode ? Color(0xFF1A1A1A) : Colors.grey.withOpacity(0.1),
foregroundColor: Colors.black, foregroundColor: isDarkMode ? Colors.white : Colors.black,
padding: EdgeInsets.symmetric(vertical: 16.h), padding: EdgeInsets.symmetric(vertical: 16.h),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),

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

@ -1,12 +1,31 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../app/theme/theme_service.dart';
class SettingsController extends GetxController { class SettingsController extends GetxController {
// 主题服务
final ThemeService _themeService = ThemeService();
// 是否是暗黑模式
final RxBool isDarkMode = false.obs;
// 翻译语言对 // 翻译语言对
final RxString sourceLanguage = '中文'.obs; final RxString sourceLanguage = '中文'.obs;
final RxString targetLanguage = '英文'.obs; final RxString targetLanguage = '英文'.obs;
final List<String> availableLanguages = ['中文', '英文', '日文', '韩文', '法文', '德文', '西班牙文', '俄文']; final List<String> availableLanguages = ['中文', '英文', '日文', '韩文', '法文', '德文', '西班牙文', '俄文'];
@override
void onInit() {
super.onInit();
isDarkMode.value = _themeService.isSavedDarkMode();
}
// 切换主题
void toggleTheme() {
_themeService.changeThemeMode();
isDarkMode.value = _themeService.isSavedDarkMode();
}
void setSourceLanguage(String language) { void setSourceLanguage(String language) {
sourceLanguage.value = language; sourceLanguage.value = language;
} }

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

@ -1,6 +1,7 @@
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 '../controllers/settings_controller.dart'; import '../controllers/settings_controller.dart';
import '../../../core/widgets/common_bottom_nav.dart'; import '../../../core/widgets/common_bottom_nav.dart';
import '../../../core/routes/app_routes.dart'; import '../../../core/routes/app_routes.dart';
@ -10,33 +11,38 @@ class SettingsView extends GetView<SettingsController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
backgroundColor: Colors.grey[50], backgroundColor: isDarkMode ? Colors.black : Colors.grey[50],
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.white, backgroundColor: isDarkMode ? Colors.black : Colors.white,
elevation: 0.5, elevation: 0.5,
title: Text( title: Text(
'设置', '设置',
style: TextStyle( style: TextStyle(
fontSize: 17.sp, fontSize: 17.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), ),
centerTitle: true, centerTitle: true,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black54), icon: Icon(
Icons.arrow_back_ios,
color: isDarkMode ? Colors.white70 : Colors.black54
),
onPressed: () => Get.back(), onPressed: () => Get.back(),
), ),
), ),
body: ListView( body: ListView(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
children: [ children: [
_buildUserInfoCard(), _buildUserInfoCard(isDarkMode),
SizedBox(height: 20.h), SizedBox(height: 20.h),
_buildSystemSettingsSection(), _buildSystemSettingsSection(isDarkMode),
SizedBox(height: 20.h), SizedBox(height: 20.h),
_buildAboutSection(), _buildAboutSection(isDarkMode),
SizedBox(height: 50.h), SizedBox(height: 50.h),
], ],
), ),
@ -45,128 +51,146 @@ class SettingsView extends GetView<SettingsController> {
} }
// 用户信息卡片 // 用户信息卡片
Widget _buildUserInfoCard() { Widget _buildUserInfoCard(bool isDarkMode) {
return Container( return Container(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: LinearGradient(
colors: [Color(0xFFE3F2FD), Color(0xFFF3E5F5)], colors: isDarkMode
? [
const Color(0xFF1A1A1A).withOpacity(0.7),
const Color(0xFF2A2A2A).withOpacity(0.7)
]
: [
const Color(0xFFE3F2FD),
const Color(0xFFF3E5F5)
],
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
), ),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
], ],
), ),
child: Row( child: ClipRRect(
children: [ borderRadius: BorderRadius.circular(16.r),
Container( child: BackdropFilter(
width: 60.w, filter: isDarkMode ? ImageFilter.blur(sigmaX: 10, sigmaY: 10) : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
height: 60.w, child: Row(
decoration: BoxDecoration( children: [
borderRadius: BorderRadius.circular(30.r), Container(
boxShadow: [ width: 60.w,
BoxShadow( height: 60.w,
color: Colors.black.withOpacity(0.1), decoration: BoxDecoration(
blurRadius: 8, borderRadius: BorderRadius.circular(30.r),
offset: const Offset(0, 2), boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
), ),
], child: ClipRRect(
), borderRadius: BorderRadius.circular(30.r),
child: ClipRRect( child: Image.network(
borderRadius: BorderRadius.circular(30.r), 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80',
child: 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,
),
),
),
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( SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Text(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h), '林美珍',
decoration: BoxDecoration( style: TextStyle(
color: Colors.blue[600], fontSize: 18.sp,
borderRadius: BorderRadius.circular(10.r), fontWeight: FontWeight.w600,
), color: isDarkMode ? Colors.white : Colors.black87,
child: Text(
'高级会员',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
),
), ),
), ),
SizedBox(width: 8.w), SizedBox(height: 4.h),
Flexible( Row(
child: Text( children: [
'已连接设备: DeepVoice Pro', Container(
style: TextStyle( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h),
fontSize: 12.sp, decoration: BoxDecoration(
color: Colors.black54, color: Colors.blue[600],
borderRadius: BorderRadius.circular(10.r),
),
child: Text(
'高级会员',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
),
),
), ),
overflow: TextOverflow.ellipsis, SizedBox(width: 8.w),
Flexible(
child: Text(
'已连接设备: DeepVoice Pro',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
SizedBox(height: 4.h),
Text(
'账号ID: deepvoice_834291',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
), ),
], ],
), ),
SizedBox(height: 4.h), ),
Text( Container(
'账号ID: deepvoice_834291', width: 32.w,
style: TextStyle( height: 32.w,
fontSize: 12.sp, decoration: BoxDecoration(
color: Colors.black54, color: isDarkMode
), ? Colors.white.withOpacity(0.1)
: 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,
Container( color: isDarkMode ? Colors.white70 : Colors.grey[600],
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 _buildSystemSettingsSection() { Widget _buildSystemSettingsSection(bool isDarkMode) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -177,100 +201,156 @@ class SettingsView extends GetView<SettingsController> {
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.blue[600], color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
letterSpacing: 1, letterSpacing: 1,
), ),
), ),
), ),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white,
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
], ],
), ),
child: Column( child: ClipRRect(
children: [ borderRadius: BorderRadius.circular(16.r),
// 通知设置 child: BackdropFilter(
_buildSimpleNavigationSetting( filter: isDarkMode ? ImageFilter.blur(sigmaX: 5, sigmaY: 5) : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
title: '通知设置', child: Column(
subtitle: '管理应用推送和提醒', children: [
icon: Icons.notifications_none, // 通知设置
iconBgColor: Colors.indigo[100]!, _buildSimpleNavigationSetting(
iconColor: Colors.indigo[600]!, title: '通知设置',
onTap: () { subtitle: '管理应用推送和提醒',
// 打开通知设置页面 icon: Icons.notifications_none,
}, iconBgColor: isDarkMode ? Colors.indigo[900]!.withOpacity(0.3) : Colors.indigo[100]!,
), iconColor: isDarkMode ? Colors.indigo[300]! : Colors.indigo[600]!,
const Divider(height: 1), titleColor: isDarkMode ? Colors.white : null,
subtitleColor: isDarkMode ? Colors.white70 : null,
// 备份与恢复 onTap: () {
_buildNavigationSetting( // 打开通知设置页面
title: '备份与恢复', },
subtitle: '备份设置和AI互动历史', isDarkMode: isDarkMode,
icon: Icons.cloud_upload_outlined, ),
iconBgColor: Colors.cyan[100]!, Divider(height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]),
iconColor: Colors.cyan[600]!,
value: '上次备份: 今天', // 主题设置
valueStyle: TextStyle( Obx(() => _buildToggleSetting(
fontSize: 12.sp, title: '暗黑模式',
color: Colors.grey[500], subtitle: '切换应用的明暗主题',
), icon: controller.isDarkMode.value ? Icons.dark_mode : Icons.light_mode,
onTap: () { iconBgColor: controller.isDarkMode.value
// 打开备份设置页面 ? Colors.indigo[900]!.withOpacity(0.3)
}, : Colors.amber[100]!,
), iconColor: controller.isDarkMode.value
const Divider(height: 1), ? Colors.indigo[300]!
: Colors.amber[600]!,
// 隐私设置 value: controller.isDarkMode.value,
_buildSimpleNavigationSetting( onChanged: (value) {
title: '隐私设置', controller.toggleTheme();
subtitle: '管理数据收集和权限', },
icon: Icons.shield_outlined, isDarkMode: isDarkMode,
iconBgColor: Colors.purple[100]!, )),
iconColor: Colors.purple[600]!, Divider(height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]),
onTap: () {
// 打开隐私设置页面 // 备份与恢复
}, _buildNavigationSetting(
), title: '备份与恢复',
const Divider(height: 1), subtitle: '备份设置和AI互动历史',
icon: Icons.cloud_upload_outlined,
// 退出登录 iconBgColor: isDarkMode ? Colors.cyan[900]!.withOpacity(0.3) : Colors.cyan[100]!,
_buildSimpleNavigationSetting( iconColor: isDarkMode ? Colors.cyan[300]! : Colors.cyan[600]!,
title: '退出登录', value: '上次备份: 今天',
icon: Icons.logout, valueStyle: TextStyle(
iconBgColor: Colors.red[50]!, fontSize: 12.sp,
iconColor: Colors.red[600]!, color: isDarkMode ? Colors.white70 : Colors.grey[500],
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('确定'),
),
],
), ),
); onTap: () {
}, // 打开备份设置页面
},
isDarkMode: isDarkMode,
),
Divider(height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]),
// 隐私设置
_buildSimpleNavigationSetting(
title: '隐私设置',
subtitle: '管理数据收集和权限',
icon: Icons.shield_outlined,
iconBgColor: isDarkMode ? Colors.purple[900]!.withOpacity(0.3) : Colors.purple[100]!,
iconColor: isDarkMode ? Colors.purple[300]! : Colors.purple[600]!,
titleColor: isDarkMode ? Colors.white : null,
subtitleColor: isDarkMode ? Colors.white70 : null,
onTap: () {
// 打开隐私设置页面
},
isDarkMode: isDarkMode,
),
Divider(height: 1, color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200]),
// 退出登录
_buildSimpleNavigationSetting(
title: '退出登录',
icon: Icons.logout,
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(
'退出登录',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87,
),
),
content: Text(
'确定要退出当前账号吗?',
style: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.black54,
),
),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'取消',
style: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.black54,
),
),
),
TextButton(
onPressed: () {
Get.back();
controller.signOut();
},
child: Text(
'确定',
style: TextStyle(
color: isDarkMode ? Colors.red[300] : Colors.red[600],
),
),
),
],
),
);
},
isDarkMode: isDarkMode,
),
],
), ),
], ),
), ),
), ),
], ],
@ -278,7 +358,7 @@ class SettingsView extends GetView<SettingsController> {
} }
// 关于应用部分 // 关于应用部分
Widget _buildAboutSection() { Widget _buildAboutSection(bool isDarkMode) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -289,7 +369,7 @@ class SettingsView extends GetView<SettingsController> {
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.blue[600], color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
letterSpacing: 1, letterSpacing: 1,
), ),
), ),
@ -297,77 +377,88 @@ class SettingsView extends GetView<SettingsController> {
Container( Container(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white,
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.05),
blurRadius: 10, blurRadius: 10,
offset: const Offset(0, 2), offset: const Offset(0, 2),
), ),
], ],
), ),
child: Row( child: ClipRRect(
mainAxisAlignment: MainAxisAlignment.spaceBetween, borderRadius: BorderRadius.circular(16.r),
children: [ child: BackdropFilter(
Row( filter: isDarkMode ? ImageFilter.blur(sigmaX: 5, sigmaY: 5) : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Container( Row(
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: [ children: [
Text( Container(
'DeepVoice', width: 40.w,
style: TextStyle( height: 40.w,
fontSize: 16.sp, decoration: BoxDecoration(
fontWeight: FontWeight.w500, gradient: LinearGradient(
color: Colors.black87, colors: [
const Color(0xFF2196F3).withOpacity(isDarkMode ? 0.7 : 1.0),
const Color(0xFF9C27B0).withOpacity(isDarkMode ? 0.7 : 1.0)
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12.r),
), ),
), child: Icon(
SizedBox(height: 2.h), Icons.headphones,
Text( size: 24.w,
'版本 2.4.1 (Build 87)', color: Colors.white,
style: TextStyle(
fontSize: 12.sp,
color: Colors.black54,
), ),
), ),
SizedBox(width: 12.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'DeepVoice',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
SizedBox(height: 2.h),
Text(
'版本 2.4.1 (Build 87)',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white70 : Colors.black54,
),
),
],
),
], ],
), ),
], Container(
), padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
Container( decoration: BoxDecoration(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), color: isDarkMode ? Colors.blue[900]!.withOpacity(0.3) : Colors.blue[100],
decoration: BoxDecoration( borderRadius: BorderRadius.circular(16.r),
color: Colors.blue[100], ),
borderRadius: BorderRadius.circular(16.r), child: Text(
), '检查更新',
child: Text( style: TextStyle(
'检查更新', fontSize: 12.sp,
style: TextStyle( color: isDarkMode ? Colors.blue[300] : Colors.blue[600],
fontSize: 12.sp, ),
color: Colors.blue[600], ),
), ),
), ],
), ),
], ),
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -378,7 +469,7 @@ class SettingsView extends GetView<SettingsController> {
'© 2023 DeepVoice Technologies', '© 2023 DeepVoice Technologies',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.grey[500], color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
@ -386,7 +477,7 @@ class SettingsView extends GetView<SettingsController> {
'连接世界,超越声音', '连接世界,超越声音',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.grey[500], color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
), ),
), ),
], ],
@ -405,6 +496,7 @@ class SettingsView extends GetView<SettingsController> {
required Color iconColor, required Color iconColor,
required bool value, required bool value,
required Function(bool) onChanged, required Function(bool) onChanged,
required bool isDarkMode,
}) { }) {
return Padding( return Padding(
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
@ -435,7 +527,7 @@ class SettingsView extends GetView<SettingsController> {
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
), ),
if (subtitle != null) if (subtitle != null)
@ -445,7 +537,7 @@ class SettingsView extends GetView<SettingsController> {
subtitle, subtitle,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
), ),
], ],
@ -472,6 +564,7 @@ class SettingsView extends GetView<SettingsController> {
required String value, required String value,
TextStyle? valueStyle, TextStyle? valueStyle,
required VoidCallback onTap, required VoidCallback onTap,
required bool isDarkMode,
}) { }) {
return InkWell( return InkWell(
onTap: onTap, onTap: onTap,
@ -504,7 +597,7 @@ class SettingsView extends GetView<SettingsController> {
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
), ),
if (subtitle != null) if (subtitle != null)
@ -514,7 +607,7 @@ class SettingsView extends GetView<SettingsController> {
subtitle, subtitle,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.black54, color: isDarkMode ? Colors.white70 : Colors.black54,
), ),
), ),
], ],
@ -527,7 +620,7 @@ class SettingsView extends GetView<SettingsController> {
value, value,
style: valueStyle ?? TextStyle( style: valueStyle ?? TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.black87, color: isDarkMode ? Colors.white : Colors.black87,
), ),
), ),
SizedBox(width: 8.w), SizedBox(width: 8.w),
@ -535,13 +628,13 @@ class SettingsView extends GetView<SettingsController> {
width: 32.w, width: 32.w,
height: 32.w, height: 32.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[100], color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100],
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
child: Icon( child: Icon(
Icons.chevron_right, Icons.chevron_right,
size: 16.w, size: 16.w,
color: Colors.grey[500], color: isDarkMode ? Colors.white70 : Colors.grey[500],
), ),
), ),
], ],
@ -560,7 +653,9 @@ class SettingsView extends GetView<SettingsController> {
required Color iconBgColor, required Color iconBgColor,
required Color iconColor, required Color iconColor,
Color? titleColor, Color? titleColor,
Color? subtitleColor,
required VoidCallback onTap, required VoidCallback onTap,
required bool isDarkMode,
}) { }) {
return InkWell( return InkWell(
onTap: onTap, onTap: onTap,
@ -593,7 +688,7 @@ class SettingsView extends GetView<SettingsController> {
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: titleColor ?? Colors.black87, color: titleColor ?? (isDarkMode ? Colors.white : Colors.black87),
), ),
), ),
if (subtitle != null) if (subtitle != null)
@ -603,7 +698,7 @@ class SettingsView extends GetView<SettingsController> {
subtitle, subtitle,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.black54, color: subtitleColor ?? (isDarkMode ? Colors.white70 : Colors.black54),
), ),
), ),
], ],
@ -614,13 +709,13 @@ class SettingsView extends GetView<SettingsController> {
width: 32.w, width: 32.w,
height: 32.w, height: 32.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[100], color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.grey[100],
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
child: Icon( child: Icon(
Icons.chevron_right, Icons.chevron_right,
size: 16.w, size: 16.w,
color: Colors.grey[500], color: isDarkMode ? Colors.white70 : Colors.grey[500],
), ),
), ),
], ],

18
lib/modules/splash/controllers/splash_controller.dart

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../../core/routes/app_routes.dart'; import '../../../core/routes/app_routes.dart';
import '../../../app/theme/theme_service.dart';
class SplashController extends GetxController { class SplashController extends GetxController {
// 进度条动画控制 // 进度条动画控制
@ -15,12 +16,18 @@ class SplashController extends GetxController {
final _isResourceLoaded = false.obs; final _isResourceLoaded = false.obs;
bool get isResourceLoaded => _isResourceLoaded.value; bool get isResourceLoaded => _isResourceLoaded.value;
// 主题服务
final ThemeService _themeService = ThemeService();
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
// 确保页面先渲染,再执行其他操作 // 确保页面先渲染,再执行其他操作
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
// 检查并应用上次保存的皮肤模式
_checkAndApplyTheme();
// 启动进度条动画 // 启动进度条动画
_startLoadingAnimation(); _startLoadingAnimation();
@ -29,12 +36,21 @@ class SplashController extends GetxController {
}); });
} }
// 检查并应用上次保存的皮肤模式
void _checkAndApplyTheme() {
// 获取保存的主题模式
final savedThemeMode = _themeService.getThemeMode();
// 应用保存的主题模式
Get.changeThemeMode(savedThemeMode);
}
// 进度条动画 // 进度条动画
void _startLoadingAnimation() { void _startLoadingAnimation() {
// 模拟0.5秒的加载进度 // 模拟0.5秒的加载进度
Timer.periodic(const Duration(milliseconds: 5), (timer) { Timer.periodic(const Duration(milliseconds: 5), (timer) {
if (_loadingProgress.value < 1.0) { if (_loadingProgress.value < 1.0) {
_loadingProgress.value += 0.06; _loadingProgress.value += 0.01;
} else { } else {
timer.cancel(); timer.cancel();
// 当进度条动画完成且资源加载完毕时,跳转到登录页面 // 当进度条动画完成且资源加载完毕时,跳转到登录页面

76
lib/modules/splash/views/splash_view.dart

@ -8,82 +8,46 @@ class SplashView extends GetView<SplashController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
backgroundColor: const Color(0xFFF5F5F7), backgroundColor: isDarkMode ? Colors.black : const Color(0xFFF5F5F7),
body: Stack( body: Stack(
children: [ children: [
// 状态栏
_buildStatusBar(),
// 主内容 // 主内容
Center( Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// Logo动画 // Logo动画
_buildAnimatedLogo(), _buildAnimatedLogo(isDarkMode),
// 应用名称 // 应用名称
_buildAppTitle(), _buildAppTitle(isDarkMode),
// 标语 // 标语
_buildSlogan(), _buildSlogan(isDarkMode),
// 加载进度条 // 加载进度条
SizedBox(height: 40.h), SizedBox(height: 40.h),
_buildLoadingBar(), _buildLoadingBar(isDarkMode),
// 额外信息 // 额外信息
SizedBox(height: 16.h), SizedBox(height: 16.h),
_buildExtraInfo(), _buildExtraInfo(isDarkMode),
], ],
), ),
), ),
// 版本号 // 版本号
_buildVersionInfo(), _buildVersionInfo(isDarkMode),
], ],
), ),
); );
} }
// 状态栏
Widget _buildStatusBar() {
return Positioned(
top: 0,
left: 0,
right: 0,
child: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'9:41',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[800],
),
),
Row(
children: [
Icon(Icons.signal_cellular_4_bar, size: 12.sp, color: Colors.grey[800]),
SizedBox(width: 4.w),
Icon(Icons.wifi, size: 12.sp, color: Colors.grey[800]),
SizedBox(width: 4.w),
Icon(Icons.battery_full, size: 12.sp, color: Colors.grey[800]),
],
),
],
),
),
),
);
}
// 动画Logo // 动画Logo
Widget _buildAnimatedLogo() { Widget _buildAnimatedLogo(bool isDarkMode) {
return TweenAnimationBuilder<double>( return TweenAnimationBuilder<double>(
tween: Tween<double>(begin: 0.8, end: 1.1), tween: Tween<double>(begin: 0.8, end: 1.1),
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
@ -130,7 +94,7 @@ class SplashView extends GetView<SplashController> {
} }
// 应用标题 // 应用标题
Widget _buildAppTitle() { Widget _buildAppTitle(bool isDarkMode) {
return TweenAnimationBuilder<double>( return TweenAnimationBuilder<double>(
tween: Tween<double>(begin: 0.0, end: 1.0), tween: Tween<double>(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 1500), duration: const Duration(milliseconds: 1500),
@ -145,7 +109,7 @@ class SplashView extends GetView<SplashController> {
style: TextStyle( style: TextStyle(
fontSize: 28.sp, fontSize: 28.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.grey[800], color: isDarkMode ? Colors.white : Colors.grey[800],
), ),
), ),
), ),
@ -155,7 +119,7 @@ class SplashView extends GetView<SplashController> {
} }
// 标语 // 标语
Widget _buildSlogan() { Widget _buildSlogan(bool isDarkMode) {
return TweenAnimationBuilder<double>( return TweenAnimationBuilder<double>(
tween: Tween<double>(begin: 0.0, end: 1.0), tween: Tween<double>(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 1500), duration: const Duration(milliseconds: 1500),
@ -169,7 +133,7 @@ class SplashView extends GetView<SplashController> {
'连接世界,岂止声音', '连接世界,岂止声音',
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
color: Colors.grey[600], color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
), ),
), ),
), ),
@ -179,7 +143,7 @@ class SplashView extends GetView<SplashController> {
} }
// 加载进度条 // 加载进度条
Widget _buildLoadingBar() { Widget _buildLoadingBar(bool isDarkMode) {
return Padding( return Padding(
padding: EdgeInsets.symmetric(horizontal: 80.w), padding: EdgeInsets.symmetric(horizontal: 80.w),
child: Stack( child: Stack(
@ -187,7 +151,7 @@ class SplashView extends GetView<SplashController> {
Container( Container(
height: 4.h, height: 4.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[200], color: isDarkMode ? Colors.grey[800] : Colors.grey[200],
borderRadius: BorderRadius.circular(2.r), borderRadius: BorderRadius.circular(2.r),
), ),
), ),
@ -216,7 +180,7 @@ class SplashView extends GetView<SplashController> {
} }
// 额外信息 // 额外信息
Widget _buildExtraInfo() { Widget _buildExtraInfo(bool isDarkMode) {
return TweenAnimationBuilder<double>( return TweenAnimationBuilder<double>(
tween: Tween<double>(begin: 0.0, end: 1.0), tween: Tween<double>(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 1500), duration: const Duration(milliseconds: 1500),
@ -228,7 +192,7 @@ class SplashView extends GetView<SplashController> {
'AI语音专家 · 随时随地', 'AI语音专家 · 随时随地',
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.grey[400], color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
), ),
), ),
); );
@ -237,7 +201,7 @@ class SplashView extends GetView<SplashController> {
} }
// 版本信息 // 版本信息
Widget _buildVersionInfo() { Widget _buildVersionInfo(bool isDarkMode) {
return Positioned( return Positioned(
bottom: 32.h, bottom: 32.h,
left: 0, left: 0,
@ -247,7 +211,7 @@ class SplashView extends GetView<SplashController> {
controller.version, controller.version,
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: Colors.grey[400], color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
), ),
), ),
), ),

28
macos/Podfile.lock

@ -8,6 +8,9 @@ PODS:
- FlutterMacOS - FlutterMacOS
- file_selector_macos (0.0.1): - file_selector_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- flutter_blue_plus_darwin (0.0.2):
- Flutter
- FlutterMacOS
- flutter_local_notifications (0.0.1): - flutter_local_notifications (0.0.1):
- FlutterMacOS - FlutterMacOS
- flutter_tts (0.0.1): - flutter_tts (0.0.1):
@ -23,17 +26,9 @@ PODS:
- FlutterMacOS - FlutterMacOS
- share_plus (0.0.1): - share_plus (0.0.1):
- FlutterMacOS - FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- speech_to_text (0.0.1):
- Flutter
- FlutterMacOS
- Try
- sqflite_darwin (0.0.4): - sqflite_darwin (0.0.4):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- Try (2.1.1)
- window_size (0.0.2): - window_size (0.0.2):
- FlutterMacOS - FlutterMacOS
@ -42,6 +37,7 @@ DEPENDENCIES:
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`) - audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`) - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- flutter_blue_plus_darwin (from `Flutter/ephemeral/.symlinks/plugins/flutter_blue_plus_darwin/darwin`)
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`) - flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
- flutter_tts (from `Flutter/ephemeral/.symlinks/plugins/flutter_tts/macos`) - flutter_tts (from `Flutter/ephemeral/.symlinks/plugins/flutter_tts/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
@ -49,15 +45,9 @@ DEPENDENCIES:
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- record_darwin (from `Flutter/ephemeral/.symlinks/plugins/record_darwin/macos`) - record_darwin (from `Flutter/ephemeral/.symlinks/plugins/record_darwin/macos`)
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- speech_to_text (from `Flutter/ephemeral/.symlinks/plugins/speech_to_text/darwin`)
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`) - window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
SPEC REPOS:
trunk:
- Try
EXTERNAL SOURCES: EXTERNAL SOURCES:
audio_service: audio_service:
:path: Flutter/ephemeral/.symlinks/plugins/audio_service/darwin :path: Flutter/ephemeral/.symlinks/plugins/audio_service/darwin
@ -67,6 +57,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
file_selector_macos: file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
flutter_blue_plus_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_blue_plus_darwin/darwin
flutter_local_notifications: flutter_local_notifications:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
flutter_tts: flutter_tts:
@ -81,10 +73,6 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/record_darwin/macos :path: Flutter/ephemeral/.symlinks/plugins/record_darwin/macos
share_plus: share_plus:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
speech_to_text:
:path: Flutter/ephemeral/.symlinks/plugins/speech_to_text/darwin
sqflite_darwin: sqflite_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin :path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
window_size: window_size:
@ -95,6 +83,7 @@ SPEC CHECKSUMS:
audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e
device_info_plus: a56e6e74dbbd2bb92f2da12c64ddd4f67a749041 device_info_plus: a56e6e74dbbd2bb92f2da12c64ddd4f67a749041
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31 file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
flutter_blue_plus_darwin: 09444a26fb6bdef523e55b68fc1c59af5a877ea6
flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7 flutter_local_notifications: 13862b132e32eb858dea558a86d45d08daeacfe7
flutter_tts: ae915565cc6948444b513acc8ee021993281e027 flutter_tts: ae915565cc6948444b513acc8ee021993281e027
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
@ -102,10 +91,7 @@ SPEC CHECKSUMS:
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
record_darwin: 30509266ae213af8afdb09a8ae7467cb64c1377e record_darwin: 30509266ae213af8afdb09a8ae7467cb64c1377e
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
speech_to_text: 9dc43a5df3cbc2813f8c7cc9bd0fbf94268ed7ac
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96
window_size: 4bd15034e6e3d0720fd77928a7c42e5492cfece9 window_size: 4bd15034e6e3d0720fd77928a7c42e5492cfece9
PODFILE CHECKSUM: 8c4442624fc136b0afb378a2502958e01c05d073 PODFILE CHECKSUM: 8c4442624fc136b0afb378a2502958e01c05d073

Loading…
Cancel
Save