Ver código fonte

feat:update plan page

xukang 4 meses atrás
pai
commit
10f9c6edb1

+ 43 - 1
TFPower-app/src/app/tab2/agent/agent.json.ts

@@ -41,4 +41,46 @@ export function extactAndParseJsonFromString(inputString: string) {
         console.error("Failed to parse JSON", error);
         return {}
     }
-}
+}
+export function extractAllJsonFromString(inputString: string) {
+    let startIndex = inputString.indexOf("{");
+    let count = 0;
+    let jsonObjects = [];  // 用来存储所有提取的JSON对象
+
+    while (startIndex !== -1) {
+        let endIndex = startIndex;
+        count = 0;
+
+        // 遍历字符串,计算花括号平衡
+        for (let i = startIndex; i < inputString.length; i++) {
+            if (inputString[i] === "{") {
+                count++;
+            } else if (inputString[i] === "}") {
+                count--;
+            }
+            // 找到完整的JSON数据
+            if (count === 0) {
+                endIndex = i;
+                break;
+            }
+        }
+
+        // 如果找到了平衡的花括号,提取JSON并解析
+        if (count === 0) {
+            const jsonString = inputString.slice(startIndex, endIndex + 1);
+            try {
+                const jsonObject = JSON.parse(jsonString);
+                jsonObjects.push(jsonObject);  // 将解析的对象添加到数组中
+            } catch (error) {
+                console.error("Failed to parse JSON:", error);
+            }
+
+            // 更新startIndex,继续查找下一个 JSON
+            startIndex = inputString.indexOf("{", endIndex + 1);
+        } else {
+            break;
+        }
+    }
+
+    return jsonObjects;
+}

+ 29 - 16
TFPower-app/src/app/tab2/edit-plan-modal/edit-plan-modal.component.html

@@ -13,26 +13,39 @@
       <ion-card-title>修改计划内容</ion-card-title>
     </ion-card-header>
     <ion-card-content>
-      <ion-item>
-        <ion-label>日期</ion-label>
-        <ion-input>{{ plan.get('date') }}</ion-input>
+      <!-- 日期输入框 -->
+      <ion-item lines="none">
+        <ion-input label="日期" [value]="plan.get('date')" (ionBlur)="onChange('date', $event)"></ion-input>
       </ion-item>
 
-      <ion-label>训练计划</ion-label>
-      <ion-col size="1.5" *ngFor="let task of plan.get('trainingItems'); let i = index" class="plan-column">
-        {{ task.item || '' }}: {{task.sets}} x {{task.reps}}
-      </ion-col>
-
+      <!-- 部位输入框 -->
+      <ion-item lines="none">
+        <ion-input label="部位" [value]="plan.get('trainingPart')" (ionBlur)="onChange(  'trainingPart', $event)">
+        </ion-input>
+      </ion-item>
 
+      <!-- 训练计划 -->
+      <ion-label>训练计划</ion-label>
+      <ion-row *ngFor="let task of plan.get('trainingItems'); let i = index" class="plan-row">
+        <ion-col size="4" class="plan-column">
+          <ion-item lines="none">
+            <ion-input label="项目{{i + 1}}" [value]="task.item || ''" (ionBlur)="onTaskChange(i, 'item', $event)">
+            </ion-input>
+          </ion-item>
+        </ion-col>
+        <ion-col size="3">
+          <ion-item lines="none">
+            <ion-input label="组数" [value]="task.sets" (ionBlur)="onTaskChange(i, 'sets', $event)"></ion-input>
+          </ion-item>
+        </ion-col>
+        <ion-col size="3">
+          <ion-item lines="none">
+            <ion-input label="次数" [value]="task.reps" (ionBlur)="onTaskChange(i, 'reps', $event)"></ion-input>
+          </ion-item>
+        </ion-col>
+      </ion-row>
 
-      <ion-item>
-        <ion-label></ion-label>
-        <ion-input [(ngModel)]="plan.trainingItems" placeholder="输入训练项目"></ion-input>
-      </ion-item>
-      <ion-item>
-        <ion-label>状态</ion-label>
-        <ion-toggle [(ngModel)]="plan.completed" color="success"></ion-toggle>
-      </ion-item>
+      <!-- 保存按钮 -->
       <ion-button expand="full" color="primary" (click)="saveChanges()">保存修改</ion-button>
     </ion-card-content>
   </ion-card>

