From a2a209000a5a55b1767520bc9c2fce931bd610f6 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Tue, 9 Dec 2025 12:36:21 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dopus=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=8D=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ble_service/BleCommandSender.kt | 27 +---------------- .../yunqiinnovation/ble_service/BleService.kt | 29 +++++++------------ 2 files changed, 11 insertions(+), 45 deletions(-) diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCommandSender.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCommandSender.kt index fba29431d..d91351069 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCommandSender.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCommandSender.kt @@ -85,17 +85,6 @@ class BleCommandSender { */ fun notifyWakeupSignalReceived() - /** - * 获取录音文件对象 - * @return 录音文件对象 - */ - fun getRecordFile(): RecordingFile? - - /** - * 获取重新压缩录音文件对象 - * @return 重新压缩录音文件对象 - */ - fun getRecordFile1(): RecordingFile? } private var callback: CommandSenderCallback? = null @@ -382,21 +371,7 @@ class BleCommandSender { else -> "未知状态($codecStatus)" } - // 处理录音文件 - if (codecStatus == BleConst.CODEC_CONTROL_DECODE_ON || - codecStatus == BleConst.CODEC_CONTROL_A2DP_PLAY || - codecStatus == BleConst.CODEC_CONTROL_CALL_RECORD_PLAY || - codecStatus == BleConst.CODEC_CONTROL_ENCODE_ON - ) { - callback?.getRecordFile1()?.closeFile() - callback?.getRecordFile1()?.creatingFiles() - callback?.getRecordFile()?.closeFile() - callback?.getRecordFile()?.creatingFiles() - } else if (codecStatus == BleConst.CODEC_CONTROL_CLOSE) { - callback?.getRecordFile()?.closeFile() - callback?.getRecordFile1()?.closeFile() - } - + Log.d(TAG, "收到设备响应,channelMode: $channelMode") // 声道模式描述 diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt index 1fc62da1b..10378a4f2 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt @@ -212,10 +212,10 @@ object BleService { scanHandler = Handler(Looper.getMainLooper()) recordfile = RecordingFile(this.context) - recordfile!!.fileName = "不拆分" + recordfile!!.fileName = "耳机端" recordfile1 = RecordingFile(this.context) - recordfile1!!.fileName = "重新压缩" + recordfile1!!.fileName = "手机端" // 初始化Opus音频管理器 if (!opusAudioManager.initialize()) { @@ -325,19 +325,7 @@ object BleService { this@BleService.notifyWakeupSignalReceived() } - /** - * 获取录音文件实例 - */ - override fun getRecordFile(): RecordingFile? { - return recordfile - } - - /** - * 获取录音文件实例1 - */ - override fun getRecordFile1(): RecordingFile? { - return recordfile1 - } + }) } @@ -875,14 +863,14 @@ object BleService { // 统计接收到的字节数 bytesReceivedInCurrentSecond += data.size processAudioData(data) - Log.i(TAG, "lxm--收到音频特征数据, 字节数=${data.size}") + // Log.i(TAG, "lxm--收到音频特征数据, 字节数=${data.size}") } BleConst.CALL_RECEIVE_AUDIO_CHAR_UUID -> { // 统计接收到的字节数 bytesReceivedInCurrentSecond += data.size processAudioData(data) - Log.i(TAG, "lxm--收到通话音频特征数据, 字节数=${data.size}") + //Log.i(TAG, "lxm--收到通话音频特征数据, 字节数=${data.size}") } // 通知特征数据(命令和控制) BleConst.NOTIFY_CHAR_UUID -> { @@ -1119,6 +1107,8 @@ object BleService { sampleRate: Int = 16000, packetSize: Int = 40 ): Boolean { + recordfile?.creatingFiles(); + return opusAudioManager.startDecodeStream(hasHeader, channel, sampleRate, packetSize) } @@ -1204,6 +1194,7 @@ object BleService { if (audioChunk != null) { // 发送音频数据块并等待回调 + recordfile1?.saveAudioDataToWav(audioChunk) sendAudioChunkWithCallback(audioChunk) Thread.sleep(AUDIO_SEND_INTERVAL) } @@ -1259,7 +1250,7 @@ object BleService { isWaitingForWriteCallback = true callWriteChar?.value = chunk - recordfile1?.saveAudioDataToWav(chunk) + //recordfile1?.saveAudioDataAsUtf8Hex(chunk, true) val isSuccess = bluetoothGatt?.writeCharacteristic(callWriteChar) @@ -1439,7 +1430,7 @@ object BleService { fun openA2DPDecoder(channelMode: Int = BleConst.AUDIO_CHANNEL_STEREO): Boolean { Log.i(TAG, "打开A2DP解码器...") startOpusEncodeStream() - + recordfile1?.creatingFiles(); startOpusStreamDecoding(false, 2, 16000, 80) val cmdData = byteArrayOf( BleConst.CODEC_CONTROL_A2DP_PLAY.toByte(), From 5548e3bdcf67ca4ceb570ac5e9b8032fcadc0334 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Tue, 9 Dec 2025 15:33:55 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A3=B0=E9=9F=B3?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/agent_service/AgentServiceImpl.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift index abefc56bc..8db661378 100644 --- a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift +++ b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift @@ -1707,14 +1707,16 @@ class ChatApiStreamCallback: StreamCallback { return } + if (responseBuilder.isEmpty) { //关闭声音 + try agentService.audioPlayer?.stopAwaitSound() + } + responseBuilder += token - if speakResponse && reply && broadcast{ try agentService.azureTtsHelper?.speakStream(sessionid:sessionid,token) // 在开始流式TTS时立即停止气泡音 } if (reply && token != "") { - try agentService.audioPlayer?.stopAwaitSound() try agentService.sendEvent(name: "assistant_token", data: ["sessionid":sessionid,"token": token]) } }catch { From 94cb289f4ccf701adab27d2cdcbec962e3420539 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Mon, 8 Dec 2025 20:01:06 +0800 Subject: [PATCH 3/5] =?UTF-8?q?refactor(=E5=95=86=E5=93=81=E9=A1=B5):=20?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=95=86=E5=93=81=E9=A1=B5=E8=84=9A=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=B9=B6=E6=9B=B4=E6=96=B0=E7=BF=BB=E8=AF=91=E6=96=87?= =?UTF-8?q?=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将商品页脚部分抽离为独立组件 GoodsFooterSection 更新多语言翻译中的版权信息和公司名称 修改 totalCount 为 totalQuota 以保持术语一致 添加内购客服QQ信息显示功能 --- lib/core/translations/language/ar_sa.dart | 3 +- lib/core/translations/language/de_de.dart | 3 +- lib/core/translations/language/en_us.dart | 6 +-- lib/core/translations/language/hi_in.dart | 3 +- lib/core/translations/language/it_it.dart | 3 +- lib/core/translations/language/ko_kr.dart | 3 +- lib/core/translations/language/pt_pt.dart | 3 +- lib/core/translations/language/ru_ru.dart | 3 +- lib/core/translations/language/zh_cn.dart | 8 +-- lib/core/translations/language/zh_hk.dart | 9 ++-- lib/modules/goods/views/goodsai_view.dart | 39 ++------------ lib/modules/goods/views/goodsmeet_view.dart | 51 ++++--------------- lib/modules/goods/views/goodstrans_view.dart | 51 ++++--------------- lib/modules/goods/views/goodsvip_view.dart | 41 ++------------- .../views/widgets/goods_footer_section.dart | 48 +++++++++++++++++ 15 files changed, 92 insertions(+), 182 deletions(-) create mode 100644 lib/modules/goods/views/widgets/goods_footer_section.dart diff --git a/lib/core/translations/language/ar_sa.dart b/lib/core/translations/language/ar_sa.dart index db74d7492..5208c374b 100644 --- a/lib/core/translations/language/ar_sa.dart +++ b/lib/core/translations/language/ar_sa.dart @@ -1188,8 +1188,7 @@ const Map arSA = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/de_de.dart b/lib/core/translations/language/de_de.dart index b07a82736..ccc28727f 100644 --- a/lib/core/translations/language/de_de.dart +++ b/lib/core/translations/language/de_de.dart @@ -909,8 +909,7 @@ const Map deDE = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/en_us.dart b/lib/core/translations/language/en_us.dart index 320bc97ed..15c5c1829 100644 --- a/lib/core/translations/language/en_us.dart +++ b/lib/core/translations/language/en_us.dart @@ -189,7 +189,7 @@ const Map enUS = { // 商品页面(AI/翻译/会议) 'availablePackages': 'Available Packages', 'remainingQuota': 'Remaining Quota', - 'totalCount': 'Total Count', + 'totalQuota': 'Total Quota', 'remaining': 'Remaining', 'featureDescription': 'Feature Description', // AI 功能卡片 @@ -232,8 +232,8 @@ const Map enUS = { // 商品页通用页脚 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'iapCustomerServiceQQLabel': 'IAP customer service QQ: @qq', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // 会议商品页描述 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/hi_in.dart b/lib/core/translations/language/hi_in.dart index 2b7578a1b..187bc6c3e 100644 --- a/lib/core/translations/language/hi_in.dart +++ b/lib/core/translations/language/hi_in.dart @@ -877,8 +877,7 @@ const Map hiIN = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/it_it.dart b/lib/core/translations/language/it_it.dart index 743d63ff3..fece149d3 100644 --- a/lib/core/translations/language/it_it.dart +++ b/lib/core/translations/language/it_it.dart @@ -896,8 +896,7 @@ const Map itIT = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/ko_kr.dart b/lib/core/translations/language/ko_kr.dart index 948a00c07..5067aae43 100644 --- a/lib/core/translations/language/ko_kr.dart +++ b/lib/core/translations/language/ko_kr.dart @@ -813,8 +813,7 @@ const Map koKR = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/pt_pt.dart b/lib/core/translations/language/pt_pt.dart index f3113f40f..4404d9d2b 100644 --- a/lib/core/translations/language/pt_pt.dart +++ b/lib/core/translations/language/pt_pt.dart @@ -898,8 +898,7 @@ const Map ptPT = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/ru_ru.dart b/lib/core/translations/language/ru_ru.dart index a420b6848..95674fdc5 100644 --- a/lib/core/translations/language/ru_ru.dart +++ b/lib/core/translations/language/ru_ru.dart @@ -891,8 +891,7 @@ const Map ruRU = { "guideSmsEnd": "Message sent—voice control is convenient", // Goods pages common footer (placeholders) 'appNameProvider': 'App: VoiTrans · Provided by: VoiTrans', - 'moreInfoViewInSettingsAbout': 'For more info, go to Settings > About', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': diff --git a/lib/core/translations/language/zh_cn.dart b/lib/core/translations/language/zh_cn.dart index 602d29489..2b5504527 100644 --- a/lib/core/translations/language/zh_cn.dart +++ b/lib/core/translations/language/zh_cn.dart @@ -183,7 +183,7 @@ const Map zhCN = { // 商品页面(AI/翻译/会议) 'availablePackages': '可购买套餐', 'remainingQuota': '剩余额度', - 'totalCount': '总次数', + 'totalQuota': '总额度', 'remaining': '剩余', 'featureDescription': '功能说明', // AI 功能卡片 @@ -225,9 +225,9 @@ const Map zhCN = { 'trans_003_desc': '含 1000 次翻译(语音/文本)', // 商品页通用页脚 - 'appNameProvider': '应用名称:VoiTrans · 服务提供:VoiTrans', - 'moreInfoViewInSettingsAbout': '更多信息请前往 设置 > 关于 查看', - 'copyrightVoiTrans': '© 2025 VoiTrans', + 'appNameProvider': '应用名称:Voitrans · 服务提供:Voitrans', + 'iapCustomerServiceQQLabel': '内购商品专属客服QQ:@qq', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // 会议商品页描述 'meetingHeaderDesc1': '录音转写、关键词检索与自动总结,提升会议效率。', diff --git a/lib/core/translations/language/zh_hk.dart b/lib/core/translations/language/zh_hk.dart index b1a13c479..535bb5f11 100644 --- a/lib/core/translations/language/zh_hk.dart +++ b/lib/core/translations/language/zh_hk.dart @@ -835,10 +835,11 @@ const Map zhHK = { "guideSmsInput": "Text Dad: I’ll be home for dinner", "guideSmsSend": "Lily will send the message", "guideSmsEnd": "Message sent—voice control is convenient", - // Goods pages common footer (placeholders) - 'appNameProvider': '應用名稱:VoiTrans · 服務提供:VoiTrans', - 'moreInfoViewInSettingsAbout': '更多信息請前往 設置 > 關於 查看', - 'copyrightVoiTrans': '© 2025 VoiTrans', + + // 商品页通用页脚 + 'appNameProvider': '應用名稱:Voitrans · 服務提供:Voitrans', + 'iapCustomerServiceQQLabel': '內购商品专属客服QQ:@qq', + 'copyrightVoitrans': '© 2025 Voitrans Technologies', // Meeting goods page (placeholders) 'meetingHeaderDesc1': '錄音轉寫、關鍵詞檢索與自動總結,提升會議效率。', diff --git a/lib/modules/goods/views/goodsai_view.dart b/lib/modules/goods/views/goodsai_view.dart index 4926f2049..74dac96bc 100644 --- a/lib/modules/goods/views/goodsai_view.dart +++ b/lib/modules/goods/views/goodsai_view.dart @@ -6,6 +6,7 @@ import '../../../data/models/goods.dart'; import '../../../data/models/user_Info.dart'; import '../controllers/goodsai_controller.dart'; import '../utils/goods_i18n.dart'; +import 'widgets/goods_footer_section.dart'; class GoodsaiView extends GetView { const GoodsaiView({super.key}); @@ -61,7 +62,7 @@ class GoodsaiView extends GetView { SizedBox(height: 16.h), _buildFeaturesSection(isDarkMode), SizedBox(height: 16.h), - _buildFooterSection(isDarkMode), + GoodsFooterSection(isDarkMode: isDarkMode), ], ); } @@ -212,7 +213,7 @@ class GoodsaiView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${'totalCount'.tr}:$totalAi', + '${'totalQuota'.tr}:$totalAi', style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], @@ -334,40 +335,6 @@ class GoodsaiView extends GetView { ); } - Widget _buildFooterSection(bool isDarkMode) { - final subColor = isDarkMode ? Colors.white60 : Colors.grey[600]; - return Padding( - padding: EdgeInsets.symmetric(vertical: 12.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: double.infinity, - child: Divider(color: isDarkMode ? Colors.white24 : Colors.black12), - ), - SizedBox(height: 8.h), - Text( - 'appNameProvider'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'moreInfoViewInSettingsAbout'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'copyrightVoiTrans'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - ], - ), - ); - } - Widget _buildFeatureCard( bool isDarkMode, { required IconData icon, diff --git a/lib/modules/goods/views/goodsmeet_view.dart b/lib/modules/goods/views/goodsmeet_view.dart index b33a36071..a32c306c5 100644 --- a/lib/modules/goods/views/goodsmeet_view.dart +++ b/lib/modules/goods/views/goodsmeet_view.dart @@ -5,6 +5,7 @@ import '../../../data/models/goods.dart'; import '../../../data/models/user_Info.dart'; import '../controllers/goodsmeet_controller.dart'; import '../utils/goods_i18n.dart'; +import 'widgets/goods_footer_section.dart'; class GoodsmeetView extends GetView { const GoodsmeetView({super.key}); @@ -64,7 +65,7 @@ class GoodsmeetView extends GetView { if (index == controller.items.length + 2) { return _buildFeaturesSection(isDarkMode); } - return _buildFooterSection(isDarkMode); + return GoodsFooterSection(isDarkMode: isDarkMode); }, ); }), @@ -195,7 +196,7 @@ class GoodsmeetView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${'totalCount'.tr}:$totalAi', + '${'totalQuota'.tr}:$totalAi', style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], @@ -256,12 +257,12 @@ class GoodsmeetView extends GetView { fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, )), - SizedBox(height: 4.h), - Text(localizedGoodsDesc(item), - style: TextStyle( - fontSize: 12.sp, - color: isDarkMode ? Colors.white70 : Colors.grey[600], - )), + // SizedBox(height: 4.h), + // Text(localizedGoodsDesc(item), + // style: TextStyle( + // fontSize: 12.sp, + // color: isDarkMode ? Colors.white70 : Colors.grey[600], + // )), ], ), ), @@ -429,38 +430,4 @@ class GoodsmeetView extends GetView { ), ); } - - Widget _buildFooterSection(bool isDarkMode) { - final subColor = isDarkMode ? Colors.white60 : Colors.grey[600]; - return Padding( - padding: EdgeInsets.symmetric(vertical: 12.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: double.infinity, - child: Divider(color: isDarkMode ? Colors.white24 : Colors.black12), - ), - SizedBox(height: 8.h), - Text( - 'appNameProvider'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'moreInfoViewInSettingsAbout'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'copyrightVoiTrans'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - ], - ), - ); - } } diff --git a/lib/modules/goods/views/goodstrans_view.dart b/lib/modules/goods/views/goodstrans_view.dart index c7d8fee28..9ac127551 100644 --- a/lib/modules/goods/views/goodstrans_view.dart +++ b/lib/modules/goods/views/goodstrans_view.dart @@ -5,6 +5,7 @@ import '../../../data/models/goods.dart'; import '../../../data/models/user_Info.dart'; import '../controllers/goodstrans_controller.dart'; import '../utils/goods_i18n.dart'; +import 'widgets/goods_footer_section.dart'; class GoodstransView extends GetView { const GoodstransView({super.key}); @@ -63,7 +64,7 @@ class GoodstransView extends GetView { if (index == controller.items.length + 2) { return _buildFeaturesSection(isDarkMode); } - return _buildFooterSection(isDarkMode); + return GoodsFooterSection(isDarkMode: isDarkMode); }, ); }), @@ -194,7 +195,7 @@ class GoodstransView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${'totalCount'.tr}:$totalAi', + '${'totalQuota'.tr}:$totalAi', style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], @@ -255,12 +256,12 @@ class GoodstransView extends GetView { fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, )), - SizedBox(height: 4.h), - Text(localizedGoodsDesc(item), - style: TextStyle( - fontSize: 12.sp, - color: isDarkMode ? Colors.white70 : Colors.grey[600], - )), + // SizedBox(height: 4.h), + // Text(localizedGoodsDesc(item), + // style: TextStyle( + // fontSize: 12.sp, + // color: isDarkMode ? Colors.white70 : Colors.grey[600], + // )), ], ), ), @@ -431,38 +432,4 @@ class GoodstransView extends GetView { ), ); } - - Widget _buildFooterSection(bool isDarkMode) { - final subColor = isDarkMode ? Colors.white60 : Colors.grey[600]; - return Padding( - padding: EdgeInsets.symmetric(vertical: 12.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: double.infinity, - child: Divider(color: isDarkMode ? Colors.white24 : Colors.black12), - ), - SizedBox(height: 8.h), - Text( - 'appNameProvider'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'moreInfoViewInSettingsAbout'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'copyrightVoiTrans'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - ], - ), - ); - } } diff --git a/lib/modules/goods/views/goodsvip_view.dart b/lib/modules/goods/views/goodsvip_view.dart index 94f1c5fb5..4cc881e3b 100644 --- a/lib/modules/goods/views/goodsvip_view.dart +++ b/lib/modules/goods/views/goodsvip_view.dart @@ -5,6 +5,7 @@ import '../../../data/models/goods.dart'; import '../../../data/models/user_Info.dart'; import '../controllers/goodsvip_controller.dart'; import '../utils/goods_i18n.dart'; +import 'widgets/goods_footer_section.dart'; class GoodsvipView extends GetView { const GoodsvipView({super.key}); @@ -68,7 +69,7 @@ class GoodsvipView extends GetView { } } - children.add(_buildFooterSection(isDarkMode)); + children.add(GoodsFooterSection(isDarkMode: isDarkMode)); content = ListView( key: ValueKey(userTick), padding: EdgeInsets.all(16.w), @@ -223,40 +224,6 @@ class GoodsvipView extends GetView { ); } - Widget _buildFooterSection(bool isDarkMode) { - final subColor = isDarkMode ? Colors.white60 : Colors.grey[600]; - return Padding( - padding: EdgeInsets.symmetric(vertical: 12.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: double.infinity, - child: Divider(color: isDarkMode ? Colors.white24 : Colors.black12), - ), - SizedBox(height: 8.h), - Text( - 'appNameProvider'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'moreInfoViewInSettingsAbout'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - SizedBox(height: 4.h), - Text( - 'copyrightVoiTrans'.tr, - textAlign: TextAlign.center, - style: TextStyle(fontSize: 11.sp, color: subColor), - ), - ], - ), - ); - } - Widget _buildTypeHeader(UsageType type, bool isDarkMode) { final titles = { UsageType.AI: 'aiFunction'.tr, @@ -442,7 +409,7 @@ class GoodsvipView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${'totalCount'.tr}:$total', + '${'totalQuota'.tr}:$total', style: TextStyle(fontSize: 12.sp, color: subColor), ), Text( @@ -701,7 +668,7 @@ class GoodsvipView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${'totalCount'.tr}:$total', + '${'totalQuota'.tr}:$total', style: TextStyle(fontSize: 12.sp, color: subColor), ), Text( diff --git a/lib/modules/goods/views/widgets/goods_footer_section.dart b/lib/modules/goods/views/widgets/goods_footer_section.dart new file mode 100644 index 000000000..00a7afabf --- /dev/null +++ b/lib/modules/goods/views/widgets/goods_footer_section.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../../../../data/models/appconfig.dart'; + +class GoodsFooterSection extends StatelessWidget { + final bool isDarkMode; + const GoodsFooterSection({super.key, required this.isDarkMode}); + + @override + Widget build(BuildContext context) { + final subColor = isDarkMode ? Colors.white60 : Colors.grey[600]; + final qq = AppConfig.env('iapCustomerServiceQQ') ?? ''; + return Padding( + padding: EdgeInsets.symmetric(vertical: 12.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: double.infinity, + child: Divider(color: isDarkMode ? Colors.white24 : Colors.black12), + ), + SizedBox(height: 8.h), + Text( + 'appNameProvider'.tr, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 11.sp, color: subColor), + ), + SizedBox(height: 4.h), + if (qq.isNotEmpty) ...[ + Text( + 'iapCustomerServiceQQLabel'.trParams({'qq': qq}), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 11.sp, color: subColor), + ), + SizedBox(height: 4.h), + ], + // SizedBox(height: 4.h), + Text( + 'copyrightVoitrans'.tr, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 11.sp, color: subColor), + ), + ], + ), + ); + } +} From 75c295c101b7b2f090ad249be4fb79db72c95023 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Tue, 9 Dec 2025 15:00:08 +0800 Subject: [PATCH 4/5] =?UTF-8?q?refactor(=E6=97=B6=E9=97=B4=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96):=20=E4=BD=BF=E7=94=A8Duration=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=97=B6=E9=97=B4=E6=A0=BC=E5=BC=8F=E5=8C=96=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=B9=B6=E7=A1=AE=E4=BF=9D=E7=A7=92=E6=95=B0=E9=9D=9E?= =?UTF-8?q?=E8=B4=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了两个视图中的_formatHms方法,使用Duration类进行时间计算,同时添加了对负数的处理,确保时间显示始终有效 --- lib/modules/meeting/views/meeting_home_view.dart | 8 +++++--- .../middleware/views/translation_middleware_view.dart | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/modules/meeting/views/meeting_home_view.dart b/lib/modules/meeting/views/meeting_home_view.dart index bf9cf58e4..36c5d610e 100644 --- a/lib/modules/meeting/views/meeting_home_view.dart +++ b/lib/modules/meeting/views/meeting_home_view.dart @@ -513,9 +513,11 @@ class _MeetingHomeViewState extends State } String _formatHms(int seconds) { - int h = seconds ~/ 3600; - int m = (seconds % 3600) ~/ 60; - int s = seconds % 60; + final sec = seconds < 0 ? 0 : seconds; // 确保秒数非负 + final d = Duration(seconds: sec); + final h = d.inHours; + final m = d.inMinutes.remainder(60); + final s = d.inSeconds.remainder(60); String twoDigits(int n) => n.toString().padLeft(2, '0'); return '${twoDigits(h)}:${twoDigits(m)}:${twoDigits(s)}'; } diff --git a/lib/modules/translation/middleware/views/translation_middleware_view.dart b/lib/modules/translation/middleware/views/translation_middleware_view.dart index 678efb2d5..9e1de5067 100644 --- a/lib/modules/translation/middleware/views/translation_middleware_view.dart +++ b/lib/modules/translation/middleware/views/translation_middleware_view.dart @@ -212,9 +212,11 @@ class TranslationMiddlewareView } String _formatHms(int seconds) { - int h = seconds ~/ 3600; - int m = (seconds % 3600) ~/ 60; - int s = seconds % 60; + final sec = seconds < 0 ? 0 : seconds; // 确保秒数非负 + final d = Duration(seconds: sec); + final h = d.inHours; + final m = d.inMinutes.remainder(60); + final s = d.inSeconds.remainder(60); String twoDigits(int n) => n.toString().padLeft(2, '0'); return '${twoDigits(h)}:${twoDigits(m)}:${twoDigits(s)}'; } From 331dbf756fa9075d5623d5b2f6f5b63947fde2e1 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Tue, 9 Dec 2025 16:23:00 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(BleManager):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=BC=96=E8=A7=A3=E7=A0=81=E5=99=A8=E7=8A=B6=E6=80=81=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加等待状态标志位来正确处理编解码器开关操作,避免状态更新混乱 同时优化翻译控制器中的日志标记和历史记录判空逻辑 --- lib/data/services/ble_manager.dart | 31 +++++++++++++++++-- .../controllers/translation_controller.dart | 7 +++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/lib/data/services/ble_manager.dart b/lib/data/services/ble_manager.dart index 1a1daabd1..357f3ccf3 100644 --- a/lib/data/services/ble_manager.dart +++ b/lib/data/services/ble_manager.dart @@ -202,6 +202,8 @@ class BleManager extends GetxService { final _isCodecActive = false.obs; bool get isCodecActive => _isCodecActive.value; RxBool get isCodecActiveRx => _isCodecActive; + bool _awaitingCodecOpen = false; //是否正在等待编码器打开的成功应答 + bool _awaitingCodecClose = false; //是否正在等待编码器关闭的成功应答 // 订阅 StreamSubscription? _statusSubscription; @@ -267,7 +269,9 @@ class BleManager extends GetxService { state == BleConnectionState.error) { Logger.info('lxm--BLE设备已断开或发生错误'); _isConnected.value = false; - // 更新设备信息Add commentMore actions + _awaitingCodecOpen = false; + _awaitingCodecClose = false; + _isCodecActive.value = false; Logger.info('lxm--断开连接时重置设备信息为0'); _updateDeviceInfoIfNeeded( batteryLevel: 0, @@ -376,7 +380,16 @@ class BleManager extends GetxService { print(" CONTROL_CODEC: $commandId,$data"); final bool codecSuccess = _isCodecControlSuccess(data); - _isCodecActive.value = codecSuccess; // 更新编解码器状态 + if (_awaitingCodecOpen) { + //如果正在等待打开编解码器 + _isCodecActive.value = codecSuccess; // 只在等待打开时更新状态 + _awaitingCodecOpen = false; + } else if (_awaitingCodecClose) { + if (codecSuccess) { + _isCodecActive.value = false; + } + _awaitingCodecClose = false; + } if (codecSuccess) { print("lxm--编解码控制成功 (rawData 第二字节非 0)"); @@ -991,19 +1004,27 @@ class BleManager extends GetxService { /// 打开解码器 Future openDecoder() async { try { + _awaitingCodecOpen = true; + _awaitingCodecClose = false; + _isCodecActive.value = false; return await _bleService.openDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); + _awaitingCodecOpen = false; return false; } } - /// 打开解码器 + /// 打开A2DP解码器 Future openA2DPDecoder() async { try { + _awaitingCodecOpen = true; + _awaitingCodecClose = false; + _isCodecActive.value = false; return await _bleService.openA2DPDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); + _awaitingCodecOpen = false; return false; } } @@ -1021,9 +1042,13 @@ class BleManager extends GetxService { /// 关闭编解码器 Future closeCodec() async { try { + _awaitingCodecOpen = false; + _awaitingCodecClose = true; + _isCodecActive.value = false; return await _bleService.closeCodec(); } catch (e) { Logger.error('关闭编解码器失败: ${e.toString()}'); + _awaitingCodecClose = false; return false; } } diff --git a/lib/modules/translation/controllers/translation_controller.dart b/lib/modules/translation/controllers/translation_controller.dart index 1d0a4c32d..b31f7dbe3 100644 --- a/lib/modules/translation/controllers/translation_controller.dart +++ b/lib/modules/translation/controllers/translation_controller.dart @@ -1008,7 +1008,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { if (event.text.isEmpty) break; //通话模式下:己方语言即为源语言,无需判断 detectedLanguageCode = sourceLanguageCode.value; - Logger.info("处理己方识别完成:${event.text}"); + Logger.info("lxm---处理己方识别完成:${event.text}"); handleFinalResult(event.text); break; @@ -1126,10 +1126,11 @@ class TranslationController extends GetxController with WidgetsBindingObserver { /// 处理最终识别结果 /// [text] 识别的文本 Future handleFinalResult(String text) async { - if (text.isEmpty || translationHistory.isEmpty) return; + if (text.isEmpty) return; // 更新当前项 - if (translationHistory.last.isIntermediate) { + if (translationHistory.isNotEmpty && + translationHistory.last.isIntermediate) { translationHistory.last.sourceText = text; translationHistory.last.isIntermediate = false; translationHistory.refresh();