18079408532 il y a 1 an
Parent
commit
183bd4d349

+ 1 - 6
src/app/app.routes.ts

@@ -3,11 +3,6 @@ import { Routes } from '@angular/router';
 export const routes: Routes = [
   {
     path: '',
-    loadChildren: () => import('./tabs/tabs.routes').then(m => m.routes)
-  },
-  {
-    path: 'login',
-    loadComponent: () => import('../lib/user/modal-user-login/modal-user-login.component')
-      .then(m => m.ModalUserLoginComponent)
+    loadChildren: () => import('./tabs/tabs.routes').then((m) => m.routes),
   }
 ];

+ 25 - 7
src/app/countdown/countdown.page.html

@@ -1,3 +1,14 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button (click)="exit()">
+        <ion-icon name="arrow-back-outline" slot="icon-only"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+    <ion-title>专注计时</ion-title>
+  </ion-toolbar>
+</ion-header>
+
 <ion-content class="ion-text-center">
   <div class="countdown-container">
     <div class="activity-info">
@@ -13,15 +24,22 @@
     </div>
 
     <div class="controls">
-      <ion-button fill="clear" (click)="togglePause()">
-        <ion-icon [name]="isRunning ? 'pause-outline' : 'play-outline'" slot="icon-only"></ion-icon>
+      <ion-button 
+        fill="clear" 
+        [class.running]="isRunning"
+        (click)="togglePause()">
+        <ion-icon 
+          [name]="isRunning ? 'pause-outline' : 'play-outline'" 
+          slot="icon-only">
+        </ion-icon>
       </ion-button>
-      <ion-button fill="clear" (click)="stop()">
+      
+      <ion-button 
+        fill="clear" 
+        (click)="reset()"
+        [disabled]="!isRunning && remainingSeconds === duration * 60">
         <ion-icon name="stop-outline" slot="icon-only"></ion-icon>
       </ion-button>
-      <ion-button fill="clear" (click)="exit()">
-        <ion-icon name="exit-outline" slot="icon-only"></ion-icon>
-      </ion-button>
     </div>
   </div>
-</ion-content>
+</ion-content>

+ 37 - 11
src/app/countdown/countdown.page.scss

@@ -4,7 +4,8 @@
   flex-direction: column;
   justify-content: center;
   align-items: center;
-  background: #f8f9fa;
+  padding: 20px;
+  background: var(--ion-background-color);
 }
 
 .activity-info {
@@ -12,21 +13,22 @@
   text-align: center;
   
   ion-icon {
-    font-size: 48px;
+    font-size: 64px;
     color: var(--ion-color-primary);
   }
   
   h2 {
     margin: 16px 0;
-    font-size: 24px;
-    color: #2c3e50;
+    font-size: 28px;
+    color: var(--ion-text-color);
+    font-weight: 500;
   }
 }
 
 .timer-circle {
   position: relative;
-  width: 280px;
-  height: 280px;
+  width: 300px;
+  height: 300px;
   display: flex;
   justify-content: center;
   align-items: center;
@@ -36,23 +38,47 @@
     position: absolute;
     width: 100%;
     height: 100%;
-    transform: rotate(-90deg);
+    border-radius: 50%;
+    overflow: hidden;
+    
+    ion-progress-bar {
+      position: absolute;
+      bottom: 0;
+      width: 100%;
+      height: 100%;
+      --progress-background: var(--ion-color-primary);
+      --buffer-background: rgba(var(--ion-color-primary-rgb), 0.2);
+      transform-origin: center;
+      transform: rotate(270deg);
+    }
   }
   
   .time {
-    font-size: 48px;
+    font-size: 56px;
     font-weight: 300;
-    color: #2c3e50;
+    color: var(--ion-text-color);
+    z-index: 1;
   }
 }
 
 .controls {
+  display: flex;
+  gap: 20px;
+  margin-top: 20px;
+
   ion-button {
-    --padding-start: 24px;
-    --padding-end: 24px;
+    --padding-start: 20px;
+    --padding-end: 20px;
+    --border-radius: 50%;
+    width: 64px;
+    height: 64px;
     
     ion-icon {
       font-size: 32px;
     }
+
+    &.running {
+      --background: var(--ion-color-danger);
+    }
   }
 }

+ 68 - 29
src/app/countdown/countdown.page.ts

@@ -1,7 +1,7 @@
 import { Component, OnInit, OnDestroy } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
