Browse Source

Merge branch 'new_dev' of https://github.com/deepcloud2048/deep_voice into new_dev

weicu
tanlongsheng 1 year ago
parent
commit
0c6803cab6
  1. 2
      lib/core/translations/language/de_de.dart
  2. 350
      lib/core/translations/language/en_us.dart
  3. 2
      lib/core/translations/language/ms_my.dart
  4. 2
      lib/core/translations/language/pl_pl.dart
  5. 2
      lib/core/translations/language/tr_tr.dart
  6. 310
      lib/core/translations/language/zh_cn.dart
  7. 2
      lib/core/translations/language/zh_hk.dart
  8. 14
      lib/data/services/account_service.dart
  9. 2
      lib/data/services/network/nw_api.dart
  10. 4
      lib/main.dart
  11. 47
      lib/modules/agent/controllers/agent_controller.dart
  12. 52
      lib/modules/agent/controllers/message_action_controller.dart
  13. 78
      lib/modules/agent/views/agent_view.dart
  14. 2
      lib/modules/agent/views/message_bubble.dart
  15. 10
      lib/modules/agent/views/music_card.dart
  16. 87
      lib/modules/agent/views/navigation_card.dart
  17. 147
      lib/modules/agent/views/weather_card.dart
  18. 5
      lib/modules/agent/widgets/full_screen_editor.dart
  19. 18
      lib/modules/common/widgets/version_update_dialog.dart
  20. 16
      lib/modules/devices/views/devices_view.dart
  21. 223
      lib/modules/feedback/views/feedback_view.dart
  22. 29
      lib/modules/login/controllers/login_controller.dart
  23. 2
      lib/modules/login/views/login_view.dart
  24. 97
      lib/modules/music/views/music_playlist_view.dart
  25. 56
      lib/modules/ota_upgrade/views/ota_upgrade_view.dart
  26. 87
      lib/modules/pairing/controllers/pairing_controller.dart
  27. 9
      lib/modules/pairing/views/pairing_view.dart
  28. 2
      lib/modules/pairing/views/pairing_view_new.dart
  29. 85
      lib/modules/profile/controllers/profile_controller.dart
  30. 7
      lib/modules/profile/views/profile_view.dart
  31. 11
      lib/modules/settings/controllers/settings_controller.dart
  32. 91
      lib/modules/settings/views/permissions_view.dart
  33. 32
      lib/modules/settings/views/settings_view.dart
  34. 2
      lib/modules/splash/views/splash_view.dart
  35. 2
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt
  36. 2
      local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt

2
lib/core/translations/language/de_de.dart

