From a913d44c9f2ece2b1b592b28b85fc14c8f5844b6 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Wed, 26 Nov 2025 14:55:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E4=BC=9A=E8=AE=AE=E4=BB=BB=E5=8A=A1):=20?= =?UTF-8?q?=E5=BC=95=E5=85=A5=E4=BB=BB=E5=8A=A1=E8=81=9A=E5=90=88=E5=99=A8?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=AE=A1=E7=90=86=E4=BB=BB=E5=8A=A1=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E4=B8=8E=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构会议任务服务架构,新增 MeetingTaskAggregator 服务聚合器,统一管理标准版与极速版任务服务的状态与列表数据: 1. 移除服务间直接状态同步逻辑,改为通过聚合器统一对外暴露状态 2. 新增聚合器服务并在初始绑定中注册 3. 修改各控制器使用聚合器替代直接服务引用 4. 优化极速版服务日志输出为中文 5. 清理冗余的状态同步代码 --- lib/core/bindings/initial_binding.dart | 6 +- .../meeting/meeting_task_aggregator.dart | 105 ++++++++ .../meeting/meeting_task_service2.dart | 228 ++++++------------ .../meeting_details_controller.dart | 3 + .../controllers/meeting_home_controller.dart | 2 + .../meeting/views/meeting_home_view.dart | 4 +- 6 files changed, 190 insertions(+), 158 deletions(-) create mode 100644 lib/data/services/meeting/meeting_task_aggregator.dart diff --git a/lib/core/bindings/initial_binding.dart b/lib/core/bindings/initial_binding.dart index 3ea94689f..2870209ff 100644 --- a/lib/core/bindings/initial_binding.dart +++ b/lib/core/bindings/initial_binding.dart @@ -12,6 +12,7 @@ import '../../../data/services/speech_impl/azure_ast_service.dart'; import 'package:get/get.dart'; import '../../data/services/meeting/meeting_task_service.dart'; import '../../data/services/meeting/meeting_task_service2.dart'; +import '../../data/services/meeting/meeting_task_aggregator.dart'; import '../../data/services/meeting/meeting_upload_service.dart'; import '../../data/services/novice_guide_service.dart'; import '../../data/services/speech_factory.dart'; @@ -71,8 +72,11 @@ class InitialBinding extends Bindings { // 会议助手任务服务 Get.lazyPut(() => MeetingTaskService(), fenix: true); - // 会议助手任务服务(极速识别版) + // 会议助手任务服务(极速识别版,2小时内音频) Get.lazyPut(() => MeetingTaskService2(), fenix: true); + // 会议助手任务服务聚合器(统一列表与状态) + Get.lazyPut(() => MeetingTaskAggregator(), + fenix: true); // 会议助手总结任务服务 Get.lazyPut(() => SummaryTaskService(), fenix: true); diff --git a/lib/data/services/meeting/meeting_task_aggregator.dart b/lib/data/services/meeting/meeting_task_aggregator.dart new file mode 100644 index 000000000..5de375cda --- /dev/null +++ b/lib/data/services/meeting/meeting_task_aggregator.dart @@ -0,0 +1,105 @@ +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; + +import 'meeting_task_service.dart'; +import 'meeting_task_service2.dart'; + +/// 会议助手任务服务聚合器(统一列表与状态) +class MeetingTaskAggregator extends GetxService { + final GetStorage _storage = GetStorage(); + + final MeetingTaskService s1 = Get.find(); + final MeetingTaskService2 s2 = Get.find(); + + RxList taskFinishList = [].obs; + RxInt tasktype = 1.obs; + int meetingId = 0; + List textList = []; + + Worker? _w1; + Worker? _w2; + Worker? _wTasktype; + + @override + void onInit() { + super.onInit(); + _w1 = ever(s1.taskFinishList, (_) => _rebuild()); + _w2 = ever(s2.taskFinishList, (_) => _rebuild()); + _rebuild(); + } + + void setMeeting(int id) { + meetingId = id; + final String svc = + (_storage.read("meeting_service_type_$id") ?? '').toString(); + final bool isFast = svc == 'fast'; + _wTasktype?.dispose(); + if (isFast) { + _wTasktype = ever(s2.tasktype, (value) { + tasktype.value = value; + if (value == 2) { + textList = s2.textList; + } + }); + } else { + _wTasktype = ever(s1.tasktype, (value) { + tasktype.value = value; + if (value == 2) { + textList = s1.textList; + } + }); + } + } + + void clearMeeting() { + meetingId = 0; + _wTasktype?.dispose(); + _wTasktype = null; + } + + void _rebuild() { + final Set ids = {}; + for (var e in s1.taskFinishList) { + if (e is Map && e['id'] is int) ids.add(e['id'] as int); + } + for (var e in s2.taskFinishList) { + if (e is Map && e['id'] is int) ids.add(e['id'] as int); + } + final List unified = []; + for (final id in ids) { + final String svc = + (_storage.read("meeting_service_type_$id") ?? '').toString(); + final Map a = s1.taskFinishList.firstWhere( + (x) => x['id'] == id, + orElse: () => {}, + ); + final Map b = s2.taskFinishList.firstWhere( + (x) => x['id'] == id, + orElse: () => {}, + ); + int va = a.isNotEmpty ? ((a['tasktype'] ?? 0) as int) : -999; + int vb = b.isNotEmpty ? ((b['tasktype'] ?? 0) as int) : -999; + int v; + if (svc == 'fast') { + if (va != -999 && vb != -999) { + v = va >= vb ? va : vb; + } else { + v = vb != -999 ? vb : va; + } + } else if (svc == 'standard') { + if (va != -999 && vb != -999) { + v = va >= vb ? va : vb; + } else { + v = va != -999 ? va : vb; + } + } else { + if (va == -999 && vb == -999) { + continue; + } + v = va == -999 ? vb : (vb == -999 ? va : (va >= vb ? va : vb)); + } + unified.add({'id': id, 'tasktype': v}); + } + taskFinishList.value = unified; + } +} diff --git a/lib/data/services/meeting/meeting_task_service2.dart b/lib/data/services/meeting/meeting_task_service2.dart index b6b455c43..8a414c076 100644 --- a/lib/data/services/meeting/meeting_task_service2.dart +++ b/lib/data/services/meeting/meeting_task_service2.dart @@ -10,7 +10,7 @@ import '../../../core/utils/logger.dart'; import '../../../core/utils/synchrodata.dart'; import '../deapsound_ai_service.dart'; import 'meeting_upload_service.dart'; -import 'meeting_task_service.dart'; +// 移除标准版服务桥接,改为通过聚合器对外暴露统一状态 import 'summary_task_service.dart'; //火山引擎录音文件识别大模型-极速版 @@ -140,43 +140,31 @@ class MeetingTaskService2 extends GetxService { taskFinishList.add({'id': id, 'tasktype': 1}); _storage.write("meeting_task_list_v2", _taskList); _storage.write("meeting_task_finish_list_v2", taskFinishList); - try { - final s1 = Get.find(); - Map taskFinishData1 = s1.taskFinishList.firstWhere( - (element) => element['id'] == id, - orElse: () => {}, - ); - if (taskFinishData1.isNotEmpty) { - taskFinishData1['tasktype'] = 3; - s1.taskFinishList.refresh(); - } - _storage.write("meeting_task_finish_list", s1.taskFinishList); - } catch (_) {} + // 由聚合器统一对外呈现状态,不直接写入标准版列表 _executeTask(); } void _executeTask() async { if (_isTask) return; _isTask = true; - Logger.debug('Starting task execution. Task count: ${_taskList.length}'); + Logger.debug('开始执行任务,任务数量:${_taskList.length}'); while (_taskList.isNotEmpty) { - Logger.debug('Task execution loop. Remaining tasks: ${_taskList.length}'); + Logger.debug('任务循环执行,剩余任务:${_taskList.length}'); await Future.delayed(const Duration(seconds: 2)); // 创建任务列表的副本,避免在迭代过程中修改原列表 List tasksCopy = List.from(_taskList); for (var element in tasksCopy) { - Logger.debug( - 'Processing task: ${element['id']} with audio: ${element['audiourl']}'); + Logger.debug('处理任务:${element['id']},音频:${element['audiourl']}'); // 检查任务是否仍在列表中(可能已被其他地方移除) if (_taskList.any((task) => task['id'] == element['id'])) { try { await _fileRecognize(element); } catch (e) { - Logger.error('Failed to process task ${element['id']}: $e'); + Logger.error('处理任务失败:${element['id']},错误:$e'); // 确保失败的任务被移除,避免无限循环 _taskList.removeWhere((task) => task['id'] == element['id']); _storage.write("meeting_task_list_v2", _taskList); @@ -185,22 +173,19 @@ class MeetingTaskService2 extends GetxService { await SqfliteApi.editMeeting(element['id'], {'tasktype': 0}); } } else { - Logger.debug( - 'Task ${element['id']} was already removed from task list'); + Logger.debug('任务 ${element['id']} 已从任务列表移除'); } } // 如果没有任务被处理,避免无限循环 if (_taskList.length == tasksCopy.length) { - Logger.warning( - 'No tasks were processed in this iteration. Breaking loop to avoid infinite execution.'); + Logger.warning('本次循环未处理任何任务,为避免无限执行终止循环'); break; } } _isTask = false; - Logger.debug( - 'Task execution completed. Remaining tasks: ${_taskList.length}'); + Logger.debug('任务执行完成,剩余任务:${_taskList.length}'); } void removeTask(int id, {bool isDeleteTask = false}) { @@ -260,9 +245,9 @@ class MeetingTaskService2 extends GetxService { try { // 记录请求详情 - Logger.debug('API Request URL: $_serviceUrl'); - Logger.debug('API Request Headers: $requestHeaders'); - Logger.debug('API Request Body: $requestBody'); + Logger.debug('API 请求地址:$_serviceUrl'); + Logger.debug('API 请求头:$requestHeaders'); + Logger.debug('API 请求体:$requestBody'); final response = await http.post( Uri.parse(_serviceUrl), @@ -270,30 +255,27 @@ class MeetingTaskService2 extends GetxService { body: requestBody, ); - Logger.debug('API Response Status: ${response.statusCode}'); - Logger.debug('API Response Headers: ${response.headers}'); + Logger.debug('API 响应状态码:${response.statusCode}'); + Logger.debug('API 响应头:${response.headers}'); if (response.statusCode != 200) { - Logger.error( - 'Recognition failed with status: ${response.statusCode}, body: ${response.body}'); - throw Exception( - 'Recognition failed with status: ${response.statusCode}'); + Logger.error('识别失败,状态码:${response.statusCode},响应体:${response.body}'); + throw Exception('识别失败,状态码:${response.statusCode}'); } final respDic = jsonDecode(response.body); - Logger.debug('Recognition response: $respDic'); + Logger.debug('识别接口响应:$respDic'); // 检查响应中是否包含资源相关信息 if (respDic.containsKey('resource_id') || respDic.containsKey('model')) { + Logger.debug('资源校验 - 使用的资源ID:volc.bigasr.auc_turbo'); Logger.debug( - 'Resource verification - Resource ID used: volc.bigasr.auc_turbo'); - Logger.debug( - 'Response resource info: ${respDic['resource_id'] ?? respDic['model'] ?? 'Not specified in response'}'); + '响应中的资源信息:${respDic['resource_id'] ?? respDic['model'] ?? '响应未包含'}'); } return respDic; } catch (e) { - Logger.error('Recognition error: ${e.toString()}'); + Logger.error('识别请求异常:${e.toString()}'); rethrow; } } @@ -315,19 +297,18 @@ class MeetingTaskService2 extends GetxService { double parsed = double.parse(timeValue); return parsed.round(); } catch (e) { - Logger.error('Failed to parse time value: $timeValue'); + Logger.error('时间值解析失败:$timeValue'); return 0; } } else { - Logger.error( - 'Unknown time value type: ${timeValue.runtimeType}, value: $timeValue'); + Logger.error('未知的时间值类型:${timeValue.runtimeType},值:$timeValue'); return 0; } } Future _fileRecognize(Map item) async { try { - Logger.debug('Starting recognition for audio: ${item['audiourl']}'); + Logger.debug('开始识别音频:${item['audiourl']}'); // 识别语言选取:若设置了目标输出语言且与录音语言一致,优先让ASR自动识别,避免错配 final String tplLang = (((item['template'] ?? {})['language']) ?? '').toString(); @@ -344,8 +325,8 @@ class MeetingTaskService2 extends GetxService { language: asrLanguage, ); - Logger.debug('Full API response structure: ${respDic.toString()}'); - Logger.debug('Response keys: ${respDic.keys.toList()}'); + Logger.debug('API 全量响应结构:${respDic.toString()}'); + Logger.debug('响应包含的键:${respDic.keys.toList()}'); // 检查响应格式并提取utterances List utterances = []; @@ -354,77 +335,67 @@ class MeetingTaskService2 extends GetxService { if (respDic['result'] != null && respDic['result']['utterances'] != null) { utterances = respDic['result']['utterances']; - Logger.debug( - 'Found utterances in result.utterances: ${utterances.length} items'); + Logger.debug('在 result.utterances 中找到 ${utterances.length} 条语句'); } else if (respDic['resp'] != null && respDic['resp']['utterances'] != null) { utterances = respDic['resp']['utterances']; - Logger.debug( - 'Found utterances in resp.utterances: ${utterances.length} items'); + Logger.debug('在 resp.utterances 中找到 ${utterances.length} 条语句'); } else if (respDic['utterances'] != null) { utterances = respDic['utterances']; - Logger.debug( - 'Found utterances in root.utterances: ${utterances.length} items'); + Logger.debug('在根级 utterances 中找到 ${utterances.length} 条语句'); } else if (respDic['data'] != null && respDic['data']['utterances'] != null) { utterances = respDic['data']['utterances']; - Logger.debug( - 'Found utterances in data.utterances: ${utterances.length} items'); + Logger.debug('在 data.utterances 中找到 ${utterances.length} 条语句'); } else if (respDic['response'] != null && respDic['response']['utterances'] != null) { utterances = respDic['response']['utterances']; - Logger.debug( - 'Found utterances in response.utterances: ${utterances.length} items'); + Logger.debug('在 response.utterances 中找到 ${utterances.length} 条语句'); } else { // 检查是否有错误信息 if (respDic['error'] != null) { - Logger.error('API returned error: ${respDic['error']}'); + Logger.error('接口返回错误:${respDic['error']}'); } else if (respDic['message'] != null) { - Logger.error('API returned message: ${respDic['message']}'); + Logger.error('接口返回消息:${respDic['message']}'); } else { - Logger.error( - 'Unknown response format. Available keys: ${respDic.keys.toList()}'); + Logger.error('未知的响应格式。可用键:${respDic.keys.toList()}'); // 尝试查找任何包含文本的字段 respDic.forEach((key, value) { - Logger.debug( - 'Key: $key, Value type: ${value.runtimeType}, Value: $value'); + Logger.debug('键:$key,值类型:${value.runtimeType},值:$value'); }); } } if (utterances.isNotEmpty) { - Logger.debug('Processing ${utterances.length} utterances'); + Logger.debug('开始处理 ${utterances.length} 条语句'); await _addTextList(item['id'], utterances, item['template']); // 从任务列表中移除已完成的任务 _taskList.removeWhere((element) => element['id'] == item['id']); _storage.write("meeting_task_list_v2", _taskList); - Logger.debug( - 'Recognition completed successfully for item ${item['id']}'); + Logger.debug('音频识别成功,会议ID:${item['id']}'); // 更新UI状态 - 如果是当前会议,触发UI更新 if (item['id'] == meetingId) { tasktype.value = 2; // 转写完成,进入分析阶段 } } else { - Logger.error( - "No utterances found in response. Full response: $respDic"); - print( - '🔥🔥🔥 NO UTTERANCES FOUND - STARTING SILENT AUDIO CHECK 🔥🔥🔥'); - print('=== DEBUGGING SILENT AUDIO DETECTION ==='); - print('Response keys: ${respDic.keys.toList()}'); - print('Response code: ${respDic['code']}'); - print('Response message: ${respDic['message']}'); + Logger.error('响应中未发现语句。完整响应:$respDic'); + Logger.debug('未检测到语句,开始执行无声音频检查'); + Logger.debug('无声音频检测调试信息'); + Logger.debug('响应键列表:${respDic.keys.toList()}'); + Logger.debug('响应代码:${respDic['code']}'); + Logger.debug('响应消息:${respDic['message']}'); // 检查是否为无声音频 bool isSilentAudio = _checkIfSilentAudio(respDic); - print('Silent audio detection result: $isSilentAudio'); + Logger.debug('无声检测结果:$isSilentAudio'); if (isSilentAudio) { - print('=== SILENT AUDIO DETECTED - SETTING TASKTYPE TO -1 ==='); + Logger.debug('检测到无声音频,设置任务类型为 -1'); // 设置无声音频状态 (使用特殊值 -1) await SqfliteApi.editMeeting(item['id'], {'tasktype': -1}); if (item['id'] == meetingId) { - print('Setting tasktype.value to -1 for current meeting'); + Logger.debug('当前会议设置 tasktype.value 为 -1'); tasktype.value = -1; // 无声音频 } @@ -438,32 +409,10 @@ class MeetingTaskService2 extends GetxService { taskFinishList.refresh(); } _storage.write("meeting_task_finish_list_v2", taskFinishList); - try { - final s1 = Get.find(); - Map taskFinishData1 = s1.taskFinishList.firstWhere( - (element) => element['id'] == item['id'], - orElse: () => {}, - ); - if (taskFinishData1.isNotEmpty) { - taskFinishData1['tasktype'] = 0; - s1.taskFinishList.refresh(); - } - _storage.write("meeting_task_finish_list", s1.taskFinishList); - } catch (_) {} - try { - final s1 = Get.find(); - Map taskFinishData1 = s1.taskFinishList.firstWhere( - (element) => element['id'] == item['id'], - orElse: () => {}, - ); - if (taskFinishData1.isNotEmpty) { - taskFinishData1['tasktype'] = -1; - s1.taskFinishList.refresh(); - } - _storage.write("meeting_task_finish_list", s1.taskFinishList); - } catch (_) {} + // 由聚合器统一对外呈现状态,不直接写入标准版列表 + // 由聚合器统一对外呈现状态,不直接写入标准版列表 } else { - Logger.error('Recognition failed for unknown reason'); + Logger.error('识别失败,原因未知'); // 识别失败,更新数据库状态为失败 await SqfliteApi.editMeeting(item['id'], {'tasktype': 0}); if (item['id'] == meetingId) { @@ -487,14 +436,14 @@ class MeetingTaskService2 extends GetxService { _storage.write("meeting_task_list_v2", _taskList); } } catch (e) { - Logger.error('Error occurred in _fileRecognize: ${e.toString()}'); - Logger.error('Stack trace: ${StackTrace.current}'); + Logger.error('文件识别流程发生异常:${e.toString()}'); + Logger.error('堆栈信息:${StackTrace.current}'); // 更新数据库状态为失败 try { await SqfliteApi.editMeeting(item['id'], {'tasktype': 0}); } catch (dbError) { - Logger.error('Failed to update meeting status in database: $dbError'); + Logger.error('数据库更新会议状态失败:$dbError'); } // 出错时也要从任务列表中移除,避免无限重试 @@ -510,7 +459,7 @@ class MeetingTaskService2 extends GetxService { /// 检查是否为无声音频 bool _checkIfSilentAudio(Map response) { - print('Checking if silent audio, response: ${response.toString()}'); + Logger.debug('检查是否为无声音频,响应:${response.toString()}'); // 检查API响应中的错误信息或状态码 // 根据实际API响应格式调整检测逻辑 @@ -518,7 +467,7 @@ class MeetingTaskService2 extends GetxService { // 检查是否有错误码表示无声音频 if (response['code'] != null) { int code = response['code']; - print('Found response code: $code'); + Logger.debug('检测到响应代码:$code'); // 常见的无声音频错误码 if (code == 40001 || code == 40002 || @@ -526,7 +475,7 @@ class MeetingTaskService2 extends GetxService { code == 50001 || code == 50002 || code == 50003) { - print('Detected silent audio by error code: $code'); + Logger.debug('根据错误码判断为无声音频:$code'); return true; } } @@ -534,7 +483,7 @@ class MeetingTaskService2 extends GetxService { // 检查错误消息 if (response['message'] != null) { String message = response['message'].toString().toLowerCase(); - print('Found response message: $message'); + Logger.debug('检测到响应消息:$message'); if (message.contains('silent') || message.contains('no audio') || message.contains('无声') || @@ -543,7 +492,7 @@ class MeetingTaskService2 extends GetxService { message.contains('no speech') || message.contains('audio too short') || message.contains('insufficient audio')) { - print('Detected silent audio by message: $message'); + Logger.debug('根据消息判断为无声音频:$message'); return true; } } @@ -551,7 +500,7 @@ class MeetingTaskService2 extends GetxService { // 检查result中的错误信息 if (response['result'] != null && response['result']['error'] != null) { String error = response['result']['error'].toString().toLowerCase(); - print('Found result error: $error'); + Logger.debug('检测到 result.error:$error'); if (error.contains('silent') || error.contains('no audio') || error.contains('无声') || @@ -559,7 +508,7 @@ class MeetingTaskService2 extends GetxService { error.contains('empty audio') || error.contains('no speech') || error.contains('audio too short')) { - print('Detected silent audio by result error: $error'); + Logger.debug('根据 result.error 判断为无声音频:$error'); return true; } } @@ -567,10 +516,10 @@ class MeetingTaskService2 extends GetxService { // 检查是否有音频时长信息且时长为0或极短 if (response['result'] != null && response['result']['duration'] != null) { double duration = (response['result']['duration'] as num).toDouble(); - print('Found audio duration: $duration seconds'); + Logger.debug('检测到音频时长:$duration 秒'); if (duration <= 0.5) { // 音频时长小于0.5秒认为是无声 - print('Detected silent audio by short duration: $duration'); + Logger.debug('根据时长过短判断为无声音频:$duration'); return true; } } @@ -618,10 +567,10 @@ class MeetingTaskService2 extends GetxService { 1000; // 转换为秒 } - print('Found empty text content, audio duration: $audioDuration seconds'); + Logger.debug('文本内容为空,音频时长:$audioDuration 秒'); if (audioDuration > 1.0) { // 音频时长大于1秒但没有文本内容,认为是无声音频 - print('Detected silent audio: empty text with sufficient duration'); + Logger.debug('判断为无声音频:文本为空且时长充足'); return true; } } @@ -637,25 +586,25 @@ class MeetingTaskService2 extends GetxService { // 如果有成功状态码但没有utterances,很可能是无声音频 if (hasSuccessCode) { - print('Detected silent audio: success code but no utterances'); + Logger.debug('判断为无声音频:成功状态码但无语句'); return true; } } - print('Not detected as silent audio'); + Logger.debug('未判定为无声音频'); return false; } Future _addTextList(int id, List utterances, [Map? templateData]) async { - Logger.debug('Processing ${utterances.length} utterances for meeting $id'); + Logger.debug('处理会议 $id 的 ${utterances.length} 条语句'); String text = ''; String personnel = ''; List> list = []; for (int i = 0; i < utterances.length; i++) { var element = utterances[i]; - Logger.debug('Processing utterance $i: ${element.toString()}'); + Logger.debug('处理第 $i 条语句:${element.toString()}'); String speaker = ''; String content = ''; @@ -681,7 +630,7 @@ class MeetingTaskService2 extends GetxService { } else if (element['transcript'] != null) { content = element['transcript'].toString(); } else { - Logger.error('No text content found in utterance: $element'); + Logger.error('语句中未找到文本内容:$element'); continue; } @@ -718,11 +667,10 @@ class MeetingTaskService2 extends GetxService { }); text += '$content\n'; - Logger.debug( - 'Added utterance: speaker=$speaker, content=$content, start=$startTime, end=$endTime'); + Logger.debug('已添加语句:说话人=$speaker,内容=$content,开始=$startTime,结束=$endTime'); } - Logger.debug('Total processed utterances: ${list.length}'); + Logger.debug('处理完成的语句总数:${list.length}'); var result = await SqfliteApi.insertMeetingSpeaker(list); if (result != null) { // 初始用于总结/概览的文本,先用原始拼接文本作为默认值 @@ -748,7 +696,7 @@ class MeetingTaskService2 extends GetxService { // 保持在“正在转写”状态,先进行翻译为目标语言 await _translateTextList(id, targetLanguage); } catch (e) { - Logger.error('Translate transcript failed: ${e.toString()}'); + Logger.error('转写文本翻译失败:${e.toString()}'); } // 翻译完成后再写入 personnel、设置已完成并刷新 UI await SqfliteApi.editMeeting( @@ -763,38 +711,8 @@ class MeetingTaskService2 extends GetxService { textList = newSpeakerList; tasktype.value = 2; } - try { - final s1 = Get.find(); - if (id == s1.meetingId) { - s1.textList = newSpeakerList; - s1.tasktype.value = 2; - } - Map taskFinishData1 = s1.taskFinishList.firstWhere( - (element) => element['id'] == id, - orElse: () => {}, - ); - if (taskFinishData1.isNotEmpty) { - taskFinishData1['tasktype'] = 2; - s1.taskFinishList.refresh(); - } - _storage.write("meeting_task_finish_list", s1.taskFinishList); - } catch (_) {} - try { - final s1 = Get.find(); - if (id == s1.meetingId) { - s1.textList = newSpeakerList; - s1.tasktype.value = 2; - } - Map taskFinishData1 = s1.taskFinishList.firstWhere( - (element) => element['id'] == id, - orElse: () => {}, - ); - if (taskFinishData1.isNotEmpty) { - taskFinishData1['tasktype'] = 2; - s1.taskFinishList.refresh(); - } - _storage.write("meeting_task_finish_list", s1.taskFinishList); - } catch (_) {} + // 由聚合器统一对外呈现状态,不直接写入标准版列表 + // 由聚合器统一对外呈现状态,不直接写入标准版列表 // 用最新(已翻译)的文本重建总结/概览输入 summarySourceText = ''; for (var element in newSpeakerList) { @@ -967,7 +885,7 @@ class MeetingTaskService2 extends GetxService { final obj = jsonDecode(translated); arr = (obj is Map && obj['data'] is List) ? (obj['data'] as List) : []; } catch (e) { - Logger.error('Parse translation JSON failed: ${e.toString()}'); + Logger.error('翻译结果 JSON 解析失败:${e.toString()}'); return; } } diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index 96996c26c..b5111338a 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -18,6 +18,7 @@ import '../../../data/services/meeting/meeting_task_service.dart'; import '../../../data/services/meeting/meeting_task_service2.dart'; import '../../../data/services/meeting/meeting_upload_service.dart'; import '../../../data/services/meeting/summary_task_service.dart'; +import '../../../data/services/meeting/meeting_task_aggregator.dart'; import '../model/meeting_details_model.dart'; import '../model/meeting_model.dart'; @@ -100,6 +101,7 @@ class MeetingDetailsController extends GetxController final bool isFast = svc == 'fast'; _meetingTaskService.meetingId = id; _meetingTaskService2.meetingId = id; + Get.find().setMeeting(id); _getDataDetails(); _loadJS(); _tasktypeListener = ever(_meetingTaskService.tasktype, (value) { @@ -141,6 +143,7 @@ class MeetingDetailsController extends GetxController tabController.dispose(); playerController.dispose(); lottieController.dispose(); + Get.find().clearMeeting(); super.onClose(); } diff --git a/lib/modules/meeting/controllers/meeting_home_controller.dart b/lib/modules/meeting/controllers/meeting_home_controller.dart index 9ac1bb6e7..fcea611a4 100644 --- a/lib/modules/meeting/controllers/meeting_home_controller.dart +++ b/lib/modules/meeting/controllers/meeting_home_controller.dart @@ -20,6 +20,7 @@ import 'package:share_plus/share_plus.dart'; import '../../../data/services/meeting/meeting_task_service.dart'; import '../../../data/services/meeting/meeting_task_service2.dart'; +import '../../../data/services/meeting/meeting_task_aggregator.dart'; import '../../../data/services/meeting/meeting_upload_service.dart'; import '../../../data/services/meeting/summary_task_service.dart'; import '../../../routes/app_routes.dart'; @@ -31,6 +32,7 @@ class MeetingHomeController extends GetxController { final meetingUploadService = Get.find(); final meetingTaskService = Get.find(); final meetingTaskService2 = Get.find(); + final taskAggregator = Get.find(); final summaryTaskService = Get.find(); final AudioPlayer _audioPlayer = AudioPlayer(); diff --git a/lib/modules/meeting/views/meeting_home_view.dart b/lib/modules/meeting/views/meeting_home_view.dart index 81cd3b22b..f9a9dd988 100644 --- a/lib/modules/meeting/views/meeting_home_view.dart +++ b/lib/modules/meeting/views/meeting_home_view.dart @@ -320,8 +320,8 @@ class _MeetingHomeViewState extends State : const SizedBox(); }), Obx(() { - Map taskData = - _controller.meetingTaskService.taskFinishList.firstWhere( + Map taskData = _controller.taskAggregator.taskFinishList + .firstWhere( (element) => element['id'] == data.id, orElse: () => {}, );