class SongModel { final int id; final int players; final String title; final String artist; final Map? utTitle; // 可选,根据不同版本标题可能不同 final List albums; final bool hasDx; final bool hasSd; final bool hasUt; final String genre; final int bpm; final String releaseDate; final String from; // 新增:四个标签字段 final bool cn; final bool jp; final bool m2l; final bool long; // 难度详情映射 key通常是 "0"(Basic), "1"(Advanced) 等,或者 ut 的特殊id final Map? dx; final Map? sd; final Map? ut; SongModel({ required this.id, required this.players, required this.title, required this.artist, this.utTitle, required this.albums, required this.hasDx, required this.hasSd, required this.hasUt, required this.genre, required this.bpm, required this.releaseDate, required this.from, // 新增 required this.cn, required this.jp, required this.m2l, required this.long, this.dx, this.sd, this.ut, }); factory SongModel.fromJson(Map json) { return SongModel( id: json['id'] ?? 0, players: json['players']??0, title: json['title'] ?? 'Unknown', artist: json['artist'] ?? 'Unknown', utTitle: json['utTitle'], albums: List.from(json['albums'] ?? []), hasDx: json['hasDx'] ?? false, hasSd: json['hasSd'] ?? false, hasUt: json['hasUt'] ?? false, genre: json['genre'] ?? '', bpm: json['bpm'] ?? 0, releaseDate: json['releaseDate'] ?? '', from: json['from'] ?? '', // 新增:JSON 解析,默认 false 更安全 cn: json['cn'] ?? false, jp: json['jp'] ?? false, m2l: json['m2l'] ?? false, long: json['long'] ?? false, dx: json['dx'], sd: json['sd'], ut: json['ut'], ); } } // 用于存储本地缓存的版本信息 class SongCacheInfo { final int songSize; final String version; final DateTime lastUpdate; SongCacheInfo({ required this.songSize, required this.version, required this.lastUpdate, }); Map toJson() => { 'songSize': songSize, 'version': version, 'lastUpdate': lastUpdate.millisecondsSinceEpoch, }; factory SongCacheInfo.fromJson(Map json) { return SongCacheInfo( songSize: json['songSize'] ?? 0, version: json['version'] ?? '', lastUpdate: DateTime.fromMillisecondsSinceEpoch(json['lastUpdate'] ?? 0), ); } } // lib/model/chart_log_model.dart class ChartLogModel { final String id; final dynamic segaChartOld; // 根据示例为 null,类型暂定为 dynamic final SegaChartNew? segaChartNew; final String userId; final int musicId; final int time; // 时间戳 ChartLogModel({ required this.id, this.segaChartOld, this.segaChartNew, required this.userId, required this.musicId, required this.time, }); factory ChartLogModel.fromJson(Map json) { return ChartLogModel( id: json['id'] as String? ?? '', segaChartOld: json['sega_chartOld'], segaChartNew: json['sega_chartNew'] != null ? SegaChartNew.fromJson(json['sega_chartNew'] as Map) : null, userId: json['userId'] as String? ?? '', musicId: json['musicId'] as int? ?? 0, time: json['time'] as int? ?? 0, ); } } class SegaChartNew { final int musicId; final String? musicName; final int level; final double levelInfo; final int romVersion; final int achievement; final int rating; final String? type; final int playCount; final int comboStatus; final int syncStatus; final int deluxscoreMax; final int scoreRank; final int extNum1; final int extNum2; final List alias; SegaChartNew({ required this.musicId, this.musicName, required this.level, required this.levelInfo, required this.romVersion, required this.achievement, required this.rating, this.type, required this.playCount, required this.comboStatus, required this.syncStatus, required this.deluxscoreMax, required this.scoreRank, required this.extNum1, required this.extNum2, required this.alias, }); factory SegaChartNew.fromJson(Map json) { // 处理 alias 可能存在的非字符串或 null 情况,确保安全性 var rawAlias = json['alias']; List aliasList = []; if (rawAlias is List) { aliasList = rawAlias.map((e) => e?.toString() ?? '').toList(); } return SegaChartNew( musicId: json['musicId'] as int? ?? 0, musicName: json['musicName'] as String?, level: json['level'] as int? ?? 0, levelInfo: (json['level_info'] as num?)?.toDouble() ?? 0.0, romVersion: json['romVersion'] as int? ?? 0, achievement: json['achievement'] as int? ?? 0, rating: json['rating'] as int? ?? 0, type: json['type'] as String?, playCount: json['playCount'] as int? ?? 0, comboStatus: json['comboStatus'] as int? ?? 0, syncStatus: json['syncStatus'] as int? ?? 0, deluxscoreMax: json['deluxscoreMax'] as int? ?? 0, scoreRank: json['scoreRank'] as int? ?? 0, extNum1: json['extNum1'] as int? ?? 0, extNum2: json['extNum2'] as int? ?? 0, alias: aliasList, ); } }