浏览代码

achieve a AIGC page

xukang 4 月之前
父节点
当前提交
dd3d5884f8

+ 10 - 2
newwisefitnessapp/ionic.config.json

@@ -3,5 +3,13 @@
   "integrations": {
     "capacitor": {}
   },
-  "type": "angular-standalone"
-}
+  "type": "angular-standalone",
+  "server": {
+    "proxy": {
+      "/api": {
+        "target": "https://test.fmode.cn",
+        "secure": false
+      }
+    }
+  }
+}

文件差异内容过多而无法显示
+ 640 - 16
newwisefitnessapp/package-lock.json


+ 3 - 0
newwisefitnessapp/package.json

@@ -27,7 +27,10 @@
     "@capacitor/keyboard": "6.0.3",
     "@capacitor/status-bar": "6.0.2",
     "@ionic/angular": "^8.0.0",
+    "@types/parse": "^3.0.9",
+    "fmode-ng": "^0.0.62",
     "ionicons": "^7.2.1",
+    "parse": "^5.3.0",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",
     "zone.js": "~0.14.2"

+ 3 - 0
newwisefitnessapp/src/app/page-rxjs/page-rxjs.component.html

@@ -0,0 +1,3 @@
+<p>
+  page-rxjs works!
+</p>

+ 0 - 0
newwisefitnessapp/src/app/page-rxjs/page-rxjs.component.scss


+ 22 - 0
newwisefitnessapp/src/app/page-rxjs/page-rxjs.component.spec.ts

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

+ 19 - 0
newwisefitnessapp/src/app/page-rxjs/page-rxjs.component.ts

@@ -0,0 +1,19 @@
+import { Component, OnInit } from '@angular/core';
+import { Observable } from 'rxjs';
+
+@Component({
+  selector: 'app-page-rxjs',
+  templateUrl: './page-rxjs.component.html',
+  styleUrls: ['./page-rxjs.component.scss'],
+  standalone: true,
+})
+export class PageRxjsComponent implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() { }
+  testRxjs() {
+    Observable
+  }
+
+}

+ 6 - 6
newwisefitnessapp/src/app/tab1/tab1.page.scss

