Browse Source

添加会议助手数据同步

weicu
tanlongsheng 1 year ago
parent
commit
c67293de8c
  1. 85
      lib/core/utils/synchrodata.dart
  2. 52
      lib/data/services/db/sqflite_api.dart
  3. 26
      lib/data/services/network/api.dart
  4. 46
      lib/modules/meeting/controllers/meeting_controller.dart
  5. 37
      lib/modules/meeting/views/meeting_view.dart

85
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;
}
}

52
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<String, Object?> 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,
});
});
}

26
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,
);
}
}

46
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<String> selected = [];
final appDocDir = getApplicationDocumentsDirectory();
//final appopus = getExternalStorageDirectories();
// final directory = Directory(
// '/storage/emulated/0/Android/data/com.yunqiinnovation.deepsound/files');
List<FileSystemEntity> 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<String, dynamic> 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<void> 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<String, Object?> 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();

37
lib/modules/meeting/views/meeting_view.dart

@ -11,27 +11,30 @@ import '../model/meeting_model.dart';
class MeetingView extends GetView<MeetingController> {
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),
),
],
),
),
);
}

Loading…
Cancel
Save