import 'dart:convert'; import 'package:dio/dio.dart'; import '../model/song_model.dart'; import '../model/user_model.dart'; import '../tool/encryption_util.dart'; class UserService { static final Dio _dio = Dio(); static const String baseUrl = "https://union.godserver.cn"; // 注册 static Future register(String username, String password, String inviter) async { try { await _dio.post( '$baseUrl/user/register', data: { "username": username, "password": password, "inviter": inviter, }, ); } on DioException catch (e) { throw _getErrorMessage(e); } } // 登录 static Future login(String username, String twoKeyCode) async { try { final raw = jsonEncode({ "username": username, "twoKeyCode": twoKeyCode, }); final encrypted = EncryptionUtil.encrypt(raw); final res = await _dio.post( '$baseUrl/api/user/user', data: { "code": 200, "timestamp": DateTime.now().millisecondsSinceEpoch, "msg": "login", "data": encrypted, }, ); return EncryptionUtil.decrypt(res.data["data"]?.toString() ?? ''); } on DioException catch (e) { throw _getErrorMessage(e); } } // 获取用户信息 static Future getUserInfo(String token) async { try { final res = await _dio.post( '$baseUrl/api/user/data', data: { "msg": "getUser", "timestamp": DateTime.now().millisecondsSinceEpoch, "data": token, }, options: Options(headers: {"Authorization": token}), ); final decrypted = EncryptionUtil.decrypt(res.data["data"]?.toString() ?? ''); return UserModel.fromJson(jsonDecode(decrypted)); } on DioException catch (e) { throw _getErrorMessage(e); } } // 保存/修改用户信息(updateUser) static Future updateUser(String token, String encryptedData) async { try { final res = await _dio.put( '$baseUrl/api/user/data', data: { "msg": "updateUser", "timestamp": DateTime.now().millisecondsSinceEpoch, "data": encryptedData, }, options: Options(headers: {"Authorization": token}), ); return res.data.toString(); } on DioException catch (e) { throw _getErrorMessage(e); } return ""; } // 检查登录状态 static Future isLogin(String token) async { try { final res = await _dio.get( '$baseUrl/api/user/isLogin', options: Options(headers: {"Authorization": token}), ); return res.data["code"] == 200; } on DioException { return false; } } // 刷新Token(接口通用逻辑) static Future refreshToken(String oldToken) async { try { final res = await _dio.post( '$baseUrl/api/user/refreshToken', options: Options(headers: {"Authorization": oldToken}), ); if (res.data["code"] == 200) { return res.data["data"]?.toString(); } return null; } on DioException { return null; } } // 获取角色 static Future getUserRole(String token) async { try { final res = await _dio.get( '$baseUrl/api/user/role', options: Options(headers: {"Authorization": token}), ); if (res.data["code"] == 200) { return res.data["data"]?.toString(); } return null; } on DioException { return null; } } // 获取性别标签 static Future> fetchSexTags() async { try { final res = await _dio.get('$baseUrl/api/union/sextag'); if (res.data is List) { return List.from(res.data); } return []; } on DioException { return []; } } // 获取好友列表 static Future> fetchFriends(String token) async { try { final res = await _dio.get( '$baseUrl/api/user/friend', options: Options(headers: {"Authorization": token}), ); if (res.data is List) { return res.data; } return []; } on DioException { return []; } } // 更新API Key static Future updateApiKey(String token) async { try { await _dio.post( '$baseUrl/api/user/updateKey', data: { "msg": "updateApiKey", "timestamp": DateTime.now().millisecondsSinceEpoch, }, options: Options(headers: {"Authorization": token}), ); } on DioException catch (e) { throw _getErrorMessage(e); } } // 绑定GitHub - 获取跳转链接 static Future bindGithub(String token) async { try { final res = await _dio.get( '$baseUrl/api/user/bind/github', options: Options(headers: {"Authorization": token}), ); return res.realUri.toString(); } on DioException catch (e) { throw _getErrorMessage(e); } } // 确认绑定GitHub static Future confirmBindGithub(String token, String uuid) async { try { await _dio.post( '$baseUrl/api/user/bind/github', options: Options(headers: { "Authorization": token, "uuid": uuid, }), ); } on DioException catch (e) { throw _getErrorMessage(e); } } // 验证SegaId static Future> verifySegaId(String token, String segaId) async { try { final res = await _dio.post( '$baseUrl/api/user/verifySegaId', queryParameters: {"useSegaId": segaId}, options: Options(headers: {"Authorization": token}), ); return res.data; } on DioException catch (e) { throw _getErrorMessage(e); } } // 获取雷达图数据 static Future> getRadarData(String token, String id) async { try { final res = await _dio.get( '$baseUrl/api/union/radar', queryParameters: {"id": id}, options: Options(headers: {"Authorization": token}), ); // 返回雷达图原始数据 return Map.from(res.data); } on DioException catch (e) { throw _getErrorMessage(e); } } // 统一错误处理 static String _getErrorMessage(DioException e) { if (e.response?.data != null) { final data = e.response!.data; if (data is Map && data["msg"] != null) { return data["msg"].toString(); } } switch (e.type) { case DioExceptionType.connectionTimeout: case DioExceptionType.receiveTimeout: case DioExceptionType.sendTimeout: return "网络超时"; case DioExceptionType.connectionError: return "网络异常"; default: return "请求失败"; } } static Future> getUserAllScores(String token, {String? name}) async { try { // 构建查询参数 final queryParameters = {}; if (name != null && name.isNotEmpty) { queryParameters['name'] = name; } final res = await _dio.get( '$baseUrl/api/union/reisaRating', queryParameters: queryParameters, options: Options(headers: {"Authorization": token}), ); if (res.data is Map) { return Map.from(res.data); } return {}; } on DioException catch (e) { throw _getErrorMessage(e); } } static Future> getSegaRatingData(String token, String segaId) async { try { final res = await _dio.get( '$baseUrl/api/union/segaReisaRating', queryParameters: {"segaId": segaId}, options: Options(headers: {"Authorization": token}), ); return Map.from(res.data); } on DioException catch (e) { throw _getErrorMessage(e); } } // 上传 Sega 成绩数据 static Future> uploadSegaRating( String token, String segaId, Map segaResult, ) async { try { final res = await _dio.post( '$baseUrl/api/union/segaReisaRating', queryParameters: { "segaId": segaId, }, data: segaResult, options: Options( headers: { "Authorization": token, }, ), ); return Map.from(res.data); } on DioException catch (e) { throw _getErrorMessage(e); } } static Future> getChartLog(String token, List musicIds) async { try { print("getChartLog"); // 构建查询参数 // 如果 API 期望的是逗号分隔的字符串 "11434,11435" final String idsParam = musicIds.map((e) => e.toString()).join(','); final res = await _dio.get( '$baseUrl/api/union/chartlog', queryParameters: { "musicId": idsParam, }, options: Options(headers: {"Authorization": token}), ); // 检查返回数据是否为 List if (res.data is List) { return (res.data as List) .map((item) => ChartLogModel.fromJson(item as Map)) .toList(); } // 如果后端在某些错误情况下返回 Map 而不是 List,这里返回空列表或抛出异常 return []; } on DioException catch (e) { throw _getErrorMessage(e); } } }