Commit 9c259642 by tanghuan

dev

1 parent 128403df
...@@ -2,6 +2,7 @@ import 'dart:async'; ...@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart'; import 'package:appframe/config/locator.dart';
import 'package:appframe/config/routes.dart'; import 'package:appframe/config/routes.dart';
import 'package:appframe/data/models/message/h5_message.dart'; import 'package:appframe/data/models/message/h5_message.dart';
...@@ -510,6 +511,7 @@ class WebCubit extends Cubit<WebState> { ...@@ -510,6 +511,7 @@ class WebCubit extends Cubit<WebState> {
pickerConfig: CameraPickerConfig( pickerConfig: CameraPickerConfig(
enableRecording: true, enableRecording: true,
onlyEnableRecording: true, onlyEnableRecording: true,
// enableTapRecording: true,
maximumRecordingDuration: Duration(seconds: maxDuration), maximumRecordingDuration: Duration(seconds: maxDuration),
), ),
); );
...@@ -704,7 +706,7 @@ class WebCubit extends Cubit<WebState> { ...@@ -704,7 +706,7 @@ class WebCubit extends Cubit<WebState> {
throw Exception("录音器未初始化"); throw Exception("录音器未初始化");
} }
if (state.recordState != 1) { if (state.recordState != 1 && state.recordState != 2) {
throw Exception("录音器状态错误"); throw Exception("录音器状态错误");
} }
...@@ -730,7 +732,10 @@ class WebCubit extends Cubit<WebState> { ...@@ -730,7 +732,10 @@ class WebCubit extends Cubit<WebState> {
// var duration = await AudioUtil.getAudioDuration(mp3Path); // var duration = await AudioUtil.getAudioDuration(mp3Path);
var duration = await AudioUtil.getAudioDuration(url); var duration = await AudioUtil.getAudioDuration(url);
return {'tempFilePath': mp3Path, 'duration': duration.inSeconds}; return {
'tempFilePath': 'http://127.0.0.1:${Constant.localServerPort}/temp$mp3Path',
'duration': duration.inSeconds,
};
} }
/// 清空录音 /// 清空录音
...@@ -827,7 +832,7 @@ class WebCubit extends Cubit<WebState> { ...@@ -827,7 +832,7 @@ class WebCubit extends Cubit<WebState> {
throw Exception("播放器未初始化"); throw Exception("播放器未初始化");
} }
if (state.playState != 1) { if (state.playState != 1 && state.playState != 2) {
throw Exception("播放器状态错误"); throw Exception("播放器状态错误");
} }
......
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart'; import 'package:appframe/config/locator.dart';
import 'package:appframe/config/routes.dart'; import 'package:appframe/config/routes.dart';
import 'package:appframe/data/repositories/wechat_auth_repository.dart'; import 'package:appframe/data/repositories/wechat_auth_repository.dart';
...@@ -62,10 +63,7 @@ class WechatAuthCubit extends Cubit<WechatAuthState> { ...@@ -62,10 +63,7 @@ class WechatAuthCubit extends Cubit<WechatAuthState> {
_fluwx = getIt.get<Fluwx>(); _fluwx = getIt.get<Fluwx>();
_fluwx.addSubscriber(_responseListener); _fluwx.addSubscriber(_responseListener);
// _textEditingController = TextEditingController()..text = '127.0.0.1'; _textEditingController = TextEditingController()..text = Constant.h5Server;
// _textEditingController = TextEditingController()..text = 'appdev-th.banxiaoer.net';
_textEditingController = TextEditingController()..text = 'appdev-xj.banxiaoer.net';
// _textEditingController = TextEditingController()..text = '192.168.1.136';
_wechatAuthRepository = getIt<WechatAuthRepository>(); _wechatAuthRepository = getIt<WechatAuthRepository>();
} }
...@@ -88,10 +86,8 @@ class WechatAuthCubit extends Cubit<WechatAuthState> { ...@@ -88,10 +86,8 @@ class WechatAuthCubit extends Cubit<WechatAuthState> {
sharedPreferences.setString('auth_userCode', userCode); sharedPreferences.setString('auth_userCode', userCode);
sharedPreferences.setString('auth_classCode', classCode); sharedPreferences.setString('auth_classCode', classCode);
sharedPreferences.setInt('auth_userType', userType); sharedPreferences.setInt('auth_userType', userType);
sharedPreferences.setString('auth_stuId', stuId??''); sharedPreferences.setString('auth_stuId', stuId ?? '');
// sharedPreferences.setString('auth_ip', 'appdev-th.banxiaoer.net'); sharedPreferences.setString('auth_ip', Constant.h5Server);
sharedPreferences.setString('auth_ip', 'appdev-xj.banxiaoer.net');
// sharedPreferences.setString('auth_ip', '192.168.1.136');
router.go( router.go(
'/web', '/web',
......
class Constant {
static const String localServerHost = '127.0.0.1';
static const int localServerPort = 35982;
static const String localServerUrl = 'http://$localServerHost:$localServerPort';
// static const String h5Server = 'appdev-xj.banxiaoer.net';
static const String h5Server = 'appdev-th.banxiaoer.net';
}
...@@ -6,6 +6,7 @@ import 'package:appframe/data/repositories/message/choose_image_handler.dart'; ...@@ -6,6 +6,7 @@ import 'package:appframe/data/repositories/message/choose_image_handler.dart';
import 'package:appframe/data/repositories/message/choose_video_handler.dart'; import 'package:appframe/data/repositories/message/choose_video_handler.dart';
import 'package:appframe/data/repositories/message/clipboard_data_handler.dart'; import 'package:appframe/data/repositories/message/clipboard_data_handler.dart';
import 'package:appframe/data/repositories/message/compress_handler.dart'; import 'package:appframe/data/repositories/message/compress_handler.dart';
import 'package:appframe/data/repositories/message/crop_image_handler.dart';
import 'package:appframe/data/repositories/message/device_info_handler.dart'; import 'package:appframe/data/repositories/message/device_info_handler.dart';
import 'package:appframe/data/repositories/message/download_file_handler.dart'; import 'package:appframe/data/repositories/message/download_file_handler.dart';
import 'package:appframe/data/repositories/message/go_login_handler.dart'; import 'package:appframe/data/repositories/message/go_login_handler.dart';
...@@ -57,13 +58,13 @@ Future<void> setupLocator() async { ...@@ -57,13 +58,13 @@ Future<void> setupLocator() async {
/// 设备信息 /// 设备信息
getIt.registerLazySingleton<MessageHandler>(() => DeviceInfoHandler(), instanceName: 'getDeviceInfo'); getIt.registerLazySingleton<MessageHandler>(() => DeviceInfoHandler(), instanceName: 'getDeviceInfo');
// 位置信息 /// 位置信息
getIt.registerLazySingleton<MessageHandler>(() => LocationHandler(), instanceName: 'getLocation'); getIt.registerLazySingleton<MessageHandler>(() => LocationHandler(), instanceName: 'getLocation');
// 网络信息 /// 网络信息
getIt.registerLazySingleton<MessageHandler>(() => NetworkTypeHandler(), instanceName: 'getNetworkType'); getIt.registerLazySingleton<MessageHandler>(() => NetworkTypeHandler(), instanceName: 'getNetworkType');
// wifi信息 /// wifi信息
getIt.registerLazySingleton<MessageHandler>(() => WifiInfoHandler(), instanceName: 'getWifiInfo'); getIt.registerLazySingleton<MessageHandler>(() => WifiInfoHandler(), instanceName: 'getWifiInfo');
/// 设备方向 /// 设备方向
...@@ -140,6 +141,9 @@ Future<void> setupLocator() async { ...@@ -140,6 +141,9 @@ Future<void> setupLocator() async {
getIt.registerLazySingleton<MessageHandler>(() => AudioStopHandler(), instanceName: 'audioStop'); getIt.registerLazySingleton<MessageHandler>(() => AudioStopHandler(), instanceName: 'audioStop');
getIt.registerLazySingleton<MessageHandler>(() => AudioClearHandler(), instanceName: 'audioClear'); getIt.registerLazySingleton<MessageHandler>(() => AudioClearHandler(), instanceName: 'audioClear');
/// 裁剪图片
getIt.registerLazySingleton<MessageHandler>(() => CropImageHandler(), instanceName: 'cropImage');
/// 震动 /// 震动
getIt.registerLazySingleton<MessageHandler>(() => VibrateShortHandler(), instanceName: 'vibrateShort'); getIt.registerLazySingleton<MessageHandler>(() => VibrateShortHandler(), instanceName: 'vibrateShort');
......
final int serverPort = 35982;
import 'dart:io'; import 'dart:io';
import 'package:appframe/config/constant.dart';
import 'package:appframe/services/dispatcher.dart'; import 'package:appframe/services/dispatcher.dart';
import 'package:appframe/utils/file_type_util.dart'; import 'package:appframe/utils/file_type_util.dart';
import 'package:appframe/utils/thumbnail_util.dart'; import 'package:appframe/utils/thumbnail_util.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:image_size_getter/file_input.dart'; import 'package:image_size_getter/file_input.dart';
import 'package:image_size_getter/image_size_getter.dart'; import 'package:image_size_getter/image_size_getter.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:video_player/video_player.dart';
class ChooseFileHandler extends MessageHandler { class ChooseFileHandler extends MessageHandler {
@override @override
...@@ -16,7 +17,11 @@ class ChooseFileHandler extends MessageHandler { ...@@ -16,7 +17,11 @@ class ChooseFileHandler extends MessageHandler {
throw Exception('参数错误'); throw Exception('参数错误');
} }
final count = params['count'] as int; var count = 1;
if (params.containsKey('count')) {
count = params['count'] as int;
}
final fileTypes = params['fileTypes'] as List<dynamic>; final fileTypes = params['fileTypes'] as List<dynamic>;
FilePickerResult? filePickerResult = await FilePicker.platform.pickFiles( FilePickerResult? filePickerResult = await FilePicker.platform.pickFiles(
...@@ -27,7 +32,7 @@ class ChooseFileHandler extends MessageHandler { ...@@ -27,7 +32,7 @@ class ChooseFileHandler extends MessageHandler {
// 用户取消选择,返回空数组 // 用户取消选择,返回空数组
if (filePickerResult == null) { if (filePickerResult == null) {
return []; throw Exception('cancel');
} }
// 限制最多count个文件 // 限制最多count个文件
...@@ -40,21 +45,12 @@ class ChooseFileHandler extends MessageHandler { ...@@ -40,21 +45,12 @@ class ChooseFileHandler extends MessageHandler {
result.add(await _handleFile(file)); result.add(await _handleFile(file));
} }
return result; return {'tempFiles': result};
} }
Future<Map<String, dynamic>> _handleFile(PlatformFile file) async { Future<Map<String, dynamic>> _handleFile(PlatformFile file) async {
// 获取临时目录
final tempDir = await getTemporaryDirectory();
// 临时文件路径
// final uniqueFileName = '${DateTime.now().millisecondsSinceEpoch}_${file.name}';
// final tempFilePath = path.join(tempDir.path, uniqueFileName);
// 所选中的文件已经被插件复制到临时目录,所以不需要再复制 // 所选中的文件已经被插件复制到临时目录,所以不需要再复制
final originalFile = File(file.path!); final originalFile = File(file.path!);
// final copiedFile = await originalFile.copy(tempFilePath);
bool isImage = await FileTypeUtil.isImage(originalFile); bool isImage = await FileTypeUtil.isImage(originalFile);
bool isVideo = false; bool isVideo = false;
...@@ -62,25 +58,43 @@ class ChooseFileHandler extends MessageHandler { ...@@ -62,25 +58,43 @@ class ChooseFileHandler extends MessageHandler {
isVideo = await FileTypeUtil.isVideo(originalFile); isVideo = await FileTypeUtil.isVideo(originalFile);
} }
// 通过image_size_getter获取图片尺寸 int? imgWidth, imgHeight;
SizeResult? sizeResult; String? imgThumbFilePath;
String? thumbTempFilePath;
if (isImage) { if (isImage) {
sizeResult = ImageSizeGetter.getSizeResult(FileInput(originalFile)); // 通过image_size_getter获取图片尺寸
thumbTempFilePath = await ThumbnailUtil.genTempThumbnail(originalFile, tempDir); var sizeResult = ImageSizeGetter.getSizeResult(FileInput(originalFile));
var size = sizeResult.size;
imgWidth = sizeResult.size.width;
imgHeight = sizeResult.size.height;
final tempDir = await getTemporaryDirectory();
imgThumbFilePath = await ThumbnailUtil.genTempThumbnail(originalFile, tempDir);
} }
double? videoWidth, videoHeight;
String? videoThumbFilePath;
if (isVideo) { if (isVideo) {
thumbTempFilePath = await ThumbnailUtil.genVideoThumbnail(originalFile.path, tempDir); // 获取视频尺寸
VideoPlayerController controller = VideoPlayerController.file(originalFile);
await controller.initialize();
var size = controller.value.size;
videoWidth = size.width;
videoHeight = size.height;
controller.dispose();
final tempDir = await getTemporaryDirectory();
videoThumbFilePath = await ThumbnailUtil.genVideoThumbnail(originalFile.path, tempDir);
} }
// 返回临时文件信息 // 返回临时文件信息
return { return {
'tempFilePath': '/temp${originalFile.path}', 'tempFilePath': 'http://127.0.0.1:${Constant.localServerPort}/temp${file.path}',
'size': file.size, 'size': file.size,
'width': sizeResult != null ? sizeResult.size.width : '', 'width': isImage ? imgWidth : (isVideo ? videoWidth : ''),
'height': sizeResult != null ? sizeResult.size.height : '', 'height': isImage ? imgHeight : (isVideo ? videoHeight : ''),
'thumbTempFilePath': thumbTempFilePath ?? '', 'thumbTempFilePath': isImage
'fileType': originalFile.path.split('/').last.split('.').last, ? 'http://127.0.0.1:${Constant.localServerPort}/temp$imgThumbFilePath'
: (isVideo ? 'http://127.0.0.1:${Constant.localServerPort}/temp$videoThumbFilePath' : ''),
'fileType': file.extension,
}; };
} }
} }
import 'dart:io';
import 'dart:typed_data';
import 'package:appframe/config/constant.dart';
import 'package:appframe/services/dispatcher.dart'; import 'package:appframe/services/dispatcher.dart';
import 'package:dio/dio.dart';
import 'package:image/image.dart' as img;
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:uuid/uuid.dart';
class CropImageHandler extends MessageHandler { class CropImageHandler extends MessageHandler {
@override @override
...@@ -6,11 +15,11 @@ class CropImageHandler extends MessageHandler { ...@@ -6,11 +15,11 @@ class CropImageHandler extends MessageHandler {
if (params is! Map<String, dynamic>) { if (params is! Map<String, dynamic>) {
throw Exception('参数错误'); throw Exception('参数错误');
} }
var url = params['sourceType'] as String?; var url = params['url'] as String?;
if (url == null || url.isEmpty) { if (url == null || url.isEmpty) {
throw Exception('参数错误'); throw Exception('参数错误');
} }
var cropScale = params['scale'] as String?; var cropScale = params['cropScale'] as String?;
if (cropScale == null || cropScale.isEmpty) { if (cropScale == null || cropScale.isEmpty) {
throw Exception('参数错误'); throw Exception('参数错误');
} }
...@@ -19,7 +28,78 @@ class CropImageHandler extends MessageHandler { ...@@ -19,7 +28,78 @@ class CropImageHandler extends MessageHandler {
throw Exception('参数错误'); throw Exception('参数错误');
} }
return false; try {
String outputPath = await _cropImageByRatio(url, cropScale);
return {'tempFilePath': 'http://127.0.0.1:${Constant.localServerPort}/temp$outputPath'};
} catch (e) {
throw Exception('裁剪出错');
}
}
Future<String> _cropImageByRatio(String url, String cropScale) async {
if (url.startsWith('http://127.0.0.1:${Constant.localServerPort}')) {
url = url.replaceFirst('http://127.0.0.1:${Constant.localServerPort}', '');
}
if (url.startsWith('/temp')) {
url = url.substring(5);
}
String extension = path.extension(url);
Directory cacheDirectory = await getApplicationCacheDirectory();
File imageFile;
// 对于远程图片,先下载到应用缓存目录,然后生成File
if (url.startsWith('https://') || url.startsWith('http://')) {
String tempFilePath = '${cacheDirectory.path}/${Uuid().v4()}$extension';
Dio dio = Dio();
Response resp = await dio.download(url, tempFilePath);
if (resp.statusCode != 200) {
throw Exception('下载图片失败');
}
dio.close(force: true);
imageFile = File(tempFilePath);
}
// 对于本地路径,直接生成File
else {
imageFile = File(url);
}
// 1. 读取图片文件并解码
Uint8List bytes = await imageFile.readAsBytes();
img.Image originalImage = img.decodeImage(bytes)!;
int originalWidth = originalImage.width;
int originalHeight = originalImage.height;
// 2. 计算目标裁剪区域
var targetRatio = cropScale.split(":");
double targetAspect = int.parse(targetRatio[0]) / int.parse(targetRatio[1]); // 例如 16/9
double currentAspect = originalWidth / originalHeight;
int cropWidth, cropHeight;
if (currentAspect > targetAspect) {
// 原图更宽,以高度为基准裁剪宽度
cropHeight = originalHeight;
cropWidth = (originalHeight * targetAspect).round();
} else {
// 原图更高,以宽度为基准裁剪高度
cropWidth = originalWidth;
cropHeight = (originalWidth / targetAspect).round();
}
// 3. 计算居中裁剪的起始点
int startX = (originalWidth - cropWidth) ~/ 2;
int startY = (originalHeight - cropHeight) ~/ 2;
// 4. 执行裁剪
img.Image croppedImage = img.copyCrop(originalImage, x: startX, y: startY, width: cropWidth, height: cropHeight);
// 5. 保存裁剪后的图片
String outputPath = '${cacheDirectory.path}/${Uuid().v4()}$extension';
await File(outputPath).writeAsBytes(img.encodeJpg(croppedImage));
return outputPath;
} }
} }
import 'package:appframe/config/constant.dart';
import 'package:appframe/services/dispatcher.dart'; import 'package:appframe/services/dispatcher.dart';
import 'package:open_file/open_file.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class OpenDocumentHandler extends MessageHandler { class OpenDocumentHandler extends MessageHandler {
...@@ -7,12 +9,25 @@ class OpenDocumentHandler extends MessageHandler { ...@@ -7,12 +9,25 @@ class OpenDocumentHandler extends MessageHandler {
if (params is! Map<String, dynamic>) { if (params is! Map<String, dynamic>) {
throw Exception('参数错误'); throw Exception('参数错误');
} }
final url = params['url'] as String;
var url = params['url'] as String;
if (url.isEmpty) { if (url.isEmpty) {
throw Exception('参数错误'); throw Exception('参数错误');
} }
if (url.startsWith('http://127.0.0.1:${Constant.localServerPort}')) {
url = url.replaceFirst('http://127.0.0.1:${Constant.localServerPort}', '');
}
if (url.startsWith('/temp')) {
url = url.substring(5);
}
if (url.startsWith('http')) {
return await _launchInBrowser(Uri.parse(url)); return await _launchInBrowser(Uri.parse(url));
} else {
return await _open(url);
}
} }
Future<bool> _launchInBrowser(Uri url) async { Future<bool> _launchInBrowser(Uri url) async {
...@@ -21,8 +36,11 @@ class OpenDocumentHandler extends MessageHandler { ...@@ -21,8 +36,11 @@ class OpenDocumentHandler extends MessageHandler {
} else { } else {
throw Exception('Could not launch $url'); throw Exception('Could not launch $url');
} }
/*if (!await launchUrl(url, mode: LaunchMode.externalNonBrowserApplication)) { }
throw Exception('Could not launch $url');
}*/ /// 暂时就简单打开一下,未做复杂调用
Future<bool> _open(String filePath) async {
var r = await OpenFile.open("filePath");
return r.type == ResultType.done;
} }
} }
import 'dart:io'; import 'dart:io';
import 'package:appframe/config/constant.dart';
import 'package:appframe/services/api_service.dart'; import 'package:appframe/services/api_service.dart';
import 'package:appframe/services/dispatcher.dart'; import 'package:appframe/services/dispatcher.dart';
import 'package:appframe/utils/file_type_util.dart'; import 'package:appframe/utils/file_type_util.dart';
...@@ -19,7 +20,17 @@ class UploadFileHandler extends MessageHandler { ...@@ -19,7 +20,17 @@ class UploadFileHandler extends MessageHandler {
throw Exception('参数错误'); throw Exception('参数错误');
} }
final result = await compute(_handleUpload, {'filePath': tempFilePath}); final String? busi = params['busi'] as String?;
if (busi == null || busi.isEmpty) {
throw Exception('参数错误');
}
final String? subBusi = params['subBusi'] as String?;
if (subBusi == null || subBusi.isEmpty) {
throw Exception('参数错误');
}
final result = await compute(_handleUpload, {'filePath': tempFilePath, 'busi': busi, 'subBusi': subBusi});
// final result = await _handleUpload({'filePath': tempFilePath}); // final result = await _handleUpload({'filePath': tempFilePath});
return result; return result;
...@@ -32,19 +43,27 @@ class UploadFileHandler extends MessageHandler { ...@@ -32,19 +43,27 @@ class UploadFileHandler extends MessageHandler {
/// 在Isolate中执行 /// 在Isolate中执行
static Future<Map<String, dynamic>> _handleUpload(Map<String, dynamic> fileParams) async { static Future<Map<String, dynamic>> _handleUpload(Map<String, dynamic> fileParams) async {
var filePath = fileParams['filePath'] as String; String filePath = fileParams['filePath'] as String;
String busi = fileParams['busi'] as String;
String subBusi = fileParams['subBusi'] as String;
if (filePath.startsWith('http://127.0.0.1:${Constant.localServerPort}')) {
filePath = filePath.replaceFirst('http://127.0.0.1:${Constant.localServerPort}', '');
}
if (filePath.startsWith('/temp')) { if (filePath.startsWith('/temp')) {
filePath = filePath.substring(5); filePath = filePath.substring(5);
} }
String logicPrefix = _getLoginPrefix(busi, subBusi);
final bxeApiService = ApiService(baseUrl: _bxeBaseUrl); final bxeApiService = ApiService(baseUrl: _bxeBaseUrl);
// 由于服务端签名时未设置Content-Type,这里必须设置为空,否则会报签名错误 // 由于服务端签名时未设置Content-Type,这里必须设置为空,否则会报签名错误
// 由于封装有默认值,所以不能不设置 // 由于封装有默认值,所以不能不设置
final obsApiService = ApiService(defaultHeaders: {'Content-Type': '', 'Accept': ''}); final obsApiService = ApiService(defaultHeaders: {'Content-Type': '', 'Accept': ''});
//并行上传分段 //并行上传分段
final uploadResult = await _uploadInParallel(bxeApiService, obsApiService, filePath); final uploadResult = await _uploadInParallel(bxeApiService, obsApiService, logicPrefix, filePath);
String objectKey = uploadResult['objectKey'] as String; String objectKey = uploadResult['objectKey'] as String;
String bucket = uploadResult['bucket'] as String; String bucket = uploadResult['bucket'] as String;
String uploadId = uploadResult['uploadId'] as String; String uploadId = uploadResult['uploadId'] as String;
...@@ -57,12 +76,14 @@ class UploadFileHandler extends MessageHandler { ...@@ -57,12 +76,14 @@ class UploadFileHandler extends MessageHandler {
bxeApiService.close(); bxeApiService.close();
obsApiService.close(); obsApiService.close();
return {'url': response.data['location']}; return {'url': _addPreUrl(response.data["location"])};
} }
/// 并行上传 /// 并行上传
static Future<Map<String, dynamic>> _uploadInParallel(ApiService bxeApiService, static Future<Map<String, dynamic>> _uploadInParallel(
ApiService bxeApiService,
ApiService obsApiService, ApiService obsApiService,
String logicPrefix,
String filePath, { String filePath, {
int maxConcurrency = 5, int maxConcurrency = 5,
}) async { }) async {
...@@ -97,8 +118,7 @@ class UploadFileHandler extends MessageHandler { ...@@ -97,8 +118,7 @@ class UploadFileHandler extends MessageHandler {
//生成唯一文件名, //生成唯一文件名,
// String objectKey = 'd2/test/file.csv'; // String objectKey = 'd2/test/file.csv';
var uuid = Uuid(); var uuid = Uuid();
// String objectKey = '${uuid.v5(Namespace.url.value, 'www.banxiaoer.com')}${path.extension(file.path)}'; String objectKey = '$logicPrefix/${uuid.v4()}${path.extension(file.path)}';
String objectKey = '${uuid.v4()}${path.extension(file.path)}';
String uploadId = ''; String uploadId = '';
Map<int, String> tagsMap = {}; Map<int, String> tagsMap = {};
...@@ -149,18 +169,21 @@ class UploadFileHandler extends MessageHandler { ...@@ -149,18 +169,21 @@ class UploadFileHandler extends MessageHandler {
} }
/// 每次上传前,请求后端获取签名信息 /// 每次上传前,请求后端获取签名信息
static Future<Map<String, dynamic>> _next(ApiService bxeApiService, static Future<Map<String, dynamic>> _next(
ApiService bxeApiService,
String objectKey, String objectKey,
String bucket, String bucket,
String uploadId, String uploadId,
int partNum,) async { int partNum,
) async {
var endpoint = '$_signatureNextUrl?objectKey=$objectKey&bucket=$bucket&uploadId=$uploadId&partNum=$partNum'; var endpoint = '$_signatureNextUrl?objectKey=$objectKey&bucket=$bucket&uploadId=$uploadId&partNum=$partNum';
final resp = await bxeApiService.get(endpoint); final resp = await bxeApiService.get(endpoint);
return resp.data; return resp.data;
} }
/// 上传段,按照最大重试次数进行上传重试 /// 上传段,按照最大重试次数进行上传重试
static Future<void> _uploadChunkWithRetry(ApiService obsApiService, static Future<void> _uploadChunkWithRetry(
ApiService obsApiService,
String signUrl, String signUrl,
int chunkIndex, int chunkIndex,
Uint8List chunk, Uint8List chunk,
...@@ -201,11 +224,13 @@ class UploadFileHandler extends MessageHandler { ...@@ -201,11 +224,13 @@ class UploadFileHandler extends MessageHandler {
} }
/// 请求合并文件 /// 请求合并文件
static Future<Response> _merge(ApiService bxeApiService, static Future<Response> _merge(
ApiService bxeApiService,
String objectKey, String objectKey,
String bucket, String bucket,
String uploadId, String uploadId,
Map<int, String> tagsMap,) async { Map<int, String> tagsMap,
) async {
final parts = []; final parts = [];
for (int i = 1; i <= tagsMap.length; i++) { for (int i = 1; i <= tagsMap.length; i++) {
parts.add({'partNumber': i, 'etag': tagsMap[i]}); parts.add({'partNumber': i, 'etag': tagsMap[i]});
...@@ -224,4 +249,27 @@ class UploadFileHandler extends MessageHandler { ...@@ -224,4 +249,27 @@ class UploadFileHandler extends MessageHandler {
return response; return response;
} }
static String _getLoginPrefix(String busi, String subBusi) {
var now = DateTime.now();
var year = now.year;
var month = now.month;
var day = now.day;
return '/d2/pridel/user/$year$month$day/bxe/${busi}_$subBusi';
}
static String _addPreUrl(String location) {
// /bxe-pics//d2/pridel/user/20251017/bxe/bxe_homework/f4ea233d-9e1b-4a3f-bc8f-b64e776f42a6.jpg
// 多了一个斜杠,暂时多截取1位
if (location.startsWith('/bxe-files')) {
return 'https://files-obs.banxiaoer.com${location.substring(11)}';
} else if (location.startsWith('/bxe-pics')) {
return 'https://pics-obs.banxiaoer.com${location.substring(10)}';
} else if (location.startsWith('/bxe-videos')) {
return 'https://videos-obs.banxiaoer.com${location.substring(12)}';
} else {
return location;
}
}
} }
import 'dart:io'; import 'dart:io';
import 'package:appframe/config/constant.dart';
import 'package:archive/archive.dart'; import 'package:archive/archive.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -13,7 +14,7 @@ class LocalServerService { ...@@ -13,7 +14,7 @@ class LocalServerService {
// 测试情况下, 每次启动服务,先解压dist文件 // 测试情况下, 每次启动服务,先解压dist文件
_extractDist(); _extractDist();
HttpServer server = await HttpServer.bind(InternetAddress.loopbackIPv4, 35982); HttpServer server = await HttpServer.bind(InternetAddress.loopbackIPv4, Constant.localServerPort);
print('本地服务器启动在端口: ${server.port}'); print('本地服务器启动在端口: ${server.port}');
server.listen((HttpRequest request) async { server.listen((HttpRequest request) async {
...@@ -189,11 +190,17 @@ class LocalServerService { ...@@ -189,11 +190,17 @@ class LocalServerService {
var distUrl = "https://github.com/xinxin-wu/flutter_web_dist/releases/download/v1.0.0/dist.zip"; var distUrl = "https://github.com/xinxin-wu/flutter_web_dist/releases/download/v1.0.0/dist.zip";
// Dio进行下载 // Dio进行下载
var dio = Dio(); var dio = Dio();
dio.download(distUrl, '$httpDirectory/dist.zip', onReceiveProgress: (received, total) { dio
.download(
distUrl,
'$httpDirectory/dist.zip',
onReceiveProgress: (received, total) {
if (total != -1) { if (total != -1) {
print((received / total * 100).toStringAsFixed(0) + "%"); print((received / total * 100).toStringAsFixed(0) + "%");
} }
}).then((_) { },
)
.then((_) {
_extractDist(); _extractDist();
}); });
dio.close(); dio.close();
......
...@@ -365,42 +365,10 @@ packages: ...@@ -365,42 +365,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: file_picker name: file_picker
sha256: e7e16c9d15c36330b94ca0e2ad8cb61f93cd5282d0158c09805aed13b5452f22 sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "10.3.2" version: "10.3.3"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.3+2"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.4+4"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.2"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.3+4"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
...@@ -709,70 +677,14 @@ packages: ...@@ -709,70 +677,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "4.1.2" version: "4.1.2"
image_picker: image:
dependency: "direct main" dependency: "direct main"
description: description:
name: image_picker name: image
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041" sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "4.5.4"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: dd7a61daaa5896cc34b7bc95f66c60225ae6bee0d167dde0e21a9d9016cac0dc
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+4"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.11.0"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
image_size_getter: image_size_getter:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -941,6 +853,70 @@ packages: ...@@ -941,6 +853,70 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.5.0" version: "0.5.0"
open_file:
dependency: "direct main"
description:
name: open_file
sha256: d17e2bddf5b278cb2ae18393d0496aa4f162142ba97d1a9e0c30d476adf99c0e
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.5.10"
open_file_android:
dependency: transitive
description:
name: open_file_android
sha256: "58141fcaece2f453a9684509a7275f231ac0e3d6ceb9a5e6de310a7dff9084aa"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.6"
open_file_ios:
dependency: transitive
description:
name: open_file_ios
sha256: "02996f01e5f6863832068e97f8f3a5ef9b613516db6897f373b43b79849e4d07"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
open_file_linux:
dependency: transitive
description:
name: open_file_linux
sha256: d189f799eecbb139c97f8bc7d303f9e720954fa4e0fa1b0b7294767e5f2d7550
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.5"
open_file_mac:
dependency: transitive
description:
name: open_file_mac
sha256: "1440b1e37ceb0642208cfeb2c659c6cda27b25187a90635c9d1acb7d0584d324"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
open_file_platform_interface:
dependency: transitive
description:
name: open_file_platform_interface
sha256: "101b424ca359632699a7e1213e83d025722ab668b9fd1412338221bf9b0e5757"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.3"
open_file_web:
dependency: transitive
description:
name: open_file_web
sha256: e3dbc9584856283dcb30aef5720558b90f88036360bd078e494ab80a80130c4f
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.4"
open_file_windows:
dependency: transitive
description:
name: open_file_windows
sha256: d26c31ddf935a94a1a3aa43a23f4fff8a5ff4eea395fe7a8cb819cf55431c875
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.3"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
...@@ -1451,7 +1427,7 @@ packages: ...@@ -1451,7 +1427,7 @@ packages:
source: hosted source: hosted
version: "3.1.4" version: "3.1.4"
video_player: video_player:
dependency: transitive dependency: "direct main"
description: description:
name: video_player name: video_player
sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a"
......
...@@ -47,12 +47,14 @@ dependencies: ...@@ -47,12 +47,14 @@ dependencies:
get_it: ^8.2.0 get_it: ^8.2.0
geolocator: ^14.0.2 geolocator: ^14.0.2
go_router: ^16.2.1 go_router: ^16.2.1
image_picker: ^1.2.0 # image_picker: ^1.2.0
image: ^4.5.4
image_size_getter: ^2.4.1 image_size_getter: ^2.4.1
json_annotation: ^4.9.0 json_annotation: ^4.9.0
mime: ^2.0.0 mime: ^2.0.0
mobile_scanner: ^7.0.1 mobile_scanner: ^7.0.1
network_info_plus: ^7.0.0 network_info_plus: ^7.0.0
open_file: ^3.5.10
path: ^1.9.1 path: ^1.9.1
path_provider: ^2.1.5 path_provider: ^2.1.5
permission_handler: ^12.0.1 permission_handler: ^12.0.1
...@@ -61,6 +63,7 @@ dependencies: ...@@ -61,6 +63,7 @@ dependencies:
uuid: ^4.5.1 uuid: ^4.5.1
vibration: ^3.1.3 vibration: ^3.1.3
video_compress: ^3.1.4 video_compress: ^3.1.4
video_player: ^2.10.0
webview_flutter: ^4.13.0 webview_flutter: ^4.13.0
wechat_assets_picker: ^9.8.0 wechat_assets_picker: ^9.8.0
wechat_camera_picker: ^4.4.0 wechat_camera_picker: ^4.4.0
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!