feat: 实现用户画像、占卜历史与后端用户管理模块
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../../../core/network/api_problem.dart';
|
||||
import '../../../../data/network/api_client.dart';
|
||||
import '../models/profile_settings.dart';
|
||||
|
||||
class ProfileApi {
|
||||
const ProfileApi({required ApiClient apiClient}) : _apiClient = apiClient;
|
||||
|
||||
final ApiClient _apiClient;
|
||||
|
||||
Future<ProfileSettingsV1> getProfile() async {
|
||||
final json = await _apiClient.getJson('/api/v1/users/me/profile');
|
||||
return _toSettings(json);
|
||||
}
|
||||
|
||||
Future<ProfileSettingsV1> updateProfile(ProfileSettingsV1 next) async {
|
||||
final payload = <String, dynamic>{
|
||||
'display_name': next.displayName,
|
||||
'bio': next.bio,
|
||||
if (next.avatarPath != null && next.avatarPath!.isNotEmpty)
|
||||
'avatar_path': next.avatarPath,
|
||||
};
|
||||
final json = await _apiClient.rawDio.patch<Map<String, dynamic>>(
|
||||
'/api/v1/users/me/profile',
|
||||
data: payload,
|
||||
);
|
||||
final data = json.data;
|
||||
if (data is! Map<String, dynamic>) {
|
||||
throw ApiProblem(
|
||||
status: 502,
|
||||
title: 'Invalid profile payload',
|
||||
detail: 'Expected profile response object',
|
||||
);
|
||||
}
|
||||
return _toSettings(data);
|
||||
}
|
||||
|
||||
Future<ProfileSettingsV1> uploadAvatar(String filePath) async {
|
||||
final formData = FormData.fromMap({
|
||||
'file': await MultipartFile.fromFile(filePath),
|
||||
});
|
||||
final response = await _apiClient.rawDio.post<Map<String, dynamic>>(
|
||||
'/api/v1/users/me/avatar',
|
||||
data: formData,
|
||||
);
|
||||
final data = response.data;
|
||||
if (data is! Map<String, dynamic>) {
|
||||
throw ApiProblem(
|
||||
status: 502,
|
||||
title: 'Invalid profile payload',
|
||||
detail: 'Expected profile response object',
|
||||
);
|
||||
}
|
||||
return _toSettings(data);
|
||||
}
|
||||
|
||||
ProfileSettingsV1 _toSettings(Map<String, dynamic> json) {
|
||||
final settingsRaw = json['settings'];
|
||||
final preferencesRaw = settingsRaw is Map<String, dynamic>
|
||||
? settingsRaw['preferences']
|
||||
: null;
|
||||
final preferences = preferencesRaw is Map<String, dynamic>
|
||||
? PreferenceSettings(
|
||||
interfaceLanguage:
|
||||
(preferencesRaw['interface_language'] as String?) ?? 'zh-CN',
|
||||
aiLanguage: (preferencesRaw['ai_language'] as String?) ?? 'zh-CN',
|
||||
timezone:
|
||||
(preferencesRaw['timezone'] as String?) ?? 'Asia/Shanghai',
|
||||
country: (preferencesRaw['country'] as String?) ?? 'CN',
|
||||
)
|
||||
: const PreferenceSettings();
|
||||
|
||||
return ProfileSettingsV1(
|
||||
displayName: (json['display_name'] as String?) ?? '',
|
||||
bio: (json['bio'] as String?) ?? '',
|
||||
avatarPath: json['avatar_path'] as String?,
|
||||
avatarUrl: json['avatar_url'] as String?,
|
||||
preferences: preferences,
|
||||
privacy: settingsRaw is Map<String, dynamic>
|
||||
? (settingsRaw['privacy'] as Map<String, dynamic>? ??
|
||||
const <String, dynamic>{})
|
||||
: const <String, dynamic>{},
|
||||
notification: settingsRaw is Map<String, dynamic>
|
||||
? (settingsRaw['notification'] as Map<String, dynamic>? ??
|
||||
const <String, dynamic>{})
|
||||
: const <String, dynamic>{},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user