ソースを参照

Merge branch 'master' of http://git.fmode.cn:3000/tomorrow_shou/ai_fitness

0210331 4 ヶ月 前
コミット
fe036211c7

+ 13 - 0
.hintrc

@@ -0,0 +1,13 @@
+{
+  "extends": [
+    "development"
+  ],
+  "hints": {
+    "axe/text-alternatives": [
+      "default",
+      {
+        "image-alt": "off"
+      }
+    ]
+  }
+}

BIN
src/assets/img/cloudy.jpg


BIN
src/assets/img/night.jpg


BIN
src/assets/img/rain.jpg


BIN
src/assets/img/sunny.jpg


+ 0 - 0
src/assets/img/tree.png → src/assets/img/tree.jpg


+ 23 - 27
src/modules/tab/tree/tree.page.html

@@ -1,61 +1,57 @@
-<ion-header [translucent]="true">
-  <!-- Header content for tree theme (optional customization) -->
-</ion-header>
+<ion-content [fullscreen]="true" class="ion-padding">
 
-<ion-content [fullscreen]="true">
   <!-- Tree image -->
   <div class="image-container">
-    <img src="../../../assets/img/tree.png" alt="Tree">
+    <img [src]="getImageSource()" [alt]="selectedScene">
   </div>
 
   <!-- Title and time display -->
   <ion-row>
     <ion-col>
       <div class="info-container">
-        <h2>Tree</h2>
+        <h2>{{ getTitle() }}</h2>
       </div>
     </ion-col>
     <ion-col>
-      <div class="timer-display">
-        <span>00:00</span>
-      </div>
-    </ion-col>
-    <ion-col>
-      <div class="timer-icon">
-        <ion-icon name="timer-outline"></ion-icon>
+      <div class="timer-container">
+        <div class="timer-display">
+          <span>{{ minutes }}:{{ seconds | number: '2.0' }}</span>
+        </div>
       </div>
     </ion-col>
   </ion-row>
+  
 
   <!-- Icon buttons -->
-  <div class="icon-buttons">
-    <ion-button class="i-button">
+  <div class="icon-buttons ion-text-center">
+    <ion-button fill="solid" [color]="selectedScene === 'tree' ? 'primary' : 'medium'" class="i-button" (click)="selectScene('tree')">
       <ion-icon name="leaf"></ion-icon>
     </ion-button>
-    <ion-button class="i-button">
+    <ion-button fill="solid" [color]="selectedScene === 'rain' ? 'primary' : 'medium'" class="i-button" (click)="selectScene('rain')">
       <ion-icon name="water"></ion-icon>
     </ion-button>
-    <ion-button class="i-button">
+    <ion-button fill="solid" [color]="selectedScene === 'sunny' ? 'primary' : 'medium'" class="i-button" (click)="selectScene('sunny')">
       <ion-icon name="sunny"></ion-icon>
     </ion-button>
-    <ion-button class="i-button">
+    <ion-button fill="solid" [color]="selectedScene === 'cloudy' ? 'primary' : 'medium'" class="i-button" (click)="selectScene('cloudy')">
       <ion-icon name="cloudy"></ion-icon>
     </ion-button>
-    <ion-button class="i-button">
-      <ion-icon name="flower"></ion-icon>
+    <ion-button fill="solid" [color]="selectedScene === 'night' ? 'primary' : 'medium'" class="i-button" (click)="selectScene('night')">
+      <ion-icon name="moon"></ion-icon>
     </ion-button>
   </div>
 
   <!-- Control buttons -->
-  <div class="control-buttons">
-    <ion-button fill="solid" class="ctrl-button">
-      <ion-icon name="play-back-outline"></ion-icon>
+  <div class="control-buttons ion-text-center">
+    <ion-button fill="solid" [color]="isPlayingMusic ? 'primary' : 'medium'" class="ctrl-button" (click)="toggleMusic()">
+      <ion-icon name="musical-notes-outline"></ion-icon>
     </ion-button>
-    <ion-button fill="solid" class="ctrl-button">
-      <ion-icon name="play-outline"></ion-icon>
+    <ion-button fill="solid" [color]="isPaused ? 'primary' : 'medium'" class="ctrl-button" (click)="togglePauseResume()">
+      <ion-icon [name]="isPaused ? ( (minutes === 0 && seconds === 0) ? 'play-outline' : 'pause-outline') : 'pause-outline'"></ion-icon>
     </ion-button>
-    <ion-button fill="solid" class="ctrl-button">
-      <ion-icon name="play-forward-outline"></ion-icon>
+    <ion-button fill="solid" [color]="exitButtonColor()" class="ctrl-button" (click)="confirmExit()">
+      <ion-icon name="stop-outline"></ion-icon>
     </ion-button>
   </div>
+  
 </ion-content>

+ 72 - 51
src/modules/tab/tree/tree.page.scss

