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> fetchCategories() async { final data = await ApiClient.get>(Endpoints.categories); return data .whereType>() .map(VideoCategory.fromJson) .toList(); } /// 5.5 获取上传凭证(开发环境返回 server 中转模式) static Future fetchUploadToken({ required String fileName, required int fileSize, }) async { final data = await ApiClient.post>( Endpoints.uploadToken, data: {'file_name': fileName, 'file_size': fileSize}, ); return UploadTokenInfo.fromJson(data); } /// 5.5 配套:multipart 中转上传(字段 object_key + file) static Future uploadFile({ required String objectKey, required String filePath, required String fileName, void Function(int sent, int total)? onProgress, }) async { final data = await ApiClient.post>( 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 publish({ required String objectKey, required String title, String description = '', required int categoryId, List tags = const [], }) async { final data = await ApiClient.post>( 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 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 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 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 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, ); }