From 1507b0e3f265a5f1778722beac6cb694def61701 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Fri, 20 Jun 2025 16:40:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BC=9A=E8=AE=AE=E5=8A=A9?= =?UTF-8?q?=E6=89=8B=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/utils/synchrodata.dart | 85 +++++++++++++++++++ lib/data/services/db/sqflite_api.dart | 52 +++--------- lib/data/services/network/api.dart | 26 ++++-- .../controllers/meeting_controller.dart | 46 +++------- lib/modules/meeting/views/meeting_view.dart | 37 ++++---- 5 files changed, 147 insertions(+), 99 deletions(-) create mode 100644 lib/core/utils/synchrodata.dart diff --git a/lib/core/utils/synchrodata.dart b/lib/core/utils/synchrodata.dart new file mode 100644 index 000000000..f8dba5c87 --- /dev/null +++ b/lib/core/utils/synchrodata.dart @@ -0,0 +1,85 @@ +import 'package:get_storage/get_storage.dart'; + +import '../../data/services/network/api.dart'; + +class Synchrodata { + static final GetStorage _storage = GetStorage(); + + static List _records = _storage.read("operation_records") ?? []; + static List _delids = _storage.read("operation_delids") ?? []; + static bool _isSynchro = false; + + // 保存操作记录 + static Future saveOperationRecord( + String method, + dynamic params, + ) async { + String userId = ''; + Map? userInfo = _storage.read("user_info"); + if (userInfo != null) { + userId = userInfo['user']['uid']; + } + String id = '${userId}_${params['id']}'; + if (params['type'] != null) { + params['rtype'] = params['type']; + } + + switch (method) { + case 'insert': + _records.add({ + ...params, + 'id': id, + 'number': params['id'], + 'uid': userId, + }); + _storage.write("operation_records", _records); + break; + case 'update': + Map? foundElement = _records.firstWhere( + (element) => element['id'] == id, + orElse: () => null, + ); + if (foundElement != null) { + foundElement.addAll({ + ...params, + 'id': id, + }); + } else { + _records.add({ + ...params, + 'id': id, + 'number': params['id'], + 'uid': userId, + }); + } + _storage.write("operation_records", _records); + break; + case 'delete': + _delids.add(id); + _storage.write("operation_delids", _delids); + break; + default: + break; + } + } + + // 获取操作记录 + static Future startSynchro() async { + if (_isSynchro) return; + _isSynchro = true; + if (_records.isNotEmpty || _delids.isNotEmpty) { + var result = await Api.putOperationRecord({ + 'delids': _delids, + 'records': _records, + }); + if (result != null) { + _records = []; + _delids = []; + _storage.write("operation_records", _records); + _storage.write("operation_delids", _delids); + } + } + var result = await Api.getOperationRecord(); + _isSynchro = false; + } +} diff --git a/lib/data/services/db/sqflite_api.dart b/lib/data/services/db/sqflite_api.dart index a5f0f1cb3..001931360 100644 --- a/lib/data/services/db/sqflite_api.dart +++ b/lib/data/services/db/sqflite_api.dart @@ -1,49 +1,10 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:get_storage/get_storage.dart'; +import '../../../core/utils/synchrodata.dart'; import 'database_helper.dart'; class SqfliteApi { - // 保存操作记录 - static Future saveMeetingOperationRecord( - String method, - dynamic params, - ) async { - GetStorage storage = GetStorage(); - String userId = ''; - Map? userInfo = storage.read("user_info"); - if (userInfo != null) { - userId = userInfo['user']['uid']; - } - - final db = await DatabaseHelper().database; - String data = ''; - if (method == 'records') { - Map records = { - ...params, - 'id': '${userId}_${params['id']}', - 'number': params['id'], - 'uid': userId, - }; - data = jsonEncode(records); - } else { - data = params; - } - db.insert('operationrecord', { - 'method': method, - 'data': data, - }); - } - - // 操作记录列表 - static Future getMeetingOperationRecord() async { - final db = await DatabaseHelper().database; - return await db.query('operationrecord'); - } - // 获取商务会议助手列表 static Future getMeetingList(int offset) async { final db = await DatabaseHelper().database; @@ -112,6 +73,10 @@ class SqfliteApi { 'summary': '', 'mindmap': '', }); + Synchrodata.saveOperationRecord('insert', { + ...meeting, + 'id': id, + }); }); return id; } catch (e) { @@ -205,6 +170,10 @@ class SqfliteApi { static Future editMeetingTitle(id, Map meeting) async { final db = await DatabaseHelper().database; await db.update('meeting', meeting, where: 'id = ?', whereArgs: [id]); + Synchrodata.saveOperationRecord('update', { + ...meeting, + 'id': id, + }); } // 删除商务会议助手 @@ -216,6 +185,9 @@ class SqfliteApi { .delete('meetingdetails', where: 'meetingid = ?', whereArgs: [id]); await txn .delete('meetingspeaker', where: 'meetingid = ?', whereArgs: [id]); + Synchrodata.saveOperationRecord('delete', { + 'id': id, + }); }); } diff --git a/lib/data/services/network/api.dart b/lib/data/services/network/api.dart index b2f43ac10..e83cbe4e5 100644 --- a/lib/data/services/network/api.dart +++ b/lib/data/services/network/api.dart @@ -44,14 +44,6 @@ class Api { '/api/home/user_setting', params: params, ); - // options: params is dio.FormData - // ? Options( - // headers: { - // 'Content-Type': 'multipart/form-data', - // }, - // ) - // : null, - // ); } //注销账号 @@ -107,4 +99,22 @@ class Api { params: params, ); } + + // 上传会议助手操作记录 + static putOperationRecord([params]) { + return DioManager().request( + NWMethod.post, + '/api/home/record_put', + params: params, + ); + } + + // 获取会议助手数据 + static getOperationRecord([params]) { + return DioManager().request( + NWMethod.post, + '/api/home/record_get', + params: params, + ); + } } diff --git a/lib/modules/meeting/controllers/meeting_controller.dart b/lib/modules/meeting/controllers/meeting_controller.dart index 13e88d22e..e38cba917 100644 --- a/lib/modules/meeting/controllers/meeting_controller.dart +++ b/lib/modules/meeting/controllers/meeting_controller.dart @@ -12,6 +12,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import '../../../core/utils/logger.dart'; +import '../../../core/utils/synchrodata.dart'; import '../../../core/utils/upload_oss.dart'; import '../../../data/services/db/sqflite_api.dart'; import '../../../core/utils/permission_util.dart'; @@ -32,9 +33,6 @@ class MeetingController extends GetxController { List selected = []; final appDocDir = getApplicationDocumentsDirectory(); - //final appopus = getExternalStorageDirectories(); - // final directory = Directory( - // '/storage/emulated/0/Android/data/com.yunqiinnovation.deepsound/files'); List files = []; TextEditingController titleController = TextEditingController(); // 录音标题 @@ -55,7 +53,6 @@ class MeetingController extends GetxController { super.onInit(); listController.addListener(_onScroll); _requestStoragePermission(); - //Permission.storage.request(); _headers = { 'Authorization': 'Bearer; $_token', 'Content-Type': 'application/json', @@ -64,7 +61,7 @@ class MeetingController extends GetxController { addMeetingAudio(); final Map args = Get.arguments ?? {}; // 检查参数是否存在且包含有效路径 - if (args != null && + if (args.isNotEmpty && args.containsKey('filePath') && args['filePath'] is String && args['filePath'].isNotEmpty) { @@ -82,6 +79,10 @@ class MeetingController extends GetxController { super.onClose(); } + void onPopInvokedWithResult(didPop, result) { + Synchrodata.startSynchro(); + } + void _onScroll() { if (isGetMore && !isLoading && @@ -109,11 +110,8 @@ class MeetingController extends GetxController { // 请求存储权限 void _requestStoragePermission() async { - // final BuildContext context = Get.overlayContext!; - PermissionUtil.instance .requestPermission( - // context: context, permissionType: Permission.storage, permissionName: "存储", explanationText: "我们需要访问存储权限,以便您可以选择并上传音频文件。", @@ -124,18 +122,14 @@ class MeetingController extends GetxController { Logger.d("Permission", "用户授予了存储权限"); } else { Logger.d("Permission", "用户未授予存储权限"); - // 可以提示用户无法进行文件操作 } }); } void loadTranslatopus() async { - // final appDir = await appopus; // 先 await 获取目录 final dir = Directory("/data/user/0/com.yunqiinnovation.deepsound/files/OpusAudio"); - print("appDocDir=${dir?.path}"); - files = dir .listSync() .where((f) => f is File && (f.path.endsWith('.opus'))) @@ -147,15 +141,12 @@ class MeetingController extends GetxController { final appDir = await appDocDir; // 先 await 获取目录 final dir = Directory("${appDir.path}/TranslatAudio"); - print("appDocDir=${dir?.path}"); - // Create directory if it doesn't exist if (!await dir.exists()) { - await dir.create(recursive: true); // Create directory tree if needed - files = []; // No files exist in new directory + await dir.create(recursive: true); + files = []; return; } - // Directory exis files = dir .listSync() .where((f) => @@ -168,20 +159,12 @@ class MeetingController extends GetxController { f.path.endsWith('.mov'))) .toList(); } catch (e) { - print("Error loading files: $e"); - files = []; // Return empty list on error + files = []; } } -// 导入音频文件 Future shareAllTranslatAudio() async { final filePath = selected[0]; - // for (final filePath in selected) { - // if (filePath.isEmpty) { - // EasyLoading.showToast('没有可分享的音频文件'); - // return; - // } - // } try { await Share.shareXFiles( [XFile(filePath)], @@ -216,7 +199,7 @@ class MeetingController extends GetxController { final files = await sourceDir.list().where((entity) => entity is File).toList(); - int addQuantity = 0; + int addUp = 0; for (final fileEntity in files) { try { final file = File(fileEntity.path); @@ -225,8 +208,6 @@ class MeetingController extends GetxController { // 设置音频源获取时长 await _audioPlayer.setAudioSource(AudioSource.file(filePath)); - print( - "_audioPlayer$_audioPlayer,filePath=$filePath,_audioPlayer.duration?.inSeconds${_audioPlayer.duration?.inSeconds}"); int seconds = _audioPlayer.duration?.inSeconds ?? 0; // 获取文件修改时间 @@ -251,7 +232,6 @@ class MeetingController extends GetxController { 'tasktype': 0, 'creationtime': creationTime, }; - print("导入数据: $data"); // 插入数据库 final meetingId = await SqfliteApi.insertMeeting(data); @@ -268,12 +248,13 @@ class MeetingController extends GetxController { await file.delete(); addQuantity++; + addUp++; } } catch (e) { print("文件处理失败: ${fileEntity.path}, 错误: $e"); } } - if (addQuantity > 0) EasyLoading.showSuccess('成功导入本地 $addQuantity 条录音'); + if (addUp > 0) EasyLoading.showSuccess('成功导入本地 $addUp 条录音'); } catch (e) { EasyLoading.showError('导入失败: $e'); } finally { @@ -292,7 +273,6 @@ class MeetingController extends GetxController { filepath: filePath, rootDir: 'TranslatAudio'); int seconds = _audioPlayer.duration?.inSeconds ?? 0; final fileName = filePath.split('/').last; - // int creationTime = DateTime.now().millisecondsSinceEpoch; Map data = { 'title': fileName, 'type': 'TRANSLAT', @@ -302,7 +282,6 @@ class MeetingController extends GetxController { 'tasktype': 0, 'creationtime': creationTime, }; - print("data=$data"); final meetingId = await SqfliteApi.insertMeeting(data); if (meetingId != null) { dataList.insert(0, { @@ -314,7 +293,6 @@ class MeetingController extends GetxController { } } catch (e) { Logger.error('导入文件失败: $filePath, error: $e'); - // 可选:继续导入下一个文件 } } EasyLoading.dismiss(); diff --git a/lib/modules/meeting/views/meeting_view.dart b/lib/modules/meeting/views/meeting_view.dart index a20cdd12a..35d34e6d8 100644 --- a/lib/modules/meeting/views/meeting_view.dart +++ b/lib/modules/meeting/views/meeting_view.dart @@ -11,27 +11,30 @@ import '../model/meeting_model.dart'; class MeetingView extends GetView { const MeetingView({super.key}); - static OverlayEntry? _recordingOverlayEntry; + @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; - return Scaffold( - backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], - appBar: _buildAppBar(context, isDarkMode), - body: _buildBody(context, isDarkMode), - floatingActionButton: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - FloatingActionButton( - heroTag: "addAudio", - onPressed: () { - _showAddAudioMenu(context, isDarkMode); - }, - child: const Icon(Icons.add), - ), - ], + return PopScope( + onPopInvokedWithResult: controller.onPopInvokedWithResult, + child: Scaffold( + backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], + appBar: _buildAppBar(context, isDarkMode), + body: _buildBody(context, isDarkMode), + floatingActionButton: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + FloatingActionButton( + heroTag: "addAudio", + onPressed: () { + _showAddAudioMenu(context, isDarkMode); + }, + child: const Icon(Icons.add), + ), + ], + ), ), ); }