Ionic社交应用实战 #

一、项目概述 #

1.1 功能需求 #

text
社交应用功能
    │
    ├── 用户系统
    │   ├── 注册登录
    │   ├── 个人资料
    │   └── 关注粉丝
    │
    ├── 动态
    │   ├── 发布动态
    │   ├── 动态列表
    │   └── 点赞评论
    │
    ├── 消息
    │   ├── 聊天列表
    │   ├── 聊天详情
    │   └── 推送通知
    │
    └── 发现
        ├── 推荐
        ├── 搜索
        └── 话题

二、用户系统 #

2.1 用户模型 #

typescript
// models/user.model.ts
export interface User {
  id: string;
  username: string;
  nickname: string;
  avatar: string;
  bio: string;
  gender: 'male' | 'female' | 'other';
  birthday: Date;
  location: string;
  website: string;
  followersCount: number;
  followingCount: number;
  postsCount: number;
  isFollowing?: boolean;
}

export interface AuthTokens {
  accessToken: string;
  refreshToken: string;
  expiresIn: number;
}

2.2 认证服务 #

typescript
// services/auth.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Router } from '@angular/router';
import { User, AuthTokens } from '../models/user.model';
import { ApiService } from './api.service';
import { StorageService } from './storage.service';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private currentUserSubject = new BehaviorSubject<User | null>(null);
  private tokensSubject = new BehaviorSubject<AuthTokens | null>(null);
  
  currentUser$ = this.currentUserSubject.asObservable();
  tokens$ = this.tokensSubject.asObservable();
  
  constructor(
    private api: ApiService,
    private storage: StorageService,
    private router: Router
  ) {
    this.loadTokens();
  }
  
  private async loadTokens() {
    const tokens = await this.storage.get<AuthTokens>('tokens');
    if (tokens) {
      this.tokensSubject.next(tokens);
      await this.loadCurrentUser();
    }
  }
  
  private async loadCurrentUser() {
    try {
      const user = await this.api.get<User>('/user/me').toPromise();
      this.currentUserSubject.next(user);
    } catch (error) {
      this.logout();
    }
  }
  
  async login(email: string, password: string): Promise<boolean> {
    try {
      const tokens = await this.api.post<AuthTokens>('/auth/login', { email, password }).toPromise();
      await this.storage.set('tokens', tokens);
      this.tokensSubject.next(tokens);
      await this.loadCurrentUser();
      return true;
    } catch (error) {
      return false;
    }
  }
  
  async register(data: { username: string; email: string; password: string }): Promise<boolean> {
    try {
      await this.api.post('/auth/register', data).toPromise();
      return await this.login(data.email, data.password);
    } catch (error) {
      return false;
    }
  }
  
  async logout() {
    await this.storage.remove('tokens');
    this.currentUserSubject.next(null);
    this.tokensSubject.next(null);
    this.router.navigate(['/auth/login']);
  }
  
  isLoggedIn(): boolean {
    return !!this.tokensSubject.value;
  }
  
  getCurrentUser(): User | null {
    return this.currentUserSubject.value;
  }
  
  getAccessToken(): string | null {
    return this.tokensSubject.value?.accessToken || null;
  }
}

三、动态系统 #

3.1 动态模型 #

typescript
// models/post.model.ts
export interface Post {
  id: string;
  author: User;
  content: string;
  images: string[];
  video?: string;
  likesCount: number;
  commentsCount: number;
  sharesCount: number;
  isLiked: boolean;
  tags: string[];
  location?: string;
  visibility: 'public' | 'friends' | 'private';
  createTime: Date;
}

export interface Comment {
  id: string;
  postId: string;
  author: User;
  content: string;
  replyTo?: User;
  likesCount: number;
  isLiked: boolean;
  createTime: Date;
}

3.2 动态服务 #

typescript
// services/post.service.ts
import { Injectable } from '@angular/core';
import { ApiService } from './api.service';
import { Post, Comment } from '../models/post.model';

@Injectable({
  providedIn: 'root'
})
export class PostService {
  
  constructor(private api: ApiService) {}
  
  getPosts(params: { page: number; limit: number }): Observable<{ data: Post[]; total: number }> {
    return this.api.get('/posts', params);
  }
  
  getUserPosts(userId: string, params: { page: number; limit: number }): Observable<{ data: Post[] }> {
    return this.api.get(`/users/${userId}/posts`, params);
  }
  
  getPost(id: string): Observable<Post> {
    return this.api.get(`/posts/${id}`);
  }
  
  createPost(data: { content: string; images?: string[]; tags?: string[] }): Observable<Post> {
    return this.api.post('/posts', data);
  }
  
