209 lines
6.2 KiB
Dart
209 lines
6.2 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:app/config/theme/base/app_theme_ext.dart';
|
|
import 'package:app/utils/transfer/upload.dart';
|
|
import 'package:app/widgets/base/actionSheet/action_sheet.dart';
|
|
import 'package:app/widgets/base/actionSheet/type.dart';
|
|
import 'package:app/widgets/base/button/index.dart';
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
|
|
import '../common/preview/file_previewer.dart';
|
|
|
|
///快捷打开文件弹窗
|
|
void showFileDialog(
|
|
BuildContext context, {
|
|
bool isUpload = true,
|
|
String? name,
|
|
List<String> files = const [],
|
|
ValueChanged<List<String>>? onConfirm,
|
|
}) {
|
|
showGeneralDialog(
|
|
context: context,
|
|
barrierDismissible: true,
|
|
// 点击外部关闭
|
|
barrierLabel: "RightSheet",
|
|
pageBuilder: (context, animation, secondaryAnimation) {
|
|
return FileDrawer(
|
|
name: name,
|
|
isUpload: isUpload,
|
|
files: files,
|
|
onConfirm: onConfirm,
|
|
);
|
|
},
|
|
transitionBuilder: (context, animation, secondaryAnimation, child) {
|
|
final tween = Tween<Offset>(begin: Offset(1, 0), end: Offset(0, 0));
|
|
return SlideTransition(
|
|
position: tween.animate(animation),
|
|
child: child,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
///文件弹窗
|
|
class FileDrawer extends StatefulWidget {
|
|
final String? name;
|
|
final List<String> files;
|
|
final bool isUpload;
|
|
final ValueChanged<List<String>>? onConfirm;
|
|
|
|
const FileDrawer({
|
|
super.key,
|
|
this.name,
|
|
this.isUpload = true,
|
|
this.files = const [],
|
|
this.onConfirm,
|
|
});
|
|
|
|
@override
|
|
State<FileDrawer> createState() => _FileDrawerState();
|
|
}
|
|
|
|
class _FileDrawerState extends State<FileDrawer> {
|
|
///文件列表
|
|
List<String> _fileList = [];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_fileList = List<String>.from(widget.files);
|
|
}
|
|
|
|
///打开选择面板
|
|
void _handOpenActionSheet() {
|
|
showActionSheet(
|
|
context,
|
|
showCancel: true,
|
|
actions: [
|
|
ActionSheetItem(title: "拍照", value: 1),
|
|
ActionSheetItem(title: "选择图片", value: 2),
|
|
ActionSheetItem(title: "选择PDF", value: 3),
|
|
],
|
|
onConfirm: (res) async {
|
|
List<File> filesToUpload = [];
|
|
try {
|
|
if (res.value == 1) {
|
|
final ImagePicker picker = ImagePicker();
|
|
final XFile? photo = await picker.pickImage(source: ImageSource.camera);
|
|
|
|
if (photo == null) return; // 用户取消
|
|
filesToUpload.add(File(photo.path));
|
|
} else if (res.value == 2) {
|
|
//选择图片
|
|
final result = await FilePicker.platform.pickFiles(
|
|
allowMultiple: true,
|
|
type: FileType.image,
|
|
);
|
|
if (result == null) return;
|
|
filesToUpload.addAll(result.paths.whereType<String>().map((e) => File(e)));
|
|
} else if (res.value == 3) {
|
|
//选择pdf
|
|
final result = await FilePicker.platform.pickFiles(
|
|
allowMultiple: true,
|
|
type: FileType.custom,
|
|
allowedExtensions: ['pdf'],
|
|
);
|
|
if (result == null) return;
|
|
filesToUpload.addAll(result.paths.whereType<String>().map((e) => File(e)));
|
|
}
|
|
if (filesToUpload.isEmpty) return;
|
|
// 4) 上传文件
|
|
EasyLoading.show(status: "文件上传中");
|
|
|
|
final uploadTasks = filesToUpload.map((file) {
|
|
return QinUpload.upload(
|
|
file: file,
|
|
path: "room/classroom",
|
|
);
|
|
});
|
|
final List<String> uploadedPaths = (await Future.wait(
|
|
uploadTasks,
|
|
)).whereType<String>().toList();
|
|
|
|
EasyLoading.dismiss();
|
|
|
|
// 更新 UI
|
|
setState(() => _fileList.addAll(uploadedPaths));
|
|
|
|
// 回调
|
|
widget.onConfirm?.call(uploadedPaths);
|
|
} catch (e) {
|
|
print(e);
|
|
EasyLoading.showToast("文件上传失败");
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Align(
|
|
alignment: Alignment.centerRight,
|
|
child: Container(
|
|
width: 300,
|
|
color: Colors.white,
|
|
padding: EdgeInsets.all(context.pagePadding),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"${widget.name ?? ""}上传文件列表",
|
|
style: Theme.of(context).textTheme.titleSmall,
|
|
),
|
|
Expanded(
|
|
child: Visibility(
|
|
visible: _fileList.isNotEmpty,
|
|
replacement: Align(
|
|
child: Text("未上传文件"),
|
|
),
|
|
child: ListView.separated(
|
|
padding: EdgeInsets.symmetric(vertical: 15),
|
|
itemBuilder: (_, index) {
|
|
String item = _fileList[index];
|
|
String suffix = item.split(".").last;
|
|
return InkWell(
|
|
key: Key(item),
|
|
onTap: () {
|
|
showFilePreviewer(context, url: item);
|
|
},
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
child: Text("文件${index + 1}.$suffix", style: TextStyle(fontSize: 14)),
|
|
),
|
|
);
|
|
},
|
|
separatorBuilder: (_, __) => SizedBox(height: 15),
|
|
itemCount: _fileList.length,
|
|
),
|
|
),
|
|
),
|
|
Visibility(
|
|
visible: widget.isUpload,
|
|
child: Button(
|
|
text: "上传",
|
|
onPressed: _handOpenActionSheet,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
///数据类
|
|
class UploadFileItem {
|
|
String url;
|
|
String name;
|
|
bool loading;
|
|
|
|
UploadFileItem({required this.url, this.loading = false, required this.name});
|
|
}
|