import 'dart:io'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import '../../../core/utils/logger.dart'; import '../../../core/utils/upload_oss.dart'; import '../usage_stats_service.dart'; import '../db/sqflite_api.dart'; import 'meeting_task_service.dart'; import 'meeting_task_service2.dart'; /// 管理会议音频文件上传服务 class MeetingUploadService extends GetxService { final _taskService = Get.find(); final GetStorage _storage = GetStorage(); RxInt meetingId = 0.obs; RxDouble uploadProgress = 0.0.obs; RxList uploadList = [].obs; bool _isUpload = false; int _handled = 0; //队列处理指针,表示当前循环语句处理的任务数量 @override void onInit() { super.onInit(); _getUploadList(); } void cancelUpload() { _isUpload = false; _handled = 0; uploadList.clear(); _storage.remove("meeting_upload_list"); } void _getUploadList() { uploadList.value = _storage.read("meeting_upload_list") ?? []; executeUpload(); } /// 添加待上传的音频文件 void addUpload( int id, String filePath, String rootDir, { bool isUpload = true, }) async { bool flash = false; int fileSize = 0; try { fileSize = await File(filePath).length(); //获取文件大小 final details = await SqfliteApi.getMeetingDetails(id); final int seconds = (details['seconds'] ?? 0) as int; flash = seconds > 0 && seconds <= 7200; } catch (_) {} _storage.write("meeting_service_type_$id", flash ? 'fast' : 'standard'); uploadList.add({ 'id': id, 'filepath': filePath, 'rootdir': rootDir, 'audiourl': '', 'isTask': false, 'isSpeaker': true, 'language': '', 'prompt': '', 'outline': '', 'useFlashASR': flash, 'fileSizeBytes': fileSize, }); _storage.write("meeting_upload_list", uploadList); if (isUpload) { executeUpload(); } } void executeUpload() async { if (_isUpload) return; _isUpload = true; _handled = 0; while (_handled < uploadList.length) { Map element = uploadList[_handled]; _handled++; if (element['audiourl'].isEmpty) { meetingId.value = element['id']; try { int _sent = 0; int _total = 0; final audiourl = await UploadOss.upload( filepath: element['filepath'], rootDir: element['rootdir'], onSendProgress: (int count, int total) { // uploadProgress.value = count / total; _sent = count; _total = total; uploadProgress.value = total > 0 ? count / total : 0.0; }, ); await SqfliteApi.editMeetingTitle( element['id'], {'audiourl': audiourl}, ); try { // 记录对象存储用量 final svc = Get.isRegistered() ? Get.find() : Get.put(UsageStatsService(), permanent: true); int fileSizeBytes = 0; try { fileSizeBytes = element['fileSizeBytes'] ?? 0; } catch (_) {} final transferred = _total > 0 ? _total : fileSizeBytes; svc.recordMeetingObjectStorage( meetingId: element['id'], storageUrl: audiourl, storageBytes: fileSizeBytes, transferBytes: transferred, uploadTimestamp: DateTime.now().millisecondsSinceEpoch, ); } catch (e) { Logger.w('MeetingOSrecord', '对象存储用量记录失败: ' + e.toString()); } if (element['isTask']) { if (element['useFlashASR'] == true) { final service2 = Get.find(); await service2.addTaskList( element['id'], audiourl, isSpeaker: element['isSpeaker'], language: element['language'], targetLanguage: '', prompt: element['prompt'], outline: element['outline'], ); } else { await _taskService.addTaskList( element['id'], audiourl, '', element['isSpeaker'], element['language'], element['prompt'], element['outline'], ); } } element['audiourl'] = audiourl; uploadProgress.value = 0.0; _storage.write("meeting_upload_list", uploadList); } catch (e) { Logger.error('Upload failed: $e'); } } } meetingId.value = 0; _isUpload = false; } void removeUpload(int id, {bool isDeleteTask = false}) { Map uploadData = uploadList.firstWhere( (element) => element['id'] == id, orElse: () => {}, ); if (uploadData.isNotEmpty) { if (isDeleteTask || uploadData['audiourl'].isNotEmpty) { uploadList.remove(uploadData); _storage.write("meeting_upload_list", uploadList); if (uploadList.isEmpty) { _handled = 0; } } } } }