Prechádzať zdrojové kódy

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

0210331 5 mesiacov pred
rodič
commit
f05f8d42ed

+ 13 - 0
src/app/app-routing.module.ts

@@ -11,6 +11,19 @@ const routes: Routes = [
     loadChildren: () => import('./calendar/calendar.module').then( m => m.CalendarPageModule)
   },
 
+  {
+    path: 'user',
+    loadChildren: () => import('../modules/user/user.module').then(m => m.UserModule)
+  },
+  {
+    path: "tree",
+    loadChildren: () => import('../modules/tab/tree/tree.module').then(m => m.TreePageModule)
+  },
+  {
+    path: 'memo',
+    loadChildren: () => import('./memo/memo.module').then( m => m.MemoPageModule)
+  },
+
   {
     path: 'user',
     loadChildren: () => import('../modules/user/user.module').then(m => m.UserModule)

+ 17 - 0
src/app/memo/memo-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { MemoPage } from './memo.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: MemoPage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class MemoPageRoutingModule {}

+ 20 - 0
src/app/memo/memo.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { MemoPageRoutingModule } from './memo-routing.module';
+
+import { MemoPage } from './memo.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    MemoPageRoutingModule
+  ],
+  declarations: [MemoPage]
+})
+export class MemoPageModule {}

+ 26 - 0
src/app/memo/memo.page.html

@@ -0,0 +1,26 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>备忘录</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+
+
+  <div *ngIf="segment === 'memo'">
+    <ion-list>
+      <ion-item *ngFor="let memo of memos">
+        {{ memo }}
+        <ion-button slot="end" color="danger" (click)="confirmDeleteMemo(memo)">
+          删除
+        </ion-button>
+      </ion-item>
+    </ion-list>
+
+    <ion-item>
+      <ion-input placeholder="添加新备忘录" [(ngModel)]="newMemo"></ion-input>
+      <ion-button (click)="addMemo()">添加</ion-button>
+    </ion-item>
+  </div>
+
+</ion-content>

+ 10 - 0
src/app/memo/memo.page.scss

@@ -0,0 +1,10 @@
+ion-label.ai {
+      color: blue;
+      text-align: left;
+    }
+    
+    ion-label.user {
+      color: green;
+      text-align: right;
+    }
+    

