You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
8.3 KiB

import 'dart:convert';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:just_audio/just_audio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../../core/utils/logger.dart';
import '../../../core/utils/upload_oss.dart';
import '../../../data/services/db/sqflite_api.dart';
import '../../../core/utils/permission_util.dart';
class MeetingController extends GetxController {
final ScrollController listController = ScrollController();
final AudioPlayer _audioPlayer = AudioPlayer();
// 是否还有更多数据
bool isGetMore = true;
bool isLoading = false;
int page = 1;
int addQuantity = 0;
TextEditingController titleController = TextEditingController(); // 录音标题
RxList dataList = [].obs;
List dataListTask = [];
bool isDisposed = false;
final String _appid = '2316081933';
final String _token = 'mcJTh6OelBqU_L78lgGd77Nyrc_-5-En';
final String _cluster = 'volc_auc_meeting_flash';
final String _serviceUrl = 'https://openspeech.bytedance.com/api/v1/auc';
Map<String, String> _headers = {};
@override
void onInit() {
super.onInit();
listController.addListener(_onScroll);
_requestStoragePermission();
//Permission.storage.request();
_headers = {
'Authorization': 'Bearer; $_token',
'Content-Type': 'application/json',
};
_getDataList();
}
@override
void onClose() {
listController.dispose();
titleController.dispose();
_audioPlayer.dispose();
isDisposed = true;
super.onClose();
}
void _onScroll() {
if (isGetMore &&
!isLoading &&
listController.position.pixels >=
listController.position.maxScrollExtent - 100) {
isLoading = true;
page++;
_getDataList();
}
}
// 请求本地数据
void _getDataList() async {
List list = await SqfliteApi.getMeetingList((page - 1) * 10 + addQuantity);
dataList.addAll(list);
queryDataListTask(list);
addQuantity = 0;
if (list.length < 10) {
isGetMore = false;
} else {
isGetMore = true;
}
isLoading = false;
}
// 请求录音权限
void _requestStoragePermission() async {
final BuildContext context = Get.overlayContext!;
PermissionUtil.instance
.requestPermission(
context: context,
permissionType: Permission.storage,
permissionName: "存储",
explanationText: "我们需要访问存储权限,以便您可以选择并上传音频文件。",
permanentDenialText: "检测到您已永久拒绝存储权限。如需继续使用此功能,请前往应用设置中手动开启存储权限。",
)
.then((granted) {
if (granted) {
Logger.d("Permission", "用户授予了存储权限");
} else {
Logger.d("Permission", "用户未授予存储权限");
// 可以提示用户无法进行文件操作
}
});
}
void addAudio() async {
EasyLoading.show();
FilePickerResult? result = await FilePicker.platform.pickFiles(
withData: true,
);
if (result != null) {
PlatformFile file = result.files.first;
String filePath = await _saveFile(file);
String fileName = file.name;
await _audioPlayer.setAudioSource(AudioSource.file(filePath));
var audiourl =
await UploadOss.upload(filepath: filePath, rootDir: 'audio');
int seconds = _audioPlayer.duration?.inSeconds ?? 0;
int creationTime = DateTime.now().millisecondsSinceEpoch;
Map<String, Object?> data = {
'title': fileName,
'type': 'IMPORT',
'seconds': seconds,
'filepath': filePath,
'audiourl': audiourl,
'tasktype': 0,
'creationtime': creationTime,
};
final meetingId = await SqfliteApi.insertMeeting(data);
if (meetingId != null) {
dataList.insert(0, {
'id': meetingId,
'taskid': '',
...data,
});
addQuantity++;
}
}
EasyLoading.dismiss();
}
Future<String> _saveFile(PlatformFile file) async {
final directory = await getApplicationDocumentsDirectory();
final String filePath = '${directory.path}/${file.name}';
final File localFile = File(filePath);
await localFile.writeAsBytes(file.bytes!);
return filePath;
}
// 修改标题
void editMeetingTitle(int id, String title) async {
if (title.isNotEmpty) {
SqfliteApi.editMeetingTitle(id, {'title': title});
int index = dataList.indexWhere((item) => item['id'] == id);
if (index != -1) {
final dataMap = Map<String, dynamic>.from(dataList[index]);
dataMap['title'] = title;
dataList[index] = dataMap;
}
}
Get.back();
}
// 删除数据
void deleteMeeting(int id, String filepath) async {
dataList.removeWhere((item) => item['id'] == id);
// 删除数据库中的记录
SqfliteApi.deleteMeeting(id);
_deleteFile(filepath);
addQuantity--;
}
// 删除文件
Future<void> _deleteFile(String filepath) async {
File file = File(filepath);
bool fileExists = await file.exists();
if (fileExists) {
await file.delete();
}
}
// 查询转写状态
void queryDataListTask(List list, {bool isAdd = true}) {
for (var element in List.from(list)) {
if (element['tasktype'] == 1) {
if (isAdd) {
dataListTask.add(element);
}
final taskId = element['taskid'];
_fileRecognize(element['id'], taskId);
}
}
}
Future<void> _fileRecognize(int id, String taskId) async {
try {
final startTime = DateTime.now().millisecondsSinceEpoch;
if (isDisposed) return;
var respDic = await _queryTask(taskId);
var code = respDic['resp']['code'] as int;
if (code == 1000) {
await SqfliteApi.editMeetingTitle(id, {'tasktype': 2});
int index = dataList.indexWhere((item) => item['id'] == id);
if (index != -1) {
final dataMap = Map<String, dynamic>.from(dataList[index]);
dataMap['tasktype'] = 2;
dataList[index] = dataMap;
int taskIndex = dataListTask.indexWhere((item) => item['id'] == id);
if (taskIndex != -1) {
dataListTask.removeAt(taskIndex);
}
}
return;
} else if (code < 2000) {
Logger.debug("FileRecognize failed");
return;
}
while (!isDisposed) {
await Future.delayed(const Duration(seconds: 2));
if (isDisposed) return;
respDic = await _queryTask(taskId);
code = respDic['resp']['code'] as int;
if (code == 1000) {
await SqfliteApi.editMeetingTitle(id, {'tasktype': 2});
int index = dataList.indexWhere((item) => item['id'] == id);
if (index != -1) {
final dataMap = Map<String, dynamic>.from(dataList[index]);
dataMap['tasktype'] = 2;
dataList[index] = dataMap;
int taskIndex = dataListTask.indexWhere((item) => item['id'] == id);
if (taskIndex != -1) {
dataListTask.removeAt(taskIndex);
}
}
return;
} else if (code < 2000) {
Logger.debug("FileRecognize failed");
return;
}
final currentTime = DateTime.now().millisecondsSinceEpoch;
if (currentTime - startTime > 300 * 1000) {
Logger.debug('wait time exceeds 300s');
return;
}
}
} catch (e) {
Logger.error('Error occurred: ${e.toString()}');
}
}
Future<Map<String, dynamic>> _queryTask(String taskId) async {
final queryBody = jsonEncode({
"appid": _appid,
"token": _token,
"id": taskId,
"cluster": _cluster,
});
try {
final response = await http.post(
Uri.parse('$_serviceUrl/query'),
headers: _headers,
body: queryBody,
);
if (response.statusCode != 200) {
throw Exception('Query failed with status: ${response.statusCode}');
}
final respDic = jsonDecode(response.body);
return respDic;
} catch (e) {
Logger.error('Query error: ${e.toString()}');
rethrow;
}
}
}