@@ -33,12 +33,12 @@ ion-card {
 }
 .swiper-pagination {
   position: absolute;
-  bottom: 10px; /* 分页器的位置 */
+  bottom: 10px;
   left: 50%;
   transform: translateX(-50%);
 }
 .page-content {
-  background: linear-gradient(#135, #5cb85c, #20c997) !important; /* 绿色到蓝色的渐变背景 */
+  background: linear-gradient(#135, #5cb85c, #20c997) !important; 
   
 }
 .card-style {
@@ -90,15 +90,15 @@ ion-button {
 }
 
 ion-button.success {
-  background-color: #28a745;
-  color: white;
+  background-color: #2874a7;
+ 
   border-radius: 5px;
   font-weight: bold;
 }
 
 ion-button.outline {
-  border: 1px solid #28a745;
-  color: #28a745;
+  border: 1px solid #287fa7;
+  color: #2878a7;
   border-radius: 5px;
 }
 

+ 14 - 1
newwisefitnessapp/src/app/test-page/test-page.component.html

@@ -84,6 +84,19 @@
     </div>
 
     <!-- 生成计划按钮 -->
-    <ion-button expand="full" (click)="generatePlan()">生成健身计划</ion-button>
+    <ion-button expand="full" (click)="generatePlan()" [disabled]="isGenerating">生成健身计划</ion-button>
+
+    <!-- 显示健身计划结果 -->
+    <div *ngIf="generatedPlan" class="result-container">
+      <h3>您的健身计划:</h3>
+      <ion-card>
+        <ion-card-header>
+          <ion-card-title>健身计划内容</ion-card-title>
+        </ion-card-header>
+        <ion-card-content>
+          <p>{{ generatedPlan }}</p>
+        </ion-card-content>
+      </ion-card>
+    </div>
   </div>
 </ion-content>

+ 88 - 9
newwisefitnessapp/src/app/test-page/test-page.component.ts

@@ -1,6 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { IonicModule } from '@ionic/angular';
 import { FormsModule } from '@angular/forms';
+import { CommonModule } from '@angular/common';  // 导入 CommonModule
 import { TagInputComponent } from '../tag-input/tag-input.component';
 import { addIcons } from 'ionicons';
 import { barbellOutline, personOutline, square, alarmOutline } from 'ionicons/icons';
@@ -10,16 +11,19 @@ import { barbellOutline, personOutline, square, alarmOutline } from 'ionicons/ic
   templateUrl: './test-page.component.html',
   styleUrls: ['./test-page.component.scss'],
   standalone: true,
-  imports: [IonicModule, FormsModule, TagInputComponent]  // 导入必要的模块
+  imports: [IonicModule, FormsModule, CommonModule, TagInputComponent]  // 添加 CommonModule
 })
 export class TestPageComponent implements OnInit {
-  selectedTags: string[] = [];  // 用来存储选择的标签
-  exercisePreference: string = '';  // 锻炼方式偏好
-  workoutFrequency: string = '';  // 每周锻炼频率
-  height: number | null = null;  // 身高
-  weight: number | null = null;  // 体重
-  age: number | null = null;  // 年龄
-  goalDescription: string = '';  // 目标描述,用来绑定文本域内容
+  selectedTags: string[] = [];
+  exercisePreference: string = '';
+  workoutFrequency: string = '';
+  height: number | null = null;
+  weight: number | null = null;
+  age: number | null = null;
+  goalDescription: string = '';
+  generatedPlan: string = '';  // 用来存储生成的健身计划
+  isGenerating: boolean = false;  // 是否正在生成计划
+  messageList: any[] = [];  // 存储消息列表
 
   constructor() {
     addIcons({ personOutline, barbellOutline, alarmOutline, square });
@@ -56,7 +60,11 @@ export class TestPageComponent implements OnInit {
     this.age = event.detail.value;
   }
 
-  generatePlan() {
+  async generatePlan() {
+    this.isGenerating = true;  // 开始生成计划时禁用按钮
+    this.generatedPlan = '';  // 清空之前的结果
+    this.messageList = [];  // 清空旧的消息列表,避免重复内容
+
     console.log('生成健身计划', {
       tags: this.selectedTags,
       exercisePreference: this.exercisePreference,
@@ -66,5 +74,76 @@ export class TestPageComponent implements OnInit {
       age: this.age,
       goalDescription: this.goalDescription
     });
+
+    let prompt = `您作为一名专业的健身计划定制大师,请帮我根据以下情况制定健身计划(健身计划请给每天的运动标上序号)。关键词:${this.selectedTags.join(",")},目标描述:${this.goalDescription},运动偏好:${this.exercisePreference},
+    健身频率一周:${this.workoutFrequency},身高:${this.height}cm,体重:${this.weight}kg,年龄:${this.age}`;
+
+    let TOKEN = `r:E4KpGvTEto-131588121831732778669`;
+    localStorage.setItem("token", TOKEN);
+
+    let messageList: any = [
+      { role: "system", content: `开始生成健身计划:${new Date().toDateString()}` },
+      { role: "user", content: prompt }
+    ];
+
+    let bodyJson = {
+      "token": `Bearer ${TOKEN}`,
+      "messages": messageList,
+      "model": "fmode-4.5-128k",
+      "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"
+      },
+      "body": JSON.stringify(bodyJson),
+      "method": "POST",
+      "mode": "cors",
+      "credentials": "omit"
+    });
+
+    let reader = response.body?.getReader();
+    if (!reader) {
+      throw new Error("Failed to get the response reader.");
+    }
+
+    let buffer = "";
+    const decoder = new TextDecoder();  // 定义 TextDecoder
+    while (true) {
+      let { done, value } = await reader.read();
+      if (done) break;
+
+      let data = decoder.decode(value);
+      buffer += data;  // 保留数据流中的内容
+
+      let messages = buffer.split("\n");
+      buffer = messages.pop() || "";  // 保留未处理的部分
+
+      messages.forEach(message => {
+        let dataText: string = message.split("data: ")[1];
+        if (dataText && dataText.startsWith("{")) {
+          try {
+            let json = JSON.parse(dataText);
+            let content = json?.choices?.[0]?.delta?.content;
+            if (content) {
+              console.log(content);
+              this.generatedPlan += content;  // 追加内容
+            }
+          } catch (err) {
+            console.error('生成计划失败:', err);
+          }
+        }
+      });
+    }
+
+    this.isGenerating = false;  // 生成结束后恢复按钮
   }
 }

+ 5 - 1
newwisefitnessapp/src/main.ts

@@ -4,7 +4,11 @@ import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalo
 
 import { routes } from './app/app.routes';
 import { AppComponent } from './app/app.component';
-
+import Parse from "parse";
+Parse.initialize("ncloudmaster");
+Parse.serverURL = "https://server.fmode.cn/parse";
+localStorage.setItem("NOVA_APIG_SERVER", 'aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG')
+Parse.User.become("'r:E4KpGvTEto-131588121831732778669")
 bootstrapApplication(AppComponent, {
   providers: [
     { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },

+ 6 - 2
newwisefitnessapp/tsconfig.json

@@ -2,6 +2,7 @@
 {
   "compileOnSave": false,
   "compilerOptions": {
+    "allowSyntheticDefaultImports": true,
     "baseUrl": "./",
     "outDir": "./dist/out-tsc",
     "forceConsistentCasingInFileNames": true,
@@ -18,7 +19,10 @@
     "importHelpers": true,
     "target": "es2022",
     "module": "es2020",
-    "lib": ["es2018", "dom"],
+    "lib": [
+      "es2018",
+      "dom"
+    ],
     "useDefineForClassFields": false
   },
   "angularCompilerOptions": {
@@ -27,4 +31,4 @@
     "strictInputAccessModifiers": true,
     "strictTemplates": true
   }
-}
+}

部分文件因为文件数量过多而无法显示