+ 26 - 0
TFPower-app/src/app/tab2/edit-plan-modal/edit-plan-modal.component.scss

@@ -0,0 +1,26 @@
+.plan-row {
+  margin-bottom: 15px;
+}
+
+.plan-column {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+
+ion-item {
+  margin-bottom: 5px;
+}
+.horizontal-item {
+  display: flex;
+  align-items: center; /* 垂直居中对齐 */
+  justify-content: space-between; /* 水平分配空间 */
+}
+
+.horizontal-item ion-label {
+  flex: 0 0 auto; /* 标签不扩展 */
+}
+
+.horizontal-item ion-input {
+  flex: 1 1 auto; /* 输入框扩展占满剩余空间 */
+}

+ 25 - 8
TFPower-app/src/app/tab2/edit-plan-modal/edit-plan-modal.component.ts

@@ -1,15 +1,15 @@
 import { Component, Input } from '@angular/core';
 import { ModalController } from '@ionic/angular/standalone';
-import { IonCol, IonHeader, IonToolbar, IonTitle, IonButtons, IonButton, IonContent, IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonItem, IonLabel, IonInput, IonToggle } from '@ionic/angular/standalone';
+import { IonRow, IonCol, IonHeader, IonToolbar, IonTitle, IonButtons, IonButton, IonContent, IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonItem, IonLabel, IonInput, IonToggle } from '@ionic/angular/standalone';
 import { FormsModule } from '@angular/forms';
 import { CommonModule } from '@angular/common';
-
 @Component({
   selector: 'app-edit-plan-modal',
   templateUrl: './edit-plan-modal.component.html',
   styleUrls: ['./edit-plan-modal.component.scss'],
   standalone: true,
   imports: [
+    IonRow,
     IonCol,
     IonHeader,
     IonToolbar,
@@ -31,14 +31,31 @@ import { CommonModule } from '@angular/common';
 })
 export class EditPlanModalComponent {
   @Input() plan: any;  // 接收传入的计划数据
-
   constructor(private modalCtrl: ModalController) { }
-
-  saveChanges() {
-    this.modalCtrl.dismiss(this.plan); // 保存修改并返回
+  // 更新数据字段
+  onChange(field: string, event: any) {
+    const value = event.target.value;
+    console.log('Before update:', this.plan.data);
+    this.plan.set({ [field]: value });  // 使用 set 来更新数据
+  }
+  // 处理任务项的变化
+  onTaskChange(index: number, field: string, event: any) {
+    const value = event.target.value;
+    this.plan.data.trainingItems[index][field] = value;
+    const updatedTrainingItems = this.plan.data.trainingItems;
+    this.plan.set({ "trainingItems": updatedTrainingItems });
+  }
+  // 保存修改并更新数据库
+  async saveChanges() {
+    try {
+      await this.plan.save();
+      console.log('计划修改成功');
+      this.modalCtrl.dismiss(this.plan);
+    } catch (error) {
+      console.error('保存失败:', error);
+    }
   }
-
   dismiss() {
-    this.modalCtrl.dismiss(); // 关闭模态框
+    this.modalCtrl.dismiss();
   }
 }

+ 38 - 3
TFPower-app/src/app/tab2/tab2.page.html

@@ -30,6 +30,33 @@
         <p>在这里打卡,开始你的一天健身之旅吧!</p>
       </ion-card-content>
     </ion-card>
+    <ion-card>
+      <!-- 未登录 -->
+      @if(!currentUser?.id){
+      <ion-card-header>
+        <ion-card-title>请登录</ion-card-title>
+        <ion-card-subtitle>暂无信息</ion-card-subtitle>
+      </ion-card-header>
+      }
+      <!-- 未登录 -->
+      @if(currentUser?.id){
+      <ion-card-header>
+        <ion-card-title>{{currentUser?.get("username")}} {{currentUser?.get("realname")}}</ion-card-title>
+        <ion-card-subtitle>性别:{{currentUser?.get("gender")||"-"}} 年龄:{{currentUser?.get("age")||"-"}}
+        </ion-card-subtitle>
+      </ion-card-header>
+      }
+      <ion-card-content>
+        @if(!currentUser?.id){
+        <ion-button expand="block" (click)="signup()">注册</ion-button>
+        <ion-button expand="block" (click)="login()">登录</ion-button>
+        }
+        @if(currentUser?.id){
+        <ion-button expand="block" (click)="editUser()">编辑资料</ion-button>
+        <ion-button expand="block" (click)="logout()" color="light">登出</ion-button>
+        }
+      </ion-card-content>
+    </ion-card>
   </div>
 
   <!-- 计划 -->
@@ -48,7 +75,7 @@
               <ion-col size="1.5" class="grid-header">项目2</ion-col>
               <ion-col size="1.5" class="grid-header">项目3</ion-col>
               <ion-col size="1.5" class="grid-header">项目4</ion-col>
-              <ion-col size="1" class="grid-header">状态</ion-col>
+              <ion-col size="1.5" class="grid-header">状态</ion-col>
               <ion-col size="2" class="grid-header">操作</ion-col> <!-- 操作列 -->
             </ion-row>
 
@@ -62,8 +89,16 @@
                 {{ task.item || '' }}: {{task.sets}} x {{task.reps}}
               </ion-col>
 
-              <ion-col size="1" class="plan-column">
-                <ion-toggle [(ngModel)]="day.completed" color="success"></ion-toggle>
+              <ion-col size="1.5" class="plan-column">
+                <ion-list>
+                  <ion-item>
+                    <ion-select aria-label="fruit" value="未完成">
+                      <ion-select-option value="未完成">未完成</ion-select-option>
+                      <ion-select-option value="已完成">已完成</ion-select-option>
+                      <ion-select-option value="修改中">修改中</ion-select-option>
+                    </ion-select>
+                  </ion-item>
+                </ion-list>
               </ion-col>
 
               <!-- 修改和删除按钮 -->

+ 23 - 0
TFPower-app/src/app/tab2/tab2.page.scss

@@ -78,6 +78,29 @@ ion-content {
   padding: 12px;
   border-bottom: 1px solid #ddd;
 }
+.plan-table ion-select {
+  width: 50%;  /* 调整宽度 */
+  height: 50%;
+  margin: 1px;
+}
+
+/* 修改状态框的选项 */
+.plan-table ion-select .select-interface-option {
+  font-size: 12px;  /* 修改选项字体大小 */
+  color: #555;  /* 修改选项字体颜色 */
+}
+
+/* 修改选中时的背景颜色 */
+.plan-table ion-select .select-placeholder {
+  color: #719e8c;  /* 占位符字体颜色 */
+}
+
+/* 修改下拉箭头的颜色 */
+.plan-table ion-select .select-icon {
+  color: #719e8c;  /* 下拉箭头颜色 */
+}
+
+/* 当选择框被激活时的样式 */
 
 .plan-table ion-button {  
   margin-right: 10px; 

+ 103 - 41
TFPower-app/src/app/tab2/tab2.page.ts

@@ -4,7 +4,7 @@ import { addIcons } from 'ionicons';
 import { checkmarkCircle, trash, calendar, helpCircle, create } from 'ionicons/icons';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
-import { IonThumbnail, IonCardSubtitle, IonImg, IonCard, IonButtons, IonItem, IonList, IonHeader, IonIcon, IonToolbar, IonContent, IonSegment, IonSegmentButton, IonGrid, IonRow, IonCol, IonButton, IonLabel, IonBadge, IonInput, ModalController, IonCardTitle, IonCardContent, IonCardHeader } from '@ionic/angular/standalone';
+import { IonSelect, IonThumbnail, IonCardSubtitle, IonImg, IonCard, IonButtons, IonItem, IonList, IonHeader, IonIcon, IonToolbar, IonContent, IonSegment, IonSegmentButton, IonGrid, IonRow, IonCol, IonButton, IonLabel, IonBadge, IonInput, ModalController, IonCardTitle, IonCardContent, IonCardHeader, IonSelectOption } from '@ionic/angular/standalone';
 import { FmodeChatCompletion, ImagineWork, DalleOptions, ChatPanelOptions, FmodeChat, FmodeChatMessage, openChatPanelModal } from "fmode-ng";
 import { AgentTaskStep } from './agent/agent.task';
 import { TaskPoemPictureDesc } from './agent/tasks/poem/poem-desc';
@@ -13,14 +13,19 @@ import { startTask } from './agent/agent.start';
 import { TaskInqueryUserStory } from './agent/tasks/poem/inquiry/1.inquiry-user-story';
 import { TaskInqueryDoctorQuestion } from './agent/tasks/poem/inquiry/2.inquiry-doctor-question';
 import { TaskInqueryUserAnswer } from './agent/tasks/poem/inquiry/3.inquiry-user-answer';
-import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 import { EditPlanModalComponent } from './edit-plan-modal/edit-plan-modal.component';
+import { AlertController } from '@ionic/angular';
+import { openUserEditModal } from 'src/lib/user/modal-user-edit/modal-user-edit.component';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
 @Component({
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss'],
   standalone: true,
   imports: [
+    IonSelectOption,
+    IonSelect,
     IonThumbnail,
     IonCardSubtitle,
     IonImg,
@@ -54,37 +59,60 @@ export class Tab2Page implements OnInit {
   ];
   coachList: any[] = [
   ];
-
-  constructor(private router: Router, private modalCtrl: ModalController, private cdr: ChangeDetectorRef) {
+  currentUser: CloudUser | undefined
+  constructor(private router: Router, private modalCtrl: ModalController, private cdr: ChangeDetectorRef, private alertController: AlertController) {
     addIcons({ checkmarkCircle, calendar, helpCircle, trash, create });
+    this.currentUser = new CloudUser();
   }
   async loadPlanList() {
     let query = new CloudQuery("fitPlan");
     this.planList = await query.find();
-    console.log(this.planList);
   }
   async loadCoachList() {
     let query = new CloudQuery("Coach");
     this.coachList = await query.find();
-    console.log(this.planList);
+
   }
   ngOnInit() {
     // 初始时不需要强制触发视图更新
     this.loadPlanList()
     this.loadCoachList()
   }
+  //打卡页面
+  async login() {
+    // 弹出登录窗口
+    let user = await openUserLoginModal(this.modalCtrl);
+    if (user?.id) {
+      this.currentUser = user
+    }
+  }
+  async signup() {
+    // 弹出注册窗口
+    let user = await openUserLoginModal(this.modalCtrl, "signup");
+    if (user?.id) {
+      this.currentUser = user
+    }
+  }
+  logout() {
+    this.currentUser?.logout();
+  }
+
+  editUser() {
+    openUserEditModal(this.modalCtrl)
+  }
+
+  //plan页面
   editPlan(day: any) {
     console.log('编辑计划:', day);
 
     // 创建一个弹出框
     this.modalCtrl.create({
-      component: EditPlanModalComponent, // 这里你需要定义一个编辑计划的 modal 组件
-      componentProps: { plan: day } // 将计划内容传递给弹出框
+      component: EditPlanModalComponent,
+      componentProps: { plan: day }
     }).then(modal => {
       modal.present();
 
       modal.onDidDismiss().then((result) => {
-        // 如果返回的数据包含修改后的计划,就更新计划列表
         if (result.data) {
           const updatedPlan = result.data;
           const index = this.planList.findIndex(item => item.id === updatedPlan.id);
@@ -95,17 +123,39 @@ export class Tab2Page implements OnInit {
       });
     });
   }
+  async deletePlan(day: any) {
+    const alert = await this.alertController.create({
+      header: '确认删除',
+      message: '确定要删除此计划吗?',
+      buttons: [
+        {
+          text: '取消',
+          role: 'cancel',
+          cssClass: 'secondary',
+          handler: () => {
+            console.log('删除操作被取消');
+          }
+        },
+        {
+          text: '确认',
+          handler: () => {
+            day.destroy()
+              .then(() => {
+                console.log('计划已删除');
+                this.loadPlanList();
+              })
+              .catch((error: any) => {
+                console.error('删除失败:', error);
+              });
+          }
+        }
+      ]
+    });
 
-  // 删除计划
-  deletePlan(day: any) {
-    console.log('删除计划:', day);
-    const index = this.planList.indexOf(day);
-    if (index !== -1) {
-      this.planList.splice(index, 1);
-    }
+    await alert.present();
   }
-  //问诊区域
 
+  //任务链
   taskList: AgentTaskStep[] = []
   //一个等待一秒的函数  每经过一秒
   wait(duration: number = 1000) {
@@ -115,9 +165,7 @@ export class Tab2Page implements OnInit {
       }, duration);
     })
   }
-
   shareData: any = {}
-
   // 任务:完成故事意境描述及图像绘制
   doPoemTask() {
     let task1 = TaskPoemPictureDesc({ shareData: this.shareData, modalCtrl: this.modalCtrl });
@@ -126,12 +174,10 @@ export class Tab2Page implements OnInit {
     this.taskList = PoemTaskList
     startTask(PoemTaskList)
   }
-
   doInqueryTask() {
     let task1 = TaskInqueryUserStory({ shareData: this.shareData, modalCtrl: this.modalCtrl });
     let task2 = TaskInqueryDoctorQuestion({ shareData: this.shareData, modalCtrl: this.modalCtrl });
     let task3 = TaskInqueryUserAnswer({ shareData: this.shareData, modalCtrl: this.modalCtrl });
-
     // 定义任务集
     let InquireServiceTaskList = [
       task1, task2, task3
@@ -142,19 +188,47 @@ export class Tab2Page implements OnInit {
     startTask(InquireServiceTaskList)
   }
   // 聊天页面
-  openInquiry(coach: CloudObject) {
+  async openInquiry(coach: CloudObject) {
+    let currentUser = new CloudUser();
+    let userPrompt = ``
+    if (!currentUser?.id) {
+      console.log("用户未登录,请登录后重试");
+      let user = await openUserLoginModal(this.modalCtrl);
+      if (!user?.id) {
+        return
+      }
+      currentUser = user;
+    }
+
+    if (currentUser?.get("realname")) {
+      userPrompt += `当前来访的患者,姓名:${currentUser?.get("realname")}`
+    }
+    if (currentUser?.get("gender")) {
+      userPrompt += `,性别:${currentUser?.get("gender")}`
+    }
+    if (currentUser?.get("age")) {
+      userPrompt += `,年龄:${currentUser?.get("age")}`
+    }
+
+
     localStorage.setItem("company", "E4KpGvTEto")
+
     let consult = new CloudObject("fitConsultation")
     let now = new Date();
     let dateStr = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`
+    // 对象权限的精确指定
+    let ACL: any = {
+      "*": { read: false, write: false }
+    }
+    if (currentUser?.id) {
+      ACL[currentUser?.id] = { read: true, write: true }
+    }
+    localStorage.setItem("company", "E4KpGvTEto")
     consult.set({
       title: `交流记录${dateStr}-${coach?.get("name")}`,
       coach: coach.toPointer(),
-      depart: {
-        __type: "Pointer",
-        className: "Coach",
-        objectId: coach.get("depart")?.objectId
-      },
+      user: currentUser.toPointer(),
+      ACL: ACL
     })
     let options: ChatPanelOptions = {
       roleId: "2DXJkRsjXK",
@@ -184,15 +258,14 @@ export class Tab2Page implements OnInit {
 - 完成训练计划时,请在消息结尾附带: [交流完成]
 # 开始话语
 当您准备好了,可以以一个健身教练的身份,向来访的学员打招呼。
-
-${coach?.get("name")}:你好!欢迎来到健身房,我是${coach?.get("name")}教练。今天你想要专注锻炼哪个部位呢?或者有什么具体的健身目标吗?`);
+你好!欢迎来到健身房,我是${coach?.get("name")}教练。今天你想要专注锻炼哪个部位呢?或者有什么具体的健身目标吗?`);
       },
       onMessage: (chat: FmodeChat, message: FmodeChatMessage) => {
         console.log("onMessage", message)
         let content: any = message?.content
         if (typeof content == "string") {
           if (content?.indexOf("[交流完成]") > -1) {
-            console.log("门诊已完成")
+            console.log("交流已完成")
             consult.set({
               content: content // 处方内容
             })
@@ -207,21 +280,16 @@ ${coach?.get("name")}:你好!欢迎来到健身房,我是${coach?.get("nam
     }
     openChatPanelModal(this.modalCtrl, options)
   }
-
   openChat() {
     let options: ChatPanelOptions = {
       roleId: "2DXJkRsjXK",
       onChatSaved: (chat: FmodeChat) => {
         // chat?.chatSession?.id 本次会话的 chatId
-
         console.log("onChatSaved", chat, chat?.chatSession, chat?.chatSession?.id)
-
       },
-
     }
     openChatPanelModal(this.modalCtrl, options)
   }
-
   restoreChat(chatId: string) {
     let options: ChatPanelOptions = {
       roleId: "2DXJkRsjXK",
@@ -229,12 +297,9 @@ ${coach?.get("name")}:你好!欢迎来到健身房,我是${coach?.get("nam
     }
     openChatPanelModal(this.modalCtrl, options)
   }
-
   goChat() {
     this.router.navigateByUrl("/chat/session/role/2DXJkRsjXK")
   }
-
-
   // audioModalHeightPoint:number = 0.35;
   // async startTalk(){
   //   // 根据手机兼容性,适配组件弹出高度
@@ -256,9 +321,6 @@ ${coach?.get("name")}:你好!欢迎来到健身房,我是${coach?.get("nam
   //   })
   //   modal.present();
   // }
-
-
-
   // 页面跳转功能
   goToPage(page: string) {
     // 更新选中的tab

+ 1 - 1
TFPower-app/src/app/tab2/tag-input/tag-input.component.spec.ts

@@ -9,7 +9,7 @@ describe('TagInputComponent', () => {
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      declarations: [ TagInputComponent ],
+      declarations: [TagInputComponent],
       imports: [IonicModule.forRoot()]
     }).compileComponents();
 

+ 4 - 0
TFPower-app/src/app/tab2/test-page/test-page.component.html

@@ -1,4 +1,5 @@
 <ion-header translucent="true">
+
   <ion-toolbar>
     <ion-title>制定个人健身计划</ion-title>
   </ion-toolbar>
@@ -6,6 +7,9 @@
 
 <ion-content [fullscreen]="true">
   <div class="content">
+    <ion-button (click)="goBack()">
+      <ion-icon slot="icon-only" name="arrow-back"></ion-icon>
+    </ion-button>
     <!-- 健身目标选择 -->
     <div class="module">
       <h2>请输入您的健身目标</h2>

+ 146 - 17
TFPower-app/src/app/tab2/test-page/test-page.component.ts

@@ -4,11 +4,13 @@ import { FormsModule } from '@angular/forms';
 import { CommonModule } from '@angular/common';
 import { TagInputComponent } from '../tag-input/tag-input.component';
 import { addIcons } from 'ionicons';
-import { barbellOutline, personOutline, square, alarmOutline } from 'ionicons/icons';
-import { FmodeChatCompletion, MarkdownPreviewModule } from 'fmode-ng';
+import { barbellOutline, personOutline, square, alarmOutline, arrowBack } from 'ionicons/icons';
+import { DalleOptions, FmodeChatCompletion, MarkdownPreviewModule } from 'fmode-ng';
 import { LoadingController } from '@ionic/angular';
 import { AlertController } from '@ionic/angular/standalone';
-
+import { NavController } from '@ionic/angular';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
+import { extractAllJsonFromString } from '../agent/agent.json';
 @Component({
   selector: 'app-test-page',
   templateUrl: './test-page.component.html',
@@ -29,13 +31,12 @@ export class TestPageComponent implements OnInit {
   generatedPlan: string = '';  // 用来存储生成的健身计划
   isGenerating: boolean = false;  // 是否正在生成计划
   messageList: any[] = [];  // 存储消息列表
-
   constructor(private toastController: ToastController,
     private loadingController: LoadingController,
-    private alertController: AlertController) {
-    addIcons({ personOutline, barbellOutline, alarmOutline, square });
+    private alertController: AlertController,
+    private navController: NavController) {
+    addIcons({ personOutline, barbellOutline, alarmOutline, square, arrowBack });
   }
-
   ngOnInit() { }
 
   onTagsChanged(tags: string[]) {
@@ -90,8 +91,8 @@ export class TestPageComponent implements OnInit {
       duration: 30000 // 加载时长可以根据实际需求调整
     });
     await loading.present();
-    this.generatedPlan = '';  // 清空之前的结果
-    this.messageList = [];  // 清空旧的消息列表,避免重复内容
+    this.generatedPlan = '';
+    this.messageList = [];
     this.isGenerating = true;
 
     console.log('生成健身计划', {
@@ -105,7 +106,7 @@ export class TestPageComponent implements OnInit {
     });
 
     let prompt = `您作为一名专业的健身计划定制大师,请帮我根据以下情况制定健身计划(健身计划请给每天的运动标上序号)。关键词:${this.selectedTags.join(",")},目标描述:${this.goalDescription},运动偏好:${this.exercisePreference},
-    健身频率周:${this.workoutFrequency},身高:${this.height}cm,体重:${this.weight}kg,年龄:${this.age}`;
+    健身频率周:${this.workoutFrequency},身高:${this.height}cm,体重:${this.weight}kg,年龄:${this.age},注意:只需给出训练日计划,训练日只做四个运动`;
 
     let messageList = new FmodeChatCompletion([
       { role: "system", content: '' },
@@ -118,17 +119,100 @@ export class TestPageComponent implements OnInit {
 
       if (message?.complete) {
         this.isGenerating = false;
+        this.getJson()
         loading.dismiss();
+      }
+    });
+  }
+  public gptre = ""
+  title: string = "123"
+  chatID = ""
+  complete: boolean = false
+  planArray: any
+  JSONcomplete: boolean = false
+  JSONdes = ""
+  JSONobject: { [key: string]: string } = {}
+  getJson() {
+    let promt = `请你以以下json格式分每天来整合文段内容:
+    {
+    "date":"周几运动",
+    "srcId": "plan001等等",
+    "trainingPart":"训练部位",
+    "trainingItems":"四个运动项目,以下面形式给出,形式如下"[
+  {
+    "item": "引体向上",
+    "reps": 8,
+    "sets": 4
+  },
+  {
+    "item": "划船",
+    "reps": 10,
+    "sets": 3
+  },
+  {
+    "item": "背部伸展",
+    "reps": 12,
+    "sets": 3
+  },
+  {
+    "item": "拉力器划船",
+    "reps": 12,
+    "sets": 3
+  }
+]"
+}
+    内容如下:${this.generatedPlan}
+`
+
+    let completion = new FmodeChatCompletion([
+      { role: "system", content: "" },
+      { role: "user", content: promt }
+    ])
+    completion.sendCompletion().subscribe((message: any) => {
+      console.log(message.content)
+      this.JSONdes = message.content;
 
-        // 弹出框确认生成的计划
+      if (message?.complete) {
+        console.log("json:", this.JSONdes);
+        this.generatedPlan = message.content;
+        this.planArray = extractAllJsonFromString(this.JSONdes);
+        console.log(this.planArray)
         this.showConfirmationAlert();
+        // planArray.forEach((plan: any) => {
+        //   plan.detail = this.generatedPlan; // 添加额外的计划内容
+        //   console.log(plan);
+
+        //   // 准备插入数据库的数据对象
+        //   let newPlan = {
+        //     "date": plan['date'],
+        //     "srcId": plan['srcId'],
+        //     "trainingPart": plan['trainingPart'],
+        //     "trainingItems": plan['trainingItems'],
+        //     "user": new CloudUser().toPointer(),
+        //   };
+
+        //   // 创建新的 CloudObject 实例
+        //   let newObject = new CloudObject("fitPlan");
+        //   newObject.set(newPlan);
+        //   newObject.save()
+        //     .then(() => {
+        //       console.log("计划保存成功");
+        //     })
+        //     .catch((error: any) => {
+        //       console.error("保存计划时发生错误", error);
+        //     });
+        // });
+        // this.JSONcomplete = true;
       }
     });
   }
   async showConfirmationAlert() {
     const alert = await this.alertController.create({
       header: '确认生成计划',
-      message: `您的健身计划是:<br><pre>${this.generatedPlan}</pre>`,
+      message: ` <div style="white-space: pre-wrap;">
+        <!-- 使用 fm-markdown-preview 渲染 Markdown 格式的内容 -->
+        <fm-markdown-preview class="content-style" [content]="generatedPlan"></fm-markdown-preview>
+      </div>`,
       buttons: [
         {
           text: '放弃',
@@ -149,11 +233,56 @@ export class TestPageComponent implements OnInit {
     });
     await alert.present();
   }
-
-  // 假设有一个保存计划到数据库的方法
-  savePlanToDatabase(plan: string) {
-    // 这里是伪代码,根据你后端的实际 API 进行调整
-    // 例如:调用后台接口将健身计划存到数据库
+  async savePlanToDatabase(plan: string) {
     console.log('计划保存到数据库', plan);
+
+    let currentUser = new CloudUser();  // 获取当前用户实例
+
+    // 查询当前用户的所有计划
+    const cloudQuery = new CloudQuery("fitPlan");
+    cloudQuery.equalTo("user", currentUser.toPointer());  // 过滤出与当前用户关联的所有计划
+
+    try {
+      const userPlans = await cloudQuery.find();  // 获取当前用户的所有计划
+      console.log("找到的计划数量:", userPlans.length);
+
+      // 删除当前用户的所有计划
+      for (const planObj of userPlans) {
+        await planObj.destroy();  // 删除每个计划
+        console.log("已删除计划:", planObj);
+      }
+
+      // 保存新的计划
+      this.planArray.forEach((plan: any) => {
+        plan.detail = this.generatedPlan; // 添加额外的计划内容
+        console.log(plan);
+
+        // 准备插入数据库的数据对象
+        let newPlan = {
+          "date": plan['date'],
+          "srcId": plan['srcId'],
+          "trainingPart": plan['trainingPart'],
+          "trainingItems": plan['trainingItems'],
+          "user": currentUser.toPointer(),  // 将当前用户指针关联到计划
+        };
+        // 创建新的 CloudObject 实例
+        let newObject = new CloudObject("fitPlan");
+        newObject.set(newPlan);
+        newObject.save()
+          .then(() => {
+            console.log("计划保存成功");
+          })
+          .catch((error: any) => {
+            console.error("保存计划时发生错误", error);
+          });
+      });
+      this.JSONcomplete = true;
+    } catch (error) {
+      console.error("查询或删除计划时发生错误", error);
+    }
+  }
+
+  goBack() {
+    this.navController.back();
   }
 }

+ 35 - 32
TFPower-app/src/lib/user/modal-user-login/modal-user-login.component.html

@@ -1,38 +1,41 @@
 <!-- 用户登录状态 -->
 <ion-card>
-     <ion-card-header>
-       <ion-card-title>
-        <ion-segment [value]="type" (ionChange)="typeChange($event)">
-          <ion-segment-button value="login">
-            <ion-label>登录</ion-label>
-          </ion-segment-button>
-          <ion-segment-button value="signup">
-            <ion-label>注册</ion-label>
-          </ion-segment-button>
-        </ion-segment>
-       </ion-card-title>
-       <ion-card-subtitle>请输入账号密码</ion-card-subtitle>
-      </ion-card-header>
-    <ion-card-content>
+  <ion-card-header>
+    <ion-card-title>
+      <ion-segment [value]="type" (ionChange)="typeChange($event)">
+        <ion-segment-button value="login">
+          <ion-label>登录</ion-label>
+        </ion-segment-button>
+        <ion-segment-button value="signup">
+          <ion-label>注册</ion-label>
+        </ion-segment-button>
+      </ion-segment>
+    </ion-card-title>
+    <ion-card-subtitle>请输入账号密码</ion-card-subtitle>
+  </ion-card-header>
+  <ion-card-content>
 
-      <ion-item>
-        <ion-input [value]="username" (ionChange)="usernameChange($event)" label="账号" placeholder="请您输入账号/手机号"></ion-input>
-      </ion-item>
-      <ion-item>
-        <ion-input [value]="password" (ionChange)="passwordChange($event)" label="密码" type="password" value="password"></ion-input>
-      </ion-item>
-      @if(type=="signup"){
-        <ion-item>
-          <ion-input [value]="password2" (ionChange)="password2Change($event)" label="密码二次" type="password" value="password"></ion-input>
-        </ion-item>
-      }
-    
-      @if(type=="login"){
-        <ion-button expand="block" (click)="login()">登录</ion-button>
-      }
-      @if(type=="signup"){
-        <ion-button expand="block" (click)="signup()">注册</ion-button>
-      }
+    <ion-item>
+      <ion-input [value]="username" (ionChange)="usernameChange($event)" label="账号" placeholder="请您输入账号/手机号">
+      </ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-input [value]="password" (ionChange)="passwordChange($event)" label="密码" type="password" value="password">
+      </ion-input>
+    </ion-item>
+    @if(type=="signup"){
+    <ion-item>
+      <ion-input [value]="password2" (ionChange)="password2Change($event)" label="确认密码" type="password"
+        value="password"></ion-input>
+    </ion-item>
+    }
+
+    @if(type=="login"){
+    <ion-button expand="block" (click)="login()">登录</ion-button>
+    }
+    @if(type=="signup"){
+    <ion-button expand="block" (click)="signup()">注册</ion-button>
+    }
 
   </ion-card-content>
 </ion-card>

+ 1 - 1
TFPower-app/src/zone-flags.ts

@@ -1,4 +1,4 @@
-/**
+ /**
  * Prevents Angular change detection from
  * running with certain Web Component callbacks
  */