-import { IonicModule, NavController } from '@ionic/angular';
+import { IonicModule, NavController, AlertController } from '@ionic/angular';
 import { ActivatedRoute } from '@angular/router';
 import { addIcons } from 'ionicons';
 import { 
@@ -19,7 +19,7 @@ import {
   playOutline,
   stopOutline,
   exitOutline,
-  trashOutline
+  arrowBackOutline
 } from 'ionicons/icons';
 
 @Component({
@@ -40,7 +40,11 @@ export class CountdownPage implements OnInit, OnDestroy {
   remainingSeconds: number = 0;
   alertAudio: HTMLAudioElement;
 
-  constructor(private route: ActivatedRoute, private navCtrl: NavController) {
+  constructor(
+    private route: ActivatedRoute, 
+    private navCtrl: NavController,
+    private alertController: AlertController
+  ) {
     addIcons({
       'school-outline': schoolOutline,
       'briefcase-outline': briefcaseOutline,
@@ -56,35 +60,36 @@ export class CountdownPage implements OnInit, OnDestroy {
       'play-outline': playOutline,
       'stop-outline': stopOutline,
       'exit-outline': exitOutline,
-      'trash-outline': trashOutline
+      'arrow-back-outline': arrowBackOutline
     });
 
-    // 初始化音频
     this.alertAudio = new Audio('assets/alert.mp3');
   }
 
   ngOnInit() {
+    console.log('CountdownPage initialized');
     this.route.queryParams.subscribe(params => {
+      console.log('Received params:', params);
       this.activityType = params['type'];
       this.activityName = params['name'];
       this.duration = parseInt(params['duration']);
-      this.remainingSeconds = this.duration * 60; // 转换为秒
-      this.startCountdown();
+      this.remainingSeconds = this.duration * 60;
+      this.remainingTime = this.formatTime(this.remainingSeconds);
+      this.progress = 1;
     });
   }
 
   ngOnDestroy() {
-    if (this.timer) {
-      clearInterval(this.timer);
-    }
+    this.stopTimer();
   }
 
-  startCountdown() {
+  startTimer() {
     if (this.timer) {
       clearInterval(this.timer);
     }
 
-    const startTime = this.remainingSeconds;
+    const startTime = this.duration * 60;
+    this.isRunning = true;
     
     this.timer = setInterval(() => {
       if (this.remainingSeconds > 0) {
@@ -92,13 +97,21 @@ export class CountdownPage implements OnInit, OnDestroy {
         this.progress = this.remainingSeconds / startTime;
         this.remainingTime = this.formatTime(this.remainingSeconds);
       } else {
-        this.isRunning = false;
-        clearInterval(this.timer);
-        this.playAlertSound(); // 播放提示音
+        this.stopTimer();
+        this.playAlertSound();
+        this.showCompletionAlert();
       }
     }, 1000);
   }
 
+  stopTimer() {
+    if (this.timer) {
+      clearInterval(this.timer);
+      this.timer = null;
+    }
+    this.isRunning = false;
+  }
+
   formatTime(seconds: number): string {
     const hours = Math.floor(seconds / 3600);
     const minutes = Math.floor((seconds % 3600) / 60);
@@ -111,31 +124,57 @@ export class CountdownPage implements OnInit, OnDestroy {
   }
 
   togglePause() {
-    console.log('Toggle Pause called');
     if (this.isRunning) {
-      clearInterval(this.timer);
-      console.log('Paused at:', this.remainingSeconds, 'seconds');
+      this.stopTimer();
     } else {
-      console.log('Resuming from:', this.remainingSeconds, 'seconds');
-      this.startCountdown();
+      this.startTimer();
     }
-    this.isRunning = !this.isRunning;
   }
 
-  stop() {
-    clearInterval(this.timer);
-    this.isRunning = false;
+  reset() {
+    this.stopTimer();
     this.remainingSeconds = this.duration * 60;
     this.remainingTime = this.formatTime(this.remainingSeconds);
     this.progress = 1;
   }
 
-  exit() {
-    this.stop();
-    this.navCtrl.back();
+  async exit() {
+    if (this.isRunning) {
+      const alert = await this.alertController.create({
+        header: '确认退出',
+        message: '计时正在进行中,确定要退出吗?',
+        buttons: [
+          {
+            text: '取消',
+            role: 'cancel'
+          },
+          {
+            text: '确定',
+            handler: () => {
+              this.stopTimer();
+              this.navCtrl.back();
+            }
+          }
+        ]
+      });
+      await alert.present();
+    } else {
+      this.navCtrl.back();
+    }
+  }
+
+  async showCompletionAlert() {
+    const alert = await this.alertController.create({
+      header: '专注完成!',
+      message: `恭喜你完成了 ${this.duration} 分钟的${this.activityName}`,
+      buttons: ['确定']
+    });
+    await alert.present();
   }
 
   private playAlertSound() {
-    this.alertAudio.play().catch(error => console.error('Error playing alert sound:', error));
+    this.alertAudio.play().catch(error => {
+      console.error('Error playing alert sound:', error);
+    });
   }
-}
+}

+ 7 - 1
src/app/tab2/tab2.page.ts

@@ -139,7 +139,13 @@ export class Tab2Page {
     
     const selectedActivity = this.activityTypes.find(t => t.id === this.selectedType);
     if (selectedActivity) {
-      this.router.navigate(['/countdown'], {
+      console.log('Navigating to countdown with params:', {
+        type: selectedActivity.icon,
+        name: selectedActivity.name,
+        duration: this.countdownMinutes
+      });
+      
+      this.router.navigate(['/tabs/countdown'], {
         queryParams: {
           type: selectedActivity.icon,
           name: selectedActivity.name,

+ 9 - 12
src/app/tabs/tabs.routes.ts

@@ -12,29 +12,26 @@ export const routes: Routes = [
       },
       {
         path: 'tab2',
-        loadComponent: () =>
-          import('../tab2/tab2.page').then((m) => m.Tab2Page),
+        loadComponent: () => import('../tab2/tab2.page').then(m => m.Tab2Page)
       },
       {
         path: 'tab3',
-        loadComponent: () =>
-          import('../tab3/tab3.page').then((m) => m.Tab3Page),
+        loadComponent: () => import('../tab3/tab3.page').then(m => m.Tab3Page)
       },
       {
-        path: 'tab4',
-        loadComponent: () =>
-          import('../tab4/tab4.page').then((m) => m.Tab4Page),
+        path: 'countdown',
+        loadComponent: () => import('../countdown/countdown.page').then(m => m.CountdownPage)
       },
       {
         path: '',
         redirectTo: '/tabs/tab1',
-        pathMatch: 'full',
-      },
-    ],
+        pathMatch: 'full'
+      }
+    ]
   },
   {
     path: '',
     redirectTo: '/tabs/tab1',
-    pathMatch: 'full',
-  },
+    pathMatch: 'full'
+  }
 ];

+ 0 - 0
src/deploy.ps1