From 7701c694c74ce740df8fc4e2842ea0bca5d99434 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Sat, 23 May 2026 10:39:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=BC=9A=E8=AE=AE=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=20=E6=9C=8D=E5=8A=A1=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/translations/language/en_us.dart | 6 + lib/core/translations/language/zh_cn.dart | 6 + lib/data/models/appconfig.dart | 2 +- lib/data/models/appconfig_model.dart | 3 + lib/data/models/appconfig_model.g.dart | 2 + .../meeting/meeting_task_service.dart | 7 + .../meeting/meeting_upload_service.dart | 9 + .../meeting_details_controller.dart | 3 + .../meeting/model/transcribe_service.dart | 22 +++ .../bottomSheet/generate_bottom_sheet.dart | 49 ++++- .../transcribe_service_bottom_sheet.dart | 173 ++++++++++++++++++ 11 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 lib/modules/meeting/model/transcribe_service.dart create mode 100644 lib/modules/meeting/views/bottomSheet/transcribe_service_bottom_sheet.dart diff --git a/lib/core/translations/language/en_us.dart b/lib/core/translations/language/en_us.dart index a6bf4f86b..2285cd932 100644 --- a/lib/core/translations/language/en_us.dart +++ b/lib/core/translations/language/en_us.dart @@ -1121,6 +1121,12 @@ const Map enUS = { "originalImage": "Original Image", "sourceLanguage": "Source Language", "targetLanguage": "Target Language", + "transcribeService": "Transcription Service", + "transcribeServiceAuto": "Auto", + "transcribeServiceByteDance": "ByteDance", + "transcribeServiceAli": "Alibaba Cloud", + "transcribeServiceGoogle": "Google", + "transcribeServiceMicrosoft": "Microsoft", "translationTime": "Translation Time", "shareInDevelopment": "Sharing feature under development", diff --git a/lib/core/translations/language/zh_cn.dart b/lib/core/translations/language/zh_cn.dart index 03d97f343..47b3ff101 100644 --- a/lib/core/translations/language/zh_cn.dart +++ b/lib/core/translations/language/zh_cn.dart @@ -1033,6 +1033,12 @@ const Map zhCN = { "originalImage": "原图片", "sourceLanguage": "源语言", "targetLanguage": "目标语言", + "transcribeService": "转写服务", + "transcribeServiceAuto": "自动", + "transcribeServiceByteDance": "字节跳动", + "transcribeServiceAli": "阿里云", + "transcribeServiceGoogle": "谷歌", + "transcribeServiceMicrosoft": "微软", "translationTime": "翻译时间", "shareInDevelopment": "分享功能开发中", diff --git a/lib/data/models/appconfig.dart b/lib/data/models/appconfig.dart index d24941c85..8ce31d29f 100644 --- a/lib/data/models/appconfig.dart +++ b/lib/data/models/appconfig.dart @@ -7,7 +7,7 @@ class AppConfig { // true => 首页/发现页切换为精简布局,新手引导跳过 AI 引导步骤 // false => 保持原有布局 // TODO: 后续接入 BLE PID 判断逻辑,B017 设备连接时自动置 true - static bool hideAiAssistant = true; + static bool hideAiAssistant = false; static late UserGetAppConfigResp config; diff --git a/lib/data/models/appconfig_model.dart b/lib/data/models/appconfig_model.dart index 2353a9444..2fa69bc04 100644 --- a/lib/data/models/appconfig_model.dart +++ b/lib/data/models/appconfig_model.dart @@ -91,6 +91,8 @@ class DBProduct { final String? channel; // 渠道附加数据(JSON 字符串),例如:{"platform_id":"...","platform_key":"...","tui":"..."} final String? channelextra; + // 是否隐藏 AI 助手(由后台按产品配置下发,true 表示该产品不展示 AI 助手) + final bool? hideaiassistant; DBProduct({ required this.id, @@ -108,6 +110,7 @@ class DBProduct { required this.updatepackageaddress, this.channel, this.channelextra, + this.hideaiassistant, }); factory DBProduct.fromJson(Map json) => diff --git a/lib/data/models/appconfig_model.g.dart b/lib/data/models/appconfig_model.g.dart index 5918c025c..31ccb5304 100644 --- a/lib/data/models/appconfig_model.g.dart +++ b/lib/data/models/appconfig_model.g.dart @@ -89,6 +89,7 @@ DBProduct _$DBProductFromJson(Map json) => DBProduct( updatepackageaddress: json['updatepackageaddress'] as String?, channel: json['channel'] as String?, channelextra: json['channelextra'] as String?, + hideaiassistant: json['hideaiassistant'] as bool?, ); Map _$DBProductToJson(DBProduct instance) => { @@ -107,4 +108,5 @@ Map _$DBProductToJson(DBProduct instance) => { 'updatepackageaddress': instance.updatepackageaddress, 'channel': instance.channel, 'channelextra': instance.channelextra, + 'hideaiassistant': instance.hideaiassistant, }; diff --git a/lib/data/services/meeting/meeting_task_service.dart b/lib/data/services/meeting/meeting_task_service.dart index 971a85c5f..b984179d5 100644 --- a/lib/data/services/meeting/meeting_task_service.dart +++ b/lib/data/services/meeting/meeting_task_service.dart @@ -6,6 +6,7 @@ import 'package:get_storage/get_storage.dart'; import '../db/sqflite_api.dart'; import '../network/api.dart'; import '../../models/user_Info.dart'; +import '../../../modules/meeting/model/transcribe_service.dart'; import 'meeting_upload_service.dart'; class MeetingTaskService extends GetxService { @@ -61,6 +62,7 @@ class MeetingTaskService extends GetxService { bool isdistinguishspeaker, int templateid, String tid, + TranscribeService serviceType, ) async { if (audiourl.isEmpty) { Map uploadData = _uploadService.uploadList.firstWhere( @@ -75,6 +77,7 @@ class MeetingTaskService extends GetxService { uploadData['isdistinguishspeaker'] = isdistinguishspeaker; uploadData['templateid'] = templateid; uploadData['tid'] = tid; + uploadData['service_type'] = serviceType.value; } else { await submitTask( id, @@ -83,6 +86,7 @@ class MeetingTaskService extends GetxService { isdistinguishspeaker, templateid, tid, + serviceType, ); } } @@ -94,6 +98,7 @@ class MeetingTaskService extends GetxService { isdistinguishspeaker, templateid, tid, + serviceType, ); } } @@ -105,6 +110,7 @@ class MeetingTaskService extends GetxService { bool isdistinguishspeaker, int templateid, String tid, + TranscribeService serviceType, ) async { await Api.startTaskEchomeet({ 'id': id, @@ -113,6 +119,7 @@ class MeetingTaskService extends GetxService { 'isdistinguishspeaker': isdistinguishspeaker, 'templateid': templateid, 'tid': tid, + 'service_type': serviceType.value, }); final seconds = await _getMeetingSeconds(id); _decrementMeetingIntegral(cost: seconds); diff --git a/lib/data/services/meeting/meeting_upload_service.dart b/lib/data/services/meeting/meeting_upload_service.dart index b3f3f6f6c..917c5e2b3 100644 --- a/lib/data/services/meeting/meeting_upload_service.dart +++ b/lib/data/services/meeting/meeting_upload_service.dart @@ -5,6 +5,7 @@ import 'package:get_storage/get_storage.dart'; import '../../../core/utils/logger.dart'; import '../../../core/utils/upload_oss.dart'; +import '../../../modules/meeting/model/transcribe_service.dart'; import '../network/api.dart'; import '../usage_stats_service.dart'; import '../db/sqflite_api.dart'; @@ -141,6 +142,13 @@ class MeetingUploadService extends GetxService { Logger.w('MeetingOSrecord', '对象存储用量记录失败: $e'); } if (element['isTask']) { + final int? svcVal = element['service_type']; + final TranscribeService svc = svcVal == null + ? TranscribeService.auto + : TranscribeService.values.firstWhere( + (e) => e.value == svcVal, + orElse: () => TranscribeService.auto, + ); await _taskService.submitTask( element['id'], element['formlanguage'], @@ -148,6 +156,7 @@ class MeetingUploadService extends GetxService { element['isdistinguishspeaker'], element['templateid'], element['tid'] ?? '', + svc, ); } element['audiourl'] = audiourl; diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index f92577083..ae0f15803 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -19,6 +19,7 @@ import '../../../data/services/meeting/meeting_upload_service.dart'; import '../../../data/services/network/api.dart'; import '../model/meeting_details_model.dart'; import '../model/meeting_model.dart'; +import '../model/transcribe_service.dart'; /// 会议详情控制器 class MeetingDetailsController extends GetxController @@ -407,6 +408,7 @@ class MeetingDetailsController extends GetxController bool isdistinguishspeaker, int templateid, String tid, + TranscribeService serviceType, ) async { EasyLoading.show(); _everType = 2; @@ -419,6 +421,7 @@ class MeetingDetailsController extends GetxController isdistinguishspeaker, templateid, tid, + serviceType, ); meetingDetails.value.tasktype = 1; meetingDetails.refresh(); diff --git a/lib/modules/meeting/model/transcribe_service.dart b/lib/modules/meeting/model/transcribe_service.dart new file mode 100644 index 000000000..cf7461a40 --- /dev/null +++ b/lib/modules/meeting/model/transcribe_service.dart @@ -0,0 +1,22 @@ +// 与 proto 中 TranscribeService 枚举保持一致 +enum TranscribeService { + unknown(0, 'Unknown'), + byteDance(1, 'ByteDance'), + ali(2, 'Ali'), + auto(3, 'Auto'), + google(4, 'Google'), + microsoft(5, 'Microsoft'); + + const TranscribeService(this.value, this.code); + + final int value; + // 与后台 / env 字段(MeetServers)中保持一致的字符串编码 + final String code; + + static TranscribeService fromCode(String code) { + for (final s in TranscribeService.values) { + if (s.code.toLowerCase() == code.trim().toLowerCase()) return s; + } + return TranscribeService.auto; + } +} diff --git a/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart b/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart index 787a34cfb..949f9c427 100644 --- a/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart +++ b/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart @@ -5,7 +5,9 @@ import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import '../../controllers/meeting_details_controller.dart'; +import '../../model/transcribe_service.dart'; import 'record_language_bottom_sheet.dart'; +import 'transcribe_service_bottom_sheet.dart'; import '../template/template_view.dart'; import '../../../../data/models/user_Info.dart'; import '../../../common/widgets/recharge_dialog.dart'; @@ -30,6 +32,7 @@ class _GenerateBottomSheetState extends State { String _formlanguage = 'zh-CN'; String _tolanguageText = 'chineseSimplified'.tr; // 对应中文:中文普通话(简体) String _tolanguage = 'zh-CN'; + TranscribeService _serviceType = TranscribeService.auto; final Map _icons = { 'auto_stories': Icons.auto_stories, @@ -309,7 +312,6 @@ class _GenerateBottomSheetState extends State { _row( 'targetLanguage'.tr, // 对应中文:目标语言 value: _tolanguageText, - isBorder: false, isDarkMode: isDarkMode, onTap: () { Get.bottomSheet( @@ -332,6 +334,33 @@ class _GenerateBottomSheetState extends State { }); }, ), + if (!widget.isSummarizeAgain) + _row( + 'transcribeService'.tr, // 对应中文:转写服务 + value: _serviceLabel(_serviceType), + isBorder: false, + isDarkMode: isDarkMode, + onTap: () { + Get.bottomSheet( + TranscribeServiceBottomSheet(_serviceType), + isScrollControlled: true, + backgroundColor: isDarkMode + ? Colors.grey[850] + : Colors.grey[100], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(12.r), + ), + ), + ).then((value) { + if (value is TranscribeService) { + setState(() { + _serviceType = value; + }); + } + }); + }, + ), ], ), ), @@ -367,6 +396,7 @@ class _GenerateBottomSheetState extends State { _isSpeaker, _templateData['id'], _templateData['tid'] ?? '', + _serviceType, ); } }, @@ -550,6 +580,23 @@ class _GenerateBottomSheetState extends State { ); } + String _serviceLabel(TranscribeService s) { + switch (s) { + case TranscribeService.auto: + return 'transcribeServiceAuto'.tr; + case TranscribeService.byteDance: + return 'transcribeServiceByteDance'.tr; + case TranscribeService.ali: + return 'transcribeServiceAli'.tr; + case TranscribeService.google: + return 'transcribeServiceGoogle'.tr; + case TranscribeService.microsoft: + return 'transcribeServiceMicrosoft'.tr; + case TranscribeService.unknown: + return s.code; + } + } + Widget _row( String title, { String? value, diff --git a/lib/modules/meeting/views/bottomSheet/transcribe_service_bottom_sheet.dart b/lib/modules/meeting/views/bottomSheet/transcribe_service_bottom_sheet.dart new file mode 100644 index 000000000..eb2ef5c7b --- /dev/null +++ b/lib/modules/meeting/views/bottomSheet/transcribe_service_bottom_sheet.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +import '../../../../data/models/appconfig.dart'; +import '../../model/transcribe_service.dart'; + +class TranscribeServiceBottomSheet extends StatefulWidget { + final TranscribeService selected; + + const TranscribeServiceBottomSheet(this.selected, {super.key}); + + @override + State createState() => + _TranscribeServiceBottomSheetState(); + + // 读取 env 中 MeetServers 字段并解析为可选服务列表(首项始终为 Auto)。 + // env 形如:"ByteDance,Ali,Google,Microsoft" + static List resolveOptions() { + final raw = AppConfig.isInitialized() + ? (AppConfig.env('MeetServers') ?? '') + : ''; + const whitelist = { + TranscribeService.byteDance, + TranscribeService.ali, + TranscribeService.google, + TranscribeService.microsoft, + }; + final result = [TranscribeService.auto]; + for (final part in raw.split(',')) { + final s = TranscribeService.fromCode(part); + if (whitelist.contains(s) && !result.contains(s)) result.add(s); + } + return result; + } +} + +class _TranscribeServiceBottomSheetState + extends State { + late final List _options; + + @override + void initState() { + super.initState(); + _options = TranscribeServiceBottomSheet.resolveOptions(); + } + + String _label(TranscribeService s) { + switch (s) { + case TranscribeService.auto: + return 'transcribeServiceAuto'.tr; // 对应中文:自动 + case TranscribeService.byteDance: + return 'transcribeServiceByteDance'.tr; // 对应中文:字节跳动 + case TranscribeService.ali: + return 'transcribeServiceAli'.tr; // 对应中文:阿里云 + case TranscribeService.google: + return 'transcribeServiceGoogle'.tr; // 对应中文:谷歌 + case TranscribeService.microsoft: + return 'transcribeServiceMicrosoft'.tr; // 对应中文:微软 + case TranscribeService.unknown: + return s.code; + } + } + + @override + Widget build(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + return SafeArea( + top: false, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 10.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'transcribeService'.tr, // 对应中文:转写服务 + style: TextStyle( + fontSize: 16.sp, + color: isDarkMode ? Colors.white : Colors.black87, + fontWeight: FontWeight.bold, + ), + ), + GestureDetector( + onTap: () => Get.back(), + child: Container( + width: 26.w, + height: 26.w, + decoration: BoxDecoration( + color: isDarkMode ? Colors.grey[700] : Colors.white, + borderRadius: BorderRadius.circular(26.r), + ), + child: Icon( + Icons.close, + size: 18.w, + color: isDarkMode ? Colors.grey[300] : Colors.grey[400], + ), + ), + ) + ], + ), + ), + Divider( + height: 1, + color: isDarkMode ? Colors.grey[700] : Colors.grey[300], + ), + Container( + margin: EdgeInsets.symmetric(vertical: 20.w), + constraints: BoxConstraints( + maxHeight: 1.sh - 180.w, + ), + decoration: BoxDecoration( + color: isDarkMode ? const Color(0xFF2D2D2D) : Colors.white, + borderRadius: BorderRadius.circular(8.r), + ), + child: ListView.builder( + itemCount: _options.length, + shrinkWrap: true, + itemBuilder: (BuildContext context, int index) { + return _item(index, _options[index], isDarkMode); + }, + ), + ), + ], + ), + ), + ); + } + + Widget _item(int index, TranscribeService data, bool isDarkMode) { + return GestureDetector( + onTap: () => Get.back(result: data), + child: Padding( + padding: EdgeInsets.only(left: 15.w), + child: Container( + height: 46.w, + padding: EdgeInsets.only(right: 10.w), + decoration: BoxDecoration( + border: index != 0 + ? Border( + top: BorderSide( + color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!, + ), + ) + : null, + ), + child: Row( + children: [ + Expanded( + child: Text( + _label(data), + style: TextStyle( + fontSize: 14.sp, + color: isDarkMode ? Colors.white : Colors.black87, + ), + ), + ), + if (widget.selected == data) + Icon( + Icons.check, + color: isDarkMode ? Colors.white : Colors.black87, + ), + ], + ), + ), + ), + ); + } +}