@@ -1,81 +1,102 @@
-ion-app {
-  --ion-background-color: #e1e1e1; /* Light grey */
-}
-
 .image-container {
   display: flex;
   justify-content: center;
-  margin-top: 20px;
+  margin: 20px 0px 20px 0px;
+
   img {
-    margin-top: 40px;
-    width: 80%;
+    margin-top: 20px;
+    width: 85%; /* Adjust width as needed */
+    height: 350px; /* Fixed height */
+    object-fit: cover; /* Ensures the image covers the fixed size without distortion */
     border-radius: 10px;
   }
 }
 
+
 .info-container {
-  margin-top: 50px;
+  display: flex;
+  /* justify-content: center;
+  align-items: center; */
+  padding-left: 15%;
   h2 {
-    width: 170px;
-    text-align: left;
-    margin-left: 30px;
-    font-size: 2.5rem;
-    color: #333;
-    font-weight: bold;
+    font-family: 'Digital-7'; /* 使用电子数字字体 */
+    margin-top: 0px;
+    font-size: 2.5rem; /* Adjust as needed */
+    padding: 5px;
+    background-color: transparent;
+    color: #000; /* Adjust button text color */
+    border: 1px solid #ccc; /* Border */
+    border-radius: 15%; /* Circular button */
+    box-shadow: 2px 2px 5px rgba(0,0,0,0.3); /* Shadow effect */
   }
+  
 }
 
-.timer-display {
-  margin-top: 50px;
-  justify-content: right;
-  font-size: 2.2rem;
-  color: #333;
-  border: 2px solid #c1c1c1;
-  border-radius: 10%;
-  padding: 5px 5px 5px 5px;
+.timer-container {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  font-size: 2rem;
+  margin-right: 20%;
 }
 
-.timer-icon {
-  margin-top: 50px;
-  margin-left: 25px;
-  font-size: 2.5rem;
-  color: black;
-  border: 2px solid #c2c2c2;
-  border-radius: 10%;
-  width: 60%;
-  height: 50%;
-  padding: 5px 5px 0px 5px;
+.timer-display {
+  font-size: 3rem; /* 调整字体大小 */
+  display: inline-block; /* 确保宽度适应内容 */
+  background-color: transparent;
+  padding: 4px 5px;
+  color: #000; /* Adjust button text color */
+  border: 1px solid #ccc; /* Border */
+  border-radius: 15%; /* Circular button */
+  box-shadow: 2px 2px 5px rgba(0,0,0,0.3); /* Shadow effect */
 }
 
+
+
+
 .icon-buttons {
   display: flex;
   justify-content: space-around;
-  margin: 45px 20px;
+  margin: 20px 0px 30px 0px;
+
   .i-button {
-    --background: #e1e1e1;
-    --border-radius: 50%;
-    --padding: 5px;
-    ion-icon {
-      font-size: 2.4rem;
-      color: rgb(178, 178, 178);
-    }
+    --padding-start: 0;
+    --padding-end: 0;
+    background-color: transparent;
+    color: #000; /* Adjust button text color */
+    font-size: 1.5rem; /* Adjust icon size */
+    width: 50px; /* Fixed width */
+    height: 50px; /* Fixed height */
+    border-radius: 50%; /* Circular button */
+    box-shadow: 2px 2px 5px rgba(0,0,0,0.3); /* Shadow effect */
+  }
+
+  .i-button:active {
+    box-shadow: inset 2px 2px 5px rgba(0,0,0,0.3); /* Inner shadow on click */
   }
 }
 
 .control-buttons {
   display: flex;
   justify-content: space-around;
-  margin: 45px 20px;
+  margin: 20px 0;
+
   .ctrl-button {
-    --background: #e1e1e1;
-    border-radius: 100%;
-    border: 5px wheat;
-    padding: 10px;
-    box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.415),
-                -4px -4px 8px rgba(255, 255, 255, 0.914);
-    ion-icon {
-      font-size: 1.8rem;
-      color: #000000;
-    }
+    --padding-start: 10px;
+    --padding-end: 10px;
+    background: linear-gradient(to bottom, #ffffff, #e6e6e6); /* Gradient effect */
+    border: 1px solid #ccc; /* Border */
+    border-radius: 50%; /* Circular button */
+    box-shadow: 2px 2px 5px rgba(0,0,0,0.3); /* Shadow effect */
+    width: 60px; /* Fixed width */
+    height: 60px; /* Fixed height */
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 24px; /* Adjust icon size */
+  }
+
+  .ctrl-button:active {
+    box-shadow: inset 2px 2px 5px rgba(0,0,0,0.3); /* Inner shadow on click */
   }
 }

+ 151 - 3
src/modules/tab/tree/tree.page.ts

@@ -1,12 +1,160 @@
-import { Component } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { AlertController, NavController } from '@ionic/angular';
 
 @Component({
   selector: 'app-tree',
   templateUrl: 'tree.page.html',
   styleUrls: ['tree.page.scss']
 })
-export class TreePage {
+export class TreePage implements OnInit, OnDestroy {
+  timer: any;
+  minutes: number = 0;
+  seconds: number = 0;
+  isRunning: boolean = false;
+  isPlayingMusic: boolean = false;
+  selectedScene: string = 'tree';
+  isPaused: boolean = true; // Start with paused (dark) icon
+  exitClicked: boolean = false; // Track if exit button is clicked
 
-  constructor() {}
+  constructor(private navCtrl: NavController, private alertController: AlertController) {}
 
+  ngOnInit() {
+    // No need to start the timer here; it starts when user interacts with it
+  }
+
+  startTimer() {
+    this.stopTimer();
+    console.log('Timer started');
+    this.isRunning = true;
+    this.timer = setInterval(() => {
+      this.seconds++;
+      if (this.seconds >= 60) {
+        this.seconds = 0;
+        this.minutes++;
+      }
+    }, 1000);
+  }
+
+  stopTimer() {
+    if (this.timer) {
+      clearInterval(this.timer);
+      console.log('Timer stopped');
+    }
+    this.isRunning = false;
+  }
+
+  togglePauseResume() {
+    if (this.minutes === 0 && this.seconds === 0) {
+      // If time is zero, start the timer
+      this.startTimer();
+      this.isPaused = false; // Set to false (bright) for play icon
+      console.log('Timer started');
+    } else {
+      // Toggle pause/play and update icon brightness
+      if (this.isPaused) {
+        this.resumeTimer();
+        console.log('Timer resumed');
+      } else {
+        this.pauseTimer();
+        console.log('Timer paused');
+      }
+      this.isPaused = !this.isPaused; // Toggle the brightness
+    }
+  }
+
+  pauseTimer() {
+    this.stopTimer();
+  }
+
+  resumeTimer() {
+    this.startTimer();
+  }
+
+  resetTimer() {
+    this.stopTimer();
+    this.minutes = 0;
+    this.seconds = 0;
+    this.isPaused = true; // Reset to paused state
+    console.log('Timer reset');
+  }
+
+  toggleMusic() {
+    this.isPlayingMusic = !this.isPlayingMusic;
+    console.log(this.isPlayingMusic ? 'Music playing' : 'Music paused');
+    // Add logic to play or pause music
+  }
+
+  async confirmExit() {
+    this.stopTimer();
+    this.isPaused = true; // Ensure the pause icon is dark when exiting
+    this.exitClicked = true; // Set exit button clicked to true
+    const alert = await this.alertController.create({
+      header: 'Confirm Exit',
+      message: 'Are you sure you want to exit and reset the timer?',
+      buttons: [
+        {
+          text: 'Cancel',
+          role: 'cancel',
+          handler: () => {
+            console.log('Exit cancelled');
+            this.exitClicked = false; // Reset exit button clicked
+          }
+        },
+        {
+          text: 'Confirm',
+          handler: () => {
+            this.resetTimer();
+            this.navCtrl.back();
+            console.log('Exited and timer reset');
+            this.exitClicked = false; // Reset exit button clicked
+          }
+        }
+      ]
+    });
+
+    await alert.present();
+  }
+
+  exitButtonColor() {
+    return this.exitClicked ? 'primary' : 'medium';
+  }
+
+  ngOnDestroy() {
+    this.stopTimer();
+  }
+  
+  selectScene(scene: string) {
+    this.selectedScene = scene;
+    console.log('Selected scene:', scene);
+  }
+
+  getImageSource(): string {
+    switch(this.selectedScene) {
+      case 'rain':
+        return '../../../assets/img/rain.jpg';
+      case 'sunny':
+        return '../../../assets/img/sunny.jpg';
+      case 'cloudy':
+        return '../../../assets/img/cloudy.jpg';
+      case 'night':
+        return '../../../assets/img/night.jpg';
+      default:
+        return '../../../assets/img/tree.jpg';
+    }
+  }
+
+  getTitle(): string {
+    switch(this.selectedScene) {
+      case 'rain':
+        return 'Rain';
+      case 'sunny':
+        return 'Sunny';
+      case 'cloudy':
+        return 'Cloudy';
+      case 'night':
+        return 'Night';
+      default:
+        return 'Tree';
+    }
+  }
 }

+ 5 - 1
src/modules/user/login/login.page.html

@@ -8,11 +8,15 @@
       <ion-card-content>
         <ion-list>
           <ion-item lines="none">
-            <ion-label  class="label-login">账号</ion-label>
+            <div>
+              <ion-label  class="label-login">账号</ion-label>
+            </div>
             <ion-input [(ngModel)]="username" placeholder="请输入用户名"></ion-input>
           </ion-item>
           <ion-item lines="none">
+            <div>
             <ion-label  class="label-login">密码</ion-label>
+            </div>
             <ion-input [(ngModel)]="password" type="password" placeholder="请输入密码"></ion-input>
           </ion-item>
         </ion-list>

+ 9 - 4
src/modules/user/login/login.page.scss

@@ -18,15 +18,20 @@
 .ion-label{
   width:32px;
 }
+
 .label-login{
-  font-size:16px;
+  width:30px;
+  display: inline-block;
+  font-size:15px;
   position: static; /* 设置为静态,不浮动 */
-  margin-right: 0px;
+  margin-right: 8px;
+  margin-bottom: 2px;
+  
 }
 
 //输入
-.sc-ion-input-md-h{
-  width:88%;
+.ion-input-md-h{
+  width: 80%;
 }
 
 //返回按钮