Commit ba18c03b by tanghuan

dev

1 parent 9c259642
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
<div id="resp"></div> <div id="resp"></div>
<input type="text" id="text" value="">
<button onclick="startRecord()">开始录音</button> <button onclick="startRecord()">开始录音</button>
<button onclick="">暂停录音</button> <button onclick="">暂停录音</button>
...@@ -23,6 +25,8 @@ ...@@ -23,6 +25,8 @@
<button onclick="">唤醒播放</button> <button onclick="">唤醒播放</button>
<button onclick="stopPlay()">停止播放</button> <button onclick="stopPlay()">停止播放</button>
<button onclick="openlink()">打开新链接</button>
<br> <br>
<br> <br>
<a href="/test/test.html">跳转测试1</a> <a href="/test/test.html">跳转测试1</a>
...@@ -62,6 +66,12 @@ ...@@ -62,6 +66,12 @@
xeJsBridge.postMessage(message); xeJsBridge.postMessage(message);
} }
function openlink() {
let url = 'https://xw.qq.com';
let message = '{ "timestamp": 1, "unique": "123", "cmd": "openlink", "params": {"url":"' + url + '"} }';
xeJsBridge.postMessage(message);
}
</script> </script>
</html> </html>
\ No newline at end of file \ No newline at end of file
import 'package:appframe/config/routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:webview_flutter/webview_flutter.dart';
class LinkState extends Equatable {
final bool loaded;
final String url;
const LinkState({this.loaded = false, this.url = ''});
LinkState copyWith({bool? loaded, String? url}) {
return LinkState(loaded: loaded ?? this.loaded, url: url ?? this.url);
}
@override
// TODO: implement props
List<Object?> get props => [loaded, url];
}
class LinkCubit extends Cubit<LinkState> {
late final WebViewController _controller;
WebViewController get controller => _controller;
LinkCubit(super.initialState) {
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onUrlChange: (UrlChange url) {},
onPageStarted: (String url) {},
onPageFinished: (String url) {
_controller.runJavaScript(
'document.querySelector("meta[name=viewport]").setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no")',
);
_finishLoading();
},
),
)
..loadRequest(Uri.parse(state.url));
}
void _finishLoading() {
emit(state.copyWith(loaded: true));
}
Future<void> handleBack(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
} else {
// context.pop(true);
router.pop('ok');
}
}
}
...@@ -197,7 +197,7 @@ class WebCubit extends Cubit<WebState> { ...@@ -197,7 +197,7 @@ class WebCubit extends Cubit<WebState> {
// closeLocalPlayer(); // closeLocalPlayer();
}, },
onPageFinished: (String url) async { onPageFinished: (String url) async {
controller.runJavaScript( _controller.runJavaScript(
'document.querySelector("meta[name=viewport]").setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no")', 'document.querySelector("meta[name=viewport]").setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no")',
); );
finishLoading(); finishLoading();
...@@ -225,8 +225,8 @@ class WebCubit extends Cubit<WebState> { ...@@ -225,8 +225,8 @@ class WebCubit extends Cubit<WebState> {
final String serverUrl; final String serverUrl;
if (state.sessionCode == null || state.sessionCode == '') { if (state.sessionCode == null || state.sessionCode == '') {
serverUrl = 'http://127.0.0.1:${_server.port}/test/login.html'; serverUrl = '${Constant.localServerTestFileUrl}/login.html';
// serverUrl = 'http://127.0.0.1:${_server.port}/test/test.html'; // serverUrl = '${Constant.localServerTestFileUrl}/test2.html';
} else { } else {
serverUrl = serverUrl =
'http://${state.ip}:${_server.port}/index.html#/h5/login/pages/applogin?sessionCode=${state.sessionCode}&userCode=${state.userCode}&classCode=${state.classCode}&userType=${state.userType}&stuId=${state.stuId}'; 'http://${state.ip}:${_server.port}/index.html#/h5/login/pages/applogin?sessionCode=${state.sessionCode}&userCode=${state.userCode}&classCode=${state.classCode}&userType=${state.userType}&stuId=${state.stuId}';
...@@ -270,7 +270,7 @@ class WebCubit extends Cubit<WebState> { ...@@ -270,7 +270,7 @@ class WebCubit extends Cubit<WebState> {
//测试 //测试
void goAuth() { void goAuth() {
// String serverUrl = 'http://${state.ip}:${_server.port}/index.html'; // String serverUrl = 'http://${state.ip}:${_server.port}/index.html';
String serverUrl = 'http://127.0.0.1:${_server.port}/index.html'; String serverUrl = '${Constant.localServerUrl}/index.html';
// String serverUrl = 'http://localdev.banxiaoer.net'; // String serverUrl = 'http://localdev.banxiaoer.net';
_controller.loadRequest(Uri.parse(serverUrl)); _controller.loadRequest(Uri.parse(serverUrl));
} }
...@@ -423,11 +423,11 @@ class WebCubit extends Cubit<WebState> { ...@@ -423,11 +423,11 @@ class WebCubit extends Cubit<WebState> {
).writeAsBytes(data!); ).writeAsBytes(data!);
return { return {
"tempFilePath": 'http://127.0.0.1:${_server.port}/temp${file!.path}', "tempFilePath": '${Constant.localServerTempFileUrl}${file!.path}',
"size": file.lengthSync(), "size": file.lengthSync(),
"width": asset.width, "width": asset.width,
"height": asset.height, "height": asset.height,
"thumbTempFilePath": 'http://127.0.0.1:${_server.port}/temp${thumbnailFile.path}', "thumbTempFilePath": '${Constant.localServerTempFileUrl}${thumbnailFile.path}',
"fileType": file.path.split('/').last.split('.').last, "fileType": file.path.split('/').last.split('.').last,
}; };
} }
...@@ -545,11 +545,11 @@ class WebCubit extends Cubit<WebState> { ...@@ -545,11 +545,11 @@ class WebCubit extends Cubit<WebState> {
).writeAsBytes(data!); ).writeAsBytes(data!);
return { return {
"tempFilePath": 'http://127.0.0.1:${_server.port}/temp${file!.path}', "tempFilePath": '${Constant.localServerTempFileUrl}${file!.path}',
"size": file.lengthSync(), "size": file.lengthSync(),
"width": asset.width, "width": asset.width,
"height": asset.height, "height": asset.height,
"thumbTempFilePath": 'http://127.0.0.1:${_server.port}/temp${thumbnailFile.path}', "thumbTempFilePath": '${Constant.localServerTempFileUrl}${thumbnailFile.path}',
"fileType": file.path.split('/').last.split('.').last, "fileType": file.path.split('/').last.split('.').last,
}; };
} }
...@@ -732,10 +732,7 @@ class WebCubit extends Cubit<WebState> { ...@@ -732,10 +732,7 @@ 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 { return {'tempFilePath': '${Constant.localServerTempFileUrl}$mp3Path', 'duration': duration.inSeconds};
'tempFilePath': 'http://127.0.0.1:${Constant.localServerPort}/temp$mp3Path',
'duration': duration.inSeconds,
};
} }
/// 清空录音 /// 清空录音
......
...@@ -19,7 +19,7 @@ class WechatAuthState extends Equatable { ...@@ -19,7 +19,7 @@ class WechatAuthState extends Equatable {
final String? stuId; final String? stuId;
const WechatAuthState({ const WechatAuthState({
this.ip = '127.0.0.1', this.ip = Constant.localServerHost,
this.result, this.result,
this.sessionCode, this.sessionCode,
this.userCode, this.userCode,
......
class Constant { class Constant {
static const String localServerHost = '127.0.0.1'; /// 应用内部 http 服务
static const int localServerPort = 35982; static const int localServerPort = 35982;
static const String localServerHost = '127.0.0.1';
static const String localServerUrl = 'http://$localServerHost:$localServerPort'; static const String localServerUrl = 'http://$localServerHost:$localServerPort';
static const String localServerTemp = '/temp';
static const String localServerTempFileUrl = '$localServerUrl$localServerTemp';
static const String localServerTest = '/test';
static const String localServerTestFileUrl = '$localServerUrl$localServerTest';
/// obs文件分片上传的分片大小:5M
static const int obsUploadChunkSize = 1024 * 1024 * 5;
// static const String h5Server = 'appdev-xj.banxiaoer.net'; /// 测试阶段使用的 h5 服务地址
static const String h5Server = 'appdev-th.banxiaoer.net'; static const String h5Server = 'appdev-xj.banxiaoer.net';
// static const String h5Server = 'appdev-th.banxiaoer.net';
// static const String h5Server = '192.168.1.136';
} }
...@@ -14,6 +14,7 @@ import 'package:appframe/data/repositories/message/image_info_handler.dart'; ...@@ -14,6 +14,7 @@ import 'package:appframe/data/repositories/message/image_info_handler.dart';
import 'package:appframe/data/repositories/message/location_handler.dart'; import 'package:appframe/data/repositories/message/location_handler.dart';
import 'package:appframe/data/repositories/message/network_type_handler.dart'; import 'package:appframe/data/repositories/message/network_type_handler.dart';
import 'package:appframe/data/repositories/message/open_document_handler.dart'; import 'package:appframe/data/repositories/message/open_document_handler.dart';
import 'package:appframe/data/repositories/message/open_link_handler.dart';
import 'package:appframe/data/repositories/message/open_weapp_handler.dart'; import 'package:appframe/data/repositories/message/open_weapp_handler.dart';
import 'package:appframe/data/repositories/message/orientation_handler.dart'; import 'package:appframe/data/repositories/message/orientation_handler.dart';
import 'package:appframe/data/repositories/message/save_file_to_disk_handler.dart'; import 'package:appframe/data/repositories/message/save_file_to_disk_handler.dart';
...@@ -159,6 +160,9 @@ Future<void> setupLocator() async { ...@@ -159,6 +160,9 @@ Future<void> setupLocator() async {
/// 设置标题和返回按钮 /// 设置标题和返回按钮
getIt.registerLazySingleton<MessageHandler>(() => SetTitleHandler(), instanceName: 'setTitle'); getIt.registerLazySingleton<MessageHandler>(() => SetTitleHandler(), instanceName: 'setTitle');
/// 新路由打开链接
getIt.registerLazySingleton<MessageHandler>(() => OpenLinkHandler(), instanceName: 'openlink');
/// 登录 /// 登录
getIt.registerLazySingleton<MessageHandler>(() => GoLoginHandler(), instanceName: 'goLogin'); getIt.registerLazySingleton<MessageHandler>(() => GoLoginHandler(), instanceName: 'goLogin');
......
import 'package:appframe/ui/pages/link_page.dart';
import 'package:appframe/ui/pages/scan_code_page.dart'; import 'package:appframe/ui/pages/scan_code_page.dart';
import 'package:appframe/ui/pages/web_page.dart'; import 'package:appframe/ui/pages/web_page.dart';
import 'package:appframe/ui/pages/wechat_auth_page.dart'; import 'package:appframe/ui/pages/wechat_auth_page.dart';
...@@ -25,5 +26,11 @@ final GoRouter router = GoRouter( ...@@ -25,5 +26,11 @@ final GoRouter router = GoRouter(
return const ScanCodePage(); return const ScanCodePage();
}, },
), ),
GoRoute(
path: '/link',
builder: (BuildContext context, GoRouterState state) {
return const LinkPage();
},
),
], ],
); );
...@@ -87,13 +87,13 @@ class ChooseFileHandler extends MessageHandler { ...@@ -87,13 +87,13 @@ class ChooseFileHandler extends MessageHandler {
// 返回临时文件信息 // 返回临时文件信息
return { return {
'tempFilePath': 'http://127.0.0.1:${Constant.localServerPort}/temp${file.path}', 'tempFilePath': '${Constant.localServerTempFileUrl}${file.path}',
'size': file.size, 'size': file.size,
'width': isImage ? imgWidth : (isVideo ? videoWidth : ''), 'width': isImage ? imgWidth : (isVideo ? videoWidth : ''),
'height': isImage ? imgHeight : (isVideo ? videoHeight : ''), 'height': isImage ? imgHeight : (isVideo ? videoHeight : ''),
'thumbTempFilePath': isImage 'thumbTempFilePath': isImage
? 'http://127.0.0.1:${Constant.localServerPort}/temp$imgThumbFilePath' ? '${Constant.localServerTempFileUrl}$imgThumbFilePath'
: (isVideo ? 'http://127.0.0.1:${Constant.localServerPort}/temp$videoThumbFilePath' : ''), : (isVideo ? '${Constant.localServerTempFileUrl}$videoThumbFilePath' : ''),
'fileType': file.extension, 'fileType': file.extension,
}; };
} }
......
...@@ -48,189 +48,3 @@ class ChooseImageHandler extends MessageHandler { ...@@ -48,189 +48,3 @@ class ChooseImageHandler extends MessageHandler {
_webCubit!.setChooseImageCmdFlag(true, _message!); _webCubit!.setChooseImageCmdFlag(true, _message!);
} }
} }
// import 'dart:io';
//
// import 'package:appframe/services/dispatcher.dart';
// import 'package:flutter_image_compress/flutter_image_compress.dart';
// import 'package:image_picker/image_picker.dart';
// import 'package:image_size_getter/file_input.dart';
// import 'package:image_size_getter/image_size_getter.dart';
// import 'package:path/path.dart' as path;
// import 'package:path_provider/path_provider.dart';
//
// class ChooseImageHandler extends MessageHandler {
// @override
// Future<dynamic> handleMessage(dynamic params) async {
// if (params is! Map<String, dynamic>) {
// throw Exception('参数错误');
// }
// var sourceType = params['sourceType'] as String;
// if (sourceType != 'album' && sourceType != 'camera') {
// throw Exception('参数错误');
// }
// // 暂时忽略对此参数的处理
// List<dynamic>? sizeType;
// if (params.containsKey('sizeType')) {
// sizeType = params['sizeType'] as List<dynamic>;
// if (sizeType.isEmpty || sizeType.length > 2) {
// throw Exception('参数错误');
// }
// }
//
// int count = 9;
// if (params.containsKey('count')) {
// count = params['count'] as int;
// if (count < 1 || count > 9) {
// throw Exception('参数错误');
// }
// }
//
// // 从相册选择
// if (sourceType == 'album') {
// if (count == 1) {
// return await _selectSingle();
// } else {
// return await _selectMulti(count);
// }
// }
// // 拍照
// else {
// return await _cameraSingle();
// }
// }
//
// ///
// /// 选择单张图片
// ///
// /// 将选择的图片放到应用的临时目录中,并在路径前面添加“/temp”,返回给调用方后,调用方可通过http方式访问图片
// ///
// Future<List<Map<String, dynamic>>?> _selectSingle() async {
// final ImagePicker picker = ImagePicker();
//
// final XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);
//
// // 用户取消选择,返回空数组
// if (pickedFile == null) {
// return [];
// }
//
// // 获取临时目录
// final Directory tempDir = await getTemporaryDirectory();
//
// return [await _handleOne(pickedFile, tempDir)];
// }
//
// ///
// /// 选择多张图片
// ///
// /// 将选择的图片放到应用的临时目录中,并在每个文件路径前面添加“/temp”,返回给调用方后,调用方可通过http方式访问图片
// ///
// Future<List<Map<String, dynamic>>?> _selectMulti(int limit) async {
// final ImagePicker picker = ImagePicker();
//
// final List<XFile> pickedFileList = await picker.pickMultiImage(limit: limit);
//
// // 用户取消选择,返回空数组
// if (pickedFileList.isEmpty) {
// return [];
// }
//
// // 限制最多limit张
// if (pickedFileList.length > limit) {
// pickedFileList.removeRange(limit, pickedFileList.length);
// }
//
// // 获取临时目录
// final Directory tempDir = await getTemporaryDirectory();
//
// final List<Map<String, dynamic>> result = [];
// for (final XFile? file in pickedFileList) {
// if (file != null) {
// result.add(await _handleOne(file, tempDir));
// }
// }
//
// return result;
// }
//
// ///
// /// 拍照
// ///
// Future<List<Map<String, dynamic>>?> _cameraSingle() async {
// final ImagePicker picker = ImagePicker();
//
// final XFile? pickedFile = await picker.pickImage(source: ImageSource.camera);
//
// // 用户取消选择,返回空数组
// if (pickedFile == null) {
// return [];
// }
//
// // 获取临时目录
// final Directory tempDir = await getTemporaryDirectory();
//
// return [await _handleOne(pickedFile, tempDir)];
// }
//
// Future<Map<String, dynamic>> _handleOne3(XFile pickedFile, Directory tempDir) async {
// // 生成唯一文件名
// final String fileName = path.basename(pickedFile.path);
// final String uniqueFileName = '${DateTime.now().millisecondsSinceEpoch}_$fileName';
//
// // 创建目标文件路径
// final String tempFilePath = path.join(tempDir.path, uniqueFileName);
//
// // 复制文件到临时目录
// var sourceFile = File(pickedFile.path);
// final File copiedFile = await sourceFile.copy(tempFilePath);
//
// // 通过image_size_getter获取图片尺寸
// final sizeResult = ImageSizeGetter.getSizeResult(FileInput(sourceFile));
// final thumbnailPath = await _genThumbnail(sourceFile, tempDir);
//
// // 返回一个元素的数组
// return {
// "tempFilePath": "/temp${copiedFile.path}",
// "size": copiedFile.lengthSync(),
// "width": sizeResult.size.width,
// "height": sizeResult.size.height,
// "thumbTempFilePath": '/temp$thumbnailPath',
// "fileType": copiedFile.path.split('/').last.split('.').last,
// };
// }
//
// Future<Map<String, dynamic>> _handleOne(XFile pickedFile, Directory tempDir) async {
// var sourceFile = File(pickedFile.path);
//
// // 通过image_size_getter获取图片尺寸
// final sizeResult = ImageSizeGetter.getSizeResult(FileInput(sourceFile));
// final thumbnailPath = await _genThumbnail(sourceFile, tempDir);
//
// // 返回一个元素的数组
// return {
// "tempFilePath": "/temp${sourceFile.path}",
// "size": sourceFile.lengthSync(),
// "width": sizeResult.size.width,
// "height": sizeResult.size.height,
// "thumbTempFilePath": '/temp$thumbnailPath',
// "fileType": sourceFile.path.split('/').last.split('.').last,
// };
// }
//
// Future<String?> _genThumbnail(File imageFile, Directory tempDir) async {
// try {
// // 缩略图路径
// final tempPath = tempDir.path;
// final targetPath = '$tempPath/thumbnail_${DateTime.now().millisecondsSinceEpoch}.jpg';
//
// // 压缩生成缩略图文件
// final compressedFile = await FlutterImageCompress.compressAndGetFile(imageFile.absolute.path, targetPath);
//
// return compressedFile!.path;
// } catch (e) {
// print('生成缩略图出错: $e');
// return null;
// }
// }
// }
...@@ -30,19 +30,19 @@ class CropImageHandler extends MessageHandler { ...@@ -30,19 +30,19 @@ class CropImageHandler extends MessageHandler {
try { try {
String outputPath = await _cropImageByRatio(url, cropScale); String outputPath = await _cropImageByRatio(url, cropScale);
return {'tempFilePath': 'http://127.0.0.1:${Constant.localServerPort}/temp$outputPath'}; return {'tempFilePath': '${Constant.localServerTempFileUrl}$outputPath'};
} catch (e) { } catch (e) {
throw Exception('裁剪出错'); throw Exception('裁剪出错');
} }
} }
Future<String> _cropImageByRatio(String url, String cropScale) async { Future<String> _cropImageByRatio(String url, String cropScale) async {
if (url.startsWith('http://127.0.0.1:${Constant.localServerPort}')) { if (url.startsWith(Constant.localServerUrl)) {
url = url.replaceFirst('http://127.0.0.1:${Constant.localServerPort}', ''); url = url.replaceFirst(Constant.localServerUrl, '');
} }
if (url.startsWith('/temp')) { if (url.startsWith(Constant.localServerTemp)) {
url = url.substring(5); url = url.replaceFirst(Constant.localServerTemp, '');
} }
String extension = path.extension(url); String extension = path.extension(url);
......
...@@ -15,12 +15,12 @@ class OpenDocumentHandler extends MessageHandler { ...@@ -15,12 +15,12 @@ class OpenDocumentHandler extends MessageHandler {
throw Exception('参数错误'); throw Exception('参数错误');
} }
if (url.startsWith('http://127.0.0.1:${Constant.localServerPort}')) { if (url.startsWith(Constant.localServerUrl)) {
url = url.replaceFirst('http://127.0.0.1:${Constant.localServerPort}', ''); url = url.replaceFirst(Constant.localServerUrl, '');
} }
if (url.startsWith('/temp')) { if (url.startsWith(Constant.localServerTemp)) {
url = url.substring(5); url = url.replaceFirst(Constant.localServerTemp, '');
} }
if (url.startsWith('http')) { if (url.startsWith('http')) {
......
import 'package:appframe/config/routes.dart';
import 'package:appframe/services/dispatcher.dart';
class OpenLinkHandler extends MessageHandler {
@override
Future<bool> handleMessage(params) async {
if (params is! Map<String, dynamic>) {
throw Exception('参数错误');
}
final String url = params['url'] as String;
if (url.isEmpty) {
throw Exception('参数错误');
}
return _openLink(url);
}
bool _openLink(String url) {
router.push('/link', extra: {'url': url});
return true;
}
}
...@@ -47,21 +47,28 @@ class UploadFileHandler extends MessageHandler { ...@@ -47,21 +47,28 @@ class UploadFileHandler extends MessageHandler {
String busi = fileParams['busi'] as String; String busi = fileParams['busi'] as String;
String subBusi = fileParams['subBusi'] as String; String subBusi = fileParams['subBusi'] as String;
if (filePath.startsWith('http://127.0.0.1:${Constant.localServerPort}')) { print('参数-------');
filePath = filePath.replaceFirst('http://127.0.0.1:${Constant.localServerPort}', ''); print('filePath:$filePath ');
print('busi:$busi ');
print('subBusi:$subBusi ');
print('参数-------');
if (filePath.startsWith(Constant.localServerUrl)) {
filePath = filePath.replaceFirst(Constant.localServerUrl, '');
} }
if (filePath.startsWith('/temp')) { if (filePath.startsWith(Constant.localServerTemp)) {
filePath = filePath.substring(5); filePath = filePath.replaceFirst(Constant.localServerTemp, '');
} }
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': ''});
String logicPrefix = _getLoginPrefix(busi, subBusi);
print('logicPrefix: $logicPrefix');
//并行上传分段 //并行上传分段
final uploadResult = await _uploadInParallel(bxeApiService, obsApiService, logicPrefix, filePath); final uploadResult = await _uploadInParallel(bxeApiService, obsApiService, logicPrefix, filePath);
String objectKey = uploadResult['objectKey'] as String; String objectKey = uploadResult['objectKey'] as String;
...@@ -70,13 +77,14 @@ class UploadFileHandler extends MessageHandler { ...@@ -70,13 +77,14 @@ class UploadFileHandler extends MessageHandler {
Map<int, String> tagsMap = uploadResult['tagsMap'] as Map<int, String>; Map<int, String> tagsMap = uploadResult['tagsMap'] as Map<int, String>;
//请求合并文件 //请求合并文件
Response response = await _merge(bxeApiService, objectKey, bucket, uploadId, tagsMap); String location = await _merge(bxeApiService, objectKey, bucket, uploadId, tagsMap);
print('location: $location');
//关闭Dio //关闭Dio
bxeApiService.close(); bxeApiService.close();
obsApiService.close(); obsApiService.close();
return {'url': _addPreUrl(response.data["location"])}; return {'url': _addPreUrl(location)};
} }
/// 并行上传 /// 并行上传
...@@ -98,8 +106,8 @@ class UploadFileHandler extends MessageHandler { ...@@ -98,8 +106,8 @@ class UploadFileHandler extends MessageHandler {
throw Exception('上传的文件过大'); throw Exception('上传的文件过大');
} }
//分段大小5M //分段大小2M
final chunkSize = 1024 * 1024 * 5; final chunkSize = Constant.obsUploadChunkSize;
//分段总数 //分段总数
final totalChunks = (fileSize / chunkSize).ceil(); final totalChunks = (fileSize / chunkSize).ceil();
...@@ -119,6 +127,7 @@ class UploadFileHandler extends MessageHandler { ...@@ -119,6 +127,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 = '$logicPrefix/${uuid.v4()}${path.extension(file.path)}'; String objectKey = '$logicPrefix/${uuid.v4()}${path.extension(file.path)}';
print('objectKey: $objectKey');
String uploadId = ''; String uploadId = '';
Map<int, String> tagsMap = {}; Map<int, String> tagsMap = {};
...@@ -146,6 +155,7 @@ class UploadFileHandler extends MessageHandler { ...@@ -146,6 +155,7 @@ class UploadFileHandler extends MessageHandler {
final nextResult = await _next(bxeApiService, objectKey, bucket, uploadId, i + 1); final nextResult = await _next(bxeApiService, objectKey, bucket, uploadId, i + 1);
chunkSignUrl = nextResult['signed_url'] as String; chunkSignUrl = nextResult['signed_url'] as String;
} }
print('chunkSignUrl: $chunkSignUrl');
// await _uploadChunkWithRetry(obsApiService, chunkSignUrl, i, chunk, tagsMap); // await _uploadChunkWithRetry(obsApiService, chunkSignUrl, i, chunk, tagsMap);
final future = _uploadChunkWithRetry(obsApiService, chunkSignUrl, i, chunk, tagsMap); final future = _uploadChunkWithRetry(obsApiService, chunkSignUrl, i, chunk, tagsMap);
...@@ -224,7 +234,7 @@ class UploadFileHandler extends MessageHandler { ...@@ -224,7 +234,7 @@ class UploadFileHandler extends MessageHandler {
} }
/// 请求合并文件 /// 请求合并文件
static Future<Response> _merge( static Future<String> _merge(
ApiService bxeApiService, ApiService bxeApiService,
String objectKey, String objectKey,
String bucket, String bucket,
...@@ -247,7 +257,7 @@ class UploadFileHandler extends MessageHandler { ...@@ -247,7 +257,7 @@ class UploadFileHandler extends MessageHandler {
throw Exception('合并文件失败'); throw Exception('合并文件失败');
} }
return response; return response.data["location"];
} }
static String _getLoginPrefix(String busi, String subBusi) { static String _getLoginPrefix(String busi, String subBusi) {
...@@ -256,18 +266,17 @@ class UploadFileHandler extends MessageHandler { ...@@ -256,18 +266,17 @@ class UploadFileHandler extends MessageHandler {
var month = now.month; var month = now.month;
var day = now.day; var day = now.day;
return '/d2/pridel/user/$year$month$day/bxe/${busi}_$subBusi'; return 'd2/pridel/user/$year$month$day/bxe/${busi}_$subBusi';
} }
static String _addPreUrl(String location) { static String _addPreUrl(String location) {
// /bxe-pics//d2/pridel/user/20251017/bxe/bxe_homework/f4ea233d-9e1b-4a3f-bc8f-b64e776f42a6.jpg // /bxe-pics/d2/pridel/user/20251017/bxe/bxe_homework/f4ea233d-9e1b-4a3f-bc8f-b64e776f42a6.jpg
// 多了一个斜杠,暂时多截取1位
if (location.startsWith('/bxe-files')) { if (location.startsWith('/bxe-files')) {
return 'https://files-obs.banxiaoer.com${location.substring(11)}'; return 'https://files-obs.banxiaoer.com${location.substring(10)}';
} else if (location.startsWith('/bxe-pics')) { } else if (location.startsWith('/bxe-pics')) {
return 'https://pics-obs.banxiaoer.com${location.substring(10)}'; return 'https://pics-obs.banxiaoer.com${location.substring(9)}';
} else if (location.startsWith('/bxe-videos')) { } else if (location.startsWith('/bxe-videos')) {
return 'https://videos-obs.banxiaoer.com${location.substring(12)}'; return 'https://videos-obs.banxiaoer.com${location.substring(11)}';
} else { } else {
return location; return location;
} }
......
...@@ -21,10 +21,10 @@ class LocalServerService { ...@@ -21,10 +21,10 @@ class LocalServerService {
final String requestPath = request.uri.path == '/' ? '/index.html' : request.uri.path; final String requestPath = request.uri.path == '/' ? '/index.html' : request.uri.path;
try { try {
if (requestPath.startsWith('/temp/')) { if (requestPath.startsWith('${Constant.localServerTemp}/')) {
// 目录文件服务逻辑 // 目录文件服务逻辑
await _serveTempFile(request, requestPath); await _serveTempFile(request, requestPath);
} else if (requestPath.startsWith('/test/')) { } else if (requestPath.startsWith('${Constant.localServerTest}/')) {
// 内部assets文件服务逻辑 // 内部assets文件服务逻辑
await _serveAssetFile(request, requestPath); await _serveAssetFile(request, requestPath);
} else { } else {
...@@ -48,7 +48,7 @@ class LocalServerService { ...@@ -48,7 +48,7 @@ class LocalServerService {
try { try {
// 临时文件路径 // 临时文件路径
// 构建文件路径(移除 /temp 前缀) // 构建文件路径(移除 /temp 前缀)
final String filePath = requestPath.substring('/temp/'.length); final String filePath = requestPath.substring(Constant.localServerTemp.length);
// 检查文件是否存在 // 检查文件是否存在
final File file = File(filePath); final File file = File(filePath);
...@@ -108,7 +108,7 @@ class LocalServerService { ...@@ -108,7 +108,7 @@ class LocalServerService {
// 访问assets目录下的文件 // 访问assets目录下的文件
Future<void> _serveAssetFile(HttpRequest request, String requestPath) async { Future<void> _serveAssetFile(HttpRequest request, String requestPath) async {
// 构建文件路径(移除 /test 前缀) // 构建文件路径(移除 /test 前缀)
final String path = requestPath.substring('/test'.length); final String path = requestPath.substring(Constant.localServerTest.length);
final String filePath = 'assets$path'; final String filePath = 'assets$path';
try { try {
......
import 'package:appframe/bloc/link_cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:webview_flutter/webview_flutter.dart';
class LinkPage extends StatelessWidget {
const LinkPage({super.key});
@override
Widget build(BuildContext buildContext) {
final Map<String, dynamic>? extraData = GoRouterState.of(buildContext).extra as Map<String, dynamic>?;
final String? url = extraData?['url'];
return BlocProvider(
create: (context) => LinkCubit(LinkState(loaded: false, url: url!)),
child: BlocConsumer<LinkCubit, LinkState>(
builder: (ctx, state) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
ctx.read<LinkCubit>().handleBack(ctx);
},
child: Scaffold(
appBar: AppBar(
title: Text('adv'),
centerTitle: true,
automaticallyImplyLeading: false,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () async {
await ctx.read<LinkCubit>().handleBack(ctx);
},
),
),
body: state.loaded
? SizedBox(
height: MediaQuery.of(ctx).size.height - 120, // 减去100像素留空
child: WebViewWidget(controller: ctx.read<LinkCubit>().controller),
)
: const Center(child: CircularProgressIndicator()),
),
);
},
listener: (context, state) {},
),
);
}
}
import 'package:appframe/bloc/web_cubit.dart'; import 'package:appframe/bloc/web_cubit.dart';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart'; import 'package:appframe/config/locator.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
...@@ -13,7 +14,7 @@ class WebPage extends StatelessWidget { ...@@ -13,7 +14,7 @@ class WebPage extends StatelessWidget {
Widget build(BuildContext buildContext) { Widget build(BuildContext buildContext) {
final Map<String, dynamic>? extraData = GoRouterState.of(buildContext).extra as Map<String, dynamic>?; final Map<String, dynamic>? extraData = GoRouterState.of(buildContext).extra as Map<String, dynamic>?;
var ip = extraData?['ip'] ?? '127.0.0.1'; var ip = extraData?['ip'] ?? Constant.localServerHost;
var sessionCode = extraData?['sessionCode']; var sessionCode = extraData?['sessionCode'];
var userCode = extraData?['userCode']; var userCode = extraData?['userCode'];
var classCode = extraData?['classCode']; var classCode = extraData?['classCode'];
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!