243 lines
6.5 KiB
Dart
243 lines
6.5 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'json_numbers.dart';
|
|
|
|
/// 奖励中心首屏数据。
|
|
class RewardOverview {
|
|
const RewardOverview({
|
|
required this.serverDate,
|
|
required this.timezone,
|
|
required this.coinBalance,
|
|
required this.checkin,
|
|
this.sections = const [],
|
|
this.activities = const [],
|
|
});
|
|
|
|
final String serverDate;
|
|
final String timezone;
|
|
final int coinBalance;
|
|
final RewardCheckinState checkin;
|
|
final List<RewardSection> sections;
|
|
final List<RewardActivity> activities;
|
|
|
|
factory RewardOverview.fromJson(Map<String, dynamic> json) {
|
|
return RewardOverview(
|
|
serverDate: json['serverDate'] as String? ?? '',
|
|
timezone: json['timezone'] as String? ?? '',
|
|
coinBalance: jsonToInt(json['coinBalance']),
|
|
checkin: RewardCheckinState.fromJson(_map(json['checkin'])),
|
|
sections: _maps(json['sections']).map(RewardSection.fromJson).toList(),
|
|
activities: _maps(
|
|
json['activities'],
|
|
).map(RewardActivity.fromJson).toList(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 七日签到状态。
|
|
class RewardCheckinState {
|
|
const RewardCheckinState({
|
|
required this.taskId,
|
|
required this.checkedInToday,
|
|
required this.streak,
|
|
required this.currentDay,
|
|
this.days = const [],
|
|
});
|
|
|
|
final String taskId;
|
|
final bool checkedInToday;
|
|
final int streak;
|
|
final int currentDay;
|
|
final List<RewardCheckinDay> days;
|
|
|
|
factory RewardCheckinState.fromJson(Map<String, dynamic> json) {
|
|
return RewardCheckinState(
|
|
taskId: (json['taskId'] ?? '').toString(),
|
|
checkedInToday: json['checkedInToday'] == true,
|
|
streak: jsonToInt(json['streak']),
|
|
currentDay: jsonToInt(json['currentDay']),
|
|
days: _maps(json['days']).map(RewardCheckinDay.fromJson).toList(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 签到周期中的一天。
|
|
class RewardCheckinDay {
|
|
const RewardCheckinDay({
|
|
required this.dayIndex,
|
|
required this.rewardCoin,
|
|
required this.checked,
|
|
required this.current,
|
|
});
|
|
|
|
final int dayIndex;
|
|
final int rewardCoin;
|
|
final bool checked;
|
|
final bool current;
|
|
|
|
factory RewardCheckinDay.fromJson(Map<String, dynamic> json) {
|
|
return RewardCheckinDay(
|
|
dayIndex: jsonToInt(json['dayIndex']),
|
|
rewardCoin: jsonToInt(json['rewardCoin']),
|
|
checked: json['checked'] == true,
|
|
current: json['current'] == true,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 一组奖励任务。
|
|
class RewardSection {
|
|
const RewardSection({
|
|
required this.code,
|
|
required this.title,
|
|
this.tasks = const [],
|
|
});
|
|
|
|
final String code;
|
|
final String title;
|
|
final List<RewardTask> tasks;
|
|
|
|
factory RewardSection.fromJson(Map<String, dynamic> json) {
|
|
return RewardSection(
|
|
code: json['code'] as String? ?? '',
|
|
title: json['title'] as String? ?? '',
|
|
tasks: _maps(json['tasks']).map(RewardTask.fromJson).toList(),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 奖励任务卡片。
|
|
class RewardTask {
|
|
const RewardTask({
|
|
required this.id,
|
|
required this.code,
|
|
required this.type,
|
|
required this.title,
|
|
required this.subtitle,
|
|
required this.ctaText,
|
|
required this.actionType,
|
|
required this.actionUrl,
|
|
required this.progressValue,
|
|
required this.targetValue,
|
|
required this.rewardCoin,
|
|
required this.status,
|
|
this.iconUrl = '',
|
|
});
|
|
|
|
final String id;
|
|
final String code;
|
|
final String type;
|
|
final String title;
|
|
final String subtitle;
|
|
final String ctaText;
|
|
final String actionType;
|
|
final String actionUrl;
|
|
final String iconUrl;
|
|
final int progressValue;
|
|
final int targetValue;
|
|
final int rewardCoin;
|
|
final String status;
|
|
|
|
bool get claimable => status == 'COMPLETED';
|
|
bool get claimed => status == 'CLAIMED';
|
|
double get progress =>
|
|
targetValue <= 0 ? 0 : (progressValue / targetValue).clamp(0.0, 1.0);
|
|
|
|
factory RewardTask.fromJson(Map<String, dynamic> json) {
|
|
return RewardTask(
|
|
id: (json['id'] ?? '').toString(),
|
|
code: json['code'] as String? ?? '',
|
|
type: json['type'] as String? ?? '',
|
|
title: json['title'] as String? ?? '',
|
|
subtitle: json['subtitle'] as String? ?? '',
|
|
ctaText: json['ctaText'] as String? ?? '',
|
|
actionType: json['actionType'] as String? ?? '',
|
|
actionUrl: json['actionUrl'] as String? ?? '',
|
|
iconUrl: json['iconUrl'] as String? ?? '',
|
|
progressValue: jsonToInt(json['progressValue']),
|
|
targetValue: jsonToInt(json['targetValue']),
|
|
rewardCoin: jsonToInt(json['rewardCoin']),
|
|
status: json['status'] as String? ?? 'IN_PROGRESS',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 奖励活动展示卡片。
|
|
class RewardActivity {
|
|
const RewardActivity({
|
|
required this.id,
|
|
required this.code,
|
|
required this.title,
|
|
required this.summary,
|
|
required this.ctaText,
|
|
required this.actionType,
|
|
required this.actionUrl,
|
|
this.coverUrl = '',
|
|
});
|
|
|
|
final String id;
|
|
final String code;
|
|
final String title;
|
|
final String summary;
|
|
final String ctaText;
|
|
final String actionType;
|
|
final String actionUrl;
|
|
final String coverUrl;
|
|
|
|
factory RewardActivity.fromJson(Map<String, dynamic> json) {
|
|
return RewardActivity(
|
|
id: (json['id'] ?? '').toString(),
|
|
code: json['code'] as String? ?? '',
|
|
title: json['title'] as String? ?? '',
|
|
summary: json['summary'] as String? ?? '',
|
|
ctaText: json['ctaText'] as String? ?? '',
|
|
actionType: json['actionType'] as String? ?? '',
|
|
actionUrl: json['actionUrl'] as String? ?? '',
|
|
coverUrl: json['coverUrl'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 签到或任务领取后的余额变化结果。
|
|
class RewardActionResult {
|
|
const RewardActionResult({
|
|
required this.rewardCoin,
|
|
required this.coinBalance,
|
|
required this.alreadyCompleted,
|
|
});
|
|
|
|
final int rewardCoin;
|
|
final int coinBalance;
|
|
final bool alreadyCompleted;
|
|
|
|
factory RewardActionResult.fromCheckin(Map<String, dynamic> json) {
|
|
return RewardActionResult(
|
|
rewardCoin: jsonToInt(json['rewardCoin']),
|
|
coinBalance: jsonToInt(json['coinBalance']),
|
|
alreadyCompleted: json['alreadyCheckedIn'] == true,
|
|
);
|
|
}
|
|
|
|
factory RewardActionResult.fromClaim(Map<String, dynamic> json) {
|
|
return RewardActionResult(
|
|
rewardCoin: jsonToInt(json['rewardCoin']),
|
|
coinBalance: jsonToInt(json['coinBalance']),
|
|
alreadyCompleted: json['alreadyGranted'] == true,
|
|
);
|
|
}
|
|
}
|
|
|
|
Map<String, dynamic> _map(Object? value) {
|
|
if (value is Map<String, dynamic>) return value;
|
|
if (value is Map) return value.cast<String, dynamic>();
|
|
return const {};
|
|
}
|
|
|
|
List<Map<String, dynamic>> _maps(Object? value) {
|
|
if (value is! List) return const [];
|
|
return value
|
|
.whereType<Map>()
|
|
.map((item) => item.cast<String, dynamic>())
|
|
.toList();
|
|
}
|