From 5481adef7cf06deac8cf0615184fef4b0cdb58df Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Wed, 3 Dec 2025 11:38:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A3=B0=E9=9F=B3=E5=A4=8D?= =?UTF-8?q?=E5=88=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../translation_middleware_controller.dart | 10 ++ .../bindings/voice_replication_binding.dart | 11 ++ .../voice_replication_controller.dart | 5 + .../views/voice_replication_view.dart | 144 ++++++++++++++++++ lib/routes/app_pages.dart | 9 ++ lib/routes/app_routes.dart | 1 + 6 files changed, 180 insertions(+) create mode 100644 lib/modules/voice_replication/bindings/voice_replication_binding.dart create mode 100644 lib/modules/voice_replication/controllers/voice_replication_controller.dart create mode 100644 lib/modules/voice_replication/views/voice_replication_view.dart diff --git a/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart b/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart index 614d8f811..ac7d4dbfa 100644 --- a/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart +++ b/lib/modules/translation/middleware/controllers/translation_middleware_controller.dart @@ -75,6 +75,16 @@ class TranslationMiddlewareController extends GetxController { iconColor: Colors.indigo[500]!, // 主靛 targetRoute: Routes.textTranslation, ), + TranslationOption( + translationId: 'voice_replication', + title: '声音复刻', + icon: Icons.volume_up, + startColor: Colors.pink[400]!, // 粉色 + endColor: Colors.pink[600]!, // 深粉 + iconBgColor: Colors.white, // 白色 + iconColor: Colors.pink[500]!, // 主粉 + targetRoute: Routes.voiceReplication, + ), ]; /// 导航到指定的翻译功能 diff --git a/lib/modules/voice_replication/bindings/voice_replication_binding.dart b/lib/modules/voice_replication/bindings/voice_replication_binding.dart new file mode 100644 index 000000000..d52da42aa --- /dev/null +++ b/lib/modules/voice_replication/bindings/voice_replication_binding.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; + +import '../controllers/voice_replication_controller.dart'; + +class VoiceReplicationBinding extends Bindings { + @override + void dependencies() { + // 注册控制器 + Get.lazyPut(() => VoiceReplicationController()); + } +} diff --git a/lib/modules/voice_replication/controllers/voice_replication_controller.dart b/lib/modules/voice_replication/controllers/voice_replication_controller.dart new file mode 100644 index 000000000..7a44eec0e --- /dev/null +++ b/lib/modules/voice_replication/controllers/voice_replication_controller.dart @@ -0,0 +1,5 @@ +import 'package:get/get.dart'; + +class VoiceReplicationController extends GetxController { + RxString speakerProfileId = ''.obs; +} diff --git a/lib/modules/voice_replication/views/voice_replication_view.dart b/lib/modules/voice_replication/views/voice_replication_view.dart new file mode 100644 index 000000000..db12c694b --- /dev/null +++ b/lib/modules/voice_replication/views/voice_replication_view.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../controllers/voice_replication_controller.dart'; + +class VoiceReplicationView extends GetView { + const VoiceReplicationView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + + return Scaffold( + backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], + appBar: _buildAppBar(isDarkMode), + body: _buildBody(isDarkMode), + ); + } + + // 构建应用栏 + PreferredSizeWidget _buildAppBar(bool isDarkMode) { + return AppBar( + backgroundColor: isDarkMode ? Colors.black : Colors.white, + elevation: 0.5, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + color: isDarkMode ? Colors.white : Colors.black, + size: 20.sp, + ), + onPressed: () => Get.back(), + ), + title: Text( + '声音复刻', + style: TextStyle( + fontSize: 17.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + centerTitle: true, + ); + } + + // 构建主体内容 + Widget _buildBody(bool isDarkMode) { + return ListView( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 15.w), + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 20.w), + margin: EdgeInsets.only(bottom: 15.w), + decoration: BoxDecoration( + color: isDarkMode ? Colors.grey[800] : Colors.white, + borderRadius: BorderRadius.circular(12.w), + boxShadow: [ + BoxShadow( + color: isDarkMode + ? Colors.black.withValues(alpha: 0.2) + : Colors.black.withValues(alpha: 0.05), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + children: [ + Container( + width: 60.w, + height: 60.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.w), + border: Border.all( + color: Colors.grey, + ), + ), + child: Icon( + Icons.voice_chat, + size: 40.w, + ), + ), + Padding( + padding: EdgeInsets.only(top: 20.w, bottom: 10.w), + child: Text( + '复刻你的声音', + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + fontSize: 18.sp, + fontWeight: FontWeight.bold, + ), + ), + ), + Text( + '使用声音复刻可为你生成专属音色档案,在配音、播报与对话中保留你的声音特征,适用于视频解说、虚拟助理、无障碍朗读等场景。', + textAlign: TextAlign.center, + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + fontSize: 14.sp, + ), + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 2.w), + decoration: BoxDecoration( + color: isDarkMode ? Colors.grey[800] : Colors.white, + borderRadius: BorderRadius.circular(12.w), + boxShadow: [ + BoxShadow( + color: isDarkMode + ? Colors.black.withValues(alpha: 0.2) + : Colors.black.withValues(alpha: 0.05), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '开启声音复刻', + style: TextStyle( + color: isDarkMode ? Colors.white : Colors.black87, + fontSize: 16.sp, + ), + ), + Obx( + () => Switch( + value: controller.speakerProfileId.value.isNotEmpty, + onChanged: (bool value) { + controller.speakerProfileId.value = value ? '0' : ''; + }, + ), + ), + ], + ), + ), + ], + ); + } +} diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index a45b799f9..81f7dd385 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -2,6 +2,8 @@ import 'package:get/get.dart'; import '../modules/qqmusic/bindings/qqmusic_playlist_binding.dart'; import '../modules/qqmusic/views/qqmusic_playlist_view.dart'; +import '../modules/voice_replication/bindings/voice_replication_binding.dart'; +import '../modules/voice_replication/views/voice_replication_view.dart'; import '/modules/ble/bindings/ble_binding.dart'; import '../modules/ble/views/ble_view.dart'; @@ -245,6 +247,13 @@ abstract class AppPages { transition: Transition.rightToLeft, transitionDuration: Duration(milliseconds: 250), ), + GetPage( + name: Routes.voiceReplication, + page: () => const VoiceReplicationView(), + binding: VoiceReplicationBinding(), + transition: Transition.rightToLeft, + transitionDuration: Duration(milliseconds: 250), + ), GetPage( name: Routes.settings, page: () => const SettingsView(), diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index 64b3900bf..22253b289 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -16,6 +16,7 @@ abstract class Routes { // 设备管理 static const OTA_UPGRADE = '/ota_upgrade'; // OTA升级 static const timbre = '/timbre'; // 音色设置 + static const voiceReplication = '/voice_replication'; // 声音复刻 static const settings = '/settings'; // 系统设置 static const permissions = '/permissions'; // 权限管理 static const recording = '/recording'; // 录音功能