fix: track flutter mobile data layer

This commit is contained in:
西街长安 2026-05-17 15:24:28 +08:00
parent db458a9a14
commit 14773248d9
9 changed files with 1385 additions and 0 deletions

2
.gitignore vendored
View File

@ -11,6 +11,8 @@ webapi-build.log
webapi-build-no-restore.log
artifacts/
data/
!mobile/lib/features/live_recorder/data/
!mobile/lib/features/live_recorder/data/**
records/
docker-data/
src/LiveRecorder.WebApi/data/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class AuthRepository {
const AuthRepository(this._apiClient);
final ApiClient _apiClient;
Future<LoginResponse> login({
required String username,
required String password,
}) async {
final response = await _apiClient.postJson(
'/api/auth/login',
body: <String, dynamic>{
'username': username,
'password': password,
},
);
return LoginResponse.fromJson(response as Map<String, dynamic>);
}
Future<void> logout() {
return _apiClient.postEmpty('/api/auth/logout');
}
Future<void> changePassword({
required String currentPassword,
required String newPassword,
}) {
return _apiClient.postEmpty(
'/api/auth/change-password',
body: <String, dynamic>{
'currentPassword': currentPassword,
'newPassword': newPassword,
},
);
}
}

View File

@ -0,0 +1,72 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class LiveRoomsRepository {
const LiveRoomsRepository(this._apiClient);
final ApiClient _apiClient;
Future<List<LiveRoom>> listRooms() async {
final response = await _apiClient.getJson('/api/live-rooms') as List<dynamic>;
return response
.map((dynamic item) => LiveRoom.fromJson(item as Map<String, dynamic>))
.toList(growable: false);
}
Future<LiveRoom> getRoom(String roomId) async {
final response = await _apiClient.getJson('/api/live-rooms/$roomId') as Map<String, dynamic>;
return LiveRoom.fromJson(response);
}
Future<LiveRoom> refreshRoom(String roomId) async {
final response = await _apiClient.postJson('/api/live-rooms/$roomId/refresh') as Map<String, dynamic>;
return LiveRoom.fromJson(response);
}
Future<LiveRoom> setRoomEnabled({
required String roomId,
required bool isEnabled,
}) async {
final response = await _apiClient.putJson(
'/api/live-rooms/$roomId/enabled',
body: <String, dynamic>{'isEnabled': isEnabled},
) as Map<String, dynamic>;
return LiveRoom.fromJson(response);
}
Future<LiveRoom> createRoom({
required String url,
int? platformOverride,
}) async {
final response = await _apiClient.postJson(
'/api/live-rooms',
body: <String, dynamic>{
'url': url,
if (platformOverride case final int value) 'platformOverride': value,
},
) as Map<String, dynamic>;
return LiveRoom.fromJson(response);
}
Future<LiveRoom> updateMetadata({
required String roomId,
required Map<String, dynamic> payload,
}) async {
final response = await _apiClient.putJson(
'/api/live-rooms/$roomId/metadata',
body: payload,
) as Map<String, dynamic>;
return LiveRoom.fromJson(response);
}
Future<LiveRoom> updateSettings({
required String roomId,
required Map<String, dynamic> payload,
}) async {
final response = await _apiClient.putJson(
'/api/live-rooms/$roomId/settings',
body: payload,
) as Map<String, dynamic>;
return LiveRoom.fromJson(response);
}
}

View File

@ -0,0 +1,34 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class LogsRepository {
const LogsRepository(this._apiClient);
final ApiClient _apiClient;
Future<List<SystemLog>> listLogs({
String? liveRoomId,
String? recordSessionId,
String? recordTaskId,
int? level,
String? content,
int take = 200,
}) async {
final response = await _apiClient.getJson(
'/api/logs',
queryParameters: <String, String>{
if (liveRoomId != null && liveRoomId.isNotEmpty) 'liveRoomId': liveRoomId,
if (recordSessionId != null && recordSessionId.isNotEmpty) 'recordSessionId': recordSessionId,
if (recordTaskId != null && recordTaskId.isNotEmpty) 'recordTaskId': recordTaskId,
if (level != null) 'level': '$level',
if (content != null && content.trim().isNotEmpty) 'content': content.trim(),
'take': '$take',
},
) as List<dynamic>;
return response
.map((dynamic item) => SystemLog.fromJson(item as Map<String, dynamic>))
.toList(growable: false);
}
}

View File

@ -0,0 +1,39 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class MediaRepository {
const MediaRepository(this._apiClient);
final ApiClient _apiClient;
Future<MediaBrowserResponse> browse({String? path}) async {
final response = await _apiClient.getJson(
'/api/media/browser',
queryParameters: <String, String>{
if (path != null && path.isNotEmpty) 'path': path,
},
) as Map<String, dynamic>;
return MediaBrowserResponse.fromJson(response);
}
Uri buildFileUri({
required String relativePath,
bool download = false,
}) {
return _apiClient.buildUri(
'/api/media/file',
queryParameters: <String, String>{
'path': relativePath,
if (download) 'download': 'true',
},
);
}
Future<String> transcodeFile(String relativePath) async {
final response = await _apiClient.postJson(
'/api/media/transcode-file',
body: <String, dynamic>{'relativePath': relativePath},
) as Map<String, dynamic>;
return response['message']?.toString() ?? '转码任务已提交';
}
}

View File

@ -0,0 +1,82 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class RecordingsRepository {
const RecordingsRepository(this._apiClient);
final ApiClient _apiClient;
Future<List<RecordTask>> listTasks({String? liveRoomId}) async {
final response = await _apiClient.getJson(
'/api/record-tasks',
queryParameters: <String, String>{
if (liveRoomId != null && liveRoomId.isNotEmpty) 'liveRoomId': liveRoomId,
},
) as List<dynamic>;
return response
.map((dynamic item) => RecordTask.fromJson(item as Map<String, dynamic>))
.toList(growable: false);
}
Future<RecordTaskDetail> getTaskDetail(String taskId) async {
final response = await _apiClient.getJson('/api/record-tasks/$taskId') as Map<String, dynamic>;
return RecordTaskDetail.fromJson(response);
}
Future<RecordTask> startRecording({
required String liveRoomId,
required String preferredQuality,
required int outputFormat,
}) async {
final response = await _apiClient.postJson(
'/api/record-tasks/start',
body: <String, dynamic>{
'liveRoomId': liveRoomId,
'preferredQuality': preferredQuality,
'outputFormat': outputFormat,
},
) as Map<String, dynamic>;
return RecordTask.fromJson(response);
}
Future<RecordTask> stopTask(String taskId) async {
final response = await _apiClient.postJson('/api/record-tasks/$taskId/stop') as Map<String, dynamic>;
return RecordTask.fromJson(response);
}
Future<RecordPreviewTicket> createPreviewTicket(String taskId) async {
final response = await _apiClient.postJson('/api/record-tasks/$taskId/preview-ticket') as Map<String, dynamic>;
return RecordPreviewTicket.fromJson(response);
}
Future<void> uploadTask(String taskId) {
return _apiClient.postEmpty('/api/record-tasks/$taskId/upload');
}
Future<List<RecordSession>> listSessions({String? liveRoomId}) async {
final response = await _apiClient.getJson(
'/api/record-sessions',
queryParameters: <String, String>{
if (liveRoomId != null && liveRoomId.isNotEmpty) 'liveRoomId': liveRoomId,
},
) as List<dynamic>;
return response
.map((dynamic item) => RecordSession.fromJson(item as Map<String, dynamic>))
.toList(growable: false);
}
Future<RecordSessionDetail> getSessionDetail(String sessionId) async {
final response = await _apiClient.getJson('/api/record-sessions/$sessionId') as Map<String, dynamic>;
return RecordSessionDetail.fromJson(response);
}
Future<RecordSession> stopSession(String sessionId) async {
final response = await _apiClient.postJson('/api/record-sessions/$sessionId/stop') as Map<String, dynamic>;
return RecordSession.fromJson(response);
}
Future<void> uploadSession(String sessionId) {
return _apiClient.postEmpty('/api/record-sessions/$sessionId/upload');
}
}

View File

@ -0,0 +1,29 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class RecoveryRepository {
const RecoveryRepository(this._apiClient);
final ApiClient _apiClient;
Future<RecoveryOverview> getOverview() async {
final response = await _apiClient.getJson('/api/recovery') as Map<String, dynamic>;
return RecoveryOverview.fromJson(response);
}
Future<RecoveryActionResult> retryLiveRoom(String roomId) async {
final response = await _apiClient.postJson('/api/recovery/live-rooms/$roomId/retry') as Map<String, dynamic>;
return RecoveryActionResult.fromJson(response);
}
Future<RecoveryActionResult> retryAllLiveRooms() async {
final response = await _apiClient.postJson('/api/recovery/live-rooms/retry-all') as Map<String, dynamic>;
return RecoveryActionResult.fromJson(response);
}
Future<RecoveryActionResult> resumeFinalization(String taskId) async {
final response = await _apiClient.postJson('/api/recovery/finalizations/$taskId/resume') as Map<String, dynamic>;
return RecoveryActionResult.fromJson(response);
}
}

View File

@ -0,0 +1,27 @@
import 'package:live_recorder_mobile/core/network/api_client.dart';
import 'package:live_recorder_mobile/features/live_recorder/data/models/live_recorder_models.dart';
class SettingsRepository {
const SettingsRepository(this._apiClient);
final ApiClient _apiClient;
Future<SystemSettings> getSettings() async {
final response = await _apiClient.getJson('/api/settings') as Map<String, dynamic>;
return SystemSettings.fromJson(response);
}
Future<SystemSettings> updateSettings(SystemSettings settings) async {
final response = await _apiClient.putJson(
'/api/settings',
body: settings.toJson(),
) as Map<String, dynamic>;
return SystemSettings.fromJson(response);
}
Future<CleanupOperation> runRetentionCleanup() async {
final response = await _apiClient.postJson('/api/settings/retention/run-now') as Map<String, dynamic>;
return CleanupOperation.fromJson(response);
}
}