  deletePost(id: string): Observable<void> {
    return this.api.delete(`/posts/${id}`);
  }
  
  likePost(id: string): Observable<void> {
    return this.api.post(`/posts/${id}/like`, {});
  }
  
  unlikePost(id: string): Observable<void> {
    return this.api.delete(`/posts/${id}/like`);
  }
  
  getComments(postId: string, params: { page: number; limit: number }): Observable<{ data: Comment[] }> {
    return this.api.get(`/posts/${postId}/comments`, params);
  }
  
  createComment(postId: string, data: { content: string; replyTo?: string }): Observable<Comment> {
    return this.api.post(`/posts/${postId}/comments`, data);
  }
}

四、即时通讯 #

4.1 消息模型 #

typescript
// models/message.model.ts
export interface Conversation {
  id: string;
  participants: User[];
  lastMessage: Message;
  unreadCount: number;
  updateTime: Date;
}

export interface Message {
  id: string;
  conversationId: string;
  sender: User;
  content: string;
  type: 'text' | 'image' | 'video' | 'file';
  status: 'sending' | 'sent' | 'delivered' | 'read';
  createTime: Date;
}

4.2 聊天服务 #

typescript
// services/chat.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { WebSocket } from 'ws';
import { Message, Conversation } from '../models/message.model';
import { ApiService } from './api.service';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root'
})
export class ChatService {
  private socket: WebSocket | null = null;
  private messagesSubject = new BehaviorSubject<Message[]>([]);
  
  messages$ = this.messagesSubject.asObservable();
  
  constructor(
    private api: ApiService,
    private auth: AuthService
  ) {}
  
  connect() {
    const token = this.auth.getAccessToken();
    if (!token) return;
    
    this.socket = new WebSocket(`wss://api.example.com/ws?token=${token}`);
    
    this.socket.onmessage = (event) => {
      const message: Message = JSON.parse(event.data);
      this.messagesSubject.next([...this.messagesSubject.value, message]);
    };
    
    this.socket.onclose = () => {
      setTimeout(() => this.connect(), 5000);
    };
  }
  
  disconnect() {
    if (this.socket) {
      this.socket.close();
      this.socket = null;
    }
  }
  
  sendMessage(conversationId: string, content: string) {
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify({
        type: 'message',
        conversationId,
        content
      }));
    }
  }
  
  getConversations(): Observable<Conversation[]> {
    return this.api.get('/conversations');
  }
  
  getMessages(conversationId: string, params: { page: number; limit: number }): Observable<{ data: Message[] }> {
    return this.api.get(`/conversations/${conversationId}/messages`, params);
  }
  
  markAsRead(conversationId: string): Observable<void> {
    return this.api.post(`/conversations/${conversationId}/read`, {});
  }
}

五、推送通知 #

5.1 推送服务 #

typescript
// services/push.service.ts
import { Injectable } from '@angular/core';
import { PushNotifications, PushNotificationSchema } from '@capacitor/push-notifications';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class PushService {
  
  constructor(private router: Router) {}
  
  async init() {
    const result = await PushNotifications.requestPermissions();
    
    if (result.receive === 'granted') {
      await PushNotifications.register();
      this.listenEvents();
    }
  }
  
  private listenEvents() {
    PushNotifications.addListener('registration', (token) => {
      console.log('Push token:', token.value);
    });
    
    PushNotifications.addListener('pushNotificationReceived', (notification) => {
      console.log('Push received:', notification);
    });
    
    PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
      const data = action.notification.data;
      
      switch (data.type) {
        case 'message':
          this.router.navigate(['/chat', data.conversationId]);
          break;
        case 'comment':
          this.router.navigate(['/post', data.postId]);
          break;
        case 'like':
          this.router.navigate(['/post', data.postId]);
          break;
        case 'follow':
          this.router.navigate(['/user', data.userId]);
          break;
      }
    });
  }
}

六、最佳实践 #

6.1 安全考虑 #

  • JWT Token管理
  • HTTPS通信
  • 敏感数据加密
  • 输入验证

6.2 性能优化 #

  • 消息分页加载
  • 图片压缩上传
  • 虚拟滚动
  • 懒加载

七、总结 #

7.1 项目要点 #

要点 说明
用户系统 JWT认证
动态系统 发布、点赞、评论
即时通讯 WebSocket
推送通知 Capacitor Push

7.2 学习总结 #

通过三个实战项目,你已经掌握了Ionic的核心开发技能,可以开始开发自己的应用了!

最后更新:2026-03-28