Browse Source

refactor(meeting): 重构音频导入逻辑并改进日志记录

- 将print语句替换为Logger进行统一日志管理
- 重构addMeetingAudio方法,添加详细注释并优化文件处理流程
- 新增_archiveTranslatToLocal方法处理翻译音频归档
- 改进addTranslatAudio方法,支持可选归档到LocalAudio目录
- 为控制器类添加文档注释
newdev_shunjiawei
lxm 11 months ago
parent
commit
61a6746e56
  1. 1
      lib/data/services/meeting/meeting_upload_service.dart
  2. 1
      lib/modules/meeting/controllers/meeting_details_controller.dart
  3. 130
      lib/modules/meeting/controllers/meeting_home_controller.dart
  4. 1
      lib/modules/meeting/controllers/mind_map_controller.dart
  5. 8
      lib/modules/translation/controllers/translation_list_controller.dart

1
lib/data/services/meeting/meeting_upload_service.dart

@ -29,6 +29,7 @@ class MeetingUploadService extends GetxService {
executeUpload();
}
/// 添加待上传的音频文件
void addUpload(
int id,
String filePath,

1
lib/modules/meeting/controllers/meeting_details_controller.dart

@ -18,6 +18,7 @@ import '../../../data/services/meeting/meeting_upload_service.dart';
import '../model/meeting_details_model.dart';
import '../model/meeting_model.dart';
/// 会议详情控制器
class MeetingDetailsController extends GetxController
with GetTickerProviderStateMixin {
late TabController tabController;

130
lib/modules/meeting/controllers/meeting_home_controller.dart

@ -41,7 +41,7 @@ class MeetingHomeController extends GetxController {
RxList originalDataList = [].obs;
RxList dataList = [].obs;
RxString filtrateType = ''.obs;
bool isAsc = false;
bool isAsc = false; // 是否升序排序
TextEditingController filtrateController = TextEditingController();
// 蓝牙服务
@ -178,15 +178,16 @@ class MeetingHomeController extends GetxController {
}
}
// 核心方法:导入本地录音文件到统一目录
void addMeetingAudio() async {
EasyLoading.show(status: 'importingLocalRecordings'.tr); // 对应中文:正在导入本地录音...
try {
int addUp = 0;
final appDir = await appDocDir;
int addUp = 0; // 新增计数
final appDir = await appDocDir; // 获取应用文档目录
final sourceDirs = [
Directory("${appDir.path}/MeetingAudio/"),
Directory("${appDir.path}/DestAudio/"),
Directory("${appDir.path}/MeetingAudio/"), // 会议录音目录
Directory("${appDir.path}/DestAudio/"), // 目标录音目录
];
// 目标目录:LocalAudio
@ -200,31 +201,33 @@ class MeetingHomeController extends GetxController {
for (final dir in sourceDirs) {
if (await dir.exists()) {
//遍历每个源目录,筛选出文件实体(仅包含文件,不包含子目录)
final files =
await dir.list().where((entity) => entity is File).toList();
allFiles.addAll(files);
allFiles.addAll(files); //合并到总文件列表
}
}
// 遍历所有文件实体
for (final fileEntity in allFiles) {
try {
final file = File(fileEntity.path);
final file = File(fileEntity.path); //将文件实体转换为具体文件操作对象
final filePath = file.path;
// 设置音频源获取时长
// 使用just_audio库加载音频文件以获取时长
await _audioPlayer.setAudioSource(AudioSource.file(filePath));
int seconds = _audioPlayer.duration?.inSeconds ?? 0;
int seconds =
_audioPlayer.duration?.inSeconds ?? 0; //获取音频时长(秒),若为空则设为0
// 获取文件修改时间
final fileStat = await file.stat();
final fileStat = await file.stat(); //获取文件状态信息,包含修改时间等
final creationTime = fileStat.changed.millisecondsSinceEpoch;
// 准备新路径
final fileName = filePath.split('/').last;
final newPath = "${destDir.path}/$fileName";
final fileName = filePath.split('/').last; //获取文件名(包含扩展名)
final newPath = "${destDir.path}/$fileName"; //构建新路径,保持原文件名
// 构建数据
// 构建要存入数据库的音频文件抽象对象
Map<String, Object?> data = {
'title': fileName,
'type': 'LOCAL',
@ -238,7 +241,7 @@ class MeetingHomeController extends GetxController {
// 插入数据库
final meetingId = await SqfliteApi.insertMeeting(data);
if (meetingId != null) {
// 上传OSS
// 安排后台上传任务
meetingUploadService.addUpload(meetingId, newPath, 'LocalAudio');
originalDataList.insert(0, {
@ -259,8 +262,8 @@ class MeetingHomeController extends GetxController {
}
// 移动文件
await file.copy(newPath);
await file.delete();
await file.copy(newPath); // 复制到新路径
await file.delete(); // 删除原文件
addUp++;
}
@ -272,10 +275,11 @@ class MeetingHomeController extends GetxController {
e.toString())); // 对应中文:文件处理失败: {filePath}, 错误: {error}
}
}
if (addUp > 0)
if (addUp > 0) {
EasyLoading.showSuccess('importSuccess'
.tr
.replaceAll('{count}', '$addUp')); // 对应中文:成功导入本地 {count} 条录音
}
} catch (e) {
EasyLoading.showError('importError'
.tr
@ -285,50 +289,88 @@ class MeetingHomeController extends GetxController {
}
}
void addTranslatAudio() async {
// 新增:将翻译音频归档到 LocalAudio 并返回新路径(优先 rename,失败再 copy+delete)
Future<String> _archiveTranslatToLocal(String srcPath) async {
// 中文注释:获取应用文档目录并确保 LocalAudio 目录存在
final appDir = await appDocDir;
final destDir = Directory(path.join(appDir.path, 'LocalAudio'));
if (!await destDir.exists()) {
await destDir.create(recursive: true);
}
// 中文注释:目标文件名与路径,处理重名冲突
final fileName = path.basename(srcPath);
final baseName = path.basenameWithoutExtension(fileName);
final ext = path.extension(fileName);
String destPath = path.join(destDir.path, fileName);
if (await File(destPath).exists()) {
final ts = DateTime.now().millisecondsSinceEpoch;
destPath = path.join(destDir.path, '$baseName\_$ts$ext');
}
// 中文注释:尝试 rename(更快),失败则 copy + delete
final srcFile = File(srcPath);
try {
await srcFile.rename(destPath);
return destPath;
} catch (_) {
await srcFile.copy(destPath);
await srcFile.delete();
return destPath;
}
}
// 修改:翻译音频导入支持归档到 LocalAudio(智能转写默认归档以隐藏原翻译目录)
void addTranslatAudio({bool archiveToLocal = true}) async {
EasyLoading.show(status: 'batchImporting'.tr); // 对应中文:正在批量导入...
for (final filePath in selected) {
for (final originalPath in selected) {
try {
await _audioPlayer.setAudioSource(AudioSource.file(filePath));
final fileStat = await File(filePath).stat();
final creationTime = fileStat.changed.millisecondsSinceEpoch; // 时间戳
int seconds = _audioPlayer.duration?.inSeconds ?? 0;
final fileName = filePath.split('/').last;
Map<String, Object?> data = {
// 中文注释:根据开关决定是否将翻译音频迁移到 LocalAudio
final usePath =
archiveToLocal ? await _archiveTranslatToLocal(originalPath) : originalPath;
// 中文注释:计算音频时长与创建时间
await _audioPlayer.setAudioSource(AudioSource.file(usePath));
final fileStat = await File(usePath).stat();
final creationTime = fileStat.changed.millisecondsSinceEpoch;
final seconds = _audioPlayer.duration?.inSeconds ?? 0;
final fileName = path.basename(usePath);
// 中文注释:归档则统一标记为 LOCAL,未归档则保留 TRANSLAT
final String recordType = archiveToLocal ? 'LOCAL' : 'TRANSLAT';
// 中文注释:写入数据库
final Map<String, Object?> data = {
'title': fileName,
'type': 'TRANSLAT',
'type': recordType,
'seconds': seconds,
'filepath': filePath,
'filepath': usePath,
'audiourl': '',
'tasktype': 0,
'creationtime': creationTime,
};
final meetingId = await SqfliteApi.insertMeeting(data);
if (meetingId != null) {
meetingUploadService.addUpload(meetingId, filePath, 'TranslatAudio');
// 中文注释:上传分类按目录区分
final uploadBucket = archiveToLocal ? 'LocalAudio' : 'TranslatAudio';
meetingUploadService.addUpload(meetingId, usePath, uploadBucket);
originalDataList.insert(0, {
'id': meetingId,
...data,
});
// 中文注释:更新列表(保持现有排序逻辑)
final record = {'id': meetingId, ...data};
originalDataList.insert(0, record);
if (isAsc) {
dataList.add({
'id': meetingId,
...data,
});
dataList.add(record);
} else {
dataList.insert(0, {
'id': meetingId,
...data,
});
dataList.insert(0, record);
}
}
} catch (e) {
Logger.error('importFailed'
.tr
.replaceAll('{filePath}', filePath)
.replaceAll('{error}',
e.toString())); // 对应中文:导入文件失败: {filePath}, error: {error}
.replaceAll('{filePath}', originalPath)
.replaceAll('{error}', e.toString())); // 对应中文:导入文件失败: {filePath}, error: {error}
}
}
EasyLoading.dismiss();

1
lib/modules/meeting/controllers/mind_map_controller.dart

@ -12,6 +12,7 @@ import 'package:webview_flutter/webview_flutter.dart';
import 'meeting_details_controller.dart';
/// 思维导图控制器
class MindMapController extends GetxController {
late final WebViewController webViewController;
final _meetingDetailsController = Get.find<MeetingDetailsController>();

8
lib/modules/translation/controllers/translation_list_controller.dart

@ -86,7 +86,7 @@ class TranslationListController extends GetxController {
await audioPlayer.setFilePath(filePath);
await audioPlayer.play();
} catch (e) {
print("播放失败: $e");
Logger.e("AudioPlayer", "播放失败: $e");
currentPlayingPath.value = '';
}
}
@ -146,7 +146,7 @@ class TranslationListController extends GetxController {
audioDurations[filePath] = duration;
return duration;
} catch (e) {
print("获取音频时长失败: $e");
Logger.e("AudioPlayer", "获取音频时长失败: $e");
return Duration.zero;
}
}
@ -156,7 +156,7 @@ class TranslationListController extends GetxController {
final appDir = await appDocDir; // 先 await 获取目录
final dir = Directory("${appDir.path}/TranslatAudio");
print("appDocDir=${dir?.path}");
Logger.d("AudioPlayer", "appDocDir=${dir?.path}");
// Create directory if it doesn't exist
if (!await dir.exists()) {
await dir.create(recursive: true); // Create directory tree if needed
@ -186,7 +186,7 @@ class TranslationListController extends GetxController {
files.value = audioFiles;
} catch (e) {
print("Error loading files: $e");
Logger.e("AudioPlayer", "Error loading files: $e");
files.value = []; // Return empty list on error
}
}

Loading…
Cancel
Save