From 53435d0707ca854c604840de60dba1b022e11aea Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Wed, 26 Nov 2025 18:56:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(meeting):=20=E4=BF=AE=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E9=87=8F=E7=BB=9F=E8=AE=A1=E6=9C=8D=E5=8A=A1=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 处理用量统计服务可能未注册的情况,添加try-catch捕获异常 在关键操作点添加详细日志记录,便于问题排查 完善会议任务服务中的用量统计功能 --- .../meeting/meeting_task_service.dart | 26 ++++++-- .../meeting/meeting_task_service2.dart | 62 ++++++++++++++++++- lib/data/services/usage_stats_service.dart | 25 ++++++++ 3 files changed, 105 insertions(+), 8 deletions(-) diff --git a/lib/data/services/meeting/meeting_task_service.dart b/lib/data/services/meeting/meeting_task_service.dart index 8dda746b6..3d7886b19 100644 --- a/lib/data/services/meeting/meeting_task_service.dart +++ b/lib/data/services/meeting/meeting_task_service.dart @@ -187,7 +187,14 @@ class MeetingTaskService extends GetxService { transcriptBytes: 0, completeTimestamp: 0, ); - Get.find().addMeetingAsrRecord(record); + try { + final svc = Get.isRegistered() + ? Get.find() + : Get.put(UsageStatsService(), permanent: true); + svc.addMeetingAsrRecord(record); + } catch (e) { + Logger.w('MeetingASRrecord', '提交用量记录失败: ' + e.toString()); + } } catch (_) {} _taskList.add({ 'id': id, @@ -451,11 +458,18 @@ class MeetingTaskService extends GetxService { final details = await SqfliteApi.getMeetingDetails(id); final tid = (details['taskid'] ?? '') as String; final transcriptBytes = utf8.encode(text).length; - Get.find().completeMeetingAsrRecord( - id: tid, - transcriptBytes: transcriptBytes, - completeTimestamp: DateTime.now().millisecondsSinceEpoch, - ); + try { + final svc = Get.isRegistered() + ? Get.find() + : Get.put(UsageStatsService(), permanent: true); + svc.completeMeetingAsrRecord( + id: tid, + transcriptBytes: transcriptBytes, + completeTimestamp: DateTime.now().millisecondsSinceEpoch, + ); + } catch (e) { + Logger.w('MeetingASRrecord', '完成用量记录失败: ' + e.toString()); + } } catch (_) {} // 触发AI分析,分别请求总结和概览 diff --git a/lib/data/services/meeting/meeting_task_service2.dart b/lib/data/services/meeting/meeting_task_service2.dart index 8a414c076..ff69e20ff 100644 --- a/lib/data/services/meeting/meeting_task_service2.dart +++ b/lib/data/services/meeting/meeting_task_service2.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; @@ -8,6 +9,8 @@ import '../db/sqflite_api.dart'; import '../../../data/models/appconfig.dart'; import '../../../core/utils/logger.dart'; import '../../../core/utils/synchrodata.dart'; +import '../usage_stats_service.dart'; +import '../../../data/models/meeting_usage_stats.dart'; import '../deapsound_ai_service.dart'; import 'meeting_upload_service.dart'; // 移除标准版服务桥接,改为通过聚合器对外暴露统一状态 @@ -124,11 +127,45 @@ class MeetingTaskService2 extends GetxService { String prompt = '', String outline = '', }) async { - await SqfliteApi.editMeeting(id, {'tasktype': 1}); + final String taskId = DateTime.now().millisecondsSinceEpoch.toString(); + await SqfliteApi.editMeeting(id, {'tasktype': 1, 'taskid': taskId}); + + try { + final detail = await SqfliteApi.getMeetingDetails(id); + final seconds = (detail['seconds'] ?? 0) as int; + final filepath = (detail['filepath'] ?? '') as String; + int fileSizeBytes = 0; + if (filepath.isNotEmpty) { + try { + fileSizeBytes = await File(filepath).length(); + } catch (_) {} + } + final record = MeetingAsrRecord( + id: taskId, + meetingId: id, + taskId: taskId, + audioSeconds: seconds, + fileSizeBytes: fileSizeBytes, + language: language, + submitTimestamp: DateTime.now().millisecondsSinceEpoch, + status: asrStatusProcessing, + transcriptBytes: 0, + completeTimestamp: 0, + ); + try { + final svc = Get.isRegistered() + ? Get.find() + : Get.put(UsageStatsService(), permanent: true); + svc.addMeetingAsrRecord(record); + } catch (e) { + Logger.w('MeetingASRrecord', '提交用量记录失败: ' + e.toString()); + } + } catch (_) {} _taskList.add({ 'id': id, 'audiourl': audiourl, 'tasktype': 1, + 'taskid': taskId, 'template': { 'isSpeaker': isSpeaker, 'language': language, @@ -209,8 +246,10 @@ class MeetingTaskService2 extends GetxService { String audiourl, { bool enableSpeakerInfo = true, String language = '', + String? requestIdOverride, }) async { - String requestId = DateTime.now().millisecondsSinceEpoch.toString(); + String requestId = + requestIdOverride ?? DateTime.now().millisecondsSinceEpoch.toString(); // 为每次请求生成新的headers - 适配大模型极速版API Map requestHeaders = { @@ -323,6 +362,9 @@ class MeetingTaskService2 extends GetxService { enableSpeakerInfo: (((item['template'] ?? {})['isSpeaker']) ?? false) as bool, language: asrLanguage, + requestIdOverride: (item['taskid'] ?? '').toString().isEmpty + ? null + : (item['taskid'] ?? '').toString(), ); Logger.debug('API 全量响应结构:${respDic.toString()}'); @@ -813,6 +855,22 @@ class MeetingTaskService2 extends GetxService { : (langDesc.isEmpty ? tplOutline : tplOutline + ' 输出语言:' + langDesc + '。请全程使用' + langDesc + '输出。'); + try { + final details = await SqfliteApi.getMeetingDetails(id); + final tid = (details['taskid'] ?? '') as String; + final transcriptBytes = utf8.encode(summarySourceText).length; + final svc = Get.isRegistered() + ? Get.find() + : Get.put(UsageStatsService(), permanent: true); + svc.completeMeetingAsrRecord( + id: tid, + transcriptBytes: transcriptBytes, + completeTimestamp: DateTime.now().millisecondsSinceEpoch, + ); + } catch (e) { + Logger.w('MeetingASRrecord', '完成用量记录失败: ' + e.toString()); + } + _summaryTaskService.addTaskList( id, summarySourceText, promptToUse, outlineToUse); } diff --git a/lib/data/services/usage_stats_service.dart b/lib/data/services/usage_stats_service.dart index fc99643cb..fb0fe792e 100644 --- a/lib/data/services/usage_stats_service.dart +++ b/lib/data/services/usage_stats_service.dart @@ -81,6 +81,8 @@ class UsageStatsService extends GetxService { void _saveMeetingDaily(MeetingAsrDailyStats stats) { _storage.write('${_meetingDailyKey}_${stats.date}', stats.toJson()); + Logger.d('MeetingASRrecord', + '保存会议当日统计: date=${stats.date}, items=${stats.items.length}'); } String _formatDate(DateTime d) { @@ -90,6 +92,10 @@ class UsageStatsService extends GetxService { return '$y-$m-$day'; } + /// 添加或更新会议ASR记录 + /// [record] 会议ASR记录 + /// 该方法用于记录一次会议语音识别(ASR)的提交记录。它会根据记录的时间戳确定日期, + /// 并将记录添加到该日期的会议ASR记录列表中。如果记录已存在,则会更新该记录。 void addMeetingAsrRecord(MeetingAsrRecord record) { final dateKey = _formatDate( DateTime.fromMillisecondsSinceEpoch(record.submitTimestamp)); @@ -97,12 +103,25 @@ class UsageStatsService extends GetxService { final idx = daily.items.indexWhere((e) => e.id == record.id); if (idx >= 0) { daily.items[idx] = record; + Logger.d('MeetingASRrecord', + '更新会议ASR记录: id=${record.id}, meetingId=${record.meetingId}, date=${dateKey}'); } else { daily.items.add(record); + Logger.d('MeetingASRrecord', + '新增会议ASR记录: id=${record.id}, meetingId=${record.meetingId}, date=${dateKey}'); } _saveMeetingDaily(daily); + Logger.i('MeetingASRrecord', + '会议ASR提交: id=${record.id}, meetingId=${record.meetingId}, audioSeconds=${record.audioSeconds}, fileSizeBytes=${record.fileSizeBytes}, language=${record.language}, date=${dateKey}'); } + /// 完成会议ASR记录 + /// [id] 会议ASR记录ID + /// [transcriptBytes] 转写结果文本字节数 + /// [completeTimestamp] 完成时间戳 + /// 该方法用于标记一次会议语音识别(ASR)任务为已完成状态。 + /// 它会根据记录ID在最近3天的会议ASR记录列表中查找匹配项, + /// 如果找到,则更新该记录的状态为已完成,并记录转写结果文本字节数和完成时间戳。 void completeMeetingAsrRecord({ required String id, required int transcriptBytes, @@ -128,6 +147,8 @@ class UsageStatsService extends GetxService { completeTimestamp: completeTimestamp, ); _saveMeetingDaily(daily); + Logger.i('MeetingASRrecord', + '会议ASR完成: id=${id}, meetingId=${old.meetingId}, transcriptBytes=${transcriptBytes}, audioSeconds=${old.audioSeconds}, date=${dateKey}'); return; } } @@ -559,6 +580,8 @@ class UsageStatsService extends GetxService { list.add(daily); } } + Logger.i('MeetingASRrecord', + '获取会议历史统计: start=${_formatDate(startDate)}, end=${_formatDate(endDate)}, 有效天数=${list.length}'); return list; } catch (e) { Logger.error('获取会议历史统计失败: $e'); @@ -578,6 +601,8 @@ class UsageStatsService extends GetxService { audioBytes += d.audioBytesTotal; transcriptBytes += d.transcriptBytesTotal; } + Logger.i('MeetingASRrecord', + '聚合会议统计: calls=${calls}, audioSeconds=${audioSeconds}, audioBytes=${audioBytes}, transcriptBytes=${transcriptBytes}'); return MeetingAsrHistoryStats( userId: getCurrentUserId(), allAsrCalls: calls,