15207938132 2 月之前
父節點
當前提交
7dbddf1f9d

+ 4 - 12
fashion-app/src/app/ai-chat-component/ai-chat-component.component.ts

@@ -154,21 +154,13 @@ sendVoiceInput() {
   }
 
   ngOnInit() {
-    this.route.params.subscribe(params => {
-      const chatId = params['chatId']; // 获取聊天记录ID
-      if (chatId) {
-        this.loadChatHistory(chatId); // 加载聊天记录
-      } else {
+ 
         this.initializeChat(); // 初始化聊天
       }
-    });
-  }
+ 
+
+
 
-  async loadChatHistory(chatId: string) {
-    const query = new CloudQuery("ChatHistory");
-    const chatHistory = await query.get(chatId); // 获取聊天记录
-    this.messages = JSON.parse(chatHistory['content']); // 解析聊天内容
-}
   
 
 //初始化聊天,将提示词添加到历史中

+ 20 - 8
fashion-app/src/app/chat-history/chat-history.component.html

@@ -1,5 +1,3 @@
-
-
 <ion-header >
   <ion-toolbar>
     <ion-buttons slot="start">
@@ -15,13 +13,27 @@
     </ion-buttons>
   </ion-toolbar>
 </ion-header>
-  <ion-list>
-    <ion-item *ngFor="let chat of chatHistories">
-      <ion-label (click)="selectChatHistory(chat) ">
-        <h2>聊天记录 {{ chat.createdAt | date:'short' }}</h2>
-        <p>{{ chat.content }}</p>
-      </ion-label>
+
+<ion-content>
+  <ion-list >
+    <ion-item *ngFor="let chat of chatHistories; let i = index" fill="clear">
+      <div class="chat-item" (click)="selectChatHistory(chat)" [ngClass]="{'first-chat': i === 0}">
+        <div class="chat-header">
+
+          <div class="user-info"><!--用户信息-->
+            <img [src]="currentUser.get('image')" alt="User Avatar" class="avatar-image"> <!-- 替换为用户头像的实际路径 -->
+            <span class="username">{{ currentUser.get('username') }}</span> <!-- 假设 chat 对象有 username 字段 -->
+          </div>
+
+            <span class="timestamp">{{ chat.createdAt | date:'yyyy-MM-dd HH:mm' }}</span>
+          
+        </div>
+        <div class="chat-content">
+          <p class="chat-text">{{chat.firstMessage}}</p> <!-- 超出省略 -->
+        </div>
+      </div>
     </ion-item>
   </ion-list>
+</ion-content>
 
 

+ 66 - 0
fashion-app/src/app/chat-history/chat-history.component.scss

@@ -0,0 +1,66 @@
+.first-chat {
+    display: flex;
+    flex-direction: column;
+    padding: 10px;
+    border: 1px solid #e0e0e0; /* 边框样式 */
+    border-radius: 8px; /* 圆角 */
+    background-color: #fff; /* 背景色 */
+    width: 100%; /* 宽度 */
+    margin-top: 25px;
+  }
+
+.chat-item {
+    display: flex;
+    flex-direction: column;
+    padding: 10px;
+    border: 1px solid #e0e0e0; /* 边框样式 */
+    border-radius: 8px; /* 圆角 */
+    margin-bottom: 10px;
+    background-color: #fff; /* 背景色 */
+    width: 100%; /* 宽度 */
+    
+  }
+  
+  .chat-header {
+    display: flex;
+    align-items: center; /* 垂直居中 */
+    justify-content: center; /* 水平居中 */
+  }
+  
+  .user-info {
+    display: flex; /* 使用户信息水平排列 */
+    align-items: center; /* 垂直居中 */
+    flex: 1; /* 占据剩余空间 */
+  }
+  
+
+  
+  .avatar-image {
+    width: 45px; /* 头像宽度 */
+    height: 45px; /* 头像高度 */
+    border-radius: 50%; /* 圆形头像 */
+    margin-right: 12px; /* 头像和用户名之间的间距 */
+  }
+  
+  
+  .username {
+    font-weight: bold; /* 用户名加粗 */
+    font-size: 27px;
+  }
+  
+  .timestamp {
+    font-size: 20px; /* 时间字体大小 */
+    color: #888; /* 时间颜色 */
+  }
+  
+  .chat-content {
+    margin-top: 10px; /* 内容与标题之间的间距 */
+  }
+  
+  .chat-text {
+    font-size: 16px; /* 聊天内容字体大小 */
+    color: #333; /* 聊天内容颜色 */
+    overflow: hidden; /* 超出部分隐藏 */
+    text-overflow: ellipsis; /* 省略号 */
+    white-space: nowrap; /* 单行显示 */
+  }

