FelixTDT пре 4 месеци
родитељ
комит
946fc777a7

+ 3 - 3
src/app/home/home.page.html

@@ -19,10 +19,10 @@
   </ion-segment>
 
   <!-- 搜索框 -->
-  <ion-searchbar placeholder="搜索"></ion-searchbar>
+  <ion-searchbar placeholder="搜索" (ionInput)="onSearch($event)"></ion-searchbar>
 
   <!-- 内容卡片 -->
-  <ion-card *ngFor="let item of items" (click)="goToPostDetail(item.id)">
+  <ion-card *ngFor="let item of filteredItems" (click)="goToPostDetail(item.id)">
     <ion-card-header>
       <ion-card-title>{{ item.title }}</ion-card-title>
       <ion-card-subtitle>{{ item.author.username }}</ion-card-subtitle>
@@ -50,4 +50,4 @@
   <ion-fab-button (click)="createPost()">
     <ion-icon name="add"></ion-icon>
   </ion-fab-button>
-</ion-fab>
+</ion-fab>

+ 70 - 29
src/app/home/home.page.ts

@@ -1,32 +1,21 @@
 import { Component, OnInit } from '@angular/core';
-import { ActivatedRoute, Router } from '@angular/router';
+import { Router } from '@angular/router';
 import * as Parse from 'parse';
 
 @Component({
   selector: 'app-home',
-  templateUrl: 'home.page.html',
-  styleUrls: ['home.page.scss']
+  templateUrl: './home.page.html',
+  styleUrls: ['./home.page.scss'],
 })
 export class HomePage implements OnInit {
-
   items: any[] = [];
+  filteredItems: any[] = [];
   newPostId: string = '';
 
-  constructor(private router: Router, private route: ActivatedRoute) {
-    // 初始化 Parse
-  }
+  constructor(private router: Router) {}
 
   ngOnInit() {
-    this.route.queryParams.subscribe(params => {
-      if (params["postId"]) {
-        this.newPostId = params["postId"];
-      }
-    });
-    // this.fetchPosts();
-  }
-
-  ionViewWillEnter() {
-    this.fetchPosts(); // 确保每次进入首页时都会加载最新的帖子
+    this.fetchPosts();
   }
 
   async fetchPosts() {
@@ -41,27 +30,79 @@ export class HomePage implements OnInit {
         author: post.get('author'),
         image: post.get('image'),
         description: post.get('description'),
-        footer: `${post.get('likes')} 赞同 · ${post.get('comments')} 评论`
+        footer: `${post.get('likes') || 0} 赞同 · ${post.get('comments') || 0} 评论`
       }));
-      if (this.newPostId) {
-        const newPost = this.items.find(post => post.id === this.newPostId);
-        if (newPost) {
-          // 可以在这里高亮新发布的帖子或者滚动到新发布的帖子位置
-          console.log('New post published:', newPost);
-        }
-        this.newPostId = ''; // 重置 newPostId
-      }
+      this.filteredItems = [...this.items]; // 初始化时展示全部帖子
     } catch (error) {
       console.error("Error while fetching posts", error);
     }
   }
 
