2 次代碼提交 b3a646cf78 ... 05ad27171f

作者 SHA1 備註 提交日期
  cainiao-hue 05ad27171f Merge branch 'master' of http://git.fmode.cn:3000/4u/workspace 3 月之前
  cainiao-hue f3d7f72ca7 update:report-modal 3 月之前

+ 64 - 7
soul-app/package-lock.json

@@ -26,6 +26,7 @@
         "@tensorflow/tfjs-backend-cpu": "^4.22.0",
         "@tensorflow/tfjs-converter": "^4.22.0",
         "@tensorflow/tfjs-core": "^4.22.0",
+        "axios": "^1.7.9",
         "fmode-ng": "^0.0.63",
         "ionicons": "^7.2.1",
         "rxjs": "~7.8.0",
@@ -8011,6 +8012,12 @@
         "node": ">=8"
       }
     },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
     "node_modules/at-least-node": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@@ -8076,13 +8083,14 @@
       }
     },
     "node_modules/axios": {
-      "version": "0.26.1",
-      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
-      "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
+      "version": "1.7.9",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.9.tgz",
+      "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
       "license": "MIT",
-      "peer": true,
       "dependencies": {
-        "follow-redirects": "^1.14.8"
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
       }
     },
     "node_modules/axobject-query": {
@@ -9000,6 +9008,18 @@
         "node": ">=0.1.90"
       }
     },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/commander": {
       "version": "2.20.3",
       "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
@@ -9673,6 +9693,15 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/depd": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
@@ -10301,6 +10330,16 @@
         "node": ">=0.12.7"
       }
     },
+    "node_modules/esdk-obs-browserjs/node_modules/axios": {
+      "version": "0.26.1",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
+      "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "follow-redirects": "^1.14.8"
+      }
+    },
     "node_modules/eslint": {
       "version": "8.57.1",
       "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.57.1.tgz",
@@ -11271,6 +11310,20 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/form-data": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.1.tgz",
+      "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
     "node_modules/forwarded": {
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@@ -14341,7 +14394,6 @@
       "version": "1.52.0",
       "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.6"
@@ -14351,7 +14403,6 @@
       "version": "2.1.35",
       "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "mime-db": "1.52.0"
@@ -16520,6 +16571,12 @@
         "node": ">= 0.10"
       }
     },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+      "license": "MIT"
+    },
     "node_modules/prr": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",

+ 1 - 0
soul-app/package.json

@@ -31,6 +31,7 @@
     "@tensorflow/tfjs-backend-cpu": "^4.22.0",
     "@tensorflow/tfjs-converter": "^4.22.0",
     "@tensorflow/tfjs-core": "^4.22.0",
+    "axios": "^1.7.9",
     "fmode-ng": "^0.0.63",
     "ionicons": "^7.2.1",
     "rxjs": "~7.8.0",

+ 2 - 2
soul-app/src/app/consult-picture/consult-picture.component.html

@@ -1,7 +1,7 @@
 <ion-header [translucent]="true">
   <ion-toolbar>
     <ion-title>
-      示例:手机壁纸生成{{imagineWork?.progress || 0}}
+      示例:图片生成{{imagineWork?.progress || 0}}
     </ion-title> 
   </ion-toolbar>
 </ion-header>
@@ -9,7 +9,7 @@
 <ion-content [fullscreen]="true">
   <!-- 生成提示词 -->
   <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="图片提示词" autoGrow="true"></ion-textarea>
-  <ion-button (click)="createImage()" expand="block">生成414*896大小手机壁纸</ion-button>
+  <ion-button (click)="createImage()" expand="block">生成图片</ion-button>
   <!--logo画面提示词-->
 
   <div>

+ 2 - 2
soul-app/src/app/consult-picture/consult-picture.component.ts

