18879852299-202226701057 4 months ago
parent
commit
075d28d989
25 changed files with 606 additions and 16 deletions
  1. 4 1
      TFPower-app/angular.json
  2. 4 5
      TFPower-app/package-lock.json
  3. 1 1
      TFPower-app/package.json
  4. 8 2
      TFPower-app/src/app/app.component.ts
  5. 10 0
      TFPower-app/src/app/app.routes.ts
  6. 20 0
      TFPower-app/src/app/components/login/login.component.html
  7. 8 0
      TFPower-app/src/app/components/login/login.component.scss
  8. 22 0
      TFPower-app/src/app/components/login/login.component.spec.ts
  9. 39 0
      TFPower-app/src/app/components/login/login.component.ts
  10. 19 0
      TFPower-app/src/app/components/post/post.component.html
  11. 0 0
      TFPower-app/src/app/components/post/post.component.scss
  12. 22 0
      TFPower-app/src/app/components/post/post.component.spec.ts
  13. 58 0
      TFPower-app/src/app/components/post/post.component.ts
  14. 17 0
      TFPower-app/src/app/components/posts/posts.component.html
  15. 0 0
      TFPower-app/src/app/components/posts/posts.component.scss
  16. 22 0
      TFPower-app/src/app/components/posts/posts.component.spec.ts
  17. 32 0
      TFPower-app/src/app/components/posts/posts.component.ts
  18. 21 0
      TFPower-app/src/app/components/register/register.component.html
  19. 0 0
      TFPower-app/src/app/components/register/register.component.scss
  20. 22 0
      TFPower-app/src/app/components/register/register.component.spec.ts
  21. 43 0
      TFPower-app/src/app/components/register/register.component.ts
  22. 32 0
      TFPower-app/src/app/services/auth.service.ts
  23. 20 0
      TFPower-app/src/app/services/post.service.ts
  24. 80 4
      TFPower-app/src/app/tab3/tab3.page.html
  25. 102 3
      TFPower-app/src/app/tab3/tab3.page.ts

+ 4 - 1
TFPower-app/angular.json

