add
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../core/network/api_client.dart';
|
||||
import '../core/network/endpoints.dart';
|
||||
|
||||
/// 上传发布服务(《03-接口文档》5.5 / 5.6 / 5.8)
|
||||
/// 开发环境链路:upload/token(server 中转模式)→ upload/file(multipart)→ 发布
|
||||
class UploadService {
|
||||
UploadService._();
|
||||
|
||||
/// 5.8 分类列表(发布时选择)
|
||||
static Future<List<VideoCategory>> fetchCategories() async {
|
||||
final data = await ApiClient.get<List<dynamic>>(Endpoints.categories);
|
||||
return data
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(VideoCategory.fromJson)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// 5.5 获取上传凭证(开发环境返回 server 中转模式)
|
||||
static Future<UploadTokenInfo> fetchUploadToken({
|
||||
required String fileName,
|
||||
required int fileSize,
|
||||
}) async {
|
||||
final data = await ApiClient.post<Map<String, dynamic>>(
|
||||
Endpoints.uploadToken,
|
||||
data: {'file_name': fileName, 'file_size': fileSize},
|
||||
);
|
||||
return UploadTokenInfo.fromJson(data);
|
||||
}
|
||||
|
||||
/// 5.5 配套:multipart 中转上传(字段 object_key + file)
|
||||
static Future<UploadFileResult> uploadFile({
|
||||
required String objectKey,
|
||||
required String filePath,
|
||||
required String fileName,
|
||||
void Function(int sent, int total)? onProgress,
|
||||
}) async {
|
||||
final data = await ApiClient.post<Map<String, dynamic>>(
|
||||
Endpoints.uploadFile,
|
||||
data: FormData.fromMap({
|
||||
'object_key': objectKey,
|
||||
'file': await MultipartFile.fromFile(filePath, filename: fileName),
|
||||
}),
|
||||
onSendProgress: onProgress,
|
||||
);
|
||||
return UploadFileResult.fromJson(data);
|
||||
}
|
||||
|
||||
/// 5.6 发布视频
|
||||
static Future<PublishResult> publish({
|
||||
required String objectKey,
|
||||
required String title,
|
||||
String description = '',
|
||||
required int categoryId,
|
||||
List<String> tags = const [],
|
||||
}) async {
|
||||
final data = await ApiClient.post<Map<String, dynamic>>(
|
||||
Endpoints.publish,
|
||||
data: {
|
||||
'object_key': objectKey,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'category_id': categoryId,
|
||||
'tags': tags,
|
||||
},
|
||||
);
|
||||
return PublishResult.fromJson(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// 视频分类
|
||||
class VideoCategory {
|
||||
VideoCategory({required this.categoryId, required this.name});
|
||||
|
||||
final int categoryId;
|
||||
final String name;
|
||||
|
||||
factory VideoCategory.fromJson(Map<String, dynamic> json) => VideoCategory(
|
||||
categoryId: (json['category_id'] as num?)?.toInt() ?? 0,
|
||||
name: (json['name'] as String?) ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/// 上传凭证(server 中转模式)
|
||||
class UploadTokenInfo {
|
||||
UploadTokenInfo({
|
||||
required this.uploadType,
|
||||
required this.objectKey,
|
||||
required this.uploadUrl,
|
||||
});
|
||||
|
||||
final String uploadType; // server / oss_sts
|
||||
final String objectKey;
|
||||
final String uploadUrl;
|
||||
|
||||
factory UploadTokenInfo.fromJson(Map<String, dynamic> json) =>
|
||||
UploadTokenInfo(
|
||||
uploadType: (json['upload_type'] as String?) ?? '',
|
||||
objectKey: (json['object_key'] as String?) ?? '',
|
||||
uploadUrl: (json['upload_url'] as String?) ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/// 中转上传结果
|
||||
class UploadFileResult {
|
||||
UploadFileResult({
|
||||
required this.objectKey,
|
||||
required this.url,
|
||||
required this.fileSize,
|
||||
});
|
||||
|
||||
final String objectKey;
|
||||
final String url;
|
||||
final int fileSize;
|
||||
|
||||
factory UploadFileResult.fromJson(Map<String, dynamic> json) =>
|
||||
UploadFileResult(
|
||||
objectKey: (json['object_key'] as String?) ?? '',
|
||||
url: (json['url'] as String?) ?? '',
|
||||
fileSize: (json['file_size'] as num?)?.toInt() ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
/// 发布结果
|
||||
class PublishResult {
|
||||
PublishResult({
|
||||
required this.videoId,
|
||||
required this.status,
|
||||
required this.statusText,
|
||||
required this.isPriority,
|
||||
});
|
||||
|
||||
final int videoId;
|
||||
final int status; // 0转码中 1待审核 2已发布 3拒绝 4下架 5转码失败
|
||||
final String statusText;
|
||||
final bool isPriority; // 会员优先转码
|
||||
|
||||
factory PublishResult.fromJson(Map<String, dynamic> json) => PublishResult(
|
||||
videoId: (json['video_id'] as num?)?.toInt() ?? 0,
|
||||
status: (json['status'] as num?)?.toInt() ?? 0,
|
||||
statusText: (json['status_text'] as String?) ?? '',
|
||||
isPriority: (json['is_priority'] as bool?) ?? false,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user