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