+ 14 - 1
fashion-app/src/app/chat-history/chat-history.component.ts

@@ -19,7 +19,7 @@ addIcons({ chevronBackSharp,ellipsisHorizontal,micCircleOutline,happyOutline,pap
 export class ChatHistoryComponent  implements OnInit {
 
   chatHistories: any[] = []; // 存储聊天记录
-
+  currentUser:any;
 
 
   constructor(private router: Router,private navCtrl: NavController) {}
@@ -33,13 +33,26 @@ export class ChatHistoryComponent  implements OnInit {
     const currentUser = await user.current(); // 获取当前用户信息
 
     if (currentUser) {
+      this.currentUser = currentUser;
       const query = new CloudQuery("ChatHistory");
       query.equalTo("user", currentUser.toPointer()); // 查询当前用户的聊天记录
       this.chatHistories = await query.find(); // 获取聊天记录
+       // 解析聊天内容并提取每条聊天记录的第一条消息
+       this.chatHistories.forEach(chat => {
+        chat.parsedContent = JSON.parse(chat.data.content); // 解析内容
+        
+        chat.firstMessage = chat.parsedContent[0] ? chat.parsedContent[0].text : ''; // 获取第一条消息
+        console.log("hhh", this.chatHistories);
+    });
+          // 按 createdAt 排序,最近的在前面
+    this.chatHistories.sort((a, b) => {
+      return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
+    });
       console.log("聊天记录已加载", this.chatHistories);
     } else {
       console.error("用户未登录,无法加载聊天记录");
     }
+    console.log("聊天记录已加载", this.chatHistories);
   }
 
 

+ 9 - 13
fashion-app/src/app/post/post.component.html

@@ -1,29 +1,25 @@
 <ion-content >
-  <div class="post">
+  <div class="post" *ngFor="let post of posts">
     <div class="post-header">
       <div class="avatar">
-        <img src="../../assets/images/cxtouxiang.jpg" alt="User Avatar" class="avatar-image">
+        <img [src]="post.get('user')?.image || 'https://tse1-mm.cn.bing.net/th/id/OIP-C.X-VG5gTN2ak8rGRij3oCogAAAA?rs=1&pid=ImgDetMain'" alt="User Avatar" class="avatar-image">
       </div>
       <div class="user-info">
-        <span class="username">用户名</span>
+        <span class="username">{{ post.get('user')?.username || "该用户还没有字" }}</span>
         <ion-icon name="ellipsis-horizontal" class="more-icon"></ion-icon>
       </div>
     </div>
-    <h2 class="post-title">帖子标题</h2>
+    <h2 class="post-title">{{ post?.get('title') }}</h2>
 <!--标签-->
 <div class="tag-container">
-  <div class="tag"><ion-icon name="bookmark-outline" class="tagpicture"></ion-icon>标签1</div>
-  <div class="tag"><ion-icon name="bookmark-outline" class="tagpicture"></ion-icon>标签2</div>
-  <div class="tag"><ion-icon name="bookmark-outline" class="tagpicture"></ion-icon>标签3</div>
-  <div class="tag"><ion-icon name="bookmark-outline" class="tagpicture"></ion-icon>标签4</div>
+  <div class="tag" *ngFor="let tag of post.get('tag')">
+    <ion-icon name="bookmark-outline" class="tagpicture"></ion-icon>{{ tag }}
+  </div>
 </div>
 
-    <p class="post-content-text">这里是帖子内容,描述了帖子的详细信息和背景。</p>
+    <p class="post-content-text">{{ post?.get('content') }}</p>
     <div class="image-gallery">
-      <img src="../../assets/images/touxiang.jpg" alt="Post Image" class="post-image">
-      <img src="../../assets/images/2.jpg" alt="Post Image" class="post-image">
-      <img src="../../assets/images/cxtouxiang.jpg" alt="Post Image" class="post-image">
-      <img src="../../assets/images/cxtouxiang.jpg" alt="Post Image" class="post-image">
+      <img *ngFor="let image of post.get('image')" [src]="image" alt="Post Image" class="post-image">
     </div>
 
      <!-- 按钮区域 -->

+ 1 - 2
fashion-app/src/app/post/post.component.scss

@@ -81,7 +81,7 @@
   
   .image-gallery {
     display: flex; /* 使用 Flexbox 布局 */
-    justify-content: space-between; /* 图片之间的间距 */
+    
     flex-wrap: wrap; /* 允许换行 */
   }
   
@@ -90,7 +90,6 @@
     height: auto; /* 高度自适应 */
     border-radius: 5px; /* 图片圆角 */
     margin-bottom: 5px; /* 图片与下一张图片之间的间距 */
-    object-fit: cover; /* 保持比例填充 */
     margin-right: 5px; /* 图片与下一张图片之间的间距 */
 
   }

+ 26 - 11
fashion-app/src/app/post/post.component.ts

@@ -1,30 +1,45 @@
+import { CommonModule } from '@angular/common';
 import { Component, OnInit } from '@angular/core';
 import { IonButton, IonContent, IonIcon } from '@ionic/angular/standalone';
 import { addIcons } from 'ionicons';
 import { bookmarkOutline, chatbubbleOutline, ellipsisHorizontal, heart, heartOutline, shareSocialOutline, } from 'ionicons/icons';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 
-addIcons({ellipsisHorizontal,bookmarkOutline,shareSocialOutline,chatbubbleOutline,heartOutline,heart})
+addIcons({ ellipsisHorizontal, bookmarkOutline, shareSocialOutline, chatbubbleOutline, heartOutline, heart })
 
 @Component({
   selector: 'app-post',
   templateUrl: './post.component.html',
   styleUrls: ['./post.component.scss'],
   standalone: true,
-  imports: [IonContent,IonIcon,IonButton]
+  imports: [IonContent, IonIcon, IonButton, CommonModule]
 
 })
-export class PostComponent  implements OnInit {
-
+export class PostComponent implements OnInit {
+  posts: CloudObject[] = []; // 存储帖子
+  resultUser: any;
   constructor() { }
 
-  ngOnInit() {}
+  async ngOnInit() {
+    const query = new CloudQuery('post'); // 创建查询对象
+    console.log(query);
+    query.include('user'); // 包含 user 属性
+    this.posts = await query.find(); // 使用 find 方法获取所有帖子
+    console.log(this.posts);
+    
+    
+  }
+
+  // 用于跟踪点赞状态
+  isLiked: boolean = false;
+
+  // 切换点赞状态
+  toggleLike() {
+    this.isLiked = !this.isLiked; // 切换状态
+  }
+
+
 
-   // 用于跟踪点赞状态
-   isLiked: boolean = false;
 
-   // 切换点赞状态
-   toggleLike() {
-     this.isLiked = !this.isLiked; // 切换状态
-   }
 
 }

+ 1 - 1
fashion-app/src/app/send-post/send-post.component.ts

@@ -65,7 +65,7 @@ this.isPost = true; // 发布成功后,将 isPost 设置为 true
     user: new CloudUser().toPointer(), // 指向当前用户
     content: this.inputText, // 帖子内容
     title: this.title, // 帖子标题
-    image: this.images, // 图片数组
+    image : this.images, // 图片数组
     tag: this.tags, // 标签数组
   });
 

+ 116 - 24
fashion-app/src/lib/ncloud.ts

@@ -63,8 +63,8 @@ export class CloudObject {
         return this;
     }
 
-    async destroy(): Promise<boolean> {
-        if (!this.id) return false;
+    async destroy(){
+        if (!this.id) return;
         
         const response = await fetch(`http://1.94.237.145:1339/parse/classes/${this.className}/${this.id}`, {
             headers: {
@@ -92,36 +92,38 @@ export class CloudObject {
 export class CloudQuery {
     className: string;
     whereOptions: Record<string, any> = {};
-
     constructor(className: string) {
         this.className = className;
     }
-
+    include(...fileds:string[]) {
+        this.whereOptions["include"] = fileds;
+    }
     greaterThan(key: string, value: any) {
-        if (!this.whereOptions[key]) this.whereOptions[key] = {};
-        this.whereOptions[key]["$gt"] = value;
+        if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
+        this.whereOptions["where"][key]["$gt"] = value;
     }
 
     greaterThanAndEqualTo(key: string, value: any) {
-        if (!this.whereOptions[key]) this.whereOptions[key] = {};
-        this.whereOptions[key]["$gte"] = value;
+        if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
+        this.whereOptions["where"][key]["$gte"] = value;
     }
 
     lessThan(key: string, value: any) {
-        if (!this.whereOptions[key]) this.whereOptions[key] = {};
-        this.whereOptions[key]["$lt"] = value;
+        if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
+        this.whereOptions["where"][key]["$lt"] = value;
     }
 
     lessThanAndEqualTo(key: string, value: any) {
-        if (!this.whereOptions[key]) this.whereOptions[key] = {};
-        this.whereOptions[key]["$lte"] = value;
+        if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
+        this.whereOptions["where"][key]["$lte"] = value;
     }
 
     equalTo(key: string, value: any) {
-        this.whereOptions[key] = value;
+        if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
+        this.whereOptions["where"][key] = value;
     }
 
-    async get(id: string): Promise<Record<string, any>> {
+    async get(id: string) {
         const url = `http://1.94.237.145.1339/parse/classes/${this.className}/${id}?`;
         const response = await fetch(url, {
             headers: {
@@ -138,16 +140,28 @@ export class CloudQuery {
             credentials: "omit"
         });
         const json = await response?.json();
-        return json || {};
+        if (json) {
+            let existsObject = this.dataToObj(json)
+            return existsObject;
+        }
+        return null
     }
 
     async find(): Promise<CloudObject[]> {
         let url = `http://1.94.237.145:1339/parse/classes/${this.className}?`;
 
-        if (Object.keys(this.whereOptions).length) {
-            const whereStr = JSON.stringify(this.whereOptions);
-            url += `where=${whereStr}`;
-        }
+        let whereStr = ``
+        Object.keys(this.whereOptions).forEach(key=>{
+            let paramStr = JSON.stringify(this.whereOptions[key]);
+            if(key=="include"){
+                paramStr = this.whereOptions[key]?.join(",")
+            }
+            if(whereStr) {
+                url += `${key}=${paramStr}`;
+            }else{
+                url += `&${key}=${paramStr}`;
+            }
+        })
 
         const response = await fetch(url, {
             headers: {
@@ -170,11 +184,11 @@ export class CloudQuery {
         return objList || [];
     }
 
-    async first(): Promise<CloudObject | null> {
+    async first() {
         let url = `http://1.94.237.145:1339/parse/classes/${this.className}?`;
 
-        if (Object.keys(this.whereOptions).length) {
-            const whereStr = JSON.stringify(this.whereOptions);
+        if (Object.keys(this.whereOptions["where"]).length) {
+            const whereStr = JSON.stringify(this.whereOptions["where"]);
             url += `where=${whereStr}`;
         }
 
@@ -202,6 +216,8 @@ export class CloudQuery {
         return null;
     }
 
+
+
     dataToObj(exists:any):CloudObject{
         let existsObject = new CloudObject(this.className);
             existsObject.set(exists);
@@ -295,15 +311,22 @@ export class CloudUser extends CloudObject {
         const result = await response?.json();
         if (result?.error) {
             console.error(result?.error);
+            if(result?.error=="Invalid session token"){
+                this.clearUserCache()
+                return true;
+            }
             return false;
         }
 
+        this.clearUserCache()
+        return true;
+    }
+    clearUserCache(){
         // 清除用户信息
-        localStorage.removeItem("NCloud/ylj/User")
+        localStorage.removeItem("NCloud/dev/User")
         this.id = null;
         this.sessionToken = null;
         this.data = {};
-        return true;
     }
 
     /** 注册 */
@@ -338,4 +361,73 @@ export class CloudUser extends CloudObject {
         this.data = result; // 保存用户数据
         return this;
     }
+
+    override async save() {
+        let method = "POST";
+        let url = `https://dev.fmode.cn/parse/users`;
+    
+        // 更新用户信息
+        if (this.id) {
+            url += `/${this.id}`;
+            method = "PUT";
+        }
+    
+        let data:any = JSON.parse(JSON.stringify(this.data))
+        delete data.createdAt
+        delete data.updatedAt
+        delete data.ACL
+        delete data.objectId
+        const body = JSON.stringify(data);
+        let headersOptions:any = {
+            "content-type": "application/json;charset=UTF-8",
+            "x-parse-application-id": "dev",
+            "x-parse-session-token": this.sessionToken, // 添加sessionToken以进行身份验证
+        }
+        const response = await fetch(url, {
+            headers: headersOptions,
+            body: body,
+            method: method,
+            mode: "cors",
+            credentials: "omit"
+        });
+    
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+        }
+        if (result?.objectId) {
+            this.id = result?.objectId;
+        }
+        localStorage.setItem("NCloud/dev/User",JSON.stringify(this.data))
+        return this;
+    }
+}
+
+export class CloudApi{
+    async fetch(path:string,body:any,options?:{
+        method:string
+        body:any
+    }){
+
+        let reqOpts:any =  {
+            headers: {
+                "x-parse-application-id": "dev",
+                "Content-Type": "application/json"
+            },
+            method: options?.method || "POST",
+            mode: "cors",
+            credentials: "omit"
+        }
+        if(body||options?.body){
+            reqOpts.body = JSON.stringify(body || options?.body);
+            reqOpts.json = true;
+        }
+        let host = `https://dev.fmode.cn`
+        // host = `http://127.0.0.1:1337`
+        let url = `${host}/api/`+path
+        console.log(url,reqOpts)
+        const response = await fetch(url,reqOpts);
+        let json = await response.json();
+        return json
+    }
 }