焦怡璇 hai 1 ano
pai
achega
f8bd3303f5

+ 5 - 0
heartvoice-app/src/app/interlocution/interlocution.component.html

@@ -2,5 +2,10 @@
   <h1>MBTI</h1>
 <img src="assets/img/9.jpg" alt="  " width="100%" height="200"/> 
 <!-- 展示:返回消息内容 -->
+@if(!currentUser?.id) {
+  <p>请登入</p>
+}
+@if(currentUser?.id) {
 <div>{{responseMsg}}</div>
+}
 </ion-content>

+ 19 - 2
heartvoice-app/src/app/interlocution/interlocution.component.ts

@@ -2,7 +2,9 @@ import { Component, OnInit } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { FmodeChatCompletion } from 'fmode-ng'; // 引入 FmodeChatCompletion 类
 import { IonicModule } from '@ionic/angular';
-
+import { CloudUser } from 'src/lib/ncloud';
+import {  Router } from '@angular/router';
+import { ModalController } from '@ionic/angular/standalone';
 @Component({
   selector: 'app-interlocution',
   templateUrl: './interlocution.component.html',
@@ -15,7 +17,22 @@ export class InterlocutionComponent implements OnInit {
   mbtiType: string | null = null; // 用于存储接收到的 MBTI 类型
   responseMsg: string = ""; // 用于展示消息内容的变量
 
-  constructor(private route: ActivatedRoute) {}
+  handleRefresh(event:any) {
+    setTimeout(() => {
+      // Any calls to load data go here
+      this.currentUser = new CloudUser();
+      event.target.complete();
+    }, 2000);
+  }
+  currentUser:CloudUser|undefined
+  constructor(
+    private route: ActivatedRoute,
+    private router: Router,
+    private modalCtrl:ModalController) {
+    this.currentUser = new CloudUser();
+  }
+
+
 
   ngOnInit() {
     // 获取路由参数

+ 147 - 128
heartvoice-app/src/app/report/report.component.ts

@@ -1,11 +1,11 @@
 import { Component, OnInit } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
-import { Cloudmy,Cloudget } from 'src/lib/ncloud';
+import { Cloudmy, Cloudget, Cloudupdate } from 'src/lib/ncloud';
 import { CloudUser } from 'src/lib/ncloud';
-import Sentiment from 'sentiment'; // 导入 Sentiment.js 用于情感分析
-import axios from 'axios'; // 导入 axios 进行 HTTP 请求
-import md5 from 'md5'; // 导入 md5 库用于生成签名
-import { FmodeChatCompletion } from 'fmode-ng'; // 导入 FmodeChatCompletion 以进行聊天完成请求
+import Sentiment from 'sentiment';
+import axios from 'axios';
+import md5 from 'md5';
+import { FmodeChatCompletion } from 'fmode-ng';
 import { IonicModule } from '@ionic/angular';
 
 @Component({
@@ -16,106 +16,138 @@ import { IonicModule } from '@ionic/angular';
   imports: [IonicModule],
 })
 export class ReportComponent implements OnInit {
-  data: any; // 用于存储接收到的数据
-  extractedContents: string[] = []; // 用于存储提取的内容
-  translatedText: string = ''; // 用于存储翻译后的文本
-  data1: any; // 用于存储 MBTI 类型
-  data2: any; // 用于存储情感得分
-  data3: any; // 用于存储合并后的内容
+  data: any;
+  extractedContents: string[] = [];
+  translatedText: string = '';
+  data1: any;
+  data2: any;
+  data3: any;
   data4: any;
   data5: any;
-  responseMsg: string = ""; // 用于展示消息内容的变量
+  responseMsg: string = "";
 
   constructor(private route: ActivatedRoute) {}
 
   async ngOnInit() {
-    // 从路由参数中获取数据
     this.route.params.subscribe(async params => {
       if (params['data']) {
         try {
-          this.data = JSON.parse(params['data']); // 尝试解析数据
-          console.log('成功返回数据:', this.data); // 打印成功消息和接收到的数据
-  
-          const query = new Cloudget('psychotherapy');
-          query.descending('createdAt'); // 按照 createdAt 降序排列
-          const latestResponse = await query.first(); // 获取最近一次的记录
-  
-          // 如果找到记录,赋值给 data5
-          if (latestResponse && latestResponse.content) {
-            this.data5 = latestResponse.content;
-            console.log('data5:', this.data5);
-          } else {
-            console.log('没有找到心理疏通文件');
-          }
-  
-          // 检查第一个数据是否为 'yes'
-          if (this.data.data.data1 === 'yes') {
-            // 如果是 'yes',查询 Userresponse 表获取 mbtiType
-            const currentUser = new CloudUser();
-            const userId = currentUser.toPointer(); // 获取当前用户 ID
-  
-            const query = new Cloudmy('Userresponse');
-            query.equalTo('user', userId);
-            query.descending('createdAt'); // 按照 createdAt 降序排列
-            const latestResponse = await query.first(); // 获取最近一次的记录
-  
-            // 如果找到记录,赋值给 data1
-            if (latestResponse && latestResponse.mbtiType) {
-              this.data1 = latestResponse.mbtiType;
-              console.log('MBTI 类型:', this.data1);
-            } else {
-              console.log('没有找到 MBTI 类型');
-            }
-          } else {
-            // 如果不是 'yes',将第一个数据赋值给 data1
-            this.data1 = this.data.data.data1;
-            console.log('赋值给 data1 的MBTI 类型:', this.data1);
-          }
-  
-          // 检查第二个数据是否为 'yes'
-          if (this.data.data.data2 === 'yes') {
-            let currentUser = new CloudUser();
-            let userId = currentUser.toPointer(); // 替换为实际的用户ID
-  
-            const query = new Cloudmy('Chat');
-            query.equalTo('user', userId);
-            query.descending('chattime'); // 按照 chattime 降序排列
-            const latestChat = await query.first(); // 获取最新聊天记录
-  
-            if (latestChat && latestChat.content) {
-              this.extractOddIndexedContents(latestChat.content);
-            }
-          } else {
-            // 如果不是 'yes'
-            this.data2 = "没数据"; 
-            this.data3 = "没数据"
-            this.data4 = "没数据"// 确保 data1 被赋予一个空字符串
-            console.log('否');
-          }
-  
-          // 等待数据处理完成后再发送消息
+          this.data = JSON.parse(params['data']);
+          console.log('成功返回数据:', this.data);
+
+          await this.fetchPsychotherapyData();
+          await this.fetchUserResponseData();
+          await this.fetchChatData();
           await this.waitForData();
+          
+
         } catch (error) {
-          console.error('解析数据时发生错误:', error); // 捕获解析错误
+          console.error('解析数据时发生错误:', error);
         }
       } else {
         this.data = null;
-        console.log('没有接收到数据。'); // 打印没有接收到数据的消息
+        console.log('没有接收到数据。');
       }
     });
   }
-  
-  // 等待数据处理完成的方法
-  private async waitForData() {
-    while (this.data2 === undefined || this.data3 === undefined) {
-      await new Promise(resolve => setTimeout(resolve, 100)); // 暂停100ms再检查
+
+  private async fetchPsychotherapyData() {
+    const query = new Cloudget('psychotherapy');
+    query.descending('createdAt');
+    const latestResponse = await query.first();
+
+    if (latestResponse && latestResponse.content) {
+      this.data5 = latestResponse.content;
+      console.log('data5:', this.data5);
+    } else {
+      console.log('没有找到心理疏通文件');
+    }
+  }
+
+  private async fetchUserResponseData() {
+    if (this.data.data.data1 === 'yes') {
+      const currentUser = new CloudUser();
+      const userId = currentUser.toPointer();
+      const query = new Cloudmy('Userresponse');
+      query.equalTo('user', userId);
+      query.descending('createdAt');
+      const latestResponse = await query.first();
+
+      if (latestResponse && latestResponse.mbtiType) {
+        this.data1 = latestResponse.mbtiType;
+        console.log('MBTI 类型:', this.data1);
+      } else {
+        console.log('没有找到 MBTI 类型');
+      }
+    } else {
+      this.data1 = this.data.data.data1;
+      console.log('赋值给 data1 的MBTI 类型:', this.data1);
     }
+  }
+
+  private async fetchChatData() {
+    if (this.data.data.data2 === 'yes') {
+      const currentUser = new CloudUser();
+      const userId = currentUser.toPointer();
+      const query = new Cloudmy('Chat');
+      query.equalTo('user', userId);
+      query.descending('chattime');
+      const latestChat = await query.first();
+
+      if (latestChat && latestChat.content) {
+        if (latestChat.sentimentscore !== undefined) {
+          this.data2 = latestChat.sentimentscore;
+          this.data3 = latestChat.sentimentAnalysisResult;
+          this.data4 = latestChat.chatContent;
+          console.log('保存聊天分析');
+        } else {
+          this.extractOddIndexedContents(latestChat.content);
+          await  this.waitForData1();
+          await  this.updateChatData(latestChat.content);
+          console.log('没生成聊天分析');
+        }
+      }
+    } else {
+      this.data2 = "没数据";
+      this.data3 = "没数据";
+      this.data4 = "没数据";
+      console.log('没聊天数据');
+    }
+  }
+
+  private async updateChatData(content: any[]) {
     
-    // 发送消息
-    this.sendMessage();
+    const chatUpdate = new Cloudupdate('Chat');
+    try {
+        // 查找包含特定内容的聊天记录
+        const chatRecord = await chatUpdate.equalTo('content', { $in: content }).first();
+        
+        if (chatRecord) {
+            await chatUpdate.setObjectId(chatRecord.objectId)
+                .set('sentimentscore', this.data2)
+                .set('sentimentAnalysisResult', this.data3)
+                .set('chatContent', this.data4)
+                .save();
+            console.log('更新成功');
+        } else {
+            console.log('没有找到对应的聊天记录进行更新');
+        }
+    } catch (error) {
+        console.error('发生错误:', error);
+    }
+}
+
+  private async waitForData() {
+    while (this.data2 === undefined || this.data3 === undefined) {
+      await new Promise(resolve => setTimeout(resolve, 100));}
+       this.sendMessage();
+  }
+ 
+  private async waitForData1() {
+    while (this.data2 === undefined || this.data3 === undefined) {
+      await new Promise(resolve => setTimeout(resolve, 100));}
+       this.sendMessage();
   }
-  
-  // 发送消息的方法
   sendMessage() {
     console.log("创建消息");
     console.log("data1:", this.data1);
@@ -123,8 +155,7 @@ export class ReportComponent implements OnInit {
     console.log("data3:", this.data3);
     console.log("data4:", this.data4);
     console.log("data5:", this.data5);
-  
-    // 检查所有需要的值是否已赋值
+
     if (this.data1 && this.data2 !== undefined && this.data3 && this.data4 && this.data5) {
       let PromptTemplate = `
       你是一名专业的心理疏导方向的专家,
@@ -134,51 +165,49 @@ export class ReportComponent implements OnInit {
       用户与AI的中用户聊天内容是${this.data4},
       请你根据他的性格,情感得分,情感分析结果以及用户的聊天内容,导出一份独属于用户的个人心理状态评估研究报告。
       以下是模板{
-个人心理状态评估研究报告
+      个人心理状态评估研究报告
 
-一、评估方法
+      一、评估方法
 
-性格测试:通过进行性格测试,了解您的大致性格,****
+      性格测试:通过进行性格测试,了解您的大致性格,****
 
-聊天对话:(如果聊天内容没数据就显示无数据)
-(有数据的话显示
-通过你与AI的对话对您的情绪进行分析,察觉到您的情绪不太好,(不要显示用户表达的话,和情感得分))***
+      聊天对话:(如果聊天内容没数据就显示无数据)
+      (有数据的话显示
+      通过你与AI的对话对您的情绪进行分析,察觉到您的情绪不太好,(不要显示用户表达的话,和情感得分))***
 
-二、评估结果
+      二、评估结果
 
-性格偏向:你是一个***人,***
+      性格偏向:你是一个***人,***
 
-情绪状态:*****
+      情绪状态:*****
 
-认知与情绪调节:****
+      认知与情绪调节:****
 
-三、建议
+      三、建议
 
-1.增强自我认知***
+      1.增强自我认知***
 
-2.专业咨询***
+      2.专业咨询***
 
-3.情绪调节训练****
+      3.情绪调节训练****
 
-}
+      }
       如果用户当前的情感得分为${this.data2}<0,参考${this.data5},再推荐1~2个心理治疗方法给用户
       {
         四、推荐心理治疗方法
 
         1.***
-      
-      2.****}。
-      不要显示用户基本信息`
-      ;
-  
+
+        2.****
+      }。
+      不要显示用户基本信息`;
+
       let completion = new FmodeChatCompletion([
         { role: "user", content: PromptTemplate }
       ]);
-  
+
       completion.sendCompletion().subscribe((message: any) => {
-        // 打印消息体
         console.log(message.content);
-        // 赋值消息内容给组件内属性
         this.responseMsg = message.content;
       });
     } else {
@@ -191,32 +220,26 @@ export class ReportComponent implements OnInit {
       });
     }
   }
-  
 
-  // 提取聊天记录中奇数索引的内容
   private extractOddIndexedContents(contentArray: any[]) {
     this.extractedContents = contentArray
-      .filter((_, index) => index % 2 === 0) // 过滤出奇数索引的对象
-      .slice(1) // 去掉第一个对象
-      .map(item => item.content); // 提取 content 的值
+      .filter((_, index) => index % 2 === 0)
+      .slice(1)
+      .map(item => item.content);
 
-    // 合并内容
     const combinedContent: string = this.extractedContents.join(' ');
     console.log('合并后的内容:', combinedContent);
     this.data4 = combinedContent;
-
-    // 调用翻译函数
     this.translateContent(combinedContent);
   }
 
-  // 翻译内容
   private async translateContent(content: string) {
     const appid = '20241224002237024'; // 替换为您的百度翻译API的appid
     const key = 'sNvEvziEi9iu8QxbjjoV'; // 替换为您的百度翻译API的key
     const salt = (new Date()).getTime();
-    const from = 'zh'; // 源语言
-    const to = 'en'; // 目标语言
-    const sign = md5(appid + content + salt + key); // 生成签名
+    const from = 'zh';
+    const to = 'en';
+    const sign = md5(appid + content + salt + key);
 
     try {
       const response = await axios.get('/api/trans/vip/translate', {
@@ -231,10 +254,8 @@ export class ReportComponent implements OnInit {
       });
 
       if (response.data && response.data.trans_result) {
-        this.translatedText = response.data.trans_result[0].dst; // 获取翻译后的文本
+        this.translatedText = response.data.trans_result[0].dst;
         console.log('翻译后的内容:', this.translatedText);
-
-        // 使用 Sentiment.js 进行情感分析
         this.analyzeSentiment(this.translatedText);
       }
     } catch (error) {
@@ -242,13 +263,11 @@ export class ReportComponent implements OnInit {
     }
   }
 
-  // 情感分析
   private analyzeSentiment(text: string) {
-    console.log('进行情感分析的文本:', text); 
+    console.log('进行情感分析的文本:', text);
     const sentiment = new Sentiment();
     const result = sentiment.analyze(text);
 
-    // 打印情感得分和分析结果
     console.log('情感得分:', result.score);
     console.log('情感分析结果:', result);
     this.data2 = result.score;

+ 9 - 5
heartvoice-app/src/app/tab2/tab2.page.html

@@ -3,11 +3,15 @@
     <ion-title>生成个性化心理报告</ion-title>
   </ion-toolbar>
 </ion-header>
+<ion-card>
 @if(!currentUser?.id) {
-  <p>请登入</p>
+  <p class="container">请登入</p>
 }
 @if(currentUser?.id) {
-<ion-content>
-  <ion-button expand="full" (click)="openModal()">生成报告</ion-button>
-</ion-content>
-}
+
+  <div class="button-container">
+    <ion-button (click)="openModal()">生成报告</ion-button>
+  </div>
+
+}
+</ion-card>

+ 43 - 8
heartvoice-app/src/app/tab2/tab2.page.scss

@@ -1,15 +1,23 @@
 ion-toolbar {
   --background: #f8d7da; /* 顶部工具栏背景色 */
+  font-family: "宋体";
 }
 
 
-  ion-button {
-    border-radius: 10px;
-    margin-top: 16px; /* 按钮的顶部外边距 */
-    --background: #f8d7da; /* 按钮背景色 */
-    --color: #161616; /* 点击时按钮字体颜色 */
-     /* 按钮圆角 */
-  }
+ion-button {
+  margin-top: 16px; /* 按钮的顶部外边距 */
+  --background: #f8d7da; /* 按钮背景色 */
+  font-family: "宋体";
+  font-weight: bold;
+  font-size: 20px;
+  --color: #161616; /* 点击时按钮字体颜色 */
+  width: 100px; /* 设置按钮的宽度 */
+  height: 100px; /* 设置按钮的高度 */
+  border-radius: 50% !important; /* 设置圆角为50%以形成球形 */
+  display: flex; /* 使用 flexbox 以便居中内容 */
+  align-items: center; /* 垂直居中内容 */
+  justify-content: center; /* 水平居中内容 */
+}
 
 ion-button:hover {
   --background: rgba(255, 221, 51, 0.1); /* 悬停时按钮背景色 */
@@ -19,4 +27,31 @@ ion-button:active {
   --color: #f96372; /* 点击时按钮字体颜色 */
 }
   
- 
+ 
+ion-card {
+  background-image: url('../../assets/img/10.jpg'); // 确保路径正确
+  background-size: cover; // 使背景图像覆盖整个区域
+  background-position: center; // 将背景图像居中
+  background-repeat: no-repeat; // 不重复背景图像
+  height: 100%; // 确保内容区域占满整个视口
+  position: relative; // 为定位做准备
+}
+
+
+.button-container {
+  position: absolute; // 使用绝对定位
+  top: 65%; 
+  left: 25%; 
+  transform: translate(-50%, -50%); // 将按钮中心对齐到指定位置
+}
+
+.container {
+  position: absolute; // 使用绝对定位
+  top: 63%; 
+  left: 24%; 
+  transform: translate(-50%, -50%); // 将按钮中心对齐到指定位置
+  font-family: "宋体";
+  font-weight: bold;
+  font-size: 20px;
+}
+

+ 2 - 2
heartvoice-app/src/app/tab2/tab2.page.ts

@@ -1,6 +1,6 @@
 import { Component } from '@angular/core';
 import { ModalHintComponent } from 'src/lib/user/modal-hint/modal-hint.component'; // 确保路径正确
-import { IonButton, IonContent, IonHeader, IonTitle, IonToolbar,ModalController } from '@ionic/angular/standalone';
+import { IonButton, IonCard, IonContent, IonHeader, IonTitle, IonToolbar,ModalController } from '@ionic/angular/standalone';
 import {  Router } from '@angular/router';
 import { CloudUser } from 'src/lib/ncloud';
 @Component({
@@ -8,7 +8,7 @@ import { CloudUser } from 'src/lib/ncloud';
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonButton], // 确保导入 IonicModule
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonCard], // 确保导入 IonicModule
 })
 export class Tab2Page {
   handleRefresh(event:any) {

+ 92 - 0
heartvoice-app/src/lib/ncloud.ts

@@ -507,6 +507,98 @@ export class Cloudget {
             url += `&order=${orderStr}`;
         }
 
+        // 发起请求
+        try {
+            const response = await fetch(url, {
+                headers: {
+                    "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
+                    "x-parse-application-id": "dev"
+                },
+                method: "GET",
+                mode: "cors",
+                credentials: "omit"
+            });
+
+            const json = await response.json();
+            return json?.results?.[0] || null; // 返回第一个结果或 null
+        } catch (error) {
+            console.error('查询时发生错误:', error);
+            throw error; // 抛出错误以便调用方处理
+        }
+    }
+}
+
+
+export class Cloudupdate {
+    private className: string; // 数据表名称
+    private queryParams: Record<string, any> = {}; // 查询参数
+    private objectId: string | null = null; // 要更新的对象 ID
+
+    constructor(className: string) {
+        this.className = className; // 设置数据表名称
+    }
+
+    // 设置等于条件
+    public equalTo(field: string, value: any) {
+        if (!this.queryParams["where"]) {
+            this.queryParams["where"] = {};
+        }
+        this.queryParams["where"][field] = value; // 添加条件
+        return this; // 支持链式调用
+    }
+
+    // 设置要更新的对象 ID
+    public setObjectId(objectId: string) {
+        this.objectId = objectId; // 设置要更新的对象 ID
+        return this; // 支持链式调用
+    }
+
+    // 设置更新的字段
+    public set(field: string, value: any) {
+        if (!this.queryParams["update"]) {
+            this.queryParams["update"] = {};
+        }
+        this.queryParams["update"][field] = value; // 添加更新字段
+        return this; // 支持链式调用
+    }
+
+    // 执行更新操作
+    public async save(): Promise<any> {
+        if (!this.objectId) {
+            throw new Error('Object ID is not set. Use setObjectId() to specify the object to update.');
+        }
+
+        const url = `https://dev.fmode.cn/parse/classes/${this.className}/${this.objectId}`;
+
+        // 发起 PUT 请求以更新对象
+        try {
+            const response = await fetch(url, {
+                method: "PUT",
+                headers: {
+                    "Content-Type": "application/json",
+                    "x-parse-application-id": "dev"
+                },
+                body: JSON.stringify(this.queryParams["update"]) // 发送更新数据
+            });
+
+            const json = await response.json();
+            return json; // 返回更新后的对象
+        } catch (error) {
+            console.error('更新时发生错误:', error);
+            throw error; // 抛出错误以便调用方处理
+        }
+    }
+
+    // 执行查询并返回第一个结果
+    public async first(): Promise<any> {
+        let url = `https://dev.fmode.cn/parse/classes/${this.className}?`;
+
+        // 添加 where 条件
+        if (this.queryParams["where"] && Object.keys(this.queryParams["where"]).length) {
+            const whereStr = JSON.stringify(this.queryParams["where"]);
+            url += `where=${encodeURIComponent(whereStr)}`; // 使用 encodeURIComponent 进行编码
+        }
+
         // 发起请求
         try {
             const response = await fetch(url, {

+ 1 - 1
heartvoice-app/src/lib/user/modal-hint/modal-hint.component.html

@@ -2,7 +2,7 @@
   <ion-toolbar>
     <ion-title>提示</ion-title>
     <ion-buttons slot="end">
-      <ion-button (click)="cancel()">关闭</ion-button>
+      <!-- <ion-button (click)="cancel()">关闭</ion-button> -->
     </ion-buttons>
   </ion-toolbar>
 </ion-header>