-  goToPostDetail(id: string) {
-    this.router.navigate(['/post-detail', id]);
+  onSearch(event: any) {
+    const query = event.target.value.toLowerCase();
+    this.filteredItems = this.items.filter(item =>
+      item.title.toLowerCase().includes(query) ||
+      item.description.toLowerCase().includes(query)
+    );
+  }
+
+  goToPostDetail(postId: string) {
+    this.router.navigate(['/post-detail', postId]);
   }
 
   createPost() {
     this.router.navigate(['/post-create']);
   }
-  
+
+  async submitPostReply(content: string, postId: string) {
+    const currentUser = Parse.User.current();
+    if (!currentUser) {
+      console.error('No user logged in. Please log in to reply.');
+      return;
+    }
+
+    const Comment240709 = Parse.Object.extend('Comment240709');
+    const comment = new Comment240709();
+
+    comment.set('author', currentUser);
+    comment.set('content', content);
+    comment.set('post', {
+      __type: 'Pointer',
+      className: 'Post240709',
+      objectId: postId
+    });
+
+    try {
+      await comment.save();
+      console.log('Reply to post saved successfully.');
+      this.updatePostInHomePage(postId);
+    } catch (error) {
+      console.error('Error while saving reply:', error);
+    }
+  }
+
+  async updatePostInHomePage(postId: string) {
+    const postIndex = this.items.findIndex(post => post.id === postId);
+    if (postIndex !== -1) {
+      const commentsCount = await this.getCommentsCount(postId);
+      this.items[postIndex].footer = `${this.items[postIndex].likes || 0} 赞同 · ${commentsCount} 评论`;
+      this.filteredItems = [...this.items];
+    }
+  }
+
+  async getCommentsCount(postId: string): Promise<number> {
+    const query = new Parse.Query('Comment240709');
+    query.equalTo('post', {
+      __type: 'Pointer',
+      className: 'Post240709',
+      objectId: postId
+    });
+    try {
+      const count = await query.count();
+      return count;
+    } catch (error) {
+      console.error('Error getting comments count:', error);
+      return 0;
+    }
+  }
 }

+ 1 - 1
src/app/tab1/tab1.page.ts

