controller.dart 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import 'package:calendar_view/utils/calendar_util.dart';
  2. import 'package:calendar_view/utils/event_type.dart';
  3. import 'package:get/get.dart';
  4. class CalendarController extends GetxController {
  5. CalendarController();
  6. /// 数据项:当前年份,当前月份,当前日期
  7. int currentYear = 2022; // 当前年份
  8. int currentMonth = 12; // 当前月份
  9. int selectedDayIndex = 0; // 当前选择的日期的下标,从0开始,范围是0-34 有时是 0-41
  10. int maxDaysLength = 35; // 最大的日期数组长度,有时是42
  11. List<DayStructure> daysList = []; // 当前维护的日期列表
  12. ///TODO: 维护一个日程列表
  13. /// TODO[Gavin]: i18n
  14. String get currentYearMonth => '$currentYear年$currentMonth月';
  15. bool get isToday => daysList[selectedDayIndex].isToday;
  16. int get calendarLines => maxDaysLength ~/ 7;
  17. // _initData() {
  18. // update(["calendar"]);
  19. // }
  20. FEventHandler<void> onDaysListChange = FEventHandler<void>();
  21. void onTap() {}
  22. @override
  23. void onInit() {
  24. super.onInit();
  25. /// 获取当前时间判断年月
  26. final DateTime now = DateTime.now();
  27. currentYear = now.year;
  28. currentMonth = now.month;
  29. daysList = _countDaysList(currentYear, currentMonth);
  30. selectToday();
  31. /// 虚拟的日程数据
  32. final List<DateTime> mockSchedule = [
  33. DateTime(2022, 12, 1),
  34. DateTime(2022, 12, 4),
  35. DateTime(2022, 12, 5),
  36. DateTime(2022, 12, 6),
  37. DateTime(2022, 12, 7),
  38. DateTime(2022, 12, 12),
  39. DateTime(2022, 12, 13),
  40. DateTime(2022, 12, 14),
  41. DateTime(2022, 12, 15),
  42. DateTime(2022, 12, 16),
  43. DateTime(2022, 12, 17),
  44. DateTime(2022, 12, 18),
  45. DateTime(2022, 12, 19),
  46. DateTime(2022, 12, 20),
  47. DateTime(2022, 12, 27),
  48. DateTime(2022, 12, 28),
  49. DateTime(2022, 12, 29),
  50. DateTime(2022, 12, 30),
  51. DateTime(2022, 12, 31),
  52. ];
  53. _setSchedule(mockSchedule);
  54. print("CalendarController 全局临时控制器初始化");
  55. }
  56. @override
  57. void onReady() {
  58. super.onReady();
  59. // _initData();
  60. }
  61. // @override
  62. // void onClose() {
  63. // super.onClose();
  64. // }
  65. /// 传入起始年月,返回35个日期结构体
  66. List<DayStructure> _countDaysList(int year, int month) {
  67. maxDaysLength = _isNeedExtraRow(year, month) ? 42 : 35;
  68. final daysList = <DayStructure>[];
  69. final firstDay = DateTime(year, month, 1);
  70. final firstDayWeek = firstDay.weekday;
  71. final lastDay = DateTime(year, month + 1, 0);
  72. final lastDayOfMonth = lastDay.day;
  73. final lastDayOfLastMonth = DateTime(year, month, 0).day;
  74. final today = DateTime.now();
  75. /// 转换后的 firstDayWeek
  76. final firstDayWeekIndex = (firstDayWeek) % 7;
  77. int nextMonthDay = 1;
  78. // 上个月的日期
  79. for (var i = 0; i < firstDayWeekIndex; i++) {
  80. daysList.add(
  81. DayStructure(
  82. index: i,
  83. date: DateTime(
  84. year, month - 1, lastDayOfLastMonth - firstDayWeekIndex + i + 1),
  85. isCurrentMonth: false,
  86. ),
  87. );
  88. }
  89. // 当月的日期
  90. for (var i = 0;
  91. (i < lastDayOfMonth) && daysList.length < maxDaysLength;
  92. i++) {
  93. daysList.add(
  94. DayStructure(
  95. index: i + firstDayWeek,
  96. date: DateTime(year, month, i + 1),
  97. isToday:
  98. today.year == year && today.month == month && today.day == i + 1,
  99. ),
  100. );
  101. }
  102. while (daysList.length < maxDaysLength) {
  103. daysList.add(DayStructure(
  104. index: daysList.length,
  105. date: DateTime(month == 12 ? year + 1 : year,
  106. month == 12 ? 1 : month + 1, nextMonthDay),
  107. isCurrentMonth: false,
  108. ));
  109. nextMonthDay++;
  110. }
  111. return daysList;
  112. }
  113. /// 计算是否需要显示六行日期,一般为5行,但是有时候会有6行
  114. bool _isNeedExtraRow(int year, int month) {
  115. final firstDay = DateTime(year, month, 1);
  116. final firstDayWeek = firstDay.weekday;
  117. final lastDay = DateTime(year, month + 1, 0);
  118. final lastDayOfMonth = lastDay.day;
  119. /// 转换后的firstDayWeek,%7是因为DateTime的weekday是从周日开始的,而我们的日历是从周一开始的
  120. final firstDayWeekIndex = (firstDayWeek) % 7;
  121. return firstDayWeekIndex + lastDayOfMonth > 35;
  122. }
  123. /// 通过下标选中日期,下标从0开始,允许的范围是0-34,有时是 0-42
  124. void handleSelectedDayByIndex(int index) {
  125. assert(index >= 0 && index < maxDaysLength,
  126. 'index must be in 0-$maxDaysLength');
  127. assert(daysList.length == maxDaysLength,
  128. 'daysList length must be maxDaysLength');
  129. for (var element in daysList) {
  130. if (element.index == index) {
  131. element.isSelected = true;
  132. } else {
  133. element.isSelected = false;
  134. }
  135. }
  136. selectedDayIndex = index;
  137. onDaysListChange.emit(this, null);
  138. }
  139. /// 选中当月第一天
  140. void _selectFirstDay() {
  141. for (var element in daysList) {
  142. if (element.isCurrentMonth) {
  143. handleSelectedDayByIndex(element.index);
  144. break;
  145. }
  146. }
  147. }
  148. /// 选中今天
  149. void selectToday() {
  150. /// 如果当前不是当月,则切换到当月
  151. final DateTime now = DateTime.now();
  152. if (currentYear != now.year || currentMonth != now.month) {
  153. currentYear = now.year;
  154. currentMonth = now.month;
  155. daysList = _countDaysList(currentYear, currentMonth);
  156. }
  157. for (var element in daysList) {
  158. if (element.isToday) {
  159. handleSelectedDayByIndex(element.index);
  160. break;
  161. }
  162. }
  163. }
  164. /// 给日期设置日程的值
  165. void _setSchedule(List<DateTime> scheduleList) {
  166. /// 如果scheduleList中存在daysList中的日期,则设置hasSchedule为true
  167. for (var element in scheduleList) {
  168. for (var day in daysList) {
  169. if (element.year == day.date.year &&
  170. element.month == day.date.month &&
  171. element.day == day.date.day) {
  172. day.hasSchedule = true;
  173. }
  174. }
  175. }
  176. }
  177. /// 上个月
  178. void handleLastMonth() {
  179. if (currentMonth == 1) {
  180. currentMonth = 12;
  181. currentYear--;
  182. } else {
  183. currentMonth--;
  184. }
  185. daysList = _countDaysList(currentYear, currentMonth);
  186. _selectFirstDay();
  187. onDaysListChange.emit(this, null);
  188. }
  189. /// 下个月
  190. void handleNextMonth() {
  191. if (currentMonth == 12) {
  192. currentMonth = 1;
  193. currentYear++;
  194. } else {
  195. currentMonth++;
  196. }
  197. daysList = _countDaysList(currentYear, currentMonth);
  198. _selectFirstDay();
  199. onDaysListChange.emit(this, null);
  200. }
  201. }