@ -125,7 +125,7 @@ const Map<String, String> deDE = {
"exploreSlogan": "Intelligente Kopfhörer, unbegrenzte Möglichkeiten",
"exploreSlogan1": "Intelligenter Begleiter, unbegrenzte Möglichkeiten",
"exploreSlogan2": "Intelligente Brille, unbegrenzte Möglichkeiten",
"exploreAi": "Entdecken Sie die KI-Funktionen von DeepSound",
"exploreAi": "Entdecken Sie die KI-Funktionen von DeapSound",
"aiFunction": "KI-Funktionen",
"allRoundAssistant": "Allround-Assistent",
"allRoundAssistantInfo": "Hilft bei der Lösung verschiedener Probleme",

350
lib/core/translations/language/en_us.dart

@ -97,6 +97,17 @@ const Map<String, String> enUS = {
"login": "Login",
"usePasswordLogin": "Use password login",
// 隐私政策弹窗
"loginDeclaration": "DeapSound Declaration", // DeapSound 声明
"welcomeToThisApp":
"Welcome to DeapSound, please read carefully ", // 欢迎使用DeapSound,请充分阅读
// "privacyPolicy": "Privacy Policy", // 《隐私政策》 - 已存在,使用现有键
// "userAgreement": "User Agreement", // 《用户协议》 - 已存在,使用现有键
"privacyPolicyText":
". By clicking \"Agree and Enter\", you indicate that you have fully read and agree to the above agreements. Clicking \"Disagree\" will exit the application.", // ,点击"同意并进入"表示您已充分阅读并同意上述协议。点击"不同意"将退出应用。
"disagree": "Disagree", // 不同意
"agreeAndEnter": "Agree and Enter", // 同意并进入
// 首页
"deviceStatus": "Device Status",
"reconnect": "Reconnect",
@ -213,8 +224,6 @@ const Map<String, String> enUS = {
"privacySettingsInfo": "Manage data collection and permissions",
"permissionManagement": "Permission Management", // 权限管理
"permissionManagementInfo": "Manage app permission settings", // 管理应用权限设置
"logout": "Log Out",
"logoutTips": "Are you sure you want to log out of the current account?",
"aboutApplication": "About",
"versions": "Version",
"checkUpdates": "Check Updates",
@ -237,31 +246,292 @@ const Map<String, String> enUS = {
'selecttimbre': 'Select Timbre',
'pleaseRead': 'Please Read',
'completeRecording': 'Complete Recording',
'deleteAccount': 'Delete Account',
'deleteAccountTips':
'Are you sure you want to permanently delete your account? This action cannot be undone.',
"firmwareUpgrade": "Firmware Upgrade", // 固件升级
"bleHeadsetFirmwareUpgrade": "BLE Headset Firmware Upgrade", // BLE耳机固件版本升级
"deviceManagement": "Device Management", // 设备管理
"manageConnectedDevices": "Manage Connected Bluetooth Devices", // 管理已绑定的蓝牙设备
//设置setting_controller
// 版本更新相关
'currentLatestVersion': 'Current version is already the latest {version}',
'checkUpdateFailed': 'Check update failed',
'networkErrorRetry': 'Network error, please try again later',
// 设备管理相关
'clearPairedDevices': 'Clear Paired Devices',
'clearPairedDevicesConfirm':
'Are you sure you want to clear all paired devices?',
'clearPairedDevicesSuccess': 'Clear paired devices successfully',
'clearPairedDevicesFailed': 'Clear paired devices failed',
// 设置页面 - 实时语音对话
'realtimeVoiceChat': 'Real-time Voice Chat',
'realtimeVoiceChatInfo':
'Experience intelligent voice interaction features (Preview)',
'loading': 'Loading...',
// 聊天页
//设备管理页面
"earphone": "Earphone", // 耳机
"voicerecorder": "Voice Recorder", // 录音笔
"notBound": "Not Bound", // 未绑定
"deviceNotBoundYet": "Device not bound yet", // 还未绑定设备
"unbind": "Unbind", // 解绑
// Agent模块
//Agent View
"XiaoYan": "XiaoYan",
"clearChatHistory": "Clear Chat History",
"online": "Online",
"inputMessage": "Type a message...",
"imListening": "Listening...",
"canStartTalking": "You may start speaking",
"addQuestionAboutImage": "Add questions or descriptions about the image...",
"summarizeImageContent": "Summarize image content",
"extractImageText": "Extract image text",
"translateImageText": "Translate image text",
"recording": "Recording...",
"holdToSpeak": "Hold to speak",
"takePhoto": "Take Photo",
"photoAlbum": "Photo Album",
"makeCall": "Make Call",
"aiVoiceCall": "AI Voice Call",
"inCall": "In call...",
"aiReplying": "AI is replying...",
"waitingToStart": "Waiting to start...",
"clickToStartCall": "Click to start call",
"listeningToYou": "Listening to you...",
"processing": "Processing...",
"loadMoreMessages": "Load more messages...",
"loadFailedClickRetry": "Load failed, click to retry",
"swipeUpForMore": "Swipe up for more",
// Agent Controller
'welcomeMessage': 'Hello! I\'m **XiaoYan**, I can help you:\n\n'
'• Answer questions and provide information\n\n'
'• Real-time voice translation\n\n'
'• Recommend music and podcasts\n\n'
'• Voice memos and reminders\n\n'
'• Control headset functions\n\n'
'What can I help you with?',
'microphonePermission': 'Microphone',
'voiceRecognitionPermissionText':
'Voice recognition requires microphone access.',
'voiceTranslationPermissionText':
'Voice recognition and translation require microphone access.',
'phoneCallPermissionText':
'Phone call function requires microphone access for voice calls.',
'permissionDeniedText':
'You have permanently denied microphone permission, please go to system settings to enable it.',
'startVoiceInput': 'Start voice input',
'startPhoneCallMode': 'Start phone call mode, begin voice input',
//Agent 全屏编辑器
'fullScreenEditorHint': 'Type your message here...', // 全屏编辑器输入提示
'characterCount': '{count} characters', // 字符计数显示
// 消息长按操作
'copy': 'Copy',
'copySuccess': 'Copy successful',
'report': 'Report',
'submitSuccess': 'Submit successful',
'submitFailed': 'Submit failed',
'reportSubmitted': 'Report submitted, we will process it as soon as possible',
//'networkError': 'Network error, please try again later',
'harmfulUnsafe': 'Harmful/Unsafe',
'pornographicVulgar': 'Pornographic/Vulgar',
'misleadingAttack': 'Misleading/Attack',
'illegalCriminal': 'Illegal/Criminal',
'privacyRelated': 'Privacy Related',
'copyrightViolation': 'Infringement of my copyright, reputation rights, etc.',
'other': 'Other',
'reportDescriptionHint':
'We want to know the reason for your report, you can describe the problem you encountered.',
//'submit': 'Submit',
//Message_bubble
'generatedByAi': 'Generated by AI',
//music_card
'recommendedMusic': 'Here are some recommended music:',
'playList': 'Playlist',
'moreMusic': 'More music',
//导航卡片 navigation_card
'kilometers': ' km', // 公里单位
'meters': ' m', // 米单位
'hours': ' hours', // 小时单位
'minutes': ' minutes', // 分钟单位
'seconds': ' seconds', // 秒单位
'navigating': 'Navigating', // 导航状态
'currentLocation': 'Current Location', // 当前位置
'approximate': 'About ', // 大约
'enterRoad': ' enter ', // 进入道路
"driving": "Driving",
"walking": "Walking",
"bicycling": "Cycling",
"tsransit": "Transit",
//天气卡片 weather_card
'weatherQuery': 'Weather Query:',
'highest': 'High',
'lowest': 'Low',
'futureForecast': 'Future Forecast',
'hotWeatherTip':
'Hot weather today, please pay attention to heat prevention and cooling, drink more water to avoid heat stroke',
'coldWeatherTip':
'Low temperature today, please keep warm when going out and be careful of catching cold',
'rainyWeatherTip':
'Rainy today, please bring rain gear when going out and pay attention to travel safety',
'snowyWeatherTip':
'Snowy today, roads are slippery, please pay attention to safety and keep warm',
'foggyWeatherTip':
'Foggy and hazy today, low visibility, please wear a mask when going out',
'windyWeatherTip':
'Strong wind today, please pay attention to safety when going out and secure items',
'sunnyWeatherTip':
'Sunny with strong UV rays today, please protect yourself from the sun when going out',
'temperatureDifferenceTip':
'Large temperature difference between day and night today, please adjust clothing accordingly',
'comfortableWeatherTip':
'Pleasant weather today, perfect for outdoor activities',
"monday": "Mon",
"tuesday": "Tue",
"wednesday": "Wed",
"thursday": "Thu",
"friday": "Fri",
"saturday": "Sat",
"sunday": "Sun",
// 天气描述
"sunny": "Sunny",
"partlyCloudy": "Partly Cloudy",
"partlySunny": "Partly Sunny",
"cloudy": "Cloudy",
"overcast": "Overcast",
"shower": "Shower",
"thundershower": "Thundershower",
"lightRain": "Light Rain",
"moderateRain": "Moderate Rain",
"heavyRain": "Heavy Rain",
"rainstorm": "Rainstorm",
"snowShower": "Snow Shower",
"lightSnow": "Light Snow",
"moderateSnow": "Moderate Snow",
"heavySnow": "Heavy Snow",
"blizzard": "Blizzard",
"fog": "Fog",
"haze": "Haze",
"strongWind": "Strong Wind",
// 编辑个人信息页
"editProfile": "Edit Profile",
"avatar": "Avatar",
"nickname": "Nickname",
"save": "Save",
"about": "About",
"enterNickname": "Please enter your nickname",
"notSet": "Not Set",
"accountSetting": "Account Setting",
"logout": "Log Out",
"logoutTips": "Are you sure you want to log out of the current account?",
'deleteAccount': 'Delete Account',
'deleteAccountTips':
'Are you sure you want to permanently delete your account? This action cannot be undone.',
//Profile 错误信息
'networkConnectionFailed':
'Network connection failed, please check network settings and try again',
'serverTemporarilyUnavailable':
'Server temporarily unavailable, please try again later',
'loginExpiredPleaseRelogin': 'Login expired, please log in again',
'noPermissionForThisOperation': 'No permission to perform this operation',
'requestedResourceNotFound': 'Requested resource not found',
'imageProcessingFailedPleaseReselect':
'Image processing failed, please select image again',
'operationFailedPleaseRetry': 'Operation failed, please try again',
'serverReturnedError': 'Server returned error',
'serverError': 'Server error',
'networkConnectionFailedCheckSettings':
'Network connection failed, please check network settings',
'serverInternalErrorRetryLater':
'Server internal error, please try again later',
//Profile 用户交互
//'error': 'Error',
//'success': 'Success',
'imageCompressionFailed': 'Image compression failed',
'avatarUpdateFailed': 'Avatar update failed',
'usernameCannotBeEmpty': 'Username cannot be empty',
'saveSuccess': 'Save Success',
'personalInfoUpdated': 'Personal information updated',
'saveFailed': 'Save Failed',
'loggedOut': 'Logged out',
'logoutFailedRetry': 'Logout failed, please try again',
'accountPermanentlyDeleted': 'Account permanently deleted',
'deleteAccountFailedRetry': 'Delete account failed, please try again',
// 账号服务相关
'clearUserDataFailed': 'Failed to clear user data', // 清理用户数据失败
'deleteUserDataFailed': 'Failed to delete user data', // 删除用户数据失败
'thirdPartyLogoutSuccess': 'Third-party logout successful', // 第三方登录退出成功
'thirdPartyLogoutFailed': 'Third-party logout failed', // 第三方登录退出失败
'signOutProcessError': 'Error occurred during sign out process', // 登出过程发生错误
'deleteAccountProcessError':
'Error occurred during account deletion process', // 删除账号过程发生错误
'userDataClearSuccess': 'User data cleared successfully', // 用户数据清理成功
'allUserDataClearSuccess': 'All user data cleared successfully', // 所有用户数据清理成功
'accountServiceInitialized':
'AccountService initialized', // AccountService 已初始化
// 权限管理页面
'getPermissionStatusFailed': 'Failed to get permission status',
'communicationPermissions': 'Communication Permissions',
'calendarPermissions': 'Calendar Permissions',
'locationPermissions': 'Location Permissions',
'phone': 'Phone',
'sms': 'SMS',
'calendarWrite': 'Calendar Write',
'calendarFullAccess': 'Calendar Full Access',
'locationInfo': 'Location Info',
'phonePermissionDesc': 'Used for phone call functionality',
'smsPermissionDesc': 'Used for SMS functionality',
'calendarWritePermissionDesc':
'Used for creating calendar events and reminders',
'calendarFullAccessPermissionDesc':
'Used for reading and managing calendar events and reminders',
'locationPermissionDesc': 'Used for getting current location information',
'appFunctionNeeds': 'App function needs',
'authorized': 'Authorized',
'unauthorized': 'Unauthorized',
'needOpenInSystemSettings': 'Need to enable in system settings',
'partialAuthorization': 'Partial Authorization',
'unknownStatus': 'Unknown Status',
'permissionGranted': 'Permission granted',
'permissionRequestError': 'Error requesting permission',
'phonePermissionDetailDesc':
'Phone call functionality requires phone permission',
'smsPermissionDetailDesc': 'SMS functionality requires SMS permission',
'calendarWritePermissionDetailDesc':
'Creating calendar events requires calendar write permission',
'calendarFullAccessPermissionDetailDesc':
'Managing calendar events requires full calendar permission',
'locationPermissionDetailDesc':
'Getting location information requires location permission',
'appNeedsPermissionForFullFunction':
'App needs this permission to provide full functionality',
'permanentDenialText':
'You have permanently denied {permission} permission, please go to app settings to enable it',
'goToSettings': 'Go to Settings',
// 版本更新对话框
'newVersionFound': 'New Version Found', // 版本更新对话框标题
'remindLater': 'Remind Later', // 稍后提醒按钮
'updateNow': 'Update Now', // 立即更新按钮
'checkUpdate': 'Check Update', // 检查更新按钮
'updateFailed': 'Update Failed', // 更新失败提示
'cannotOpenAppStore':
'Cannot open app store, please update manually', // 无法打开应用商店提示
'updateErrorRetry':
'Error occurred during update, please try again later', // 更新错误重试提示
// 国家列表
"邮箱": "Email",
@ -371,12 +641,6 @@ const Map<String, String> enUS = {
"斐济": "Fiji",
"所罗门群岛": "Solomon Islands",
// 导航
"driving": "Driving",
"walking": "Walking",
"bicycling": "Cycling",
"tsransit": "Transit",
// 翻译模块
// 翻译主页
"translationHistory": "Translation History",
@ -448,6 +712,7 @@ const Map<String, String> enUS = {
"confirmBinding": "Confirm Binding",
"associatingDevice": "Associating device...",
"goToBluetoothSettings": "Go to Bluetooth Settings",
'bluetooth': 'Bluetooth',
// 配对状态文本
"readyToPair": "Ready to pair",
@ -473,6 +738,38 @@ const Map<String, String> enUS = {
"Authorization failed, please check authorization code",
"pairingFailedRetry": "Pairing failed, please retry",
//配对控制器相关
//'connectDevice': 'Connect Device',
'pleaseEnableBluetooth': 'Please enable Bluetooth',
'deviceDisconnected': 'Device disconnected',
'readyToStartPairing': 'Ready to start pairing',
'checkingEnvironment': 'Checking environment...',
'ensureHeadsetOnAndPairingMode':
'Please ensure headset is on and in pairing mode',
//'goToBluetoothSettings': 'Go to Bluetooth Settings',
//'verifyingDevice': 'Verifying device...',
//'confirmBinding': 'Confirm Binding',
//'associatingDevice': 'Associating device...',
'establishingSecureConnection': 'Establishing secure connection...',
'needManualBindingAuthCode': 'Manual binding authorization code required...',
'pairingSuccessful': 'Pairing successful!',
'enableBluetooth': 'Enable Bluetooth',
'grantPermissions': 'Grant Permissions',
'retryAssociation': 'Retry Association',
'retryAuthorization': 'Retry Authorization',
'pleaseGrantNecessaryPermissions': 'Please grant necessary permissions',
'checkFailedRetry': 'Check failed, please retry',
'pleaseConnectDeepSoundDevice': 'Please connect DeepSound device',
'verificationFailedRetry': 'Verification failed, please retry',
'invalidDeviceAddress': 'Invalid device address',
'bleDeviceAssociationFailed': 'BLE device association failed',
'deviceAssociationFailedRetry': 'Device association failed, please retry',
'bleConnectionTimeoutRetry': 'BLE connection timeout, please retry',
'blePairingStartupFailed': 'BLE pairing startup failed',
'bleConnectionFailed': 'BLE connection failed',
'deviceAuthorizationFailedCheckCode':
'Device authorization failed, please check authorization code',
// 用户反馈页
"feedback": "Feedback",
'feedbackInfo': 'Provide feedback or suggestions',
@ -485,6 +782,35 @@ const Map<String, String> enUS = {
'feedbackSubmitSuccess': 'Feedback submitted successfully, thank you!',
'feedbackSubmitFailed': 'Failed to submit feedback, please try again later',
// OTA升级模块
"upgradeExitConfirm":
"Currently upgrading, exiting will interrupt the upgrade process. Are you sure you want to exit?",
"deviceModel": "Device Model",
"unknownDevice": "Unknown Device",
"currentFirmwareVersion": "Current Firmware Version",
"latestFirmwareVersion": "Latest Firmware Version",
"ota_newVersionFound": "New Version Found",
"latestVersion": "Latest Version",
"gettingDeviceInfo": "Getting device information...",
"keepDeviceConnected": "Please keep device connected",
"connectionFailed": "Connection Failed",
"retryConnection": "Retry Connection",
"ota_updateNow": "Update Now",
"keepConnectedDontClose":
"Please keep device connected, do not close the app",
"doNotDisconnect": "Do not disconnect",
"charging": "Charging",
"updateContent": "Update Content",
"removeEarbudsEnsureBattery":
"Remove both earbuds and ensure battery level is above 30%",
// 音乐列表页面
"noMusic": "No Music", // 暂无音乐
"noPlayingMusic": "No Playing Music", // 暂无播放音乐
"unknownSong": "Unknown Song", // 未知歌曲
"unknownArtist": "Unknown Artist", // 未知歌手
"playAll": "Play All", // 播放全部
// 语言名称
"中文(简体)": "Chinese (Simplified)",
"中文(繁体)": "Chinese (Traditional)",

2
lib/core/translations/language/ms_my.dart

@ -122,7 +122,7 @@ const Map<String, String> msMY = {
"exploreSlogan": "Fon Telinga Pintar, Kemungkinan Tanpa Had",
"exploreSlogan1": "Teman pintar, Kemungkinan Tanpa Had",
"exploreSlogan2": "Cermin mata pintar, Kemungkinan Tanpa Had",
"exploreAi": "Terokai ciri AI yang disediakan oleh DeepSound",
"exploreAi": "Terokai ciri AI yang disediakan oleh DeapSound",
"aiFunction": "Ciri AI",
"allRoundAssistant": "Pembantu Serba Boleh",
"allRoundAssistantInfo": "Membantu menyelesaikan pelbagai masalah",

2
lib/core/translations/language/pl_pl.dart

@ -125,7 +125,7 @@ const Map<String, String> plPL = {
"exploreSlogan": "Inteligentne słuchawki, nieskończone możliwości",
"exploreSlogan1": "Inteligentny towarzysz, nieskończone możliwości",
"exploreSlogan2": "Inteligentne okulary, nieskończone możliwości",
"exploreAi": "Odkrywaj funkcje AI dostarczane przez DeepSound",
"exploreAi": "Odkrywaj funkcje AI dostarczane przez DeapSound",
"aiFunction": "Funkcje AI",
"allRoundAssistant": "Wszechstronny asystent",
"allRoundAssistantInfo": "Pomaga rozwiązywać różne problemy",

2
lib/core/translations/language/tr_tr.dart

@ -123,7 +123,7 @@ const Map<String, String> trTR = {
"exploreSlogan1": "Akıllı arkadaş, Sonsuz Olasılıklar",
"exploreSlogan2": "Akıllı gözlükler, Sonsuz Olasılıklar",
"exploreAi":
"DeepSound tarafından sağlanan yapay zeka özelliklerini keşfedin",
"DeapSound tarafından sağlanan yapay zeka özelliklerini keşfedin",
"aiFunction": "Yapay Zeka Özellikleri",
"allRoundAssistant": "Çok Yönlü Asistan",
"allRoundAssistantInfo": "Çeşitli sorunları çözmeye yardımcı olur",

310
lib/core/translations/language/zh_cn.dart

@ -95,6 +95,16 @@ const Map<String, String> zhCN = {
"login": "登录",
"usePasswordLogin": "使用密码登录",
// 隐私政策弹窗
"loginDeclaration": "DeapSound 声明", // DeapSound 声明
"welcomeToThisApp": "欢迎使用DeapSound,请充分阅读", // 欢迎使用DeapSound,请充分阅读
// "privacyPolicy": "《隐私政策》", // 《隐私政策》 - 已存在,使用现有键
// "userAgreement": "《用户协议》", // 《用户协议》 - 已存在,使用现有键
"privacyPolicyText":
",点击'同意并进入'表示您已充分阅读并同意上述协议。点击'不同意'将退出应用。", // ,点击"同意并进入"表示您已充分阅读并同意上述协议。点击"不同意"将退出应用。
"disagree": "不同意", // 不同意
"agreeAndEnter": "同意并进入", // 同意并进入
// 首页
"deviceStatus": "设备状态",
"reconnect": "重新连接",
@ -208,8 +218,6 @@ const Map<String, String> zhCN = {
"privacySettingsInfo": "管理数据收集和权限",
"permissionManagement": "权限管理", // 权限管理
"permissionManagementInfo": "管理应用权限设置", // 管理应用权限设置
"logout": "退出登录",
"logoutTips": "确定要退出当前账号吗?",
"aboutApplication": "关于应用",
"versions": "版本",
"checkUpdates": "检查更新",
@ -230,29 +238,258 @@ const Map<String, String> zhCN = {
'selecttimbre': '选择音色',
'pleaseRead': '请朗读',
'completeRecording': '完成录制',
'deleteAccount': '注销账号',
'deleteAccountTips': '确定要永久删除您的账号吗?此操作不可撤销',
"firmwareUpgrade": "固件升级",
"bleHeadsetFirmwareUpgrade": "BLE耳机固件版本升级",
"deviceManagement": "设备管理",
"manageConnectedDevices": "管理已绑定的蓝牙设备",
//设置setting_controller
// 版本更新相关
'currentLatestVersion': '当前已是最新版本 {version}',
'checkUpdateFailed': '检查更新失败',
'networkErrorRetry': '网络错误,请稍后重试',
// 设备管理相关
'clearPairedDevices': '清除配对设备',
'clearPairedDevicesConfirm': '确定要清除所有配对设备吗?',
'clearPairedDevicesSuccess': '清除配对设备成功',
'clearPairedDevicesFailed': '清除配对设备失败',
// 设置页面 - 实时语音对话
"realtimeVoiceChat": "实时语音对话",
"realtimeVoiceChatInfo": "体验智能语音交互功能(功能预览)",
"loading": "加载中...",
// 聊天页
//设备管理页面
"earphone": "耳机",
"voicerecorder": "录音笔",
"notBound": "未绑定",
"deviceNotBoundYet": "还未绑定设备",
"unbind": "解绑",
//Agent 模块
// agent View
"XiaoYan": "小言",
"clearChatHistory": "清空聊天记录",
"online": "在线",
"inputMessage": "输入消息...",
"imListening": "正在聆听...",
"canStartTalking": "你可以开始说话",
"addQuestionAboutImage": "添加对图片的问题或描述...",
"summarizeImageContent": "总结图片内容",
"extractImageText": "抽取图像文字",
"translateImageText": "翻译图像文字",
"recording": "正在录音...",
"holdToSpeak": "按住说话",
"takePhoto": "拍照",
"photoAlbum": "相册",
"makeCall": "打电话",
"aiVoiceCall": "AI语音通话",
"inCall": "正在通话中...",
"aiReplying": "AI正在回复...",
"waitingToStart": "等待开始...",
"clickToStartCall": "点击开始通话",
"listeningToYou": "正在听您说话...",
"processing": "正在处理...",
"loadMoreMessages": "加载更多消息...",
"loadFailedClickRetry": "加载失败,点击重试",
"swipeUpForMore": "向上滑动查看更多",
// Agent controller
'welcomeMessage': '你好!我是**小言**,我能帮你:\n\n'
'• 答问题和提供信息\n\n'
'• 实时语音翻译\n\n'
'• 推荐音乐和播客\n\n'
'• 语音备忘录和提醒\n\n'
'• 控制耳机功能\n\n'
'有什么我可以帮你的吗?',
'microphonePermission': '麦克风',
'voiceRecognitionPermissionText': '语音识别功能需要访问麦克风。',
'voiceTranslationPermissionText': '语音识别与翻译功能需要访问麦克风。',
'phoneCallPermissionText': '打电话功能需要访问麦克风进行语音通话。',
'permissionDeniedText': '您已永久拒绝麦克风权限,请前往系统设置开启权限。',
'startVoiceInput': '开始语音输入',
'startPhoneCallMode': '开始打电话模式,开始语音输入',
// Agent 全屏编辑器
'fullScreenEditorHint': '在这里输入你的消息...', // 全屏编辑器输入提示
'characterCount': '{count} 字符', // 字符计数显示
// 消息长按操作
'copy': '复制',
'copySuccess': '复制成功',
'report': '举报',
'submitSuccess': '提交成功',
'submitFailed': '提交失败',
'reportSubmitted': '举报已提交,我们会尽快处理',
//'networkError': '网络错误,请稍后重试',
'harmfulUnsafe': '有害/不安全',
'pornographicVulgar': '色情低俗',
'misleadingAttack': '误导攻击',
'illegalCriminal': '违法犯罪',
'privacyRelated': '隐私相关',
'copyrightViolation': '侵犯我的著作权、名誉权等',
'other': '其他',
'reportDescriptionHint': '我们想知道你举报的原因,你可以描述你遇到的问题。',
//'submit': '提交',
//Message_bubble
'generatedByAi': '由AI生成',
//音乐卡片 music_card
'recommendedMusic': '以下是一些推荐的音乐:',
'playList': '播放列表',
'moreMusic': '更多音乐',
//导航卡片 navigation_card
'kilometers': '公里', // 公里单位
'meters': '米', // 米单位
'hours': '小时', // 小时单位
'minutes': '分钟', // 分钟单位
'seconds': '秒', // 秒单位
'navigating': '导航中', // 导航状态
'currentLocation': '当前位置', // 当前位置
'approximate': '约', // 大约
'enterRoad': '进入', // 进入道路
"driving": "驾车",
"walking": "步行",
"bicycling": "骑行",
"tsransit": "公交",
//天气卡片 weather_card
'weatherQuery': '查询天气情况:',
'highest': '最高',
'lowest': '最低',
'futureForecast': '未来预报',
'hotWeatherTip': '今日高温炎热,请注意防暑降温,多喝水避免中暑',
'coldWeatherTip': '今日气温较低,外出请注意保暖,小心感冒',
'rainyWeatherTip': '今日有雨,外出请携带雨具,注意出行安全',
'snowyWeatherTip': '今日有雪,路面湿滑请注意安全,做好保暖措施',
'foggyWeatherTip': '今日有雾霾,能见度较低,外出请佩戴口罩',
'windyWeatherTip': '今日风力较大,外出请注意安全,固定好物品',
'sunnyWeatherTip': '今日阳光充足紫外线较强,外出请做好防晒',
'temperatureDifferenceTip': '今日昼夜温差较大,请适时增减衣物',
'comfortableWeatherTip': '今日天气适宜,是外出活动的好时光',
"monday": "周一",
"tuesday": "周二",
"wednesday": "周三",
"thursday": "周四",
"friday": "周五",
"saturday": "周六",
"sunday": "周日",
// 天气描述
"sunny": "晴",
"partlyCloudy": "少云",
"partlySunny": "晴间多云",
"cloudy": "多云",
"overcast": "阴",
"shower": "阵雨",
"thundershower": "雷阵雨",
"lightRain": "小雨",
"moderateRain": "中雨",
"heavyRain": "大雨",
"rainstorm": "暴雨",
"snowShower": "阵雪",
"lightSnow": "小雪",
"moderateSnow": "中雪",
"heavySnow": "大雪",
"blizzard": "暴雪",
"fog": "雾",
"haze": "霾",
"strongWind": "大风",
//编辑个人信息页
"editProfile": "编辑个人信息",
"avatar": "头像",
"nickname": "昵称",
"save": "保存",
"about": "关于",
"enterNickname": "请输入昵称",
"notSet": "未设置",
"accountSetting": "账号设置",
"logout": "退出登录",
"logoutTips": "确定要退出当前账号吗?",
'deleteAccount': '注销账号',
'deleteAccountTips': '确定要永久删除您的账号吗?此操作不可撤销',
// Profile 错误信息
'networkConnectionFailed': '网络连接失败,请检查网络设置后重试',
'serverTemporarilyUnavailable': '服务器暂时无法响应,请稍后重试',
'loginExpiredPleaseRelogin': '登录已过期,请重新登录',
'noPermissionForThisOperation': '没有权限执行此操作',
'requestedResourceNotFound': '请求的资源不存在',
'imageProcessingFailedPleaseReselect': '图片处理失败,请重新选择图片',
'operationFailedPleaseRetry': '操作失败,请重试',
'serverReturnedError': '服务器返回错误',
'serverError': '服务器错误',
'networkConnectionFailedCheckSettings': '网络连接失败,请检查网络设置',
'serverInternalErrorRetryLater': '服务器内部错误,请稍后重试',
// Profile 用户交互
//'error': '错误',
//'success': '成功',
'imageCompressionFailed': '图片压缩失败',
'avatarUpdateFailed': '头像更新失败',
'usernameCannotBeEmpty': '用户名不能为空',
'saveSuccess': '保存成功',
'personalInfoUpdated': '个人信息已更新',
'saveFailed': '保存失败',
'loggedOut': '已退出登录',
'logoutFailedRetry': '退出登录失败,请重试',
'accountPermanentlyDeleted': '账号已被永久删除',
'deleteAccountFailedRetry': '删除账号失败,请重试',
// 账号服务相关
'clearUserDataFailed': '清理用户数据失败', // 清理用户数据失败
'deleteUserDataFailed': '删除用户数据失败', // 删除用户数据失败
'thirdPartyLogoutSuccess': '第三方登录退出成功', // 第三方登录退出成功
'thirdPartyLogoutFailed': '第三方登录退出失败', // 第三方登录退出失败
'signOutProcessError': '登出过程发生错误', // 登出过程发生错误
'deleteAccountProcessError': '删除账号过程发生错误', // 删除账号过程发生错误
'userDataClearSuccess': '用户数据清理成功', // 用户数据清理成功
'allUserDataClearSuccess': '所有用户数据清理成功', // 所有用户数据清理成功
'accountServiceInitialized': 'AccountService 已初始化', // AccountService 已初始化
// 权限管理页面
'getPermissionStatusFailed': '获取权限状态失败',
'communicationPermissions': '通讯权限',
'calendarPermissions': '日历权限',
'locationPermissions': '位置权限',
'phone': '电话',
'sms': '短信',
'calendarWrite': '日历写入',
'calendarFullAccess': '日历完整访问',
'locationInfo': '位置信息',
'phonePermissionDesc': '用于拨打电话功能',
'smsPermissionDesc': '用于发送短信功能',
'calendarWritePermissionDesc': '用于创建日历事件和提醒',
'calendarFullAccessPermissionDesc': '用于读取和管理日历事件及提醒',
'locationPermissionDesc': '用于获取当前位置信息',
'appFunctionNeeds': '应用功能需要',
'authorized': '已授权',
'unauthorized': '未授权',
'needOpenInSystemSettings': '需要在系统设置中开启',
'partialAuthorization': '部分授权',
'unknownStatus': '未知状态',
'permissionGranted': '权限已授予',
'permissionRequestError': '请求权限时出错',
'phonePermissionDetailDesc': '拨打电话功能需要电话权限',
'smsPermissionDetailDesc': '发送短信功能需要短信权限',
'calendarWritePermissionDetailDesc': '创建日历事件需要日历写入权限',
'calendarFullAccessPermissionDetailDesc': '管理日历事件需要完整日历权限',
'locationPermissionDetailDesc': '获取位置信息需要位置权限',
'appNeedsPermissionForFullFunction': '应用需要此权限以提供完整功能',
'permanentDenialText': '您已永久拒绝{permission}权限,请前往应用设置开启',
'goToSettings': '去设置',
// 版本更新对话框
'newVersionFound': '发现新版本', // 版本更新对话框标题
'remindLater': '稍后提醒', // 稍后提醒按钮
'updateNow': '立即更新', // 立即更新按钮
'checkUpdate': '检查更新', // 检查更新按钮
'updateFailed': '更新失败', // 更新失败提示
'cannotOpenAppStore': '无法打开应用商店,请手动前往应用商店更新', // 无法打开应用商店提示
'updateErrorRetry': '更新过程中发生错误,请稍后重试', // 更新错误重试提示
//国家列表
"邮箱": "邮箱",
@ -362,12 +599,6 @@ const Map<String, String> zhCN = {
"斐济": "斐济",
"所罗门群岛": "所罗门群岛",
// 导航
"driving": "驾车",
"walking": "步行",
"bicycling": "骑行",
"tsransit": "公交",
// 翻译模块
// 翻译主页 (translation_view.dart)
"translationHistory": "翻译历史",
@ -434,6 +665,7 @@ const Map<String, String> zhCN = {
"confirmBinding": "确认绑定",
"associatingDevice": "正在关联设备...",
"goToBluetoothSettings": "前往蓝牙设置",
'bluetooth': '蓝牙',
// 配对状态文本
"readyToPair": "准备开始配对",
@ -453,6 +685,36 @@ const Map<String, String> zhCN = {
"authorizationFailedCheckCode": "授权失败,请检查授权码是否正确",
"pairingFailedRetry": "配对失败,请重试",
// 配对控制器相关
//'connectDevice': '连接设备',
'pleaseEnableBluetooth': '请开启蓝牙',
'deviceDisconnected': '设备已断开',
'readyToStartPairing': '准备开始配对',
'checkingEnvironment': '正在检查环境...',
'ensureHeadsetOnAndPairingMode': '请确保耳机已开启并进入配对模式',
//'goToBluetoothSettings': '前往蓝牙设置',
//'verifyingDevice': '正在验证设备...',
//'confirmBinding': '确认绑定',
//'associatingDevice': '正在关联设备...',
'establishingSecureConnection': '正在建立安全连接...',
'needManualBindingAuthCode': '需要手动绑定授权码...',
'pairingSuccessful': '配对成功!',
'enableBluetooth': '开启蓝牙',
'grantPermissions': '授予权限',
'retryAssociation': '重新关联',
'retryAuthorization': '重新授权',
'pleaseGrantNecessaryPermissions': '请授予必要权限',
'checkFailedRetry': '检查失败,请重试',
'pleaseConnectDeepSoundDevice': '请连接 DeepSound 设备',
'verificationFailedRetry': '验证失败,请重试',
'invalidDeviceAddress': '设备地址无效',
'bleDeviceAssociationFailed': 'BLE设备关联失败',
'deviceAssociationFailedRetry': '设备关联失败,请重试',
'bleConnectionTimeoutRetry': 'BLE连接超时,请重试',
'blePairingStartupFailed': 'BLE配对启动失败',
'bleConnectionFailed': 'BLE连接失败',
'deviceAuthorizationFailedCheckCode': '设备授权失败,请检查授权码',
//用户反馈页
"feedback": "用户反馈",
'feedbackInfo': '提供反馈或建议',
@ -465,6 +727,32 @@ const Map<String, String> zhCN = {
'feedbackSubmitSuccess': '反馈提交成功,感谢您的反馈!',
'feedbackSubmitFailed': '反馈提交失败,请稍后重试',
// OTA升级模块
"upgradeExitConfirm": "当前正在升级,退出将中断升级进程,确定要退出吗?",
"deviceModel": "设备型号",
"unknownDevice": "未知设备",
"currentFirmwareVersion": "当前固件版本",
"latestFirmwareVersion": "最新固件版本",
"ota_newVersionFound": "发现新版本",
"latestVersion": "已是最新版本",
"gettingDeviceInfo": "正在获取设备信息...",
"keepDeviceConnected": "请保持设备连接",
"connectionFailed": "连接失败",
"retryConnection": "重试连接",
"ota_updateNow": "立即更新",
"keepConnectedDontClose": "请保持设备连接,不要关闭应用",
"doNotDisconnect": "请勿断开连接",
"charging": "充电中",
"updateContent": "更新内容",
"removeEarbudsEnsureBattery": "取出双耳机,并保证电量均为30%以上的状态",
// 音乐列表页面
"noMusic": "暂无音乐", // 暂无音乐
"noPlayingMusic": "暂无播放音乐", // 暂无播放音乐
"unknownSong": "未知歌曲", // 未知歌曲
"unknownArtist": "未知歌手", // 未知歌手
"playAll": "播放全部", // 播放全部
// 语言名称
"中文(简体)": "中文(简体)",
"中文(繁体)": "中文(繁体)",

2
lib/core/translations/language/zh_hk.dart

@ -118,7 +118,7 @@ const Map<String, String> zhHK = {
"exploreSlogan": "智能耳機,無限可能",
"exploreSlogan1": "智能陪伴,無限可能",
"exploreSlogan2": "智能眼鏡,無限可能",
"exploreAi": "探索DeepSound提供的AI功能",
"exploreAi": "探索DeapSound提供的AI功能",
"aiFunction": "AI功能",
"allRoundAssistant": "全能助理",
"allRoundAssistantInfo": "幫你解決各類問題",

14
lib/data/services/account_service.dart

@ -81,7 +81,7 @@ class AccountService extends GetxService {
if (!dataCleaned) {
return AccountOperationResult(
success: false,
errorMessage: '清理用户数据失败',
errorMessage: 'clearUserDataFailed'.tr, // 清理用户数据失败
);
}
@ -90,13 +90,13 @@ class AccountService extends GetxService {
return AccountOperationResult(
success: true,
message: '已退出登录',
message: 'loggedOut'.tr,
);
} catch (e) {
logger.e('登出过程发生错误: $e');
return AccountOperationResult(
success: false,
errorMessage: '退出登录失败,请重试',
errorMessage: 'logoutFailedRetry'.tr, // 退出登录失败,请重试
);
}
}
@ -112,7 +112,7 @@ class AccountService extends GetxService {
if (response == null) {
return AccountOperationResult(
success: false,
errorMessage: '删除用户数据失败',
errorMessage: 'deleteUserDataFailed'.tr, // 删除用户数据失败
);
}
@ -122,7 +122,7 @@ class AccountService extends GetxService {
if (!dataCleaned) {
return AccountOperationResult(
success: false,
errorMessage: '清理用户数据失败',
errorMessage: 'clearUserDataFailed'.tr, // 清理用户数据失败
);
}
@ -131,13 +131,13 @@ class AccountService extends GetxService {
return AccountOperationResult(
success: true,
message: '账号已被永久删除',
message: 'accountPermanentlyDeleted'.tr, // 账号已被永久删除
);
} catch (e) {
logger.e('删除账号过程发生错误: $e');
return AccountOperationResult(
success: false,
errorMessage: '删除账号失败,请重试',
errorMessage: 'deleteAccountFailedRetry'.tr, // 删除账号失败,请重试
);
}
}

2
lib/data/services/network/nw_api.dart

@ -1,5 +1,5 @@
class NWApi {
// static const baseApi = "https://www.deapsound.com";
static const baseApi = "https://api.deapsound.com";
static const baseApi = "https://api.ideapsound.com";
// static const baseApi = "https://api.ideapsound.com";
}

4
lib/main.dart

@ -33,7 +33,7 @@ void main() async {
const double width = 375.0;
const double height = 812.0;
setWindowTitle('DeepSound');
setWindowTitle('DeapSound');
setWindowMinSize(const Size(width, height));
setWindowMaxSize(const Size(width, height));
@ -68,7 +68,7 @@ class MainApp extends StatelessWidget {
splitScreenMode: true,
builder: (_, child) {
return GetMaterialApp(
title: 'DeepSound',
title: 'DeapSound',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeMode, // 使用提前获取的主题模式

47
lib/modules/agent/controllers/agent_controller.dart

@ -447,13 +447,7 @@ class AgentController extends GetxController {
void _addWelcomeMessage() {
messages.add(Message(
isUser: false,
text: '你好!我是**小言**,我能帮你:\n\n'
'• 答问题和提供信息\n\n'
'• 实时语音翻译\n\n'
'• 推荐音乐和播客\n\n'
'• 语音备忘录和提醒\n\n'
'• 控制耳机功能\n\n'
'有什么我可以帮你的吗?',
text: 'welcomeMessage'.tr, // 你好!我是**小言**,我能帮你:
));
}
@ -983,11 +977,11 @@ class AgentController extends GetxController {
final hasPermission = await PermissionUtil.instance.requestPermission(
// context: Get.context!,
permissionType: Permission.microphone,
permissionName: '麦克风',
explanationText: '语音识别功能需要访问麦克风。',
permanentDenialText: '您已永久拒绝麦克风权限,请前往系统设置开启权限。',
settingsButtonText: '去设置',
cancelButtonText: '取消',
permissionName: 'microphonePermission'.tr, // 麦克风
explanationText: 'voiceRecognitionPermissionText'.tr, // 语音识别功能需要访问麦克风。
permanentDenialText: 'permissionDeniedText'.tr, // 您已永久拒绝麦克风权限,请前往系统设置开启权限。
settingsButtonText: 'goToSettings'.tr, // 去设置
cancelButtonText: 'cancel'.tr, // 取消
);
if (!hasPermission) {
return; // 权限未获取,保持文本模式
@ -1011,15 +1005,15 @@ class AgentController extends GetxController {
// 开始语音输入
Future<void> startVoiceInput() async {
if (isListening.value) return;
print("开始语音输入"); // 检查麦克风权限
print('startVoiceInput'.tr); // 开始语音输入
final hasPermission = await PermissionUtil.instance.requestPermission(
// context: Get.context!,
permissionType: Permission.microphone,
permissionName: '麦克风',
explanationText: '语音识别与翻译功能需要访问麦克风。',
permanentDenialText: '您已永久拒绝麦克风权限,请前往系统设置开启权限。',
settingsButtonText: '去设置',
cancelButtonText: '取消',
permissionName: 'microphonePermission'.tr, // 麦克风
explanationText: 'voiceTranslationPermissionText'.tr, // 语音识别与翻译功能需要访问麦克风。
permanentDenialText: 'permissionDeniedText'.tr, // 您已永久拒绝麦克风权限,请前往系统设置开启权限。
settingsButtonText: 'goToSettings'.tr, // 去设置
cancelButtonText: 'cancel'.tr, // 取消
);
if (!hasPermission) {
isTextInputMode.value = true; // 如果没有权限,切回文本模式
@ -1286,11 +1280,11 @@ class AgentController extends GetxController {
// 检查麦克风权限
final hasPermission = await PermissionUtil.instance.requestPermission(
permissionType: Permission.microphone,
permissionName: '麦克风',
explanationText: '打电话功能需要访问麦克风进行语音通话。',
permanentDenialText: '您已永久拒绝麦克风权限,请前往系统设置开启权限。',
settingsButtonText: '去设置',
cancelButtonText: '取消',
permissionName: 'microphonePermission'.tr, // 麦克风
explanationText: 'phoneCallPermissionText'.tr, // 打电话功能需要访问麦克风进行语音通话。
permanentDenialText: 'permissionDeniedText'.tr, // 您已永久拒绝麦克风权限,请前往系统设置开启权限。
settingsButtonText: 'goToSettings'.tr, // 去设置
cancelButtonText: 'cancel'.tr, // 取消
);
if (!hasPermission) {
@ -1305,7 +1299,7 @@ class AgentController extends GetxController {
// 打电话模式不使用按住说话模式,而是持续语音输入
//isPushToTalkMode.value = false;
// 开始语音识别
print("开始打电话模式,开始语音输入");
print('startPhoneCallMode'.tr); // 开始打电话模式,开始语音输入
await AgentService.audioContinue();
}
}
@ -1568,6 +1562,11 @@ class AgentController extends GetxController {
Future<void> updateMusicProgress(int currentIdInternal, int newPosition,
int newDuration, double newProgress) async {
try {
// 如果正在加载音乐,避免进度回调干扰状态更新
if (isLoadingMusic.value) {
return;
}
if (currentIdInternal != 0) {
isPlaying.value = true;
// return; // 如果没有在播放,直接返回

52
lib/modules/agent/controllers/message_action_controller.dart

@ -28,9 +28,10 @@ class MessageActionController extends GetxController {
) {
// 触发触觉反馈
Haptics.vibrate(HapticsType.success);
// 计算弹出菜单位置
RenderBox? renderBox = Overlay.of(context).context.findRenderObject() as RenderBox;
RenderBox? renderBox =
Overlay.of(context).context.findRenderObject() as RenderBox;
final RelativeRect position = RelativeRect.fromRect(
Rect.fromLTRB(
details.globalPosition.dx,
@ -67,7 +68,7 @@ class MessageActionController extends GetxController {
size: 20.w,
color: isDarkMode ? Colors.white : Colors.black87,
),
'复制',
'copy'.tr, // 复制
isDarkMode ? Colors.white : Colors.black87,
() => _copyMessage(message),
),
@ -95,7 +96,7 @@ class MessageActionController extends GetxController {
size: 20.w,
color: isDarkMode ? Colors.red[700] : Colors.red,
),
'举报'.tr,
'report'.tr, //举报
isDarkMode ? Colors.red[700]! : Colors.red,
() => _showReportForm(context, isDarkMode, message),
),
@ -138,7 +139,7 @@ class MessageActionController extends GetxController {
Clipboard.setData(ClipboardData(text: message.text)).then((_) {
Get.snackbar(
'success'.tr,
'复制成功',
'copySuccess'.tr, // 复制成功
backgroundColor: Colors.blue.withOpacity(0.8),
colorText: Colors.white,
);
@ -205,7 +206,7 @@ class MessageActionController extends GetxController {
try {
// 调用API提交举报
var response = await Api.reportAiContent(reportData);
if (response != null) {
print('提交举报响应: $response');
}
@ -220,8 +221,8 @@ class MessageActionController extends GetxController {
// 显示成功通知
Get.snackbar(
'提交成功',
'举报已提交,我们会尽快处理',
'submitSuccess'.tr, // 提交成功
'reportSubmitted'.tr, // 举报已提交,我们会尽快处理
backgroundColor: Colors.green.withOpacity(0.8),
colorText: Colors.white,
duration: const Duration(seconds: 2),
@ -229,8 +230,8 @@ class MessageActionController extends GetxController {
} catch (e) {
// 显示错误通知
Get.snackbar(
'提交失败',
'网络错误,请稍后重试',
'submitFailed'.tr, // 提交失败
'networkError'.tr, // 网络错误,请稍后重试
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,
duration: const Duration(seconds: 2),
@ -242,7 +243,8 @@ class MessageActionController extends GetxController {
/// 举报表单组件
class _ReportForm extends StatelessWidget {
final bool isDarkMode;
final MessageActionController controller = Get.find<MessageActionController>();
final MessageActionController controller =
Get.find<MessageActionController>();
_ReportForm({required this.isDarkMode});
@ -262,7 +264,7 @@ class _ReportForm extends StatelessWidget {
children: [
Center(
child: Text(
'举报',
'report'.tr, // 举报
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
@ -300,13 +302,20 @@ class _ReportForm extends StatelessWidget {
spacing: 8.w,
runSpacing: 8.h,
children: [
_buildReportChip('有害/不安全', isDarkMode, controller),
_buildReportChip('色情低俗', isDarkMode, controller),
_buildReportChip('误导攻击', isDarkMode, controller),
_buildReportChip('违法犯罪', isDarkMode, controller),
_buildReportChip('隐私相关', isDarkMode, controller),
_buildReportChip('侵犯我的著作权、名誉权等', isDarkMode, controller),
_buildReportChip('其他', isDarkMode, controller),
_buildReportChip(
'harmfulUnsafe'.tr, isDarkMode, controller), // 有害/不安全
_buildReportChip('pornographicVulgar'.tr, isDarkMode,
controller), // 色情低俗
_buildReportChip('misleadingAttack'.tr, isDarkMode,
controller), // 误导攻击
_buildReportChip(
'illegalCriminal'.tr, isDarkMode, controller), // 违法犯罪
_buildReportChip(
'privacyRelated'.tr, isDarkMode, controller), // 隐私相关
_buildReportChip('copyrightViolation'.tr, isDarkMode,
controller), // 侵犯我的著作权、名誉权等
_buildReportChip(
'other'.tr, isDarkMode, controller), // 其他
],
);
},
@ -328,7 +337,8 @@ class _ReportForm extends StatelessWidget {
color: isDarkMode ? Colors.white : Colors.black,
),
decoration: InputDecoration(
hintText: '我们想知道你举报的原因,你可以描述你遇到的问题。',
hintText:
'reportDescriptionHint'.tr, // 我们想知道你举报的原因,你可以描述你遇到的问题。
hintStyle: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.black54,
fontSize: 14.sp,
@ -350,7 +360,7 @@ class _ReportForm extends StatelessWidget {
borderRadius: BorderRadius.circular(8.r),
),
),
child: Text('提交'),
child: Text('submit'.tr), // 提交
onPressed: () => controller.submitReport(),
),

78
lib/modules/agent/views/agent_view.dart

@ -92,7 +92,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'小言'.tr,
'XiaoYan'.tr,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
@ -111,7 +111,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
),
const SizedBox(width: 4),
Text(
'在线'.tr,
'online'.tr,
style: TextStyle(
fontSize: 12,
color: Colors.green,
@ -171,7 +171,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
children: [
Icon(Icons.delete_outline, color: primaryColor, size: 20),
const SizedBox(width: 8),
Text('清除聊天记录'.tr, style: TextStyle(fontSize: 14)),
Text('clearChatHistory'.tr, style: TextStyle(fontSize: 14)),
],
),
onTap: () => Future.delayed(
@ -200,10 +200,12 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
reverse: true,
padding: const EdgeInsets.symmetric(
vertical: 16, horizontal: 16),
itemCount: controller.messages.length + (controller.hasMoreMessages.value ? 1 : 0),
itemCount: controller.messages.length +
(controller.hasMoreMessages.value ? 1 : 0),
itemBuilder: (context, index) {
// 如果是最后一项且有更多消息,显示加载指示器
if (index == controller.messages.length && controller.hasMoreMessages.value) {
if (index == controller.messages.length &&
controller.hasMoreMessages.value) {
return _buildLoadMoreIndicator();
}
@ -305,20 +307,20 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
children: [
_buildPromptChip(
context: context,
label: '总结图片内容'.tr,
label: 'summarizeImageContent'.tr,//总结图片内容
onTap: () => controller.summarizeImage(),
),
const SizedBox(width: 8),
_buildPromptChip(
context: context,
label: '抽取图像文字'.tr,
label: 'extractImageText'.tr,//抽取图像文字
onTap: () =>
controller.extractTextFromImage(),
),
const SizedBox(width: 8),
_buildPromptChip(
context: context,
label: '翻译图像文字'.tr,
label: 'translateImageText'.tr,//翻译图像文字
onTap: () =>
controller.translateImageText(),
),
@ -440,8 +442,10 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
),
decoration: InputDecoration(
hintText: isImageActive
? '添加对图片的问题或描述...'
: '输入消息...',
? 'addQuestionAboutImage'
.tr // 添加对图片的问题或描述...
: 'inputMessage'
.tr, // 输入消息...
hintStyle: TextStyle(
color: Colors.grey[500],
fontSize: 15,
@ -576,8 +580,10 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
const SizedBox(width: 6),
Text(
isPushToTalkActive
? '正在录音...'
: '按住说话',
? 'recording'
.tr // 正在录音...
: 'holdToSpeak'
.tr, // 按住说话
style: TextStyle(
fontSize: 14,
fontWeight:
@ -735,7 +741,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
_buildPlusOptionButton(
context: context,
icon: Icons.camera_alt,
label: '拍照',
label: 'takePhoto'.tr, // 拍照
onTap: () async {
//controller.collapsePlusOptions();
await controller.takePhoto();
@ -746,7 +752,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
_buildPlusOptionButton(
context: context,
icon: Icons.photo_library,
label: '相册',
label: 'photoAlbum'.tr, // 相册
onTap: () async {
//controller.collapsePlusOptions();
await controller.pickImage();
@ -768,7 +774,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
_buildPlusOptionButton(
context: context,
icon: Icons.phone,
label: '打电话',
label: 'makeCall'.tr, // 打电话
onTap: () {
// 启动打电话模式
controller.startPhoneCall();
@ -945,7 +951,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'AI语音通话',
'aiVoiceCall'.tr, // AI语音通话
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
@ -954,10 +960,10 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
),
Obx(() {
final status = controller.isListening.value
? '正在通话中...'
? 'inCall'.tr // 正在通话中...
: controller.isSpeaking.value
? 'AI正在回复...'
: '等待开始...';
? 'aiReplying'.tr // AI正在回复...
: 'waitingToStart'.tr; // 等待开始...
return Text(
status,
style: TextStyle(
@ -1010,13 +1016,13 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
// 状态文字
Obx(() {
String statusText = '点击开始通话';
String statusText = 'clickToStartCall'.tr; // 点击开始通话
if (controller.isListening.value) {
statusText = '正在听您说话...';
statusText = 'listeningToYou'.tr; // 正在听您说话...
} else if (controller.isSpeaking.value) {
statusText = 'AI正在回复...';
statusText = 'aiReplying'.tr; // AI正在回复...
} else if (controller.isProcessing.value) {
statusText = '正在处理...';
statusText = 'processing'.tr; // 正在处理...
}
return Text(
@ -1135,21 +1141,21 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
// 正在加载状态
return Container(
padding: const EdgeInsets.symmetric(vertical: 16),
child: const Center(
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
SizedBox(width: 8),
const SizedBox(width: 8),
Text(
'加载更多消息...',
style: TextStyle(
'loadMoreMessages'.tr, // 加载更多消息...
style: const TextStyle(
fontSize: 14,
color: Colors.grey,
),
@ -1165,18 +1171,18 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
child: Center(
child: GestureDetector(
onTap: () => controller.loadMoreMessages(),
child: const Row(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
const Icon(
Icons.refresh,
size: 16,
color: Colors.grey,
),
SizedBox(width: 8),
const SizedBox(width: 8),
Text(
'加载失败,点击重试',
style: TextStyle(
'loadFailedClickRetry'.tr, // 加载失败,点击重试
style: const TextStyle(
fontSize: 14,
color: Colors.grey,
),
@ -1190,10 +1196,10 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver {
// 默认状态(有更多消息但未加载)
return Container(
padding: const EdgeInsets.symmetric(vertical: 8),
child: const Center(
child: Center(
child: Text(
'向上滑动查看更多',
style: TextStyle(
'swipeUpForMore'.tr, // 向上滑动查看更多
style: const TextStyle(
fontSize: 12,
color: Colors.grey,
),

2
lib/modules/agent/views/message_bubble.dart

@ -110,7 +110,7 @@ class MessageBubble extends GetView<AgentController> {
Padding(
padding: const EdgeInsets.only(left: 8),
child: Text(
"由AI生成".tr,
"generatedByAi".tr,// 由AI生成
style: TextStyle(
fontSize: 8,
color: Colors.blue[600],

10
lib/modules/agent/views/music_card.dart

@ -67,7 +67,9 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url,
style: TextStyle(
fontSize: 13.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white.withValues(alpha: 0.9) : Colors.grey[800],
color: isDarkMode
? Colors.white.withValues(alpha: 0.9)
: Colors.grey[800],
),
overflow: TextOverflow.ellipsis,
),
@ -146,7 +148,7 @@ Widget buildMusicContent(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'以下是一些推荐的音乐:',
'recommendedMusic'.tr, //以下是一些推荐的音乐:
style: TextStyle(
color:
isDarkMode ? Colors.white.withValues(alpha: 0.9) : Colors.black87,
@ -184,7 +186,7 @@ Widget buildMusicContent(
),
const SizedBox(width: 6),
Text(
'播放列表'.tr,
'playList'.tr, //播放列表
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
@ -235,7 +237,7 @@ Widget buildMusicContent(
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text(
'查看更多推荐',
'moreMusic'.tr, //更多音乐,
style: TextStyle(
fontSize: 12,
color: Theme.of(context).primaryColor,

87
lib/modules/agent/views/navigation_card.dart

@ -9,9 +9,9 @@ String formatDistance(String distanceStr) {
if (distance >= 1000) {
final km = distance / 1000;
return '${km.toStringAsFixed(1)} 公里';
return '${km.toStringAsFixed(1)} KM';
} else {
return '${distance.toStringAsFixed(0)} 米';
return '${distance.toStringAsFixed(0)} M';
}
}
@ -24,9 +24,10 @@ String formatDuration(String secondsStr) {
int seconds = duration.inSeconds.remainder(60);
List<String> parts = [];
if (hours > 0) parts.add('$hours小时');
if (minutes > 0) parts.add('$minutes分钟');
if (seconds > 0 || parts.isEmpty) parts.add('$seconds秒');
if (hours > 0) parts.add('$hours${'hours'.tr}'); // 小时
if (minutes > 0) parts.add('$minutes${'minutes'.tr}'); // 分钟
//不需要秒
//if (seconds > 0 || parts.isEmpty) parts.add('$seconds${'seconds'.tr}'); // 秒
return parts.join('');
}
@ -126,7 +127,7 @@ Widget navigationCard(
),
SizedBox(width: 4.w),
Text(
'导航中',
'navigating'.tr, // 导航中
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
@ -190,24 +191,24 @@ Widget navigationCard(
: Colors.grey,
size: 20.sp,
),
SizedBox(height: 4.h),
Text(
(mode["ntype"] as String).tr,
textAlign: TextAlign.center,
style: TextStyle(
color: isEnabled
? (isSelected
? Theme.of(context).primaryColor
: (isDarkMode
? Colors.white70
: Colors.black87))
: Colors.grey,
fontSize: 11.sp,
fontWeight: isSelected
? FontWeight.w600
: FontWeight.w400,
),
),
// SizedBox(height: 4.h),
// Text(
// (mode["ntype"] as String).tr,
// textAlign: TextAlign.center,
// style: TextStyle(
// color: isEnabled
// ? (isSelected
// ? Theme.of(context).primaryColor
// : (isDarkMode
// ? Colors.white70
// : Colors.black87))
// : Colors.grey,
// fontSize: 11.sp,
// fontWeight: isSelected
// ? FontWeight.w600
// : FontWeight.w400,
// ),
// ),
],
),
),
@ -237,26 +238,25 @@ Widget navigationCard(
size: 16.sp,
color: Theme.of(context).primaryColor,
),
SizedBox(width: 6.w),
// 当前位置文本
Text(
'当前位置',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: isDarkMode
? Colors.white70
: Colors.black54,
),
),
// SizedBox(width: 6.w),
// // 当前位置文本
// Text(
// 'currentLocation'.tr, // 当前位置
// style: TextStyle(
// fontSize: 14.sp,
// fontWeight: FontWeight.w500,
// color: isDarkMode
// ? Colors.white70
// : Colors.black54,
// ),
// ),
SizedBox(width: 8.w),
// 箭头图标
Icon(
Icons.arrow_forward,
size: 16.sp,
color: isDarkMode
? Colors.white54
: Colors.black45,
color:
isDarkMode ? Colors.white54 : Colors.black45,
),
SizedBox(width: 8.w),
// 目的地图标
@ -319,7 +319,7 @@ Widget navigationCard(
),
SizedBox(width: 4.w),
Text(
'约${formatDuration(modes[currentIndex]["duration"])}',
'${'approximate'.tr}${formatDuration(modes[currentIndex]["duration"])}', // 约
style: TextStyle(
fontSize: 14.sp,
color: Theme.of(context).primaryColor,
@ -343,7 +343,7 @@ Widget navigationCard(
borderRadius: BorderRadius.circular(6.r),
),
child: Text(
"${navigation["distanceText"]}进入${navigation["nextRoad"]}",
"${navigation["distanceText"]}${'enterRoad'.tr}${navigation["nextRoad"]}", // 进入
style: TextStyle(
fontSize: 12.sp,
color: Theme.of(context).primaryColor,
@ -372,9 +372,8 @@ Widget navigationCard(
borderRadius: BorderRadius.circular(12.r),
boxShadow: [
BoxShadow(
color: Theme.of(context)
.primaryColor
.withOpacity(0.3),
color:
Theme.of(context).primaryColor.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 2),
),

147
lib/modules/agent/views/weather_card.dart

@ -1,6 +1,7 @@
import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
/// 构建天气内容卡片
Widget buildWeatherContent(BuildContext context, String city,
@ -11,9 +12,10 @@ Widget buildWeatherContent(BuildContext context, String city,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'查询天气情况:',
'weatherQuery'.tr, // 翻译键代表的中文文本内容:查询天气情况:
style: TextStyle(
color: isDarkMode ? Colors.white.withValues(alpha: 0.9) : Colors.black87,
color:
isDarkMode ? Colors.white.withValues(alpha: 0.9) : Colors.black87,
fontSize: 14.sp,
height: 1.4,
fontWeight: FontWeight.w400,
@ -55,15 +57,15 @@ Widget buildWeatherContent(BuildContext context, String city,
children: [
Text(
"${city} ${now["date"]}",
style: const TextStyle(
fontSize: 16,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
SizedBox(height: 4),
Text(
now["dayweather"],
_getWeatherDescriptionTranslation(now["dayweather"]),
style: TextStyle(
fontSize: 14.sp,
color: Colors.white.withValues(alpha: 0.9),
@ -85,14 +87,14 @@ Widget buildWeatherContent(BuildContext context, String city,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'最高: ${now["daytemp"]}°',
'${'highest'.tr}: ${now["daytemp"]}°', // 翻译键代表的中文文本内容:最高
style: TextStyle(
fontSize: 12.sp,
color: Colors.white.withValues(alpha: 0.9),
),
),
Text(
'最低: ${now["nighttemp"]}°',
'${'lowest'.tr}: ${now["nighttemp"]}°', // 翻译键代表的中文文本内容:最低
style: TextStyle(
fontSize: 12.sp,
color: Colors.white.withValues(alpha: 0.9),
@ -118,7 +120,7 @@ Widget buildWeatherContent(BuildContext context, String city,
),
SizedBox(height: 16.h),
Text(
'未来预报',
'futureForecast'.tr, // 翻译键代表的中文文本内容:未来预报
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
@ -135,8 +137,11 @@ Widget buildWeatherContent(BuildContext context, String city,
DateTime? date = DateUtil.getDateTime(dateStr);
IconData weatherIcon =
getWeatherIcon(days[index]['dayweather']);
String weekday = DateUtil.getWeekday(date,
languageCode: "zh", short: true);
// 获取星期几的翻译键
String weekdayKey = _getWeekdayTranslationKey(date);
String weekday = weekdayKey.tr; // 翻译键代表的中文文本内容:对应的星期几
String temp = "${days[index]['daytemp']}°";
return _buildForecastDay(
weekday,
@ -155,8 +160,75 @@ Widget buildWeatherContent(BuildContext context, String city,
);
}
/// 获取天气描述的翻译
String _getWeatherDescriptionTranslation(String weatherDescription) {
final description = weatherDescription.trim();
// 天气描述映射表
final Map<String, String> weatherMap = {
// 晴天类
'晴': 'sunny'.tr, // 翻译键代表的中文文本内容:晴
'少云': 'partlyCloudy'.tr, // 翻译键代表的中文文本内容:少云
'晴间多云': 'partlySunny'.tr, // 翻译键代表的中文文本内容:晴间多云
// 多云类
'多云': 'cloudy'.tr, // 翻译键代表的中文文本内容:多云
'阴': 'overcast'.tr, // 翻译键代表的中文文本内容:阴
// 雨天类
'阵雨': 'shower'.tr, // 翻译键代表的中文文本内容:阵雨
'雷阵雨': 'thundershower'.tr, // 翻译键代表的中文文本内容:雷阵雨
'小雨': 'lightRain'.tr, // 翻译键代表的中文文本内容:小雨
'中雨': 'moderateRain'.tr, // 翻译键代表的中文文本内容:中雨
'大雨': 'heavyRain'.tr, // 翻译键代表的中文文本内容:大雨
'暴雨': 'rainstorm'.tr, // 翻译键代表的中文文本内容:暴雨
// 雪天类
'阵雪': 'snowShower'.tr, // 翻译键代表的中文文本内容:阵雪
'小雪': 'lightSnow'.tr, // 翻译键代表的中文文本内容:小雪
'中雪': 'moderateSnow'.tr, // 翻译键代表的中文文本内容:中雪
'大雪': 'heavySnow'.tr, // 翻译键代表的中文文本内容:大雪
'暴雪': 'blizzard'.tr, // 翻译键代表的中文文本内容:暴雪
// 雾霾类
'雾': 'fog'.tr, // 翻译键代表的中文文本内容:雾
'霾': 'haze'.tr, // 翻译键代表的中文文本内容:霾
// 风类
'大风': 'strongWind'.tr, // 翻译键代表的中文文本内容:大风
};
// 返回翻译后的描述,如果没有找到对应翻译则返回原文
return weatherMap[description] ?? description;
}
/// 获取星期几的翻译键
String _getWeekdayTranslationKey(DateTime? date) {
if (date == null) return 'unknown';
switch (date.weekday) {
case 1:
return 'monday'; // 翻译键代表的中文文本内容:周一
case 2:
return 'tuesday'; // 翻译键代表的中文文本内容:周二
case 3:
return 'wednesday'; // 翻译键代表的中文文本内容:周三
case 4:
return 'thursday'; // 翻译键代表的中文文本内容:周四
case 5:
return 'friday'; // 翻译键代表的中文文本内容:周五
case 6:
return 'saturday'; // 翻译键代表的中文文本内容:周六
case 7:
return 'sunday'; // 翻译键代表的中文文本内容:周日
default:
return 'unknown';
}
}
/// 构建智能天气提示
Widget _buildWeatherTip(BuildContext context, Map<String, dynamic> now, bool isDarkMode) {
Widget _buildWeatherTip(
BuildContext context, Map<String, dynamic> now, bool isDarkMode) {
final weatherTip = _generateWeatherTip(now);
return Container(
@ -205,72 +277,79 @@ WeatherTip _generateWeatherTip(Map<String, dynamic> now) {
// 高温提示 (>= 35°C)
if (dayTemp >= 35) {
return const WeatherTip(
return WeatherTip(
icon: Icons.local_fire_department,
message: '今日高温炎热,请注意防暑降温,多喝水避免中暑',
message: 'hotWeatherTip'.tr, // 翻译键代表的中文文本内容:今日高温炎热,请注意防暑降温,多喝水避免中暑
);
}
// 低温提示 (<= 5°C)
if (dayTemp <= 5) {
return const WeatherTip(
return WeatherTip(
icon: Icons.ac_unit,
message: '今日气温较低,外出请注意保暖,小心感冒',
message: 'coldWeatherTip'.tr, // 翻译键代表的中文文本内容:今日气温较低,外出请注意保暖,小心感冒
);
}
// 雨天提示
if (dayWeather.contains('雨') || ['阵雨', '雷阵雨', '小雨', '中雨', '大雨', '暴雨'].any((rain) => dayWeather.contains(rain))) {
return const WeatherTip(
if (dayWeather.contains('雨') ||
['阵雨', '雷阵雨', '小雨', '中雨', '大雨', '暴雨']
.any((rain) => dayWeather.contains(rain))) {
return WeatherTip(
icon: Icons.umbrella,
message: '今日有雨,外出请携带雨具,注意出行安全',
message: 'rainyWeatherTip'.tr, // 翻译键代表的中文文本内容:今日有雨,外出请携带雨具,注意出行安全
);
}
// 雪天提示
if (dayWeather.contains('雪') || ['阵雪', '小雪', '中雪', '大雪', '暴雪'].any((snow) => dayWeather.contains(snow))) {
return const WeatherTip(
if (dayWeather.contains('雪') ||
['阵雪', '小雪', '中雪', '大雪', '暴雪'].any((snow) => dayWeather.contains(snow))) {
return WeatherTip(
icon: Icons.ac_unit,
message: '今日有雪,路面湿滑请注意安全,做好保暖措施',
message: 'snowyWeatherTip'.tr, // 翻译键代表的中文文本内容:今日有雪,路面湿滑请注意安全,做好保暖措施
);
}
// 雾霾提示
if (dayWeather.contains('雾') || dayWeather.contains('霾') || ['雾', '浓雾', '霾', '中度霾', '重度霾'].any((fog) => dayWeather.contains(fog))) {
return const WeatherTip(
if (dayWeather.contains('雾') ||
dayWeather.contains('霾') ||
['雾', '浓雾', '霾', '中度霾', '重度霾'].any((fog) => dayWeather.contains(fog))) {
return WeatherTip(
icon: Icons.blur_on,
message: '今日有雾霾,能见度较低,外出请佩戴口罩',
message: 'foggyWeatherTip'.tr, // 翻译键代表的中文文本内容:今日有雾霾,能见度较低,外出请佩戴口罩
);
}
// 大风提示
if (dayWeather.contains('风') || ['大风', '强风', '疾风', '烈风'].any((wind) => dayWeather.contains(wind))) {
return const WeatherTip(
if (dayWeather.contains('风') ||
['大风', '强风', '疾风', '烈风'].any((wind) => dayWeather.contains(wind))) {
return WeatherTip(
icon: Icons.air,
message: '今日风力较大,外出请注意安全,固定好物品',
message: 'windyWeatherTip'.tr, // 翻译键代表的中文文本内容:今日风力较大,外出请注意安全,固定好物品
);
}
// 晴天紫外线提示 (温度 >= 25°C)
if (['晴', '少云', '晴间多云'].any((sunny) => dayWeather.contains(sunny)) && dayTemp >= 25) {
return const WeatherTip(
if (['晴', '少云', '晴间多云'].any((sunny) => dayWeather.contains(sunny)) &&
dayTemp >= 25) {
return WeatherTip(
icon: Icons.wb_sunny,
message: '今日阳光充足紫外线较强,外出请做好防晒',
message: 'sunnyWeatherTip'.tr, // 翻译键代表的中文文本内容:今日阳光充足紫外线较强,外出请做好防晒
);
}
// 温差大提示 (>= 10°C)
if ((dayTemp - nightTemp).abs() >= 10) {
return const WeatherTip(
return WeatherTip(
icon: Icons.thermostat,
message: '今日昼夜温差较大,请适时增减衣物',
message: 'temperatureDifferenceTip'.tr, // 翻译键代表的中文文本内容:今日昼夜温差较大,请适时增减衣物
);
}
// 默认舒适天气提示
return const WeatherTip(
return WeatherTip(
icon: Icons.wb_sunny_outlined,
message: '今日天气适宜,是外出活动的好时光',
message: 'comfortableWeatherTip'.tr, // 翻译键代表的中文文本内容:今日天气适宜,是外出活动的好时光
);
}

5
lib/modules/agent/widgets/full_screen_editor.dart

@ -72,7 +72,7 @@ class _FullScreenEditorState extends State<FullScreenEditor> {
height: 1.5,
),
decoration: InputDecoration(
hintText: '在这里输入你的消息...',
hintText: 'fullScreenEditorHint'.tr, // 在这里输入你的消息...
hintStyle: TextStyle(
color: isDarkMode ? Colors.white54 : Colors.grey[500],
fontSize: 16.sp,
@ -106,7 +106,8 @@ class _FullScreenEditorState extends State<FullScreenEditor> {
valueListenable: _textController,
builder: (context, value, child) {
return Text(
'${value.text.length} 字符',
'characterCount'.tr.replaceAll('{count}',
'${value.text.length}'), // ${value.text.length} 字符
style: TextStyle(
color: isDarkMode
? Colors.white60

18
lib/modules/common/widgets/version_update_dialog.dart

@ -70,7 +70,7 @@ class VersionUpdateDialog extends StatelessWidget {
// 标题
Text(
'发现新版本',
'newVersionFound'.tr, // 发现新版本
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
@ -135,7 +135,7 @@ class VersionUpdateDialog extends StatelessWidget {
),
),
child: Text(
'稍后提醒',
'remindLater'.tr, // 稍后提醒
style: TextStyle(
fontSize: 16.sp,
color:
@ -185,11 +185,11 @@ class VersionUpdateDialog extends StatelessWidget {
String _getUpdateButtonText() {
switch (updateInfo.updateType) {
case UpdateType.force:
return '立即更新';
return 'updateNow'.tr; // 立即更新
case UpdateType.optional:
return '立即更新';
return 'updateNow'.tr; // 立即更新
default:
return '检查更新';
return 'checkUpdate'.tr; // 检查更新
}
}
@ -212,8 +212,8 @@ class VersionUpdateDialog extends StatelessWidget {
if (!success) {
Get.snackbar(
'更新失败',
'无法打开应用商店,请手动前往应用商店更新',
'updateFailed'.tr, // 更新失败
'cannotOpenAppStore'.tr, // 无法打开应用商店,请手动前往应用商店更新
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,
@ -226,8 +226,8 @@ class VersionUpdateDialog extends StatelessWidget {
}
Get.snackbar(
'更新失败',
'更新过程中发生错误,请稍后重试',
'updateFailed'.tr, // 更新失败
'updateErrorRetry'.tr, // 更新过程中发生错误,请稍后重试
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,

16
lib/modules/devices/views/devices_view.dart

@ -31,7 +31,7 @@ class DevicesView extends GetView<DevicesController> {
},
),
title: Text(
'设备管理'.tr,
'deviceManagement'.tr,
style: TextStyle(
fontSize: 20.sp,
color: isDarkMode ? Colors.white : Colors.black,
@ -58,7 +58,7 @@ class DevicesView extends GetView<DevicesController> {
Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text(
'earphone'.tr, // AI设置
'earphone'.tr, // 耳机
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
@ -95,10 +95,10 @@ class DevicesView extends GetView<DevicesController> {
_buildSimpleNavigationSetting(
title: controller.earphonestate.value != 0
? controller.earphoneName.value
: "未绑定",
: "notBound".tr, // 未绑定
subtitle: controller.earphonestate.value != 0
? controller.earphoneMac.value
: "还未绑定设备",
: "deviceNotBoundYet".tr, // 还未绑定设备
icon: Icons.headphones,
iconBgColor: isDarkMode
? const Color.fromARGB(255, 255, 255, 255)!
@ -167,8 +167,8 @@ class DevicesView extends GetView<DevicesController> {
// 实时对话入口
Obx(
() => _buildSimpleNavigationSetting(
title: '未绑定',
subtitle: '还未绑定设备',
title: 'notBound'.tr, // 未绑定
subtitle: 'deviceNotBoundYet'.tr, // 还未绑定设备
icon: Icons.edit,
iconBgColor: isDarkMode
? const Color.fromARGB(255, 255, 255, 255)!
@ -275,8 +275,8 @@ class DevicesView extends GetView<DevicesController> {
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 2),
),
onPressed: onPressed,
child: const Text(
'解绑',
child: Text(
'unbind'.tr, // 解绑
style: TextStyle(
color: Colors.white,
),

223
lib/modules/feedback/views/feedback_view.dart

@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'dart:ui';
import '../controllers/feedback_controller.dart';
class FeedbackView extends GetView<FeedbackController> {
@ -51,148 +50,120 @@ class FeedbackView extends GetView<FeedbackController> {
),
SizedBox(height: 16.h),
// 反馈内容输入框
// 反馈内容输入框 - 统一容器样式
Container(
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withOpacity(0.05)
: Colors.white,
// 保持适合各自模式的背景色
color: isDarkMode ? Colors.grey[800] : Colors.white,
// 统一圆角
borderRadius: BorderRadius.circular(16.r),
// 统一阴影效果 - 关键改进点
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withOpacity(0.2)
: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
? Colors.black.withOpacity(0.3)
: Colors.black.withOpacity(0.08),
blurRadius: 12,
offset: const Offset(0, 4),
spreadRadius: 0,
),
],
// 统一边框样式 - 关键改进点
border: Border.all(
color: isDarkMode ? Colors.grey[700]! : Colors.grey[200]!,
width: 1.5,
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: BackdropFilter(
filter: isDarkMode
? ImageFilter.blur(sigmaX: 5, sigmaY: 5)
: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
child: Padding(
padding:
EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
child: TextFormField(
controller: controller.feedbackController,
maxLines: 8,
maxLength: 500,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87,
),
decoration: InputDecoration(
hintText: 'feedbackHint'.tr, // 请输入您的反馈内容...
hintStyle: TextStyle(
color: isDarkMode ? Colors.white38 : Colors.black38,
),
border: InputBorder.none,
counterStyle: TextStyle(
color: isDarkMode ? Colors.white54 : Colors.black54,
),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'feedbackRequired'.tr; // 请输入反馈内容
}
return null;
},
child: Padding(
padding:
EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
child: TextFormField(
controller: controller.feedbackController,
maxLines: 8,
maxLength: 500,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87,
fontSize: 14.sp,
height: 1.4,
),
decoration: InputDecoration(
hintText: 'feedbackHint'.tr, // 请输入您的反馈内容...
hintStyle: TextStyle(
color: isDarkMode ? Colors.grey[400] : Colors.grey[500],
fontSize: 14.sp,
),
border: InputBorder.none,
focusedBorder: InputBorder.none,
counterStyle: TextStyle(
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
fontSize: 12.sp,
),
contentPadding: EdgeInsets.zero,
fillColor: Colors.transparent,
filled: true,
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'feedbackRequired'.tr; // 请输入反馈内容
}
return null;
},
),
),
),
SizedBox(height: 24.h),
// 联系方式标题
// Text(
// 'contactInfo'.tr, // 联系方式
// style: TextStyle(
// fontSize: 14.sp,
// color: isDarkMode ? Colors.white70 : Colors.black54,
// ),
// ),
// SizedBox(height: 16.h),
SizedBox(height: 40.h),
// // 联系方式输入框
// Container(
// decoration: BoxDecoration(
// color: isDarkMode
// ? Colors.white.withOpacity(0.05)
// : Colors.white,
// borderRadius: BorderRadius.circular(16.r),
// boxShadow: [
// BoxShadow(
// color: isDarkMode
// ? Colors.black.withOpacity(0.2)
// : Colors.black.withOpacity(0.05),
// blurRadius: 10,
// offset: const Offset(0, 2),
// ),
// ],
// ),
// child: ClipRRect(
// borderRadius: BorderRadius.circular(16.r),
// child: BackdropFilter(
// filter: isDarkMode
// ? ImageFilter.blur(sigmaX: 5, sigmaY: 5)
// : ImageFilter.blur(sigmaX: 0, sigmaY: 0),
// child: Padding(
// padding:
// EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
// child: TextFormField(
// controller: controller.contactController,
// style: TextStyle(
// color: isDarkMode ? Colors.white : Colors.black87,
// ),
// decoration: InputDecoration(
// hintText: 'contactHint'.tr, // 邮箱/手机号,方便我们联系您
// hintStyle: TextStyle(
// color: isDarkMode ? Colors.white38 : Colors.black38,
// ),
// border: InputBorder.none,
// ),
// ),
// ),
// ),
// ),
// ),
// SizedBox(height: 40.h),
// 提交按钮
Obx(() => ElevatedButton(
onPressed: controller.isSubmitting.value
? null
: controller.submitFeedback,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue[600],
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
// 提交按钮 - 统一容器样式
Obx(() => Container(
// 统一按钮容器装饰
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
// 统一阴影效果
boxShadow: controller.isSubmitting.value
? []
: [
BoxShadow(
color: Colors.blue.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 4),
spreadRadius: 0,
),
],
),
child: controller.isSubmitting.value
? SizedBox(
height: 20.h,
width: 20.h,
child: CircularProgressIndicator(
strokeWidth: 2.w,
valueColor: const AlwaysStoppedAnimation<Color>(
Colors.white),
),
)
: Text(
'submit'.tr, // 提交
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: Colors.white,
child: ElevatedButton(
onPressed: controller.isSubmitting.value
? null
: controller.submitFeedback,
style: ElevatedButton.styleFrom(
backgroundColor: controller.isSubmitting.value
? Colors.grey[400]
: Colors.blue[600],
padding: EdgeInsets.symmetric(vertical: 14.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
shadowColor: Colors.transparent,
),
child: controller.isSubmitting.value
? SizedBox(
height: 20.h,
width: 20.h,
child: CircularProgressIndicator(
strokeWidth: 2.w,
valueColor: const AlwaysStoppedAnimation<Color>(
Colors.white),
),
)
: Text(
'submit'.tr, // 提交
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
)),
],
),

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

@ -218,7 +218,7 @@ class LoginController extends GetxController {
mainAxisSize: MainAxisSize.min,
children: [
Text(
'DeapSound 声明',
'loginDeclaration'.tr, //APP 声明
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
@ -233,7 +233,7 @@ class LoginController extends GetxController {
TextSpan(
children: [
TextSpan(
text: '欢迎使用DeapSound,请充分阅读',
text: 'welcomeToThisApp'.tr, //欢迎使用本APP,请充分阅读
style: TextStyle(
fontSize: 14,
color: isDarkMode
@ -252,12 +252,12 @@ class LoginController extends GetxController {
}
Get.to(() => WebViewPage(
url: url,
title: 'privacyPolicy'.tr,
title: 'privacyPolicy'.tr, //隐私政策
));
},
child: const Text(
'《隐私政策》',
style: TextStyle(
child: Text(
'privacyPolicy'.tr, //隐私政策
style: const TextStyle(
fontSize: 14,
color: Color(0xFF3B82F6),
),
@ -265,7 +265,7 @@ class LoginController extends GetxController {
),
),
TextSpan(
text: '和',
text: 'and'.tr, //和
style: TextStyle(
fontSize: 14,
color: isDarkMode ? Colors.white70 : Colors.black87,
@ -282,12 +282,12 @@ class LoginController extends GetxController {
}
Get.to(() => WebViewPage(
url: url,
title: 'userAgreement'.tr,
title: 'userAgreement'.tr, //用户协议
));
},
child: const Text(
'《用户协议》',
style: TextStyle(
child: Text(
'userAgreement'.tr, //用户协议
style: const TextStyle(
fontSize: 14,
color: Color(0xFF3B82F6),
),
@ -295,7 +295,8 @@ class LoginController extends GetxController {
),
),
TextSpan(
text: ',点击“同意并进入”表示您已充分阅读并同意上述协议。点击“不同意”将退出应用。',
text: 'privacyPolicyText'
.tr, //',点击“同意并进入”表示您已充分阅读并同意上述协议。点击“不同意”将退出应用。',
style: TextStyle(
fontSize: 14,
color: isDarkMode ? Colors.white70 : Colors.black87,
@ -321,7 +322,7 @@ class LoginController extends GetxController {
: Colors.black54, // 暗黑模式使用浅灰色
),
child: Text(
'不同意',
'disagree'.tr, //不同意
style: TextStyle(
color: isDarkMode ? Colors.grey[400] : Colors.black54,
),
@ -346,7 +347,7 @@ class LoginController extends GetxController {
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 10), // 统一的内边距
),
child: const Text('同意并进入'),
child: Text('agreeAndEnter'.tr),
),
],
),

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

@ -129,7 +129,7 @@ class LoginView extends GetView<LoginController> {
),
SizedBox(height: 16.h),
Text(
'DeepSound',
'DeapSound',
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,

97
lib/modules/music/views/music_playlist_view.dart

@ -38,7 +38,7 @@ class MusicPlaylistView extends StatelessWidget {
),
SizedBox(height: 16.h),
Text(
'暂无音乐',
'noMusic'.tr, // 暂无音乐
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey[600],
@ -103,7 +103,7 @@ class MusicPlaylistView extends StatelessWidget {
),
SizedBox(height: 12.h),
Text(
'暂无播放音乐',
'noPlayingMusic'.tr, // 暂无播放音乐
style: TextStyle(
fontSize: 16.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
@ -115,11 +115,11 @@ class MusicPlaylistView extends StatelessWidget {
);
}
final title = currentSong['name'] ?? currentSong['title'] ?? '未知歌曲';
final title = currentSong['name'] ?? currentSong['title'] ?? 'unknownSong'.tr; // 未知歌曲
final artist = currentSong['singer'] ??
currentSong['sgener'] ??
currentSong['artist'] ??
'未知歌手';
'unknownArtist'.tr; // 未知歌手
final coverUrl = currentSong['image'] ?? currentSong['coverUrl'] ?? '';
return Container(
@ -161,7 +161,7 @@ class MusicPlaylistView extends StatelessWidget {
},
icon: Icon(Icons.play_arrow, color: Colors.white, size: 20.w),
label: Text(
'播放全部',
'playAll'.tr, // 播放全部
style: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.w600,
@ -190,9 +190,9 @@ class MusicPlaylistView extends StatelessWidget {
itemBuilder: (context, index) {
final item = playlist[index];
final id = item["id"] ?? 0;
final name = item["name"] ?? "未知歌曲";
final name = item["name"] ?? 'unknownSong'.tr; // 未知歌曲
final url = item["url"] ?? "";
final singer = item["singer"] ?? item["sgener"] ?? "未知歌手";
final singer = item["singer"] ?? item["sgener"] ?? 'unknownArtist'.tr; // 未知歌手
final image = item["image"] ?? "";
return _buildMusicItem(
@ -228,8 +228,8 @@ class MusicPlaylistView extends StatelessWidget {
};
return GestureDetector(
onTap: () {
_playSelectedSong(controller, song, Get.arguments ?? []);
onTap: () async {
await _playSelectedSong(controller, song, Get.arguments ?? []);
},
child: Container(
margin: EdgeInsets.only(bottom: 10.h),
@ -512,7 +512,7 @@ class MusicPlaylistView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () => _playPrevious(controller, playlist),
onPressed: () async => await _playPrevious(controller, playlist),
iconSize: 32.w,
padding: EdgeInsets.all(8.w), // 增大触摸区域
icon: Icon(
@ -548,7 +548,7 @@ class MusicPlaylistView extends StatelessWidget {
),
SizedBox(width: 16.w),
IconButton(
onPressed: () => _playNext(controller, playlist),
onPressed: () async => await _playNext(controller, playlist),
iconSize: 32.w,
padding: EdgeInsets.all(8.w), // 增大触摸区域
icon: Icon(
@ -580,26 +580,71 @@ class MusicPlaylistView extends StatelessWidget {
}
// 播放上一曲
void _playPrevious(
AgentController controller, List<Map<String, dynamic>> playlist) {
controller.updateCurrentPlaylistContext(
playlist, controller.currentId.value);
controller.playPrevious();
Future<void> _playPrevious(
AgentController controller, List<Map<String, dynamic>> playlist) async {
// 防止重复点击导致的状态混乱
if (controller.isLoadingMusic.value) {
return;
}
try {
// 设置加载状态,防止重复操作
controller.isLoadingMusic.value = true;
// 更新播放列表上下文
controller.updateCurrentPlaylistContext(
playlist, controller.currentId.value);
// 执行上一曲操作
await controller.playPrevious();
} finally {
// 确保加载状态被重置
controller.isLoadingMusic.value = false;
}
}
// 播放下一曲
void _playNext(
AgentController controller, List<Map<String, dynamic>> playlist) {
controller.updateCurrentPlaylistContext(
playlist, controller.currentId.value);
controller.playNext();
Future<void> _playNext(
AgentController controller, List<Map<String, dynamic>> playlist) async {
// 防止重复点击导致的状态混乱
if (controller.isLoadingMusic.value) {
return;
}
try {
// 设置加载状态,防止重复操作
controller.isLoadingMusic.value = true;
// 更新播放列表上下文
controller.updateCurrentPlaylistContext(
playlist, controller.currentId.value);
// 执行下一曲操作
await controller.playNext();
} finally {
// 确保加载状态被重置
controller.isLoadingMusic.value = false;
}
}
// 播放选中的歌曲
void _playSelectedSong(AgentController controller, Map<String, dynamic> song,
List<Map<String, dynamic>> playlist) {
final songId = song['id'] ?? 0;
controller.updateCurrentPlaylistContext(playlist, songId);
controller.musicPlay(song);
Future<void> _playSelectedSong(AgentController controller, Map<String, dynamic> song,
List<Map<String, dynamic>> playlist) async {
// 防止重复点击导致的状态混乱
if (controller.isLoadingMusic.value) {
return;
}
try {
// 设置加载状态,防止重复操作
controller.isLoadingMusic.value = true;
final songId = song['id'] ?? 0;
controller.updateCurrentPlaylistContext(playlist, songId);
await controller.musicPlay(song);
} finally {
// 确保加载状态被重置
controller.isLoadingMusic.value = false;
}
}
}

56
lib/modules/ota_upgrade/views/ota_upgrade_view.dart

@ -17,12 +17,13 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
// 显示确认弹窗
await Get.dialog(
AlertDialog(
title: Text('提示'),
content: Text('当前正在升级,退出将中断升级进程,确定要退出吗?'),
title: Text('tip'.tr), // 提示
content:
Text('upgradeExitConfirm'.tr), // 当前正在升级,退出将中断升级进程,确定要退出吗?
actions: [
TextButton(
onPressed: () => Get.back(), // 关闭弹窗
child: Text('取消'),
child: Text('cancel'.tr), // 取消
),
TextButton(
onPressed: () {
@ -30,7 +31,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
Get.back(); // 关闭弹窗
Get.back(); // 返回上一页
},
child: Text('确定'),
child: Text('confirm'.tr), // 确定
),
],
),
@ -57,12 +58,13 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
// 显示确认弹窗
Get.dialog(
AlertDialog(
title: Text('提示'),
content: Text('当前正在升级,退出将中断升级进程,确定要退出吗?'),
title: Text('tip'.tr), // 提示
content: Text(
'upgradeExitConfirm'.tr), // 当前正在升级,退出将中断升级进程,确定要退出吗?
actions: [
TextButton(
onPressed: () => Get.back(), // 关闭弹窗
child: Text('取消'),
child: Text('cancel'.tr), // 取消
),
TextButton(
onPressed: () {
@ -70,7 +72,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
Get.back(); // 关闭弹窗
Get.back(); // 返回上一页
},
child: Text('确定'),
child: Text('confirm'.tr), // 确定
),
],
),
@ -81,7 +83,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
},
),
title: Text(
'固件升级'.tr,
'firmwareUpgrade'.tr, //固件升级
style: TextStyle(
fontSize: 20.sp,
color: isDarkMode ? Colors.white : Colors.black,
@ -217,8 +219,8 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
// 设备型号信息
_buildDeviceInfoRow(
icon: Icons.headset,
label: '设备型号',
value: deviceInfo?.name ?? '未知设备',
label: 'deviceModel'.tr, // 设备型号
value: deviceInfo?.name ?? 'unknownDevice'.tr, // 未知设备
isDarkMode: isDarkMode,
),
// SizedBox(height: 10.h),
@ -361,7 +363,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
if (isCharging) ...[
SizedBox(height: 1.h),
Text(
'充电中',
'charging'.tr, // 充电中
style: TextStyle(
fontSize: 10.sp,
color: batteryColor,
@ -380,7 +382,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
children: [
// 当前版本信息
_buildVersionInfoRow(
label: '当前固件版本'.tr,
label: 'currentFirmwareVersion'.tr, //当前固件版本
version: controller.currentVersion,
isDarkMode: isDarkMode,
isLatest: false,
@ -388,7 +390,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
SizedBox(height: 8.h),
// 最新版本信息
_buildVersionInfoRow(
label: '最新固件版本'.tr,
label: 'latestFirmwareVersion'.tr, //最新固件版本
version: controller.latestVersion,
isDarkMode: isDarkMode,
isLatest: true,
@ -499,7 +501,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
),
SizedBox(width: 6.w),
Text(
'发现新版本',
'ota_newVersionFound'.tr, // 发现新版本
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
@ -530,7 +532,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
),
SizedBox(width: 6.w),
Text(
'已是最新版本',
'latestVersion'.tr, // 已是最新版本
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
@ -596,7 +598,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
),
SizedBox(width: 12.w),
Text(
'更新内容'.tr,
'updateContent'.tr, //更新内容
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -667,7 +669,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
),
SizedBox(height: 24.h),
Text(
'正在获取设备信息...',
'gettingDeviceInfo'.tr, // 正在获取设备信息...
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
@ -676,7 +678,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
),
SizedBox(height: 8.h),
Text(
'请保持设备连接',
'keepDeviceConnected'.tr, // 请保持设备连接
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[500] : Colors.grey[500],
@ -731,7 +733,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
SizedBox(height: 16.h),
// 错误标题
Text(
'连接失败',
'connectionFailed'.tr, // 连接失败
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
@ -756,7 +758,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
child: ElevatedButton.icon(
icon: Icon(Icons.refresh, size: 18.sp),
label: Text(
'重试连接'.tr,
'retryConnection'.tr, //重试连接
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
@ -832,7 +834,9 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
size: 20.sp,
),
label: Text(
controller.isUpdateAvailable.value ? '立即更新' : '已是最新版本',
controller.isUpdateAvailable.value
? 'ota_updateNow'.tr
: 'latestVersion'.tr, // 立即更新 : 已是最新版本
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
@ -877,7 +881,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
SizedBox(width: 12.w),
Expanded(
child: Text(
'取出双耳机,并保证电量均为30%以上的状态'.tr,
'removeEarbudsEnsureBattery'.tr, //取出双耳机,并保证电量均为30%以上的状态
style: TextStyle(
fontSize: 13.sp,
color: isDarkMode
@ -965,10 +969,10 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
],
),
SizedBox(height: 16.h),
// 提示信息
Text(
'请保持设备连接,不要关闭应用',
'keepConnectedDontClose'.tr, // 请保持设备连接,不要关闭应用
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
@ -1081,7 +1085,7 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
),
),
Text(
'请勿断开连接',
'doNotDisconnect'.tr, // 请勿断开连接
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],

87
lib/modules/pairing/controllers/pairing_controller.dart

@ -70,10 +70,12 @@ class PairingController extends GetxController {
// 增加临时跳过绑定按钮状态
final showSkipBindingButton = false.obs; // 新增临时跳过绑定按钮
final connectButtonText = '连接设备'.obs;
final retryButtonText = '重试'.obs;
final connectButtonText = 'connectDevice'.tr.obs; //连接设备
final retryButtonText = 'retry'.tr.obs;
final deviceCode = ''.obs;
bool isShowSkipButton = false; //是否显示跳过按钮
// ========== 监听器管理 ==========
final List<Worker> _workers = [];
Timer? _bleTimeoutTimer;
@ -107,6 +109,12 @@ class PairingController extends GetxController {
Future.delayed(const Duration(milliseconds: 300), () {
_startInitialCheck();
});
final app_authcode_jump = AppConfig.env('APP_AUTHCODE_JUMP') ?? "";
//print('app_authcode_jump: $app_authcode_jump');
if (app_authcode_jump == "true") {
isShowSkipButton = true; // 启用跳过按钮
}
}
@override
@ -168,8 +176,7 @@ class PairingController extends GetxController {
/// 处理蓝牙开关状态变化
void _handleBluetoothStateChange(String state) {
if (state == 'off') {
// 蓝牙关闭,进入错误状态
_setError(ErrorType.bluetoothOff, '请开启蓝牙');
_setError(ErrorType.bluetoothOff, 'pleaseEnableBluetooth'.tr);
} else if (state == 'on' && _errorType.value == ErrorType.bluetoothOff) {
// 蓝牙重新开启,恢复流程
Logger.i(_tag, '检测到蓝牙已开启,自动恢复配对流程');
@ -210,7 +217,7 @@ class PairingController extends GetxController {
case PairingState.completed:
if (device == null) {
// 设备断开,返回等待连接状态
_setError(ErrorType.noClassicDevice, '设备已断开');
_setError(ErrorType.noClassicDevice, 'deviceDisconnected'.tr); //设备已断开
}
break;
@ -260,34 +267,33 @@ class PairingController extends GetxController {
showRetryChectButton.value = false;
switch (state) {
case PairingState.idle:
statusText.value = '准备开始配对';
statusText.value = 'readyToStartPairing'.tr;
break;
case PairingState.checking:
statusText.value = '正在检查环境...';
statusText.value = 'checkingEnvironment'.tr;
isLoading.value = true;
break;
case PairingState.waitingClassic:
statusText.value = '请确保耳机已开启并进入配对模式';
statusText.value = 'ensureHeadsetOnAndPairingMode'.tr;
showConnectButton.value = true;
showSkipButton.value = true;
connectButtonText.value = '前往蓝牙设置';
showSkipButton.value = isShowSkipButton;
connectButtonText.value = 'goToBluetoothSettings'.tr;
break;
case PairingState.verifying:
statusText.value = '正在验证设备...';
statusText.value = 'verifyingDevice'.tr;
isLoading.value = true;
break;
case PairingState.binding:
statusText.value = '确认绑定';
statusText.value = 'confirmBinding'.tr;
isLoading.value = true;
showBindButton.value = true;
showRetryChectButton.value = true;
break;
case PairingState.associating:
statusText.value = '正在关联设备...';
statusText.value = 'associatingDevice'.tr;
isLoading.value = true;
// 延迟执行关联,确保状态已更新
Future.delayed(const Duration(milliseconds: 200), () {
@ -296,7 +302,7 @@ class PairingController extends GetxController {
break;
case PairingState.waitingBle:
statusText.value = '正在建立安全连接...';
statusText.value = 'establishingSecureConnection'.tr;
isLoading.value = true;
// 延迟一下再调用,给BLE管理器时间更新状态
Future.delayed(const Duration(milliseconds: 200), () {
@ -304,14 +310,14 @@ class PairingController extends GetxController {
});
break;
case PairingState.manualbinding:
statusText.value = '需要手动绑定授权码...';
statusText.value = 'needManualBindingAuthCode'.tr;
isLoading.value = false;
showAutoCodeInput.value = true;
// showSkipButton.value = true;
// showSkipButton.value = isShowSkipButton;
showSkipBindingButton.value = true; // 显示临时跳过绑定按钮
break;
case PairingState.completed:
statusText.value = '配对成功!';
statusText.value = 'pairingSuccessful'.tr;
isLoading.value = false;
_navigateToHome();
break;
@ -319,33 +325,33 @@ class PairingController extends GetxController {
case PairingState.error:
statusText.value = _errorMessage.value;
isLoading.value = false;
showSkipButton.value = true;
showSkipButton.value = isShowSkipButton;
// 根据错误类型决定显示哪个按钮和按钮文本
switch (_errorType.value) {
case ErrorType.bluetoothOff:
showConnectButton.value = true;
connectButtonText.value = '开启蓝牙';
connectButtonText.value = 'enableBluetooth'.tr; //开启蓝牙
break;
case ErrorType.noClassicDevice:
showConnectButton.value = true;
connectButtonText.value = '前往蓝牙设置';
connectButtonText.value = 'goToBluetoothSettings'.tr; //前往蓝牙设备
break;
case ErrorType.noPermission:
showRetryButton.value = true;
retryButtonText.value = '授予权限';
retryButtonText.value = 'grantPermissions'.tr; //授予权限
break;
case ErrorType.associationFailed:
showRetryButton.value = true;
retryButtonText.value = '重新关联';
retryButtonText.value = 'retryAssociation'.tr; //重新关联
break;
case ErrorType.authnFailed:
showRetryButton.value = true;
retryButtonText.value = '重新授权';
retryButtonText.value = 'retryAuthorization'.tr; //重新授权
break;
default:
showRetryButton.value = true;
retryButtonText.value = '重试';
retryButtonText.value = 'retry'.tr; //重试
break;
}
break;
@ -380,13 +386,13 @@ class PairingController extends GetxController {
try {
// 1. 检查蓝牙状态
if (_bluetoothManager.bluetoothState == 'off') {
_setError(ErrorType.bluetoothOff, '请开启蓝牙');
_setError(ErrorType.bluetoothOff, 'pleaseEnableBluetooth'.tr);
return;
}
// 2. 检查权限
if (!await _checkPermissions()) {
_setError(ErrorType.noPermission, '请授予必要权限');
_setError(ErrorType.noPermission, 'pleaseGrantNecessaryPermissions'.tr);
return;
}
@ -406,7 +412,7 @@ class PairingController extends GetxController {
await _verifyDevice(classicDevice);
} catch (e) {
Logger.e(_tag, '状态检查失败: $e');
_setError(ErrorType.networkError, '检查失败,请重试');
_setError(ErrorType.networkError, 'checkFailedRetry'.tr);
}
}
@ -452,12 +458,13 @@ class PairingController extends GetxController {
//验证失败 进入手动授权
_transition(PairingState.manualbinding);
} else {
_setError(ErrorType.deviceNotMatch, '请连接 DeepSound 设备');
_setError(ErrorType.deviceNotMatch,
'pleaseConnectDeepSoundDevice'.tr); //请连接DeepSound设备
}
}
} catch (e) {
Logger.e(_tag, '设备验证异常: $e');
_setError(ErrorType.networkError, '验证失败,请重试');
_setError(ErrorType.networkError, 'verificationFailedRetry'.tr); //验证失败请重试
}
}
@ -496,7 +503,8 @@ class PairingController extends GetxController {
void _startDeviceAssociation() async {
try {
if (_verifiedDeviceAddress == null) {
_setError(ErrorType.associationFailed, '设备地址无效');
_setError(
ErrorType.associationFailed, 'invalidDeviceAddress'.tr); //无效的设备地址
return;
}
@ -513,11 +521,13 @@ class PairingController extends GetxController {
// 关联成功后,转到等待BLE连接状态
_transition(PairingState.waitingBle);
} else {
_setError(ErrorType.associationFailed, 'BLE设备关联失败');
_setError(ErrorType.associationFailed,
'bleDeviceAssociationFailed'.tr); //BLE设备关联失败
}
} catch (e) {
Logger.e(_tag, 'BLE设备关联异常: $e');
_setError(ErrorType.associationFailed, '设备关联失败,请重试');
_setError(ErrorType.associationFailed,
'deviceAssociationFailedRetry'.tr); //设备关联失败,请重试
}
}
@ -528,7 +538,8 @@ class PairingController extends GetxController {
_bleTimeoutTimer?.cancel();
_bleTimeoutTimer = Timer(const Duration(seconds: 30), () {
if (_currentState.value == PairingState.waitingBle) {
_setError(ErrorType.bleTimeout, 'BLE连接超时,请重试');
_setError(ErrorType.bleTimeout,
'bleConnectionTimeoutRetry'.tr); //BLE连接超时,请重试
}
});
@ -549,12 +560,13 @@ class PairingController extends GetxController {
final success = await _bleManager.registerBackgroundScan(
macAddress: _verifiedDeviceAddress);
if (!success && _currentState.value == PairingState.waitingBle) {
_setError(ErrorType.bleTimeout, 'BLE配对启动失败');
_setError(
ErrorType.bleTimeout, 'blePairingStartupFailed'.tr); //BLE配对启动失败
}
}
} catch (e) {
Logger.e(_tag, 'BLE连接失败: $e');
_setError(ErrorType.bleTimeout, 'BLE连接失败');
_setError(ErrorType.bleTimeout, 'bleConnectionFailed'.tr); //BLE连接失败
}
}
@ -665,7 +677,8 @@ class PairingController extends GetxController {
_verifyDevice(_currentClassicDevice!);
} else {
Logger.e(_tag, '手动绑定失败!');
_setError(ErrorType.authnFailed, '设备授权失败,请检查授权码');
_setError(ErrorType.authnFailed,
'deviceAuthorizationFailedCheckCode'.tr); //设备授权失败,请检查授权码
}
}

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

@ -73,7 +73,7 @@ class PairingView extends GetView<PairingController> {
return Column(
children: [
Text(
'DeepSound',
'DeapSound',
style: TextStyle(
fontSize: 30.sp,
fontWeight: FontWeight.bold,
@ -328,7 +328,8 @@ class PairingView extends GetView<PairingController> {
case ErrorType.noPermission:
return 'lackPermissions'.tr; // 缺少蓝牙权限
case ErrorType.noClassicDevice:
return 'connectDeepSoundViaSystemBluetooth'.tr; // 请先通过系统蓝牙连接DeapSound设备
return 'connectDeepSoundViaSystemBluetooth'
.tr; // 请先通过系统蓝牙连接DeapSound设备
case ErrorType.deviceNotMatch:
return 'ensureConnectedDeepSoundDevice'.tr; // 请确保连接的是DeapSound设备
case ErrorType.deviceBound:
@ -424,9 +425,9 @@ class PairingView extends GetView<PairingController> {
// 获取连接按钮图标
IconData _getConnectButtonIcon() {
final buttonText = controller.connectButtonText.value;
if (buttonText.contains('蓝牙')) {
if (buttonText.contains('bluetooth'.tr)) {
return Icons.bluetooth;
} else if (buttonText.contains('设置')) {
} else if (buttonText.contains('settings'.tr)) {
return Icons.settings;
}
return Icons.bluetooth_searching;

2
lib/modules/pairing/views/pairing_view_new.dart

@ -54,7 +54,7 @@ class PairingView extends GetView<PairingController> {
),
SizedBox(height: 8.h),
Text(
'connectYourDeepSoundHeadset'.tr, // 连接您的 DeepSound 耳机
'connectYourDeepSoundHeadset'.tr, // 连接您的 DeapSound 耳机
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],

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

@ -50,22 +50,22 @@ class ProfileController extends GetxController {
errorStr.contains('socket') ||
errorStr.contains('timeout') ||
errorStr.contains('connection')) {
return '网络连接失败,请检查网络设置后重试';
return 'networkConnectionFailed'.tr; //网络连接失败
} else if (errorStr.contains('server') ||
errorStr.contains('500') ||
errorStr.contains('502') ||
errorStr.contains('503')) {
return '服务器暂时无法响应,请稍后重试';
errorStr.contains('500') ||
errorStr.contains('502') ||
errorStr.contains('503')) {
return 'serverTemporarilyUnavailable'.tr; //服务器暂时不可用
} else if (errorStr.contains('401') || errorStr.contains('unauthorized')) {
return '登录已过期,请重新登录';
return 'loginExpiredPleaseRelogin'.tr; //登录过期,请重新登录
} else if (errorStr.contains('403') || errorStr.contains('forbidden')) {
return '没有权限执行此操作';
return 'noPermissionForThisOperation'.tr; //没有权限执行此操作
} else if (errorStr.contains('404')) {
return '请求的资源不存在';
return 'requestedResourceNotFound'.tr; //请求的资源不存在
} else if (errorStr.contains('file') || errorStr.contains('image')) {
return '图片处理失败,请重新选择图片';
return 'imageProcessingFailedPleaseReselect'.tr; //图片处理失败,请重新选择图片
} else {
return '操作失败,请重试';
return 'operationFailedPleaseRetry'.tr; //操作失败,请重试
}
}
@ -236,9 +236,11 @@ class ProfileController extends GetxController {
if (response != null && response is Map<String, dynamic>) {
// 检查响应是否包含错误
if (response.containsKey('error') || response.containsKey('msg')) {
final errorMsg = response['error'] ?? response['msg'] ?? '服务器返回错误';
final errorMsg = response['error'] ??
response['msg'] ??
'serverReturnedError'.tr; //服务器返回错误
Logger().e('服务器返回错误: $errorMsg');
throw Exception('服务器错误: $errorMsg');
throw Exception('${'serverError'.tr}: $errorMsg'); //服务器错误
}
Logger().d('更新成功: $response');
@ -252,7 +254,8 @@ class ProfileController extends GetxController {
});
// 如果服务器返回了新的头像URL,下载并保存到本地
if (response['avatar'] != null && response['avatar'].toString().isNotEmpty) {
if (response['avatar'] != null &&
response['avatar'].toString().isNotEmpty) {
final serverAvatar = response['avatar'].toString();
if (serverAvatar.startsWith('http')) {
// 异步下载新头像,不阻塞当前流程
@ -272,10 +275,12 @@ class ProfileController extends GetxController {
if (e.toString().contains('SocketException') ||
e.toString().contains('TimeoutException') ||
e.toString().contains('network')) {
throw Exception('network: 网络连接失败,请检查网络设置');
throw Exception(
'network: ${'networkConnectionFailedCheckSettings'.tr}'); //网络连接失败,请检查网络设置
} else if (e.toString().contains('500') ||
e.toString().contains('server')) {
throw Exception('server: 服务器内部错误,请稍后重试');
e.toString().contains('server')) {
throw Exception(
'server: ${'serverInternalErrorRetryLater'.tr}'); //服务器内部错误,请稍后重试
} else {
throw Exception('unknown: ${e.toString()}');
}
@ -350,7 +355,8 @@ class ProfileController extends GetxController {
_originalName = userInfo.value.name;
_originalAvatar = userInfo.value.avatar;
_originalLocalAvatar = localAvatar.value;
Logger().d('已保存原始状态 - 名称: $_originalName, 头像: $_originalAvatar, 本地头像: $_originalLocalAvatar');
Logger().d(
'已保存原始状态 - 名称: $_originalName, 头像: $_originalAvatar, 本地头像: $_originalLocalAvatar');
}
// 回滚到原始状态
@ -377,7 +383,8 @@ class ProfileController extends GetxController {
Logger().e('回滚状态同步到本地存储失败: $e');
}
Logger().d('已回滚到原始状态 - 名称: $_originalName, 头像: $_originalAvatar, 本地头像: $_originalLocalAvatar');
Logger().d(
'已回滚到原始状态 - 名称: $_originalName, 头像: $_originalAvatar, 本地头像: $_originalLocalAvatar');
}
// 开始编辑昵称(内联编辑)
@ -509,7 +516,7 @@ class ProfileController extends GetxController {
);
if (compressedImage == null) {
Get.snackbar('错误', '图片压缩失败');
Get.snackbar('error'.tr, 'imageCompressionFailed'.tr); //图片压缩失败
return;
}
@ -535,10 +542,12 @@ class ProfileController extends GetxController {
} catch (e) {
Logger().e('更新头像失败: $e');
final errorMessage = _getErrorMessage(e);
Get.snackbar('头像更新失败', errorMessage,
Get.snackbar(
'avatarUpdateFailed'.tr,
errorMessage,
duration: const Duration(seconds: 3),
snackPosition: SnackPosition.TOP,
);
); //头像更新失败
// 发生错误时回滚状态
await _rollbackToOriginalState();
}
@ -549,7 +558,7 @@ class ProfileController extends GetxController {
Future<void> updateUserNameAndAvatar(String name) async {
if (name.trim().isEmpty) {
Logger().e('无效名称: $name');
Get.snackbar('错误', '用户名不能为空');
Get.snackbar('error'.tr, 'usernameCannotBeEmpty'.tr); //用户名不能为空
return;
}
@ -582,8 +591,8 @@ class ProfileController extends GetxController {
// 显示成功提示
Get.snackbar(
'保存成功',
'个人信息已更新',
'saveSuccess'.tr,
'personalInfoUpdated'.tr,
duration: const Duration(seconds: 3),
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withOpacity(0.1),
@ -596,7 +605,7 @@ class ProfileController extends GetxController {
borderRadius: 8,
isDismissible: true,
forwardAnimationCurve: Curves.easeOutBack,
);
); //个人信息更新成功
Logger().d('成功提示已显示');
@ -604,12 +613,12 @@ class ProfileController extends GetxController {
Future.delayed(const Duration(milliseconds: 100), () {
if (Get.context != null) {
ScaffoldMessenger.of(Get.context!).showSnackBar(
const SnackBar(
SnackBar(
content: Row(
children: [
Icon(Icons.check_circle, color: Colors.white),
SizedBox(width: 8),
Text('个人信息已更新'),
Text('personalInfoUpdated'.tr),
],
),
backgroundColor: Colors.green,
@ -619,7 +628,6 @@ class ProfileController extends GetxController {
);
}
});
} catch (e) {
Logger().e('更新用户名和头像错误: $e');
@ -628,10 +636,12 @@ class ProfileController extends GetxController {
// 显示错误提示
final errorMessage = _getErrorMessage(e);
Get.snackbar('保存失败', errorMessage,
Get.snackbar(
'saveFailed'.tr,
errorMessage,
duration: const Duration(seconds: 4),
snackPosition: SnackPosition.TOP,
);
); //保存失败
} finally {
// 隐藏加载状态
isUpdating.value = false;
@ -655,7 +665,7 @@ class ProfileController extends GetxController {
if (result.success) {
// 先显示成功提示
Get.snackbar('成功', result.message ?? '已退出登录');
Get.snackbar('success'.tr, result.message ?? 'loggedOut'.tr); //已退出登录
Logger().d('退出登录成功');
// 然后导航到登录页面
@ -663,7 +673,8 @@ class ProfileController extends GetxController {
await Get.offAllNamed(Routes.login);
}
} else {
Get.snackbar('错误', result.errorMessage ?? '退出登录失败,请重试');
Get.snackbar('error'.tr,
result.errorMessage ?? 'logoutFailedRetry'.tr); //退出登录失败,请重试
Logger().e('退出登录失败: ${result.errorMessage}');
}
} catch (e) {
@ -671,7 +682,7 @@ class ProfileController extends GetxController {
if (Get.isDialogOpen ?? false) {
Get.back();
}
Get.snackbar('错误', '退出登录失败,请重试');
Get.snackbar('error'.tr, 'logoutFailedRetry'.tr); //退出登录失败,请重试
Logger().e('退出登录错误: $e');
}
}
@ -693,7 +704,8 @@ class ProfileController extends GetxController {
if (result.success) {
// 先显示成功提示
Get.snackbar('成功', result.message ?? '账号已被永久删除');
Get.snackbar('success'.tr,
result.message ?? 'accountPermanentlyDeleted'.tr); //账号已被永久删除
Logger().d('账号删除成功');
// 然后导航到登录页面
@ -701,7 +713,8 @@ class ProfileController extends GetxController {
await Get.offAllNamed(Routes.login);
}
} else {
Get.snackbar('错误', result.errorMessage ?? '删除账号失败,请重试');
Get.snackbar('error'.tr,
result.errorMessage ?? 'deleteAccountFailedRetry'.tr); //删除账号失败,请重试
Logger().e('删除账号失败: ${result.errorMessage}');
}
} catch (e) {
@ -709,7 +722,7 @@ class ProfileController extends GetxController {
if (Get.isDialogOpen ?? false) {
Get.back();
}
Get.snackbar('错误', '删除账号失败,请重试');
Get.snackbar('error'.tr, 'deleteAccountFailedRetry'.tr); //删除账号失败,请重试
Logger().e('删除账号失败: $e');
}
}

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

@ -233,7 +233,7 @@ class EditProfileView extends GetView<ProfileController> {
Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text(
'editProfile'.tr, // 编辑资料
'editProfile'.tr, // 编辑个人信息
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
@ -461,7 +461,8 @@ class EditProfileView extends GetView<ProfileController> {
Widget _buildNicknameEditingMode(BuildContext context, bool isDarkMode,
TextEditingController nameController) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), // 与显示模式保持一致的padding
padding: EdgeInsets.symmetric(
horizontal: 16.w, vertical: 16.h), // 与显示模式保持一致的padding
child: Row(
children: [
// 图标 - 保持与显示模式相同的绿色主题
@ -646,7 +647,7 @@ class EditProfileView extends GetView<ProfileController> {
Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text(
'AccountSetting'.tr, // 账号设置
'accountSetting'.tr, // 账号设置
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,

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

@ -469,7 +469,7 @@ class SettingsController extends GetxController {
style: TextButton.styleFrom(
foregroundColor: Colors.red,
),
child: const Text('确定'),
child: Text('confirm'.tr), //确认
),
],
),
@ -513,8 +513,9 @@ class SettingsController extends GetxController {
} else {
// 显示已是最新版本的提示
Get.snackbar(
'检查更新',
'当前已是最新版本 ${updateInfo.currentVersion}',
'checkUpdate'.tr,
'currentLatestVersion' //当前已是最新版本
.trParams({'version': updateInfo.currentVersion}),
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withOpacity(0.8),
colorText: Colors.white,
@ -527,8 +528,8 @@ class SettingsController extends GetxController {
}
Get.snackbar(
'检查更新失败',
'网络连接异常,请稍后重试',
'error'.tr,
'networkErrorRetry'.tr, // 网络错误,请稍后重试
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,

91
lib/modules/settings/views/permissions_view.dart

@ -27,7 +27,7 @@ class PermissionsView extends GetView<SettingsController> {
onPressed: () => Get.back(),
),
title: Text(
'权限管理'.tr,
'permissionManagement'.tr, // 权限管理
style: TextStyle(
fontSize: 17.sp,
fontWeight: FontWeight.w600,
@ -44,7 +44,9 @@ class PermissionsView extends GetView<SettingsController> {
}
if (snapshot.hasError) {
return Center(child: Text('获取权限状态失败: ${snapshot.error}'.tr));
return Center(
child: Text('getPermissionStatusFailed'.tr +
': ${snapshot.error}')); // 获取权限状态失败
}
final permissionStatuses = snapshot.data ?? {};
@ -54,7 +56,7 @@ class PermissionsView extends GetView<SettingsController> {
children: [
// 通讯权限组
_buildPermissionSection(
'通讯权限',
'communicationPermissions'.tr, // 通讯权限
Icons.phone_android,
[Permission.phone, Permission.sms],
permissionStatuses,
@ -64,7 +66,7 @@ class PermissionsView extends GetView<SettingsController> {
// 日历权限组
_buildPermissionSection(
'日历权限',
'calendarPermissions'.tr, // 日历权限
Icons.calendar_today,
[Permission.calendarFullAccess],
permissionStatuses,
@ -73,8 +75,12 @@ class PermissionsView extends GetView<SettingsController> {
SizedBox(height: 20.h),
// 位置权限组
_buildPermissionSection('位置权限', Icons.location_on,
[Permission.location], permissionStatuses, isDarkMode),
_buildPermissionSection(
'locationPermissions'.tr, // 位置权限
Icons.location_on,
[Permission.location],
permissionStatuses,
isDarkMode),
],
);
},
@ -147,15 +153,15 @@ class PermissionsView extends GetView<SettingsController> {
String getName(Permission permission) {
switch (permission) {
case Permission.phone:
return '电话';
return 'phone'.tr; // 电话
case Permission.sms:
return '短信';
return 'sms'.tr; // 短信
case Permission.calendarFullAccess:
return '日历写入';
return 'calendarWrite'.tr; // 日历写入
case Permission.calendarFullAccess:
return '日历完整访问';
return 'calendarFullAccess'.tr; // 日历完整访问
case Permission.location:
return '位置信息';
return 'locationInfo'.tr; // 位置信息
default:
return permission.toString();
}
@ -165,17 +171,17 @@ class PermissionsView extends GetView<SettingsController> {
String getDescription(Permission permission) {
switch (permission) {
case Permission.phone:
return '用于拨打电话功能';
return 'phonePermissionDesc'.tr; // 用于拨打电话功能
case Permission.sms:
return '用于发送短信功能';
return 'smsPermissionDesc'.tr; // 用于发送短信功能
case Permission.calendarFullAccess:
return '用于创建日历事件和提醒';
return 'calendarWritePermissionDesc'.tr; // 用于创建日历事件和提醒
case Permission.calendarFullAccess:
return '用于读取和管理日历事件及提醒';
return 'calendarFullAccessPermissionDesc'.tr; // 用于读取和管理日历事件及提醒
case Permission.location:
return '用于获取当前位置信息';
return 'locationPermissionDesc'.tr; // 用于获取当前位置信息
default:
return '应用功能需要';
return 'appFunctionNeeds'.tr; // 应用功能需要
}
}
@ -265,19 +271,19 @@ class PermissionsView extends GetView<SettingsController> {
Color color;
if (status.isGranted) {
text = '已授权'.tr;
text = 'authorized'.tr; // 已授权
color = Colors.green;
} else if (status.isDenied) {
text = '未授权'.tr;
text = 'unauthorized'.tr; // 未授权
color = Colors.red;
} else if (status.isPermanentlyDenied) {
text = '需要在系统设置中开启'.tr;
text = 'needOpenInSystemSettings'.tr; // 需要在系统设置中开启
color = Colors.orange;
} else if (status.isLimited) {
text = '部分授权'.tr;
text = 'partialAuthorization'.tr; // 部分授权
color = Colors.orange;
} else {
text = '未知状态'.tr;
text = 'unknownStatus'.tr; // 未知状态
color = Colors.grey;
}
@ -299,7 +305,7 @@ class PermissionsView extends GetView<SettingsController> {
// if (context == null) return;
final permissionName = _getPermissionName(permission);
final explanationText = _getExplanationText(permission);
final explanationText = getDetailedDescription(permission);
// 使用 PermissionUtil 请求权限
final hasPermission = await PermissionUtil.instance.requestPermission(
@ -307,15 +313,16 @@ class PermissionsView extends GetView<SettingsController> {
permissionType: permission,
permissionName: permissionName,
explanationText: explanationText,
permanentDenialText: '您已永久拒绝$permissionName权限,请前往应用设置开启',
settingsButtonText: '去设置',
cancelButtonText: '取消',
permanentDenialText: 'permanentDenialText'.tr.replaceAll(
'{permission}', permissionName), // 您已永久拒绝{permission}权限,请前往应用设置开启
settingsButtonText: 'goToSettings'.tr, // 去设置
cancelButtonText: 'cancel'.tr, // 取消
);
if (hasPermission) {
Get.snackbar(
'成功'.tr,
'$permissionName权限已授予'.tr,
'success'.tr, // 成功
'permissionGranted'.tr, // 权限已授予
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
colorText: Colors.white,
@ -326,8 +333,8 @@ class PermissionsView extends GetView<SettingsController> {
Get.forceAppUpdate();
} catch (e) {
Get.snackbar(
'错误'.tr,
'请求权限时出错: $e'.tr,
'error'.tr, // 错误
'permissionRequestError'.tr, // 请求权限时出错
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
@ -339,35 +346,35 @@ class PermissionsView extends GetView<SettingsController> {
String _getPermissionName(Permission permission) {
switch (permission) {
case Permission.phone:
return '电话';
return 'phone'.tr; // 电话
case Permission.sms:
return '短信';
return 'sms'.tr; // 短信
case Permission.calendarFullAccess:
return '日历写入';
return 'calendarWrite'.tr; // 日历写入
case Permission.calendarFullAccess:
return '日历完整访问';
return 'calendarFullAccess'.tr; // 日历完整访问
case Permission.location:
return '位置信息';
return 'locationInfo'.tr; // 位置信息
default:
return permission.toString();
}
}
// 获取权限说明文本
String _getExplanationText(Permission permission) {
String getDetailedDescription(Permission permission) {
switch (permission) {
case Permission.phone:
return '拨打电话功能需要电话权限';
return 'phonePermissionDetailDesc'.tr; // 拨打电话功能需要电话权限
case Permission.sms:
return '发送短信功能需要短信权限';
return 'smsPermissionDetailDesc'.tr; // 发送短信功能需要短信权限
case Permission.calendarFullAccess:
return '创建日历事件需要日历写入权限';
return 'calendarWritePermissionDetailDesc'.tr; // 创建日历事件需要日历写入权限
case Permission.calendarFullAccess:
return '管理日历事件需要完整日历权限';
return 'calendarFullAccessPermissionDetailDesc'.tr; // 管理日历事件需要完整日历权限
case Permission.location:
return '获取位置信息需要位置权限';
return 'locationPermissionDetailDesc'.tr; // 获取位置信息需要位置权限
default:
return '应用需要此权限以提供完整功能';
return 'appNeedsPermissionForFullFunction'.tr; // 应用需要此权限以提供完整功能
}
}
}

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

@ -214,7 +214,7 @@ class SettingsView extends GetView<SettingsController> {
// SizedBox(width: 8.w),
// Flexible(
// child: Text(
// '${'joinDevice'.tr} DeepSound Pro', // 已连接设备:
// '${'joinDevice'.tr} DeapSound Pro', // 已连接设备:
// style: TextStyle(
// fontSize: 12.sp,
// color: isDarkMode
@ -374,18 +374,18 @@ class SettingsView extends GetView<SettingsController> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
child: Text(
'systemSettings'.tr, // 系统设置
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
letterSpacing: 1,
),
),
),
// Padding(
// padding: EdgeInsets.only(left: 4.w, bottom: 8.h),
// child: Text(
// 'systemSettings'.tr, // 系统设置
// style: TextStyle(
// fontSize: 12.sp,
// fontWeight: FontWeight.w500,
// color: isDarkMode ? Colors.blue[400] : Colors.blue[600],
// letterSpacing: 1,
// ),
// ),
// ),
Container(
decoration: BoxDecoration(
color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white,
@ -503,11 +503,11 @@ class SettingsView extends GetView<SettingsController> {
? Colors.white.withOpacity(0.1)
: Colors.grey[200]),
// 清除配对设备
// 配对设备管理
_buildSimpleNavigationSetting(
title: 'deviceManagement'.tr, // 设备管理
subtitle: 'manageConnectedDevices'.tr, // 管理已绑定的蓝牙设备
icon: Icons.settings_bluetooth,
icon: Icons.device_hub,
iconBgColor: isDarkMode
? Colors.red[900]!.withOpacity(0.3)
: Colors.red[100]!,
@ -813,7 +813,7 @@ class SettingsView extends GetView<SettingsController> {
child: Column(
children: [
Text(
'© 2025 DeepSound Technologies',
'© 2025 DeapSound Technologies',
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[500],

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

@ -105,7 +105,7 @@ class SplashView extends GetView<SplashController> {
child: Padding(
padding: EdgeInsets.only(top: 24.h),
child: Text(
'DeepSound',
'DeapSound',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,

2
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt

@ -277,7 +277,7 @@ class BleMediaService : Service(), CoroutineScope {
// 构建通知
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("DeepSound")
.setContentTitle("DeapSound")
.setContentText("语音助手代理服务运行中")
.setSmallIcon(android.R.drawable.ic_dialog_info)

2
local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt

@ -178,7 +178,7 @@ class MusicService : MediaBrowserServiceCompat() {
instance = this
isRunning.set(true)
setupMediaSession()
startForeground(NOTIFICATION_ID, createNotification("等待播放","DeepSound",""))
startForeground(NOTIFICATION_ID, createNotification("等待播放","DeapSound",""))
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
// 注册广播监听器

Loading…
Cancel
Save