@@ -31,7 +31,7 @@ export class Tab1Page implements OnInit {
   }
 
   addAIResponse() {
-    let aiResponse = '这是AI的回复'; // 示例AI回复
+    let aiResponse = 'AI'; // 示例AI回复
     let aiMessage: TestChatMessage = {
       role: 'ai',
       content: ''

+ 15 - 15
src/app/tab2/tab2.page.ts

@@ -22,23 +22,23 @@ export class Tab2Page {
       "汪汪:姜萍事件很快就会有结果,做点分析预测\n阿里达摩院在6.21发布了决赛通知,确认姜萍参赛。今天是6.24,姜萍考试结束,我觉得我可以写点东西了。前..."
     ];
   
-    for (let i = 0; i < 3; i++) {
-      const Post240709 = Parse.Object.extend('Post240709');
-      const post = new Post240709();
+  //   for (let i = 0; i < 3; i++) {
+  //     const Post240709 = Parse.Object.extend('Post240709');
+  //     const post = new Post240709();
   
-      post.set('author', {username:currentUser.getUsername(),avatarUrl:'https://pics0.baidu.com/feed/2cf5e0fe9925bc31187a4ea7cc89c7bfcb13704a.jpeg'});
-      post.set('content', randomNews[Math.floor(Math.random() * randomNews.length)]);
-      post.set('image', fixedImageUrl);
-      post.set('title', `测试帖子${i + 1}`);
-      post.set('likes', Math.floor(Math.random() * 1000)); // 随机生成 0-999 的赞同数
+  //     post.set('author', {username:currentUser.getUsername(),avatarUrl:'https://pics0.baidu.com/feed/2cf5e0fe9925bc31187a4ea7cc89c7bfcb13704a.jpeg'});
+  //     post.set('content', randomNews[Math.floor(Math.random() * randomNews.length)]);
+  //     post.set('image', fixedImageUrl);
+  //     post.set('title', `测试帖子${i + 1}`);
+  //     post.set('likes', Math.floor(Math.random() * 1000)); // 随机生成 0-999 的赞同数
   
-      try {
-        await post.save();
-        console.log(`Test post ${i + 1} created successfully.`);
-      } catch (error) {
-        console.error('Error while creating test post:', error);
-      }
-    }
+  //     try {
+  //       await post.save();
+  //       console.log(`Test post ${i + 1} created successfully.`);
+  //     } catch (error) {
+  //       console.error('Error while creating test post:', error);
+  //     }
+  //   }
   }
   invitationMessages = [  
     { inviter: { username: 'Alice' }, question: 'How to use Ionic v7?', time: new Date(new Date().getTime() - 3600000) },  

+ 12 - 11
src/app/tabs/tabs.page.html

@@ -1,24 +1,25 @@
 <ion-tabs>
   <ion-tab-bar slot="bottom">
-     <!-- 新增的Tab -->
-     <ion-tab-button tab="home">
-      <ion-icon name="home"></ion-icon>
-      <ion-label>Home</ion-label>
-     </ion-tab-button>
+
+    <ion-tab-button tab="home">
+      <ion-icon name="home-outline"></ion-icon>
+      <ion-label>首页</ion-label>
+    </ion-tab-button>
 
     <ion-tab-button tab="tab1">
-      <ion-icon name="home"></ion-icon>
-      <ion-label>Tab 1</ion-label>
+      <ion-icon name="chatbox-ellipses-outline"></ion-icon>
+      <ion-label>AI</ion-label>
     </ion-tab-button>
 
     <ion-tab-button tab="tab2">
-      <ion-icon name="home"></ion-icon>
-      <ion-label>Tab 2</ion-label>
+      <ion-icon name="mail-outline"></ion-icon>
+      <ion-label>消息</ion-label>
     </ion-tab-button>
 
     <ion-tab-button tab="tab3">
-      <ion-icon name="home"></ion-icon>
-      <ion-label>Tab 3</ion-label>
+      <ion-icon name="person-outline"></ion-icon>
+      <ion-label>我的</ion-label>
     </ion-tab-button>
+
   </ion-tab-bar>
 </ion-tabs>

+ 12 - 3
src/modules/post-create/post-create.page.html

@@ -18,8 +18,17 @@
     <ion-textarea [(ngModel)]="content"></ion-textarea>
   </ion-item>
 
-  <ion-button expand="block" (click)="uploadImage()">上传图片</ion-button>
-  <ion-img [src]="image" *ngIf="image"></ion-img>
+  <ion-item>
+    <ion-label position="floating">图片URL</ion-label>
+    <ion-input [(ngModel)]="image"></ion-input>
+    <ion-button slot="end" (click)="uploadImage()">上传图片</ion-button>
+  </ion-item>
+
+  <ion-item *ngIf="image">
+    <ion-label>已上传的图片:</ion-label>
+    <img [src]="image" alt="Uploaded Image">
+  </ion-item>
 
-  <ion-button expand="block" (click)="submitPost()">发布</ion-button>
+  <ion-button expand="full" (click)="submitPost()">发布</ion-button>
 </ion-content>
+  

+ 1 - 1
src/modules/post-create/post-create.page.ts

@@ -75,7 +75,7 @@ export class PostCreatePage {
     const post = new Post240709();
     post.set('title', this.title);
     post.set('content', this.content);
-    post.set('imageUrl', this.image);
+    post.set('image', this.image);
     post.set('author', authorInfo); // 设置 author 字段为包含 username 和 avatarUrl 的对象
 
     try {

+ 61 - 71
src/modules/post-detail/post-detail.page.html

@@ -3,109 +3,99 @@
     <ion-buttons slot="start">
       <ion-back-button defaultHref="/home"></ion-back-button>
     </ion-buttons>
-    <ion-title>帖子详情</ion-title>
+    <ion-title>{{ post?.title }}</ion-title>
   </ion-toolbar>
 </ion-header>
 
 <ion-content>
-  <!-- 内容区 -->
-  <ion-card>
+  <ion-card *ngIf="post">
     <ion-card-header>
-      <ion-item lines="none">
-        <ion-avatar slot="start" (click)="generateTestComments()">
+      <ion-card-title>{{ post.title }}</ion-card-title>
+      <ion-card-subtitle>
+        <ion-avatar slot="start">
           <img [src]="post.authorAvatar" />
         </ion-avatar>
-        <ion-label>
-          <h2>{{ post.author }}</h2>
-          <p>{{ post.time | date: 'short' }}</p>
-        </ion-label>
-      </ion-item>
+        {{ post.author }} · {{ post.time | date:'short' }}
+      </ion-card-subtitle>
     </ion-card-header>
     <ion-card-content>
-      <h2>{{ post.title }}</h2>
-      <img [src]="post.image" *ngIf="post.image" />
+      <img [src]="post.image" *ngIf="post.image"/>
       <p>{{ post.content }}</p>
+      <ion-chip>
+        <ion-icon name="thumbs-up" (click)="togglePostLike()"></ion-icon>
+        <ion-label>{{ post.likes }}</ion-label>
+      </ion-chip>
+      <ion-button expand="block" (click)="replyToPost()">回复帖子</ion-button>
     </ion-card-content>
-    <ion-item lines="none">
-      <ion-button fill="clear" slot="start" (click)="togglePostLike()">
-        <ion-icon name="thumbs-up"></ion-icon>
-        <ion-label>{{ post.likes }} 点赞</ion-label>
-      </ion-button>
-      <ion-button fill="clear" slot="end" (click)="sharePost()">
-        <ion-icon name="share-social"></ion-icon>
-        <ion-label>分享</ion-label>
-      </ion-button>
-      <ion-button fill="clear" slot="end" (click)="replyToPost()">
-        <ion-icon name="chatbubble-ellipses"></ion-icon>
-        <ion-label>回复</ion-label>
-      </ion-button>
-    </ion-item>
   </ion-card>
 
-  <!-- 评论区 -->
-  <ion-segment value="all">
-    <ion-segment-button value="all">
-      <ion-label>全部回复</ion-label>
-    </ion-segment-button>
-    <ion-segment-button value="author">
-      <ion-label>只看楼主</ion-label>
-    </ion-segment-button>
-  </ion-segment>
-
-  <ion-segment value="popular" (ionChange)="sortComments($event)">
-    <ion-segment-button value="popular">
-      <ion-label>热门</ion-label>
-    </ion-segment-button>
-    <ion-segment-button value="asc">
-      <ion-label>时间正序</ion-label>
-    </ion-segment-button>
-    <ion-segment-button value="desc">
-      <ion-label>时间倒序</ion-label></ion-segment-button>
-  </ion-segment>
-
-  <ion-list>
-    <ion-item *ngFor="let comment of comments" (click)="replyToComment(comment)">
+  <ion-list *ngIf="comments.length > 0">
+    <ion-list-header>
+      <ion-label>评论 ({{ post?.commentsCount }})</ion-label>
+      <ion-select placeholder="排序" (ionChange)="sortComments($event)">
+        <ion-select-option value="popular">按赞同数</ion-select-option>
+        <ion-select-option value="asc">时间正序</ion-select-option>
+        <ion-select-option value="desc">时间倒序</ion-select-option>
+      </ion-select>
+    </ion-list-header>
+    <ion-item *ngFor="let comment of comments">
       <ion-avatar slot="start">
         <img [src]="comment.authorAvatar" />
       </ion-avatar>
       <ion-label>
         <h2>{{ comment.author }}</h2>
         <p>{{ comment.content }}</p>
-        <p>{{ comment.time | date: 'short' }}</p>
-        <p>楼层: {{ comment.floor }} | 点赞: {{ comment.likes }}</p>
-        <ion-item *ngFor="let reply of comment.replies" lines="none">
-          <ion-label>
-            <small>{{ reply.author }}: {{ reply.content }} - {{ reply.time | date: 'short' }}</small>
-          </ion-label>
-          <ion-button fill="clear" slot="end" (click)="toggleLike(reply)">
-            <ion-icon name="thumbs-up"></ion-icon>
-            <ion-label>{{ reply.likes }}</ion-label>
-          </ion-button>
-          <ion-button fill="clear" slot="end" (click)="replyToComment(reply)">
-            <ion-icon name="chatbubble-ellipses"></ion-icon>
-            <ion-label>回复</ion-label>
-          </ion-button>
-        </ion-item>
+        <p>{{ comment.time | date:'short' }}</p>
+        <ion-chip>
+          <ion-icon name="thumbs-up" (click)="toggleLike(comment)"></ion-icon>
+          <ion-label>{{ comment.likes }}</ion-label>
+        </ion-chip>
+        <ion-button size="small" (click)="replyToComment(comment)">回复</ion-button>
+        <ion-list *ngIf="comment.replies.length > 0">
+          <ion-item *ngFor="let reply of comment.replies">
+            <ion-avatar slot="start">
+              <img [src]="reply.authorAvatar" />
+            </ion-avatar>
+            <ion-label>
+              <h2>{{ reply.author }}</h2>
+              <p>{{ reply.content }}</p>
+              <p>{{ reply.time | date:'short' }}</p>
+              <ion-chip>
+                <ion-icon name="thumbs-up" (click)="toggleLike(reply)"></ion-icon>
+                <ion-label>{{ reply.likes }}</ion-label>
+              </ion-chip>
+            </ion-label>
+          </ion-item>
+        </ion-list>
       </ion-label>
-      <ion-button fill="clear" slot="end" (click)="toggleLike(comment)">
-        <ion-icon name="thumbs-up"></ion-icon>
-        <ion-label>{{ comment.likes }}</ion-label>
-      </ion-button>
     </ion-item>
   </ion-list>
 </ion-content>
 
-<!-- 分享二维码模态框 -->
+
 <ion-modal #shareModal>
   <ion-header>
     <ion-toolbar>
-      <ion-title>分享帖子</ion-title>
+      <ion-title>分享</ion-title>
       <ion-buttons slot="end">
         <ion-button (click)="shareModal.dismiss()">关闭</ion-button>
       </ion-buttons>
     </ion-toolbar>
   </ion-header>
   <ion-content>
-    <ion-img src="assets/images/123456.png"></ion-img>
+    <ion-list>
+      <ion-item>
+        <ion-label>分享链接</ion-label>
+        <ion-button (click)="shareModal.dismiss()">复制链接</ion-button>
+      </ion-item>
+      <ion-item>
+        <ion-label>分享到微信</ion-label>
+        <ion-button (click)="shareModal.dismiss()">分享</ion-button>
+      </ion-item>
+      <ion-item>
+        <ion-label>分享到微博</ion-label>
+        <ion-button (click)="shareModal.dismiss()">分享</ion-button>
+      </ion-item>
+    </ion-list>
   </ion-content>
 </ion-modal>

+ 8 - 9
src/modules/post-detail/post-detail.page.ts

@@ -40,8 +40,9 @@ export class PostDetailPage implements OnInit {
         time: post.createdAt,
         title: post.get('title'),
         content: post.get('content'),
-        image: post.get('imageUrl'),
+        image: post.get('image'),  // 确保图片在帖子详情页显示
         likes: post.get('likes') || 0
+        
       };
     } catch (error) {
       console.error('Error loading post:', error);
@@ -72,7 +73,7 @@ export class PostDetailPage implements OnInit {
             authorAvatar: comment.get('author').get("avatarUrl"),
             content: comment.get('content'),
             time: comment.createdAt,
-            likes: comment.get('likes'),
+            likes: comment.get('likes') || 0,
             floor: index + 1,
             replies: replies.map(reply => ({
               id: reply.id,
@@ -80,7 +81,7 @@ export class PostDetailPage implements OnInit {
               authorAvatar: reply.get('author').get("avatarUrl"),
               content: reply.get('content'),
               time: reply.createdAt,
-              likes: reply.get('likes')
+              likes: reply.get('likes') || 0
             }))
           };
         })
@@ -261,23 +262,21 @@ export class PostDetailPage implements OnInit {
 
     const Comment240709 = Parse.Object.extend('Comment240709');
 
-    for (let i = 0; i < 5; i++) {
+    for (let i = 0; i < hotPhrases.length; i++) {
       const comment = new Comment240709();
       comment.set('author', currentUser);
-      comment.set('content', hotPhrases[Math.floor(Math.random() * hotPhrases.length)]);
+      comment.set('content', hotPhrases[i]);
       comment.set('post', {
         __type: 'Pointer',
         className: 'Post240709',
         objectId: this.post.id
       });
-      comment.set('likes', Math.floor(Math.random() * 100));
-      comment.set('floor', this.comments.length + i + 1);
 
       try {
         await comment.save();
-        console.log('Test comment saved successfully.');
+        console.log(`Test comment ${i + 1} saved successfully.`);
       } catch (error) {
-        console.error('Error while saving test comment:', error);
+        console.error(`Error while saving test comment ${i + 1}:`, error);
       }
     }