+ 17 - 0
src/app/memo/memo.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MemoPage } from './memo.page';
+
+describe('MemoPage', () => {
+  let component: MemoPage;
+  let fixture: ComponentFixture<MemoPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MemoPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 88 - 0
src/app/memo/memo.page.ts

@@ -0,0 +1,88 @@
+import { Component, OnInit } from '@angular/core';
+import { AlertController } from '@ionic/angular';
+
+
+@Component({
+  selector: 'app-memo',
+  templateUrl: './memo.page.html',
+  styleUrls: ['./memo.page.scss'],
+})
+
+
+
+export class MemoPage implements OnInit {
+  segment: string = 'memo';
+  memos: string[] = [];
+  newMemo: string = '';
+  newMessage: string = '';
+  constructor(private alertController: AlertController) {}
+
+  ngOnInit() {
+    this.loadMemos();
+  }
+  //加载备忘录
+  loadMemos() {
+    const memos = localStorage.getItem('memos');
+    if (memos) {
+      this.memos = JSON.parse(memos);
+    }
+  }
+  //保存备忘录
+  saveMemos() {
+    localStorage.setItem('memos', JSON.stringify(this.memos));
+  }
+
+  //获取时间戳
+  getCurrentTimestamp(): string {
+    const now = new Date();
+    const year = now.getFullYear();
+    const month = (now.getMonth() + 1).toString().padStart(2, '0');
+    const day = now.getDate().toString().padStart(2, '0');
+    const hours = now.getHours().toString().padStart(2, '0');
+    const minutes = now.getMinutes().toString().padStart(2, '0');
+    return `${year}年${month}月${day}日${hours}:${minutes}`;
+  }
+
+  //异步函数,添加备忘录
+  async addMemo() {
+    if (this.newMemo.trim().length > 0) {
+      this.memos.push(this.newMemo);
+      this.newMemo = '';
+      this.saveMemos();
+      const alert = await this.alertController.create({
+        header: '提示',
+        message: '添加成功',
+        buttons: ['确定']
+      });
+      await alert.present();
+    }
+  }
+  //异步函数,确认删除
+  async confirmDeleteMemo(memo: string) {
+    const alert = await this.alertController.create({
+      header: '确认删除',
+      message: `你确定要删除 "${memo}" 吗?`,
+      buttons: [
+        {
+          text: '取消',
+          role: 'cancel'
+        },
+        {
+          text: '删除',
+          handler: () => {
+            this.memos = this.memos.filter(m => m !== memo);
+            this.saveMemos();
+          }
+        }
+      ]
+    });
+    await alert.present();
+  }
+
+  //删除备忘录
+  deleteMemo(memo: string) {
+    this.memos = this.memos.filter(m => m !== memo);
+    this.saveMemos();
+  }
+
+}

+ 92 - 0
src/app/tab2/class-chat-completion.ts

@@ -0,0 +1,92 @@
+export interface TestChatMessage {
+  role: string
+  content: string
+}
+export class TestChatCompletion {
+  messageList: Array<TestChatMessage>
+  constructor(messageList: Array<TestChatMessage>) {
+    this.messageList = messageList
+  }
+  async createCompletionByStream() {
+
+    let token = localStorage.getItem("token");
+    let bodyJson = {
+      "token": `Bearer ${token}`,
+      "messages": this.messageList,
+      "model": "gpt-3.5-turbo",
+      "temperature": 0.5,
+      "presence_penalty": 0,
+      "frequency_penalty": 0,
+      "top_p": 1,
+      "stream": true
+    };
+
+    let response = await fetch("https://test.fmode.cn/api/apig/aigc/gpt/v1/chat/completions", {
+      "headers": {
+        "accept": "text/event-stream",
+        "sec-fetch-dest": "empty",
+        "sec-fetch-mode": "cors",
+        "sec-fetch-site": "same-site"
+      },
+      "referrer": "https://ai.fmode.cn/",
+      "referrerPolicy": "strict-origin-when-cross-origin",
+      "body": JSON.stringify(bodyJson),
+      "method": "POST",
+      "mode": "cors",
+      "credentials": "omit"
+    });
+
+    let messageAiReply = ""
+    let messageIndex = this.messageList.length
+    let reader = response.body?.getReader();
+    if (!reader) {
+      throw new Error("Failed to get the response reader.");
+    }
+
+    let decoder = new TextDecoder();
+    let buffer = "";
+
+    while (true) {
+      let { done, value } = await reader.read();
+      if (done) {
+        break;
+      }
+
+      buffer += decoder.decode(value);
+
+      // Split the buffer by newlines to get individual messages
+      let messages = buffer.split("\n");
+
+      // Process each message
+      for (let i = 0; i < messages.length - 1; i++) {
+        let message = messages[i];
+
+
+        let dataText = message.replace("data:\ ", "")
+        if (dataText.startsWith("{")) {
+          try {
+            let dataJson = JSON.parse(dataText)
+            console.log(dataJson)
+            messageAiReply += dataJson?.choices?.[0]?.delta?.content || ""
+            this.messageList[messageIndex] = {
+              role: "assistant",
+              content: messageAiReply
+            }
+          } catch (err) { }
+        }
+        if (dataText.startsWith("[")) {
+          console.log(message)
+          console.log("完成")
+          this.messageList[messageIndex] = {
+            role: "assistant",
+            content: messageAiReply
+          }
+          messageAiReply = ""
+        }
+
+        // Clear the processed message from the buffer
+        buffer = buffer.slice(message.length + 1);
+      }
+    }
+  }
+}

+ 17 - 35
src/app/tab2/tab2.page.html

@@ -5,43 +5,25 @@
 </ion-header>
 
 <ion-content>
-  <ion-segment [(ngModel)]="segment">
-    <ion-segment-button value="memo">
-      <ion-label>备忘录</ion-label>
-    </ion-segment-button>
-    <ion-segment-button value="chat">
-      <ion-label>AI对话</ion-label>
-    </ion-segment-button>
-  </ion-segment>
-
-  <div *ngIf="segment === 'memo'">
-    <ion-list>
-      <ion-item *ngFor="let memo of memos">
-        {{ memo }}
-        <ion-button slot="end" color="danger" (click)="confirmDeleteMemo(memo)">
-          删除
-        </ion-button>
-      </ion-item>
-    </ion-list>
+  
 
+  <ion-content>
     <ion-item>
-      <ion-input placeholder="添加新备忘录" [(ngModel)]="newMemo"></ion-input>
-      <ion-button (click)="addMemo()">添加</ion-button>
+      <ion-input placeholder="输入消息" [(ngModel)]="userInput"></ion-input>
     </ion-item>
-  </div>
 
-  <div *ngIf="segment === 'chat'">
-    <ion-list>
-      <ion-item *ngFor="let message of messages">
-        <ion-label [ngClass]="{'ai': message.sender === 'ai', 'user': message.sender === 'user'}">
-          {{ message.text }}
-        </ion-label>
-      </ion-item>
-    </ion-list>
+    <ion-button expand="block" (click)="sendMessage()">发送</ion-button>
 
-    <ion-item>
-      <ion-input placeholder="输入消息" [(ngModel)]="newMessage"></ion-input>
-      <ion-button (click)="sendMessage()">发送</ion-button>
-    </ion-item>
-  </div>
-</ion-content>
+    <ion-card *ngFor="let message of messageList">
+      <ion-card-header>
+        {{message?.role}}
+      </ion-card-header>
+      <ion-card-content>
+        {{ message?.content }}
+      </ion-card-content>
+    </ion-card>
+  </ion-content>
+
+
+
+</ion-content>

+ 17 - 78
src/app/tab2/tab2.page.ts

@@ -1,98 +1,37 @@
 import { Component,OnInit } from '@angular/core';
 import { AlertController } from '@ionic/angular';
+// 引用FmodeChatCompletion类
+import { TestChatCompletion, TestChatMessage } from './class-chat-completion';
 @Component({
   selector: 'app-tab2',
   templateUrl: './tab2.page.html',
   styleUrls: ['./tab2.page.scss'],
 })
 export class Tab2Page implements OnInit {
-  segment: string = 'memo';
-  memos: string[] = [];
-  newMemo: string = '';
   messages: { sender: string, text: string }[] = [];
   newMessage: string = '';
+  messageList:Array<TestChatMessage> = []
+  userInput:string = ""
 
-  constructor(private alertController: AlertController) {}
+  completion:TestChatCompletion
 
-  ngOnInit() {
-    this.loadMemos();
-  }
-  //加载备忘录
-  loadMemos() {
-    const memos = localStorage.getItem('memos');
-    if (memos) {
-      this.memos = JSON.parse(memos);
-    }
-  }
-  //保存备忘录
-  saveMemos() {
-    localStorage.setItem('memos', JSON.stringify(this.memos));
-  }
+  constructor(private alertController: AlertController) {this.completion = new TestChatCompletion(this.messageList)}
 
-  //获取时间戳
-  getCurrentTimestamp(): string {
-    const now = new Date();
-    const year = now.getFullYear();
-    const month = (now.getMonth() + 1).toString().padStart(2, '0');
-    const day = now.getDate().toString().padStart(2, '0');
-    const hours = now.getHours().toString().padStart(2, '0');
-    const minutes = now.getMinutes().toString().padStart(2, '0');
-    return `${year}年${month}月${day}日${hours}:${minutes}`;
-  }
 
-  //异步函数,添加备忘录
-  async addMemo() {
-    if (this.newMemo.trim().length > 0) {
-      this.memos.push(this.newMemo);
-      this.newMemo = '';
-      this.saveMemos();
-      const alert = await this.alertController.create({
-        header: '提示',
-        message: '添加成功',
-        buttons: ['确定']
-      });
-      await alert.present();
-    }
-  }
-  //异步函数,确认删除
-  async confirmDeleteMemo(memo: string) {
-    const alert = await this.alertController.create({
-      header: '确认删除',
-      message: `你确定要删除 "${memo}" 吗?`,
-      buttons: [
-        {
-          text: '取消',
-          role: 'cancel'
-        },
-        {
-          text: '删除',
-          handler: () => {
-            this.memos = this.memos.filter(m => m !== memo);
-            this.saveMemos();
-          }
-        }
-      ]
-    });
-    await alert.present();
+  ngOnInit() {
+  
   }
+  
 
-  //删除备忘录
-  deleteMemo(memo: string) {
-    this.memos = this.memos.filter(m => m !== memo);
-    this.saveMemos();
-  }
+  //ai对话
+  sendMessage(){
+    this.messageList.push({
+      role:"user",
+      content: this.userInput
+    })
+    this.userInput = ""
+    this.completion.createCompletionByStream()
 
-  //
-  sendMessage() {
-    if (this.newMessage.trim().length > 0) {
-      this.messages.push({ sender: 'user', text: this.newMessage });
-      this.newMessage = '';
-      
-      // 模拟AI回复
-      setTimeout(() => {
-        this.messages.push({ sender: 'ai', text: 'AI的回复' });
-      }, 1000);
-    }
   }
 
 }

+ 4 - 0
src/app/tabs/tabs-routing.module.ts

@@ -11,6 +11,10 @@ const routes: Routes = [
         path: 'tab1',
         loadChildren: () => import('../tab1/tab1.module').then(m => m.Tab1PageModule)
       },
+      {
+        path: 'memo',
+        loadChildren: () => import('../memo/memo.module').then(m => m.MemoPageModule)
+      },
       {
         path: 'tab2',
         loadChildren: () => import('../tab2/tab2.module').then(m => m.Tab2PageModule)

+ 12 - 3
src/app/tabs/tabs.page.html

@@ -1,15 +1,24 @@
 <ion-tabs>
   <ion-tab-bar slot="bottom">
     <ion-tab-button tab="tab1" href="/tabs/tab1">
-      <ion-icon aria-hidden="true" name="home"></ion-icon>
+      <ion-icon aria-hidden="true" name="scale-outline"></ion-icon>
       <ion-label>首页</ion-label>
     </ion-tab-button>
 
+
+    <ion-tab-button tab="memo" href="/tabs/memo">
+      <ion-icon aria-hidden="true" name="receipt-outline"></ion-icon>
+      <ion-label>备忘录</ion-label>
+    </ion-tab-button>
+
+    
     <ion-tab-button tab="tab2" href="/tabs/tab2">
-      <ion-icon aria-hidden="true" name="pencil"></ion-icon>
-      <ion-label>记录一下</ion-label>
+      <ion-icon aria-hidden="true" name="chatbox-ellipses-outline"></ion-icon>
+      <ion-label>ai对话</ion-label>
     </ion-tab-button>
 
+
+
     <ion-tab-button (click)="checkLogin()">
       <ion-icon aria-hidden="true" name="person"></ion-icon>
       <ion-label>我的</ion-label>