tab2.page.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit } from '@angular/core';
  2. import { CommonModule } from '@angular/common';
  3. import { FormsModule } from '@angular/forms';
  4. import { IonicModule } from '@ionic/angular';
  5. import { Router } from '@angular/router';
  6. import { addIcons } from 'ionicons';
  7. import {
  8. schoolOutline,
  9. briefcaseOutline,
  10. moonOutline,
  11. barbellOutline,
  12. bookOutline,
  13. codeSlashOutline,
  14. leafOutline,
  15. musicalNotesOutline,
  16. languageOutline,
  17. pencilOutline,
  18. trashOutline,
  19. addOutline,
  20. arrowBackOutline,
  21. pauseOutline,
  22. playOutline,
  23. stopOutline
  24. } from 'ionicons/icons';
  25. import { AlertController } from '@ionic/angular';
  26. import { FocusDataService } from '../services/focus-data.service';
  27. interface TimerRecord {
  28. id: number;
  29. type: string;
  30. startTime: string;
  31. endTime: string;
  32. duration: number;
  33. parseId?: string;
  34. }
  35. @Component({
  36. selector: 'app-tab2',
  37. templateUrl: 'tab2.page.html',
  38. styleUrls: ['tab2.page.scss'],
  39. standalone: true,
  40. schemas: [CUSTOM_ELEMENTS_SCHEMA],
  41. imports: [IonicModule, CommonModule, FormsModule]
  42. })
  43. export class Tab2Page implements OnInit {
  44. activityTypes = [
  45. { id: 'study', name: '学习', icon: 'school-outline' },
  46. { id: 'work', name: '工作', icon: 'briefcase-outline' },
  47. { id: 'sleep', name: '睡眠', icon: 'moon-outline' },
  48. { id: 'sport', name: '运动', icon: 'barbell-outline' },
  49. { id: 'reading', name: '阅读', icon: 'book-outline' },
  50. { id: 'coding', name: '编程', icon: 'code-slash-outline' },
  51. { id: 'meditation', name: '冥想', icon: 'leaf-outline' },
  52. { id: 'music', name: '音乐', icon: 'musical-notes-outline' },
  53. { id: 'language', name: '语言', icon: 'language-outline' },
  54. { id: 'writing', name: '写作', icon: 'pencil-outline' }
  55. ];
  56. selectedType: string = '';
  57. isTimerRunning: boolean = false;
  58. timerStartTime: Date | null = null;
  59. currentTime: string = '00:00:00';
  60. records: TimerRecord[] = [];
  61. timer: any;
  62. countdownMinutes: number = 25;
  63. constructor(
  64. private router: Router,
  65. private alertController: AlertController,
  66. private focusDataService: FocusDataService
  67. ) {
  68. addIcons({
  69. schoolOutline,
  70. briefcaseOutline,
  71. moonOutline,
  72. barbellOutline,
  73. bookOutline,
  74. codeSlashOutline,
  75. leafOutline,
  76. musicalNotesOutline,
  77. languageOutline,
  78. pencilOutline,
  79. trashOutline,
  80. addOutline,
  81. arrowBackOutline,
  82. pauseOutline,
  83. playOutline,
  84. stopOutline
  85. });
  86. }
  87. ngOnInit() {
  88. this.loadRecords();
  89. }
  90. async loadRecords() {
  91. try {
  92. const records = await this.focusDataService.getFocusRecords();
  93. this.records = records.map(record => ({
  94. id: Date.now(),
  95. type: record.category,
  96. startTime: record.date.toISOString(),
  97. endTime: record.date.toISOString(),
  98. duration: record.duration,
  99. parseId: record.id
  100. }));
  101. } catch (error) {
  102. console.error('加载记录失败:', error);
  103. this.showErrorAlert('加载记录失败');
  104. }
  105. }
  106. selectType(typeId: string) {
  107. this.selectedType = typeId;
  108. }
  109. startTimer() {
  110. if (!this.selectedType) {
  111. return;
  112. }
  113. this.isTimerRunning = true;
  114. this.timerStartTime = new Date();
  115. this.timer = setInterval(() => {
  116. const now = new Date();
  117. const diff = now.getTime() - this.timerStartTime!.getTime();
  118. const hours = Math.floor(diff / 3600000);
  119. const minutes = Math.floor((diff % 3600000) / 60000);
  120. const seconds = Math.floor((diff % 60000) / 1000);
  121. this.currentTime = `${this.padNumber(hours)}:${this.padNumber(minutes)}:${this.padNumber(seconds)}`;
  122. }, 1000);
  123. }
  124. async stopTimer() {
  125. if (this.timer) {
  126. clearInterval(this.timer);
  127. const endTime = new Date();
  128. const duration = Math.floor((endTime.getTime() - this.timerStartTime!.getTime()) / 60000);
  129. try {
  130. const savedRecord = await this.focusDataService.addFocusRecord({
  131. duration: duration,
  132. category: this.selectedType,
  133. startTime: this.timerStartTime!,
  134. endTime: endTime
  135. });
  136. const record: TimerRecord = {
  137. id: Date.now(),
  138. type: this.selectedType,
  139. startTime: this.timerStartTime!.toISOString(),
  140. endTime: endTime.toISOString(),
  141. duration: duration,
  142. parseId: savedRecord.id
  143. };
  144. this.records.unshift(record);
  145. } catch (error) {
  146. console.error('保存专注记录失败:', error);
  147. this.showErrorAlert('保存记录失败');
  148. }
  149. this.isTimerRunning = false;
  150. this.timerStartTime = null;
  151. this.currentTime = '00:00:00';
  152. this.selectedType = '';
  153. }
  154. }
  155. startCountdown() {
  156. if (!this.selectedType) {
  157. return;
  158. }
  159. const selectedActivity = this.activityTypes.find(t => t.id === this.selectedType);
  160. if (selectedActivity) {
  161. this.router.navigate(['/countdown'], {
  162. queryParams: {
  163. type: selectedActivity.icon,
  164. name: selectedActivity.name,
  165. duration: this.countdownMinutes,
  166. category: selectedActivity.id
  167. }
  168. });
  169. }
  170. }
  171. private padNumber(num: number): string {
  172. return num.toString().padStart(2, '0');
  173. }
  174. getTypeName(typeId: string): string {
  175. const type = this.activityTypes.find(t => t.id === typeId);
  176. return type ? type.name : '';
  177. }
  178. getTypeIcon(typeId: string): string {
  179. const type = this.activityTypes.find(t => t.id === typeId);
  180. return type ? type.icon : '';
  181. }
  182. formatDuration(minutes: number): string {
  183. const hours = Math.floor(minutes / 60);
  184. const mins = minutes % 60;
  185. return hours > 0 ? `${hours}小时${mins}分钟` : `${mins}分钟`;
  186. }
  187. async deleteRecord(index: number) {
  188. const record = this.records[index];
  189. if (!record.parseId) {
  190. return;
  191. }
  192. const alert = await this.alertController.create({
  193. header: '确认删除',
  194. message: '你确定要删除这条记录吗?',
  195. buttons: [
  196. {
  197. text: '取消',
  198. role: 'cancel',
  199. },
  200. {
  201. text: '删除',
  202. role: 'destructive',
  203. handler: async () => {
  204. try {
  205. await this.focusDataService.deleteFocusRecord(record.parseId!);
  206. this.records.splice(index, 1);
  207. } catch (error) {
  208. console.error('删除记录失败:', error);
  209. this.showErrorAlert('删除记录失败');
  210. }
  211. }
  212. }
  213. ]
  214. });
  215. await alert.present();
  216. }
  217. private async showErrorAlert(message: string) {
  218. const alert = await this.alertController.create({
  219. header: '错误',
  220. message,
  221. buttons: ['确定']
  222. });
  223. await alert.present();
  224. }
  225. }