import 'dart:convert'; import 'dart:math'; import 'package:dio/dio.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../model/song_model.dart'; import 'user_service.dart'; // 引用 baseUrl class SongService { static final Dio _dio = new Dio(); static const String _cacheKeySongs = 'cached_songs_json'; static const String _cacheKeyInfo = 'cached_song_info'; /// 获取所有歌曲数据(带缓存逻辑) static Future> getAllSongs() async { try { // 1. 获取远程元数据 (判断是否需要更新) final metaRes = await _dio.get('${UserService.baseUrl}/api/union/'); final remoteSize = metaRes.data['songSize'] as int? ?? 0; final remoteVersion = metaRes.data['version'] as String? ?? ''; // 2. 获取本地缓存信息 final prefs = await SharedPreferences.getInstance(); final cachedInfoJson = prefs.getString(_cacheKeyInfo); bool needFetch = true; if (cachedInfoJson != null) { final cachedInfo = SongCacheInfo.fromJson(jsonDecode(cachedInfoJson)); // 如果本地歌曲数量与远程一致,且版本号一致,则使用缓存 // 注意:这里简单判断 size 相同即认为无需更新,实际业务中可能需要更严格的版本对比 if (cachedInfo.songSize == remoteSize && cachedInfo.version == remoteVersion) { needFetch = false; } } if (needFetch) { print("SongService: Cache miss or outdated. Fetching full song list..."); // 3. 拉取最新全量数据 final songsRes = await _dio.get('${UserService.baseUrl}/api/union/uni'); final List songsJson = songsRes.data as List; // 4. 保存新数据和元数据到本地 final songsList = songsJson.map((e) => SongModel.fromJson(e)).toList(); final newInfo = SongCacheInfo( songSize: remoteSize, version: remoteVersion, lastUpdate: DateTime.now() ); await prefs.setString(_cacheKeySongs, jsonEncode(songsJson)); await prefs.setString(_cacheKeyInfo, jsonEncode(newInfo.toJson())); return songsList; } else { print("SongService: Using cached song list."); // 5. 使用缓存 final cachedSongsJson = prefs.getString(_cacheKeySongs); if (cachedSongsJson != null) { final List songsJson = jsonDecode(cachedSongsJson); return songsJson.map((e) => SongModel.fromJson(e)).toList(); } } } catch (e) { print("SongService Error: $e"); // 如果出错,尝试返回旧缓存以防万一 final prefs = await SharedPreferences.getInstance(); final cachedSongsJson = prefs.getString(_cacheKeySongs); if (cachedSongsJson != null) { final List songsJson = jsonDecode(cachedSongsJson); return songsJson.map((e) => SongModel.fromJson(e)).toList(); } } return []; } static Future> getUserAllScores(String token, {String? name}) async { try { if(name!=null) { return await UserService.getUserAllScores(token,name: name); }else{ return await UserService.getUserAllScores(token); } } 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 "请求失败"; } } }