@@ -16,7 +16,7 @@ import { DalleOptions, ImagineWork,FmodeChatCompletion } from 'fmode-ng';
 })
 export class ConsultPictureComponent  implements OnInit {
 
-  userPrompt:string = "生成一个手机壁纸图片,在浅色系且是暖色系的颜色交织中,颜色不要太亮眼,绘画卡通风格,通过小爱心、小星星、花瓣和小泡泡点缀,营造出一种温馨和放松的氛围,让人感到心灵的宁静与舒适。"
+  userPrompt:string = "生成一张图片,手工绘画,小时候动画里的猪猪侠"
   promptInput(ev:any){
     this.userPrompt = ev.detail.value;
   }
@@ -34,7 +34,7 @@ export class ConsultPictureComponent  implements OnInit {
   async createImage(){
     this.imagineWork = new ImagineWork();
     //文本生成
-    let PromptTemplate = `请你作为一名专业的设计师,结合壁纸的基础设计元素以及丰富的想象力帮我设计一个贴切我项目的手机壁纸
+    let PromptTemplate = `请你作为一名专业的设计师,结合丰富的想象力帮我设计图片
     要求如下:
     ${this.userPrompt}
     `

+ 44 - 1
soul-app/src/app/report-modal/report-modal.component.html

@@ -1,4 +1,4 @@
-<ion-header>
+<!--<ion-header>
   <ion-toolbar>
     <ion-title>聊天记录报告</ion-title>
     <ion-buttons slot="end">
@@ -21,4 +21,47 @@
     </ion-list>
   </ion-card>
 </section>
+</ion-content>-->
+<ion-header>
+  <ion-toolbar>
+    <ion-title>聊天记录</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="closeModal()">关闭</ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+<section>
+  <ion-card>
+    <ion-list>
+      <ion-item *ngFor="let chatrecord of chatrecordList; let i = index">
+        <ion-label>
+          <ng-container *ngFor="let contentItem of chatrecord.get('content')">
+            <div *ngIf="contentItem.role && contentItem.content">
+              <p style="font-size: 18px; line-height: 1.5; color: #333; margin: 8px 0;">
+                <span *ngIf="contentItem.role === 'system'">
+                  <strong>第{{ i + 1 }}次:</strong> <!-- 只在 system 角色前显示序号 -->
+                  <br>
+                </span>
+                <strong>{{ contentItem.role }}:</strong> {{ contentItem.content }}
+                <br>
+                <small style="color: #777;">{{ contentItem.createdAt | date: 'short' }}</small>
+              </p>
+               <!-- 展示情感分析结果 -->
+               <p *ngIf="contentItem.role === 'user'" style="font-size: 18px; line-height: 1.5; color: #333; margin: 8px 0;">
+                <strong>内心心情分析:</strong> 
+                <br>
+                <span *ngIf="userFeelings.length > 0">
+                  <strong>(情感标签: {{ userFeelings[userFeelings.length - 1].label }})</strong>
+                </span>
+                <span *ngIf="userFeelings.length === 0">分析中...</span>
+              </p>
+            </div>
+          </ng-container>
+        </ion-label>
+      </ion-item>
+    </ion-list>
+  </ion-card>
+</section>
 </ion-content>

+ 73 - 3
soul-app/src/app/report-modal/report-modal.component.ts

@@ -5,6 +5,15 @@ import { IonCard, IonItem, IonLabel, IonList } from '@ionic/angular/standalone';
 import { IonButton, IonButtons, IonContent, IonHeader, IonTitle, IonToolbar, ModalController } from '@ionic/angular/standalone';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 
+// 定义 ContentItem 接口
+interface ContentItem {
+  role: string;
+  content: string;
+  createdAt?: string; // 可选属性
+  hidden?: boolean;   // 可选属性
+  complete?: boolean; // 可选属性
+  cid?: string;      // 可选属性
+}
 @Component({
   selector: 'app-report-modal',
   templateUrl: './report-modal.component.html',
@@ -17,6 +26,7 @@ import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 export class ReportModalComponent  implements OnInit {
 
   constructor(private modalCtrl: ModalController,private router: Router) {}
+  userFeelings: Array<{ content: string, score: number, label: string }> = []; // 存储用户内容和情感分析结果
   closeModal() {
     this.router.navigate(['tabs/tab3']);
   }
@@ -24,9 +34,69 @@ export class ReportModalComponent  implements OnInit {
   async loadChatRecordList(){
     let query = new CloudQuery("ChatRecord");
     this.chatrecordList = await query.find()
-    
+    // 遍历 chatrecordList,去除每个记录中 user 的第一条 content
+    this.chatrecordList.forEach(chatrecord => {
+      const contentArray = chatrecord.get('content');
+      if (contentArray && contentArray.length > 0) {
+        // 找到第一条 role 为 user 的内容并移除
+        const userIndex = contentArray.findIndex((item: ContentItem) => item.role === 'user');
+        if (userIndex !== -1) {
+          contentArray.splice(userIndex, 1); // 移除第一条 user 内容
+        }
+      }
+    })
+  }
+  analyzeUserFeeling(content: string): { score: number; label: string } {
+    const moodScores = {
+      positive: {
+        words: ['开心', '高兴', '喜欢', '快乐', '棒', '兴奋', '满足', '美好'],
+        score: 2
+      },
+      neutral: {
+        words: ['一般', '还好', '可以', '无所谓', '正常'],
+        score: 0
+      },
+      negative: {
+        words: ['难过', '生气', '失望', '讨厌', '悲伤', '烦恼', '痛苦', '沮丧'],
+        score: -2
+      }
+    };
+
+    let totalScore = 0;
+
+    // 分析内容并计算分数
+    const contentWords = content.split(/\s+/);
+    contentWords.forEach(word => {
+      for (const mood in moodScores) {
+        if ((moodScores as any)[mood].words.includes(word)) {
+          totalScore += (moodScores as any)[mood].score;
+        }
+      }
+    });
+
+    // 判断心情状态
+    let label = '中性';
+    if (totalScore > 0) {
+      label = '积极';
+    } else if (totalScore < 0) {
+      label = '消极';
+    }
+
+    return { score: totalScore, label };
   }
-  ngOnInit() {
-    this.loadChatRecordList()
+
+
+  async ngOnInit() {
+    await this.loadChatRecordList();
+    // 在这里可以遍历 chatrecordList 中的用户内容并进行情感分析
+    this.chatrecordList.forEach(chatrecord => {
+      const contentArray = chatrecord.get('content');
+      contentArray.forEach((contentItem: ContentItem) => {
+        if (contentItem.role === 'user') {
+          const analysis = this.analyzeUserFeeling(contentItem.content);
+          this.userFeelings.push({ content: contentItem.content, score: analysis.score, label: analysis.label });
+        }
+      });
+    });
   }
 }

+ 2 - 3
soul-app/src/lib/user/modal-user-edit/modal-user-edit.component.ts

@@ -1,6 +1,6 @@
 import { OnInit } from '@angular/core';
 import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController, IonInput, IonItem, IonSegment, IonSegmentButton, IonLabel } from '@ionic/angular/standalone';
+import {   IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController, IonInput, IonItem, IonSegment, IonSegmentButton, IonLabel } from '@ionic/angular/standalone';
 import { CloudUser } from 'src/lib/ncloud';
 
 @Component({
@@ -8,8 +8,7 @@ import { CloudUser } from 'src/lib/ncloud';
   templateUrl: './modal-user-edit.component.html',
   styleUrls: ['./modal-user-edit.component.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, 
-    IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,
+  imports: [IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,
     IonInput,IonItem,
     IonSegment,IonSegmentButton,IonLabel
   ],