Browse Source

feat(会议任务): 引入任务聚合器统一管理任务状态与列表

重构会议任务服务架构,新增 MeetingTaskAggregator 服务聚合器,统一管理标准版与极速版任务服务的状态与列表数据:
1. 移除服务间直接状态同步逻辑,改为通过聚合器统一对外暴露状态
2. 新增聚合器服务并在初始绑定中注册
3. 修改各控制器使用聚合器替代直接服务引用
4. 优化极速版服务日志输出为中文
5. 清理冗余的状态同步代码
newdev_shunjiawei
lxm 11 months ago
parent
commit
a913d44c9f
  1. 6
      lib/core/bindings/initial_binding.dart
  2. 105
      lib/data/services/meeting/meeting_task_aggregator.dart
  3. 228
      lib/data/services/meeting/meeting_task_service2.dart
  4. 3
      lib/modules/meeting/controllers/meeting_details_controller.dart
  5. 2
      lib/modules/meeting/controllers/meeting_home_controller.dart
  6. 4
      lib/modules/meeting/views/meeting_home_view.dart

6
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>(() => MeetingTaskService(), fenix: true);
// 会议助手任务服务(极速识别版)
// 会议助手任务服务(极速识别版,2小时内音频)
Get.lazyPut<MeetingTaskService2>(() => MeetingTaskService2(), fenix: true);
// 会议助手任务服务聚合器(统一列表与状态)
Get.lazyPut<MeetingTaskAggregator>(() => MeetingTaskAggregator(),
fenix: true);
// 会议助手总结任务服务
Get.lazyPut<SummaryTaskService>(() => SummaryTaskService(), fenix: true);

105
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<MeetingTaskService>();
final MeetingTaskService2 s2 = Get.find<MeetingTaskService2>();
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<int> 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;
}
}

228
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<MeetingTaskService>();
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<void> _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<MeetingTaskService>();
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<MeetingTaskService>();
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<String, dynamic> 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<void> _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<Map<String, Object?>> 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<MeetingTaskService>();
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<MeetingTaskService>();
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;
}
}

3
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<MeetingTaskAggregator>().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<MeetingTaskAggregator>().clearMeeting();
super.onClose();
}

2
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<MeetingUploadService>();
final meetingTaskService = Get.find<MeetingTaskService>();
final meetingTaskService2 = Get.find<MeetingTaskService2>();
final taskAggregator = Get.find<MeetingTaskAggregator>();
final summaryTaskService = Get.find<SummaryTaskService>();
final AudioPlayer _audioPlayer = AudioPlayer();

4
lib/modules/meeting/views/meeting_home_view.dart

@ -320,8 +320,8 @@ class _MeetingHomeViewState extends State<MeetingHomeView>
: const SizedBox();
}),
Obx(() {
Map taskData =
_controller.meetingTaskService.taskFinishList.firstWhere(
Map taskData = _controller.taskAggregator.taskFinishList
.firstWhere(
(element) => element['id'] == data.id,
orElse: () => {},
);

Loading…
Cancel
Save