items.dart 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import 'package:flutter/material.dart';
  2. abstract class ListItem {
  3. String get id;
  4. String get title;
  5. int get width;
  6. int get height;
  7. int get difficulty;
  8. int get rows => difficulty;
  9. int get cols => difficulty;
  10. bool get hard;
  11. String get thumb;
  12. String get image;
  13. String get cachePath => 'cache/$id.jpeg';
  14. ValueNotifier notifier = ValueNotifier(0);
  15. // 新增:用于序列化
  16. Map<String, dynamic> toJson(); // 添加抽象方法,强制子类实现
  17. }
  18. /// assets图片, 内置图
  19. class AssetItem extends ListItem {
  20. @override
  21. final String id;
  22. @override
  23. final String title;
  24. @override
  25. final int width;
  26. @override
  27. final int height;
  28. @override
  29. final int difficulty;
  30. @override
  31. final bool hard;
  32. @override
  33. final String thumb;
  34. @override
  35. final String image;
  36. AssetItem(this.id, this.title, this.width, this.height, this.difficulty, this.hard, this.thumb, this.image);
  37. // 从JSON文件读取
  38. AssetItem.fromJSON(Map<String, dynamic> json)
  39. : id = json['_id'],
  40. title = json['title'] ?? '',
  41. width = json['width'],
  42. height = json['height'],
  43. difficulty = json['difficulty'],
  44. hard = json['hard'] ?? false,
  45. thumb = json['thumb'],
  46. image = json['raw'];
  47. @override
  48. String toString() {
  49. return 'AssetItem(id=$id, width=$width, height=$height, rows=$rows, cols=$cols, thumb=$thumb, image=$image';
  50. }
  51. @override
  52. Map<String, dynamic> toJson() => {'_id': id, 'width': width, 'height': height, 'difficulty': difficulty, 'hard': hard, 'thumb': thumb, 'raw': image};
  53. }
  54. class RemoteItem extends ListItem {
  55. @override
  56. final String id;
  57. @override
  58. final String title;
  59. @override
  60. final int width;
  61. @override
  62. final int height;
  63. @override
  64. final int difficulty;
  65. @override
  66. final bool hard;
  67. @override
  68. final String thumb;
  69. @override
  70. final String image;
  71. RemoteItem(this.id, this.title, this.width, this.height, this.difficulty, this.hard, this.thumb, this.image);
  72. factory RemoteItem.fromJSON(Map<String, dynamic> json) {
  73. // return RemoteItem(json['_id'], json['width'], json['height'], json['difficulty'], json['raw']);
  74. return RemoteItem(
  75. json['_id'],
  76. json['title'] ?? '',
  77. json['width'],
  78. json['height'],
  79. json['difficulty'] ?? 3,
  80. json['hard'] ?? false,
  81. json['thumb'],
  82. json['raw'],
  83. ); // 临时本地调试
  84. }
  85. @override
  86. Map<String, dynamic> toJson() => {
  87. '_id': id,
  88. 'title': title,
  89. 'width': width,
  90. 'height': height,
  91. 'difficulty': difficulty,
  92. 'hard': hard,
  93. 'thumb': thumb,
  94. 'raw': image,
  95. };
  96. }
  97. // 记录已完成作品的信息
  98. class Work extends ListItem {
  99. @override
  100. final String id; // 作品ID
  101. @override
  102. final String title; // 作品标题
  103. @override
  104. final int difficulty; // 难度 (rows/cols)
  105. @override
  106. final bool hard; // 是否困难模式
  107. @override
  108. final int width; // 原始图片宽度
  109. @override
  110. final int height; // 原始图片高度
  111. @override
  112. final String thumb;
  113. @override
  114. final String image;
  115. final DateTime completedTime; // 完成时间
  116. final Duration? timeSpent; // 完成耗时 (可选)
  117. Work({
  118. required this.id,
  119. required this.title,
  120. required this.difficulty,
  121. required this.hard,
  122. required this.width,
  123. required this.height,
  124. required this.thumb,
  125. required this.image,
  126. required this.completedTime,
  127. this.timeSpent,
  128. });
  129. // 序列化为 JSON
  130. @override
  131. Map<String, dynamic> toJson() {
  132. return {
  133. 'id': id,
  134. 'title': title,
  135. 'difficulty': difficulty,
  136. 'hard': hard,
  137. 'width': width,
  138. 'height': height,
  139. 'thumb': thumb,
  140. 'image': image,
  141. 'completedTime': completedTime.toIso8601String(), // 日期时间转为ISO字符串
  142. 'timeSpentSeconds': timeSpent?.inSeconds, // 耗时转为秒
  143. };
  144. }
  145. // 从 JSON 反序列化
  146. factory Work.fromJson(Map<String, dynamic> json) {
  147. return Work(
  148. id: json['id'],
  149. title: json['title'] ?? '',
  150. difficulty: json['difficulty'],
  151. hard: json['hard'] ?? false,
  152. width: json['width'],
  153. height: json['height'],
  154. thumb: json['thumb'],
  155. image: json['image'],
  156. completedTime: DateTime.parse(json['completedTime']),
  157. timeSpent: json['timeSpentSeconds'] != null ? Duration(seconds: json['timeSpentSeconds']) : null,
  158. );
  159. }
  160. // 从 ListItem 创建 Work
  161. factory Work.fromListItem(ListItem item, {Duration? timeSpent}) {
  162. return Work(
  163. id: item.id,
  164. title: item.title,
  165. difficulty: item.difficulty,
  166. hard: item.hard,
  167. width: item.width,
  168. height: item.height,
  169. thumb: item.thumb,
  170. image: item.image,
  171. completedTime: DateTime.now(),
  172. timeSpent: timeSpent,
  173. );
  174. }
  175. }