二次开发源码提交

This commit is contained in:
2026-05-15 08:52:48 +08:00
parent 4131f7321a
commit eb35a1d067
191 changed files with 34566 additions and 0 deletions
+255
View File
@@ -0,0 +1,255 @@
import 'dart:io';
/// 上传状态
enum UploadStatus {
waiting, // 等待中
uploading, // 上传中
completed, // 已完成
paused, // 已暂停
failed, // 失败
cancelled, // 已取消
}
/// 上传会话模型(从 API 返回的上传会话信息)
class UploadSessionModel {
final String sessionId;
final String? uploadId;
final int chunkSize;
final int expires;
final List<String>? uploadUrls;
final String? credential;
final String? completeUrl;
final StoragePolicyModel storagePolicy;
final String? mimeType;
final String? uploadPolicy;
final String? callbackSecret;
UploadSessionModel({
required this.sessionId,
this.uploadId,
required this.chunkSize,
required this.expires,
this.uploadUrls,
this.credential,
this.completeUrl,
required this.storagePolicy,
this.mimeType,
this.uploadPolicy,
this.callbackSecret,
});
factory UploadSessionModel.fromJson(Map<String, dynamic> json) {
return UploadSessionModel(
sessionId: json['session_id'] as String,
uploadId: json['upload_id'] as String?,
chunkSize: json['chunk_size'] as int,
expires: json['expires'] as int,
uploadUrls: json['upload_urls'] != null
? (json['upload_urls'] as List).map((e) => e as String).toList()
: null,
credential: json['credential'] as String?,
completeUrl: json['completeURL'] as String?,
storagePolicy: StoragePolicyModel.fromJson(json['storage_policy'] as Map<String, dynamic>),
mimeType: json['mime_type'] as String?,
uploadPolicy: json['upload_policy'] as String?,
callbackSecret: json['callback_secret'] as String?,
);
}
/// 是否支持分片上传
bool get isMultipartEnabled => chunkSize > 0;
/// 是否使用中继上传(上传到 Cloudreve 服务器)
bool get isRelayUpload => storagePolicy.relay == true || storagePolicy.type == 'local';
}
/// 存储策略模型
class StoragePolicyModel {
final String id;
final String name;
final String type;
final int maxSize;
final bool? relay;
StoragePolicyModel({
required this.id,
required this.name,
required this.type,
required this.maxSize,
this.relay,
});
factory StoragePolicyModel.fromJson(Map<String, dynamic> json) {
return StoragePolicyModel(
id: json['id'] as String,
name: json['name'] as String,
type: json['type'] as String,
maxSize: json['max_size'] as int,
relay: json['relay'] as bool?,
);
}
}
/// 上传任务模型
class UploadTaskModel {
final String id;
final File file;
final String fileName;
final int fileSize;
final String targetPath; // 目标路径,例如 cloudreve://my/subfolder
final DateTime createdAt;
DateTime? completedAt;
final UploadStatus status;
final int uploadedBytes;
final double progress;
final int uploadedChunks; // 已上传的分片数量
final int totalChunks; // 总分片数量
final String? errorMessage;
final UploadSessionModel? session; // 上传会话信息
final int speed; // 上传速度,字节/秒
UploadTaskModel({
required this.id,
required this.file,
required this.fileName,
required this.fileSize,
required this.targetPath,
DateTime? createdAt,
this.completedAt,
UploadStatus? status,
this.uploadedBytes = 0,
this.progress = 0,
this.uploadedChunks = 0,
this.totalChunks = 1,
this.errorMessage,
this.session,
this.speed = 0,
}) : createdAt = createdAt ?? DateTime.now(),
status = status ?? UploadStatus.waiting;
/// 计算总分片数
int calculateTotalChunks(int chunkSize) {
if (chunkSize <= 0) return 1;
return (fileSize / chunkSize).ceil();
}
/// 获取状态文本
String get statusText {
switch (status) {
case UploadStatus.waiting:
return '等待中';
case UploadStatus.uploading:
return '上传中...';
case UploadStatus.completed:
return '上传完成';
case UploadStatus.paused:
return '已暂停';
case UploadStatus.failed:
return '上传失败';
case UploadStatus.cancelled:
return '已取消';
}
}
/// 获取进度文本
String get progressText {
if (status == UploadStatus.completed) {
return '100%';
}
return '${(progress * 100).toStringAsFixed(1)}%';
}
/// 获取可读的文件大小
String get readableFileSize {
if (fileSize < 1024) {
return '$fileSize B';
} else if (fileSize < 1024 * 1024) {
return '${(fileSize / 1024).toStringAsFixed(1)} KB';
} else if (fileSize < 1024 * 1024 * 1024) {
return '${(fileSize / (1024 * 1024)).toStringAsFixed(1)} MB';
} else {
return '${(fileSize / (1024 * 1024 * 1024)).toStringAsFixed(1)} GB';
}
}
/// 获取可读的上传速度
String get speedText {
if (speed <= 0) return '';
if (speed < 1024) return '$speed B/s';
if (speed < 1024 * 1024) return '${(speed / 1024).toStringAsFixed(1)} KB/s';
return '${(speed / (1024 * 1024)).toStringAsFixed(1)} MB/s';
}
/// 克隆任务
UploadTaskModel copyWith({
UploadStatus? status,
int? uploadedBytes,
double? progress,
int? uploadedChunks,
int? totalChunks,
String? errorMessage,
UploadSessionModel? session,
DateTime? completedAt,
int? speed,
}) {
return UploadTaskModel(
id: id,
file: file,
fileName: fileName,
fileSize: fileSize,
targetPath: targetPath,
createdAt: createdAt,
completedAt: completedAt ?? this.completedAt,
status: status ?? this.status,
uploadedBytes: uploadedBytes ?? this.uploadedBytes,
progress: progress ?? this.progress,
uploadedChunks: uploadedChunks ?? this.uploadedChunks,
totalChunks: totalChunks ?? this.totalChunks,
errorMessage: errorMessage ?? this.errorMessage,
session: session ?? this.session,
speed: speed ?? this.speed,
);
}
/// 转换为 JSON(用于持久化)
Map<String, dynamic> toJson() {
return {
'id': id,
'file_path': file.path,
'file_name': fileName,
'file_size': fileSize,
'target_path': targetPath,
'created_at': createdAt.toIso8601String(),
'completed_at': completedAt?.toIso8601String(),
'status': status.index,
'uploaded_bytes': uploadedBytes,
'progress': progress,
'uploaded_chunks': uploadedChunks,
'total_chunks': totalChunks,
'error_message': errorMessage,
'speed': speed,
};
}
/// 从 JSON 创建(用于持久化恢复)
factory UploadTaskModel.fromJson(Map<String, dynamic> json) {
return UploadTaskModel(
id: json['id'] as String,
file: File(json['file_path'] as String),
fileName: json['file_name'] as String,
fileSize: json['file_size'] as int,
targetPath: json['target_path'] as String,
createdAt: DateTime.parse(json['created_at'] as String),
completedAt: json['completed_at'] != null
? DateTime.parse(json['completed_at'] as String)
: null,
status: UploadStatus.values[json['status'] as int],
uploadedBytes: json['uploaded_bytes'] as int,
progress: json['progress'] as double,
uploadedChunks: json['uploaded_chunks'] as int,
totalChunks: json['total_chunks'] as int,
errorMessage: json['error_message'] as String?,
speed: json['speed'] as int? ?? 0,
);
}
}