@@ -126,7 +126,10 @@
     }
   },
   "cli": {
-    "schematicCollections": ["@ionic/angular-toolkit"]
+    "schematicCollections": [
+      "@ionic/angular-toolkit"
+    ],
+    "analytics": "04cf2083-c9ba-42a4-aa90-e6550256fe08"
   },
   "schematics": {
     "@ionic/angular-toolkit:component": {

+ 4 - 5
TFPower-app/package-lock.json

@@ -22,7 +22,7 @@
         "@capacitor/keyboard": "6.0.3",
         "@capacitor/status-bar": "6.0.2",
         "@ionic/angular": "^8.0.0",
-        "fmode-ng": "^0.0.62",
+        "fmode-ng": "^0.0.63",
         "ionicons": "^7.2.1",
         "rxjs": "~7.8.0",
         "tslib": "^2.3.0",
@@ -10378,10 +10378,9 @@
       "license": "ISC"
     },
     "node_modules/fmode-ng": {
-      "version": "0.0.62",
-      "resolved": "https://registry.npmmirror.com/fmode-ng/-/fmode-ng-0.0.62.tgz",
-      "integrity": "sha512-F0RzEu47NgKpaHp/vBEzjsU4efJ1lKLAbbdPE5hltj1W1cDaeht/i6UlEidid4FAEdAg7c9rrQrLgOh/zUfCsg==",
-      "license": "COPYRIGHT © 未来飞马 未来全栈 www.fmode.cn All RIGHTS RESERVED",
+      "version": "0.0.63",
+      "resolved": "https://registry.npmmirror.com/fmode-ng/-/fmode-ng-0.0.63.tgz",
+      "integrity": "sha512-gTiDZO2CchcTYAmlaweapasqV/8PdhG2vizJNn5dYZyXjgtrjyW+KeW5k2EVyIDvM1+bMGjjhGmr76Fc0TElxw==",
       "dependencies": {
         "tslib": "^2.3.0"
       },

+ 1 - 1
TFPower-app/package.json

@@ -27,7 +27,7 @@
     "@capacitor/keyboard": "6.0.3",
     "@capacitor/status-bar": "6.0.2",
     "@ionic/angular": "^8.0.0",
-    "fmode-ng": "^0.0.62",
+    "fmode-ng": "^0.0.63",
     "ionicons": "^7.2.1",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",

+ 8 - 2
TFPower-app/src/app/app.component.ts

@@ -1,12 +1,18 @@
 import { Component } from '@angular/core';
 import { IonApp, IonRouterOutlet } from '@ionic/angular/standalone';
-
+import { Router } from '@angular/router';
+import { HttpClientModule } from '@angular/common/http';
 @Component({
   selector: 'app-root',
   templateUrl: 'app.component.html',
+  styleUrls: ['app.component.scss'],
   standalone: true,
   imports: [IonApp, IonRouterOutlet],
 })
 export class AppComponent {
-  constructor() {}
+  
+  constructor(private router: Router) {} // 注入 Router
+  navigateTo(route: string) {
+    this.router.navigate([route]);
+  }
 }

+ 10 - 0
TFPower-app/src/app/app.routes.ts

@@ -1,8 +1,18 @@
 import { Routes } from '@angular/router';
 
+import { RegisterComponent } from './components/register/register.component';
+import { LoginComponent } from './components/login/login.component';
+import { PostComponent } from './components/post/post.component';
+
 export const routes: Routes = [
   {
     path: '',
     loadChildren: () => import('./tabs/tabs.routes').then((m) => m.routes),
   },
+  { path: 'register', component: RegisterComponent },
+  { path: 'login', component: LoginComponent },
+
+  { path: 'post', component: PostComponent },
+  { path: '', redirectTo: 'login', pathMatch: 'full' },
+  { path: '**', redirectTo: 'login' }
 ];

+ 20 - 0
TFPower-app/src/app/components/login/login.component.html

@@ -0,0 +1,20 @@
+<ion-content class="ion-padding">
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>用户登录</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <form (ngSubmit)="login()">
+        <ion-item>
+          <ion-label position="floating">用户名</ion-label>
+          <ion-input type="text" [(ngModel)]="username" name="username" required></ion-input>
+        </ion-item>
+        <ion-item>
+          <ion-label position="floating">密码</ion-label>
+          <ion-input type="password" [(ngModel)]="password" name="password" required></ion-input>
+        </ion-item>
+        <ion-button expand="full" type="submit">登录</ion-button>
+      </form>
+      <ion-button expand="full" color="light" (click)="router.navigate(['/register'])">注册</ion-button> <!-- 跳转到注册页面 -->
+    </ion-card-content>
+  </ion-card>

+ 8 - 0
TFPower-app/src/app/components/login/login.component.scss

@@ -0,0 +1,8 @@
+ion-card {
+  margin: 20px;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+}
+
+ion-button {
+  margin-top: 10px;
+}

+ 22 - 0
TFPower-app/src/app/components/login/login.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+  let component: LoginComponent;
+  let fixture: ComponentFixture<LoginComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [LoginComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(LoginComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 39 - 0
TFPower-app/src/app/components/login/login.component.ts

@@ -0,0 +1,39 @@
+import { Component, OnInit } from '@angular/core';
+import { AuthService } from '../../services/auth.service';
+import { Router } from '@angular/router';
+import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardTitle, IonContent, IonHeader, IonInput, IonItem, IonLabel, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+import { FormsModule } from '@angular/forms';
+
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.component.html',
+  styleUrls: ['./login.component.scss'],
+  standalone: true,
+  imports:[IonHeader,IonToolbar,IonTitle,IonContent
+    ,IonItem,IonLabel,IonInput,IonButton,
+    IonCard,IonCardContent,IonCardHeader,IonCardTitle,
+    FormsModule
+  ]
+})
+export class LoginComponent  implements OnInit {
+
+  username: string = '';
+  password: string = '';
+
+  constructor(private authService: AuthService, public router: Router) {}
+
+  login() {
+    this.authService.login(this.username, this.password).subscribe(
+      (response:any) => {
+        alert('登录成功!');
+        this.router.navigate(['/posts']); // 登录成功后跳转到动态列表页面
+      },
+      (error:any) => {
+        alert('登录失败!');
+      }
+    );
+  }
+
+  ngOnInit() {}
+
+}

+ 19 - 0
TFPower-app/src/app/components/post/post.component.html

@@ -0,0 +1,19 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>发布动态</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content padding>
+  <form (ngSubmit)="createPost()">
+    <ion-item>
+      <ion-label position="floating">动态内容</ion-label>
+      <ion-textarea [(ngModel)]="content" name="content" required></ion-textarea>
+    </ion-item>
+    <ion-item>
+      <ion-label>选择图片</ion-label>
+      <input type="file" (change)="onFileSelected($event)" />
+    </ion-item>
+    <ion-button expand="full" type="submit">发布</ion-button>
+  </form>
+</ion-content>

+ 0 - 0
TFPower-app/src/app/components/post/post.component.scss


+ 22 - 0
TFPower-app/src/app/components/post/post.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { PostComponent } from './post.component';
+
+describe('PostComponent', () => {
+  let component: PostComponent;
+  let fixture: ComponentFixture<PostComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [PostComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(PostComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 58 - 0
TFPower-app/src/app/components/post/post.component.ts

@@ -0,0 +1,58 @@
+import { Component, OnInit } from '@angular/core';
+import { PostService } from '../../services/post.service';
+import { Router } from '@angular/router';
+import { IonButton, IonContent, IonHeader, IonInput, IonItem, IonLabel, IonTextarea, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+import { FormsModule } from '@angular/forms';
+import { AuthService } from '../../services/auth.service'; // 导入 AuthService
+
+@Component({
+  selector: 'app-post',
+  templateUrl: './post.component.html',
+  styleUrls: ['./post.component.scss'],
+  standalone: true,
+  imports:[IonHeader,IonToolbar,IonTitle,IonContent
+    ,IonItem,IonLabel,IonInput,IonButton,IonTextarea
+    ,FormsModule
+  ]
+})
+export class PostComponent  implements OnInit {
+
+  content: string = '';
+  image: File | null = null;
+
+  constructor(private postService: PostService,private authService: AuthService, private router: Router) {
+  
+  }
+
+  onFileSelected(event: any) {
+    this.image = event.target.files[0];
+  }
+
+  createPost() {
+    if (!this.authService.isLoggedIn()) {
+      alert('请先登录才能发布动态!');
+      this.router.navigate(['/login']); // 导航到登录页面
+      return; // 结束发布流程
+    }
+    const formData = new FormData();
+    formData.append('content', this.content);
+    if (this.image) {
+      formData.append('image', this.image);
+    }
+
+    this.postService.createPost(formData).subscribe(
+      (response:any) => {
+        alert('动态发布成功!');
+        this.content = ''; // 清空输入框
+        this.image = null; // 清空图片
+        this.router.navigate(['/posts']); // 发布成功后跳转到动态列表页面
+      },
+      (error:any) => {
+        alert('发布失败!');
+      }
+    );
+  }
+
+  ngOnInit() {}
+
+}

+ 17 - 0
TFPower-app/src/app/components/posts/posts.component.html

@@ -0,0 +1,17 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>动态列表</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-list>
+    <ion-item *ngFor="let post of posts">
+      <ion-label>
+        <h2>{{ post.content }}</h2>
+        <p>{{ post.createdAt }}</p>
+        <img *ngIf="post.imageUrl" [src]="post.imageUrl" alt="Post Image" style="width: 100%; height: auto;" />
+      </ion-label>
+    </ion-item>
+  </ion-list>
+</ion-content>

+ 0 - 0
TFPower-app/src/app/components/posts/posts.component.scss


+ 22 - 0
TFPower-app/src/app/components/posts/posts.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { PostsComponent } from './posts.component';
+
+describe('PostsComponent', () => {
+  let component: PostsComponent;
+  let fixture: ComponentFixture<PostsComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [PostsComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(PostsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 32 - 0
TFPower-app/src/app/components/posts/posts.component.ts

@@ -0,0 +1,32 @@
+import { Component, OnInit } from '@angular/core';
+import { PostService } from '../../services/post.service';
+import { IonButton, IonContent, IonHeader, IonInput, IonItem, IonLabel, IonList, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+import { CommonModule } from '@angular/common';
+@Component({
+  selector: 'app-posts',
+  templateUrl: './posts.component.html',
+  styleUrls: ['./posts.component.scss'],
+  standalone: true,
+  imports:[IonHeader,IonToolbar,IonTitle,IonContent
+    ,IonItem,IonLabel,IonInput,IonButton,IonList
+    ,CommonModule
+  ]
+})
+export class PostsComponent  implements OnInit {
+
+  posts: any[] = [];
+
+  constructor(private postService: PostService) {}
+
+  ngOnInit() {
+    this.loadPosts();
+  }
+
+  loadPosts() {
+    this.postService.getPosts().subscribe((data:any) => {
+      this.posts = data;  // 设置动态列表
+    });
+  }
+
+
+}

+ 21 - 0
TFPower-app/src/app/components/register/register.component.html

@@ -0,0 +1,21 @@
+<ion-content class="ion-padding">
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>用户注册</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <form (ngSubmit)="register()">
+        <ion-item>
+          <ion-label position="floating">用户名</ion-label>
+          <ion-input type="text" [(ngModel)]="username" name="username" required></ion-input>
+        </ion-item>
+        <ion-item>
+          <ion-label position="floating">密码</ion-label>
+          <ion-input type="password" [(ngModel)]="password" name="password" required></ion-input>
+        </ion-item>
+        <ion-button expand="full" type="submit">注册</ion-button>
+      </form>
+      <ion-button expand="full" color="light" (click)="router.navigate(['/login'])">返回登录</ion-button> <!-- 跳转到登录页面 -->
+    </ion-card-content>
+  </ion-card>
+</ion-content>

+ 0 - 0
TFPower-app/src/app/components/register/register.component.scss


+ 22 - 0
TFPower-app/src/app/components/register/register.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { RegisterComponent } from './register.component';
+
+describe('RegisterComponent', () => {
+  let component: RegisterComponent;
+  let fixture: ComponentFixture<RegisterComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [RegisterComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(RegisterComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 43 - 0
TFPower-app/src/app/components/register/register.component.ts

@@ -0,0 +1,43 @@
+import { Component, OnInit } from '@angular/core';
+import { AuthService } from '../../services/auth.service';
+
+import { Router } from '@angular/router';
+import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardTitle, IonContent, IonHeader, IonInput, IonItem, IonLabel, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+
+import { FormsModule } from '@angular/forms'; // 导入 FormsModule
+import { CommonModule } from '@angular/common';
+@Component({
+  selector: 'app-register',
+  templateUrl: './register.component.html',
+  styleUrls: ['./register.component.scss'],
+  standalone: true,
+  imports:[IonHeader,IonToolbar,IonTitle,IonContent
+    ,IonItem,IonLabel,IonInput,IonButton,
+    IonCard,IonCardContent,IonCardHeader,IonCardTitle,
+
+    FormsModule,CommonModule
+  ]
+})
+export class RegisterComponent  implements OnInit {
+
+
+  ngOnInit() {}
+
+  username: string = '';
+  password: string = '';
+
+  constructor(private authService: AuthService, public router: Router) {}
+
+  register() {
+    this.authService.register(this.username, this.password).subscribe(
+      (response:any) => {
+        alert('注册成功!');
+        this.router.navigate(['/login']); // 注册成功后跳转到登录页面
+      },
+      (error:any) => {
+        alert('注册失败!');
+      }
+    );
+  }
+
+}

+ 32 - 0
TFPower-app/src/app/services/auth.service.ts

@@ -0,0 +1,32 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { tap } from 'rxjs';
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthService {
+  private apiUrl = 'http://localhost:8080/api';
+  private loggedIn = false; // 用户登录状态
+  constructor(private http: HttpClient) {}
+
+  register(username: string, password: string): Observable<any> {
+    return this.http.post(`${this.apiUrl}/register`, { username, password });
+  }
+
+  login(username: string, password: string): Observable<any> {
+    return this.http.post(`${this.apiUrl}/login`, { username, password }).pipe(
+      tap(response => {
+        // 假设登录成功后设置状态
+        this.loggedIn = true; // 用户登录状态设置为 true
+      })
+    );
+    }
+    isLoggedIn(): boolean {
+      return this.loggedIn; // 返回用户登录状态
+    }
+  
+    logout() {
+      this.loggedIn = false; // 用户登出,重置状态
+    }
+}

+ 20 - 0
TFPower-app/src/app/services/post.service.ts

@@ -0,0 +1,20 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class PostService {
+  private apiUrl = 'http://localhost:8080/api/posts';
+
+  constructor(private http: HttpClient) {}
+
+  createPost(formData: FormData): Observable<any> {
+    return this.http.post(this.apiUrl, formData);
+  }
+
+  getPosts(): Observable<any[]> {
+    return this.http.get<any[]>(this.apiUrl);
+  }
+}

+ 80 - 4
TFPower-app/src/app/tab3/tab3.page.html

@@ -1,7 +1,7 @@
 <ion-header [translucent]="true">
   <ion-toolbar>
     <ion-title>
-      Tab 3
+      社区
     </ion-title>
   </ion-toolbar>
 </ion-header>
@@ -9,9 +9,85 @@
 <ion-content [fullscreen]="true">
   <ion-header collapse="condense">
     <ion-toolbar>
-      <ion-title size="large">Tab 3</ion-title>
+      <ion-title size="large">社区动态</ion-title>
     </ion-toolbar>
   </ion-header>
 
-  <app-explore-container name="Tab 3 page"></app-explore-container>
-</ion-content>
+  <!-- 用户注册表单 -->
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>用户注册</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <form (ngSubmit)="register()">
+        <ion-item>
+          <ion-label position="floating">用户名</ion-label>
+          <ion-input type="text" [(ngModel)]="registerUsername" name="username" required></ion-input>
+        </ion-item>
+        <ion-item>
+          <ion-label position="floating">密码</ion-label>
+          <ion-input type="password" [(ngModel)]="registerPassword" name="password" required></ion-input>
+        </ion-item>
+        <ion-button expand="full" type="submit">注册</ion-button>
+      </form>
+    </ion-card-content>
+  </ion-card>
+
+  <!-- 用户登录表单 -->
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>用户登录</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <form (ngSubmit)="login()">
+        <ion-item>
+          <ion-label position="floating">用户名</ion-label>
+          <ion-input type="text" [(ngModel)]="loginUsername" name="username" required></ion-input>
+        </ion-item>
+        <ion-item>
+          <ion-label position="floating">密码</ion-label>
+          <ion-input type="password" [(ngModel)]="loginPassword" name="password" required></ion-input>
+        </ion-item>
+        <ion-button expand="full" type="submit">登录</ion-button>
+      </form>
+    </ion-card-content>
+  </ion-card>
+
+  <!-- 发布动态 -->
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>发布动态</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <form (ngSubmit)="createPost()">
+        <ion-item>
+          <ion-label position="floating">动态内容</ion-label>
+          <ion-textarea [(ngModel)]="postContent" name="content" required></ion-textarea>
+        </ion-item>
+        <ion-item>
+          <ion-label>选择图片</ion-label>
+          <input type="file" (change)="onFileSelected($event)" />
+        </ion-item>
+        <ion-button expand="full" type="submit">发布</ion-button>
+      </form>
+    </ion-card-content>
+  </ion-card>
+
+  <!-- 查看动态列表 -->
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>动态列表</ion-card-title>
+    </ion-card-header>
+    <ion-card-content>
+      <ion-list>
+        <ion-item *ngFor="let post of posts">
+          <ion-label>
+            <h2>{{ post.content }}</h2>
+            <p>{{ post.createdAt }}</p>
+            <img *ngIf="post.imageUrl" [src]="post.imageUrl" alt="Post Image" style="width: 100%; height: auto;" />
+          </ion-label>
+        </ion-item>
+      </ion-list>
+    </ion-card-content>
+  </ion-card>
+</ion-content>

+ 102 - 3
TFPower-app/src/app/tab3/tab3.page.ts

@@ -1,14 +1,113 @@
 import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonItem, IonLabel, IonInput, IonButton, IonTextarea, IonList } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { AuthService } from '../services/auth.service'; // 导入 AuthService
+import { PostService } from '../services/post.service'; // 导入 PostService
+import { Router } from '@angular/router'; // 导入 Router
+import { FormsModule } from '@angular/forms';
+import { CommonModule } from '@angular/common';
 
 @Component({
   selector: 'app-tab3',
   templateUrl: 'tab3.page.html',
   styleUrls: ['tab3.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent],
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent
+,IonCard
+,IonCardHeader
+,IonCardTitle
+,IonCardContent
+,IonItem
+,IonLabel
+,IonInput
+,IonButton
+,IonTextarea
+,IonList
+,IonItem
+,FormsModule
+,CommonModule
+  ],
 })
 export class Tab3Page {
-  constructor() {}
+    // 用户注册和登录属性
+    registerUsername: string = '';
+    registerPassword: string = '';
+    loginUsername: string = '';
+    loginPassword: string = '';
+  
+    // 发布动态属性
+    postContent: string = '';
+    image: File | null = null;
+  
+    // 动态列表
+    posts: any[] = [];
+  
+    constructor(
+      private authService: AuthService, // 注入 AuthService
+      private postService: PostService, // 注入 PostService
+      private router: Router // 注入 Router
+    ) {}
+  
+    ngOnInit() {
+      this.loadPosts(); // 加载动态列表
+    }
+  
+    // 注册用户
+    register() {
+      this.authService.register(this.registerUsername, this.registerPassword).subscribe(
+        (response:any) => {
+          alert('注册成功!');
+          this.router.navigate(['/login']); // 注册成功后导航到登录页面
+        },
+        (error:any) => {
+          alert('注册失败!');
+        }
+      );
+    }
+  
+    // 登录用户
+    login() {
+      this.authService.login(this.loginUsername, this.loginPassword).subscribe(
+        (response:any) => {
+          alert('登录成功!');
+          this.router.navigate(['/posts']); // 登录成功后导航到动态列表页面
+        },
+        (error:any) => {
+          alert('登录失败!');
+        }
+      );
+    }
+  
+    // 处理文件选择
+    onFileSelected(event: any) {
+      this.image = event.target.files[0]; // 获取用户选择的文件
+    }
+  
+    // 发布动态
+    createPost() {
+      const formData = new FormData(); // 创建 FormData 对象
+      formData.append('content', this.postContent); // 将动态内容添加到 FormData
+      if (this.image) {
+        formData.append('image', this.image); // 将图片添加到 FormData
+      }
+  
+      this.postService.createPost(formData).subscribe(
+        (response:any) => {
+          alert('动态发布成功!'); // 发布成功提示
+          this.postContent = ''; // 清空输入框
+          this.image = null; // 清空选择的图片
+          this.loadPosts(); // 重新加载动态列表
+        },
+        (error:any) => {
+          alert('发布失败!'); // 发布失败提示
+        }
+      );
+    }
+  
+    // 加载动态列表
+    loadPosts() {
+      this.postService.getPosts().subscribe((data:any) => {
+        this.posts = data; // 设置动态列表
+      });
+    }
 }