Browse Source

feat:new yuyin

15207938132 2 months ago
parent
commit
cada782921

+ 16 - 2
fashion-app/src/app/ai-chat-component/ai-chat-component.component.html

@@ -28,10 +28,24 @@
 <ion-footer style="background-color: #99d75c;">
   <ion-toolbar>
     <div class="footer-content">
-      <ion-buttons>
-        <ion-button (click)="startVoice()" fill="clear">
+
+      <ion-buttons>  <!--语音输入-->
+        <ion-button (click)="startVoice()" fill="clear" id="open-modal">
           <ion-icon name="mic-circle-outline" style="color: white; font-size: 40px;"></ion-icon>
         </ion-button>
+        
+        <ion-modal trigger="open-modal" [initialBreakpoint]="0.25" [breakpoints]="[0, 0.25, 0.5, 0.75]" handleBehavior="cycle">
+          <ng-template>
+            <ion-content style="background-color: #99d75c; display: flex; flex-direction: column; justify-content: center; align-items: center;">
+              <div style="display: flex; justify-content: space-between; width: 100%; padding: 10px;">
+                <ion-button (click)="cancelVoiceInput()" fill="clear" style="color: black;">取消</ion-button>
+                <div style="color: black; font-size: 24px;" id="timer">{{ timer }}</div>
+                <ion-button (click)="sendVoiceInput()" fill="clear" style="color: black;">发送</ion-button>
+              </div> 
+            </ion-content>
+          </ng-template>
+        </ion-modal>
+        
       </ion-buttons>
 
       <ion-input placeholder="输入消息..." class="input-box" [(ngModel)]="userMessage">

+ 24 - 0
fashion-app/src/app/ai-chat-component/ai-chat-component.component.scss

@@ -82,4 +82,28 @@ justify-content: center; /* 水平居中对齐 */
   margin: 5px 0; /* 外边距 */
   max-width: 80%; /* 最大宽度 */
   word-wrap: break-word; /* 自动换行 */
+}
+
+.animation-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100px; /* 根据需要调整高度 */
+}
+
+.pulse-animation {
+  width: 50px; /* 根据需要调整宽度 */
+  height: 50px; /* 根据需要调整高度 */
+  background-color: white; /* 音律跳动的颜色 */
+  border-radius: 50%; /* 圆形 */
+  animation: pulse 1s infinite; /* 调整动画速度 */
+}
+
+@keyframes pulse {
+  0%, 100% {
+    transform: scale(1);
+  }
+  50% {
+    transform: scale(1.2);
+  }
 }

+ 86 - 51
fashion-app/src/app/ai-chat-component/ai-chat-component.component.ts

@@ -1,11 +1,12 @@
 import { CommonModule } from '@angular/common';
 import { Component, OnInit } from '@angular/core';
 import { FormsModule } from '@angular/forms';
-import { NavController } from '@ionic/angular';
-import { IonButtons, IonHeader, IonToolbar,IonButton, IonIcon, IonTitle, IonInput, IonFooter, IonContent, AlertController } from '@ionic/angular/standalone';
+import {  NavController } from '@ionic/angular';
+import { IonButtons, IonHeader, IonToolbar,IonButton, IonIcon, IonTitle, IonInput, IonFooter, IonContent, AlertController,  } from '@ionic/angular/standalone';
 import { FmodeChatCompletion } from 'fmode-ng';
 import { addIcons } from 'ionicons';
 import { chevronBackSharp, ellipsisHorizontal, happyOutline, micCircleOutline, paperPlane } from 'ionicons/icons';
+import { IonModal, IonLabel } from '@ionic/angular/standalone'; // 导入独立组件
 
 addIcons({ chevronBackSharp,ellipsisHorizontal,micCircleOutline,happyOutline,paperPlane });
 
@@ -21,7 +22,7 @@ interface Window {
   standalone: true,
   imports: [
     IonHeader,IonToolbar,IonButtons,IonButton,IonIcon,IonTitle,IonInput,IonFooter,CommonModule,IonContent,
-    FormsModule
+    FormsModule,IonModal,IonLabel
   ],
  
 })
@@ -32,6 +33,13 @@ export class AiChatComponentComponent  implements OnInit {
   aiMessage: string = ''; // 用于存储AI的回复
   initialPrompt: string = ''; // 用于存储初始化提示
   recognition: any; // 用于存储语音识别实例
+  recognizedContent: string = ''; // 用于存储识别到的语音内容
+  timer: string = '00:00'; // 用于显示计时器
+  interval: any; // 用于存储定时器的引用
+  elapsedSeconds: number = 0; // 计时器的秒数
+  isVoiceInputVisible: boolean = false; // 控制语音输入框的显示状态
+ 
+
   constructor(private navCtrl: NavController,private alertController: AlertController) {
     // 初始化语音识别
     this.initSpeechRecognition();
@@ -41,63 +49,90 @@ export class AiChatComponentComponent  implements OnInit {
 
    
   // 初始化语音识别
-  initSpeechRecognition() {
-    const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
-    if (SpeechRecognition) {
-      this.recognition = new SpeechRecognition();
-      this.recognition.lang = 'zh-CN'; // 设置语言为中文
-      this.recognition.interimResults = false; // 不返回中间结果
-      this.recognition.maxAlternatives = 1; // 最大替代结果数
-
-      this.recognition.onresult = (event: any) => {
-        const transcript = event.results[0][0].transcript; // 获取识别结果
-        console.log("识别到的内容:", transcript); // 打印识别到的内容
-        this.confirmSpeechInput(transcript); // 调用确认输入方法
-      };
-
-      this.recognition.onerror = (event: any) => {
+initSpeechRecognition() {
+  const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
+  if (SpeechRecognition) {
+    this.recognition = new SpeechRecognition();
+    this.recognition.lang = 'zh-CN'; // 设置语言为中文
+    this.recognition.interimResults = false; // 不返回中间结果
+    this.recognition.maxAlternatives = 1; // 最大替代结果数
+    this.recognition.continuous = true; // 设置为连续识别
+    
+
+    // 处理识别结果
+    this.recognition.onresult = (event: any) => {
+      this.recognizedContent += event.results[event.results.length - 1][0].transcript; // 追加识别结果
+      console.log("识别到的内容:", this.recognizedContent); // 打印识别到的内容
+    };
+
+    // 处理识别错误
+    this.recognition.onerror = (event: any) => {
+      if (event.error === 'no-speech') {
+        console.warn('没有检测到语音,继续监听...');
+      } else {
         console.error('语音识别错误:', event.error);
-      };
-    } else {
-      console.log('该浏览器不支持语音识别');
-    }
+      }
+    };
+  } else {
+    console.log('该浏览器不支持语音识别');
   }
+}
 
-  // 启动语音输入
-  startVoice() {
-    if (this.recognition) {
-      this.recognition.start(); // 启动语音识别
-      console.log('语音识别启动...');
-    }
+
+startVoice() {
+  if (this.recognition && this.recognition.state !== 'active') { // 检查识别状态
+    this.recognition.start(); // 启动语音识别
+    console.log('语音识别启动...');
+    this.startTimer(); // 启动计时器
+    this.isVoiceInputVisible = true; // 显示语音输入框
+  } else {
+    console.warn('语音识别已经在运行中'); // 提示用户语音识别已在运行
   }
+}
 
-  // 确认语音输入
-  async confirmSpeechInput(transcript: string) {
-    const alert = await this.alertController.create({
-      header: '确认语音输入',
-      message: `识别到的内容是: "${transcript}",是否确认?`,
-      buttons: [
-        {
-          text: '取消',
-          role: 'cancel',
-          handler: () => {
-            console.log('用户取消输入');
-          }
-        },
-        {
-          text: '确定',
-          handler: () => {
-            this.userMessage = transcript; // 将识别结果赋值给用户消息
-            console.log("已确认输入:", this.userMessage); // 打印确认后的内容
-          }
-        }
-      ]
-    });
+  // 启动计时器
+  startTimer() {
+    this.elapsedSeconds = 0; // 重置秒数
+    this.timer = '00:00'; // 重置计时器显示
+    this.interval = setInterval(() => {
+      this.elapsedSeconds++;
+      const minutes = Math.floor(this.elapsedSeconds / 60);
+      const seconds = this.elapsedSeconds % 60;
+      this.timer = `${this.padZero(minutes)}:${this.padZero(seconds)}`; // 更新计时器显示
+    }, 1000);
+  }
 
-    await alert.present();
+  // 格式化数字为两位数
+  padZero(num: number): string {
+    return num < 10 ? '0' + num : num.toString();
+  }
+// 取消语音输入
+cancelVoiceInput() {
+  if (this.recognition) {
+    this.recognition.stop(); // 停止语音识别
+    console.log('语音识别已停止');
+    clearInterval(this.interval); // 清除计时器
+    this.timer = '00:00'; // 重置计时器显示
+    this.recognizedContent = ''; // 清空识别内容
   }
+  this.isVoiceInputVisible = false; // 隐藏语音输入框
 
+}
+
+// 发送语音输入
+sendVoiceInput() {
+  if (this.recognition) {
+    this.recognition.stop(); // 停止语音识别
+    console.log('语音识别已停止');
+    clearInterval(this.interval); // 清除计时器
+    this.timer = '00:00'; // 重置计时器显示
+    // 将识别到的内容传到输入框中
+    this.userMessage = this.recognizedContent.trim(); // 将识别内容赋值给输入框,并去除多余空格
+    this.recognizedContent = ''; // 清空识别内容
+  }
+  this.isVoiceInputVisible = false; // 隐藏语音输入框
 
+}
   goBack() {
     this.navCtrl.back(); // 返回上一页
   }

+ 7 - 0
fashion-app/src/app/page-yuyin/page-yuyin.component.html

@@ -0,0 +1,7 @@
+<ion-content style="background-color: #99d75c; display: flex; flex-direction: column; justify-content: center; align-items: center;">
+  <div style="display: flex; justify-content: space-between; width: 100%; padding: 10px;">
+    <ion-button (click)="cancelVoiceInput()" fill="clear" style="color: black;">取消</ion-button>
+    <div style="color: black; font-size: 24px;" id="timer">{{ timer }}</div>
+    <ion-button (click)="sendVoiceInput()" fill="clear" style="color: black;">发送</ion-button>
+  </div> 
+</ion-content>

+ 0 - 0
fashion-app/src/app/page-yuyin/page-yuyin.component.scss


+ 22 - 0
fashion-app/src/app/page-yuyin/page-yuyin.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { PageYuyinComponent } from './page-yuyin.component';
+
+describe('PageYuyinComponent', () => {
+  let component: PageYuyinComponent;
+  let fixture: ComponentFixture<PageYuyinComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [PageYuyinComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(PageYuyinComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 16 - 0
fashion-app/src/app/page-yuyin/page-yuyin.component.ts

@@ -0,0 +1,16 @@
+import { Component, OnInit } from '@angular/core';
+import { ModalController } from '@ionic/angular';
+
+@Component({
+  selector: 'app-page-yuyin',
+  templateUrl: './page-yuyin.component.html',
+  styleUrls: ['./page-yuyin.component.scss'],
+  standalone: true,
+})
+export class PageYuyinComponent  implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {}
+
+}