7. 社交动态应用(technical-architecture)
1. 架构设计
2. 技术栈描述
- 前端框架: React@18 + Vite
- 状态管理: Zustand@4
- UI组件库: Ant Design@5 + TailwindCSS@3
- 富文本编辑器: react-quill + quill-image-resize-module
- 初始化工具: vite-init
- 后端服务: Supabase(提供认证、数据库、存储)
- 实时通信: Supabase Realtime
- 图片处理: browser-image-compression
3. 路由定义
| 路由路径 | 页面用途 |
|---|---|
| / | 动态首页,展示好友动态和推荐内容 |
| /publish | 发布动态页面,支持富文本编辑和媒体上传 |
| /post/:id | 动态详情页面,展示完整内容和评论区 |
| /messages | 消息列表页面,展示私信对话和通知 |
| /chat/:userId | 聊天页面,支持一对一实时对话 |
| /friends | 好友列表页面,支持搜索和分组管理 |
| /profile/:userId | 个人主页,展示用户信息和动态 |
| /profile/settings | 设置页面,账号和隐私设置 |
| /login | 登录页面,支持手机号/邮箱登录 |
| /register | 注册页面,新用户注册流程 |
4. 数据模型
4.1 数据库实体关系图
erDiagram
USERS ||--o{ POSTS : creates
USERS ||--o{ COMMENTS : writes
USERS ||--o{ LIKES : gives
USERS ||--o{ MESSAGES : sends
USERS ||--o{ FRIENDSHIPS : has
POSTS ||--o{ COMMENTS : receives
POSTS ||--o{ LIKES : receives
POSTS ||--o{ POST_MEDIA : contains
USERS {
uuid id PK
string email UK
string phone UK
string username UK
string password_hash
string nickname
string avatar_url
string bio
string background_image
boolean is_verified
timestamp created_at
timestamp updated_at
}
POSTS {
uuid id PK
uuid user_id FK
string content
json media_urls
string visibility
json tags
string location
integer like_count
integer comment_count
timestamp created_at
timestamp updated_at
}
COMMENTS {
uuid id PK
uuid post_id FK
uuid user_id FK
uuid parent_id FK
string content
integer like_count
timestamp created_at
}
LIKES {
uuid id PK
uuid user_id FK
uuid post_id FK
uuid comment_id FK
timestamp created_at
}
MESSAGES {
uuid id PK
uuid sender_id FK
uuid receiver_id FK
string content
string message_type
boolean is_read
timestamp created_at
}
FRIENDSHIPS {
uuid id PK
uuid user_id FK
uuid friend_id FK
string status
timestamp created_at
}
POST_MEDIA {
uuid id PK
uuid post_id FK
string media_url
string media_type
integer sort_order
timestamp created_at
}
4.2 数据定义语言
用户表 (users)
-- 创建用户表
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE,
phone VARCHAR(20) UNIQUE,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
nickname VARCHAR(100) NOT NULL,
avatar_url TEXT,
bio TEXT,
background_image TEXT,
is_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 创建索引
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_phone ON users(phone);
动态表 (posts)
-- 创建动态表
CREATE TABLE posts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
content TEXT NOT NULL,
media_urls JSONB DEFAULT '[]',
visibility VARCHAR(20) DEFAULT 'public' CHECK (visibility IN ('public', 'friends', 'private')),
tags JSONB DEFAULT '[]',
location VARCHAR(255),
like_count INTEGER DEFAULT 0,
comment_count INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 创建索引
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_posts_created_at ON posts(created_at DESC);
CREATE INDEX idx_posts_visibility ON posts(visibility);
评论表 (comments)
-- 创建评论表
CREATE TABLE comments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
parent_id UUID REFERENCES comments(id) ON DELETE CASCADE,
content TEXT NOT NULL,
like_count INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 创建索引
CREATE INDEX idx_comments_post_id ON comments(post_id);
CREATE INDEX idx_comments_user_id ON comments(user_id);
CREATE INDEX idx_comments_parent_id ON comments(parent_id);
点赞表 (likes)
-- 创建点赞表
CREATE TABLE likes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
comment_id UUID REFERENCES comments(id) ON DELETE CASCADE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, post_id),
UNIQUE(user_id, comment_id)
);
-- 创建索引
CREATE INDEX idx_likes_user_post ON likes(user_id, post_id);
CREATE INDEX idx_likes_user_comment ON likes(user_id, comment_id);
消息表 (messages)
-- 创建消息表
CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sender_id UUID REFERENCES users(id) ON DELETE CASCADE,
receiver_id UUID REFERENCES users(id) ON DELETE CASCADE,
content TEXT NOT NULL,
message_type VARCHAR(20) DEFAULT 'text' CHECK (message_type IN ('text', 'image', 'video', 'audio')),
is_read BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 创建索引
CREATE INDEX idx_messages_sender ON messages(sender_id);
CREATE INDEX idx_messages_receiver ON messages(receiver_id);
CREATE INDEX idx_messages_created_at ON messages(created_at DESC);
好友关系表 (friendships)
-- 创建好友关系表
CREATE TABLE friendships (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
friend_id UUID REFERENCES users(id) ON DELETE CASCADE,
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'blocked')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, friend_id)
);
-- 创建索引
CREATE INDEX idx_friendships_user_id ON friendships(user_id);
CREATE INDEX idx_friendships_friend_id ON friendships(friend_id);
CREATE INDEX idx_friendships_status ON friendships(status);
5. 权限配置
-- 基本权限授予
GRANT SELECT ON users TO anon;
GRANT SELECT ON posts TO anon;
GRANT SELECT ON comments TO anon;
GRANT SELECT ON likes TO anon;
-- 认证用户权限
GRANT ALL PRIVILEGES ON users TO authenticated;
GRANT ALL PRIVILEGES ON posts TO authenticated;
GRANT ALL PRIVILEGES ON comments TO authenticated;
GRANT ALL PRIVILEGES ON likes TO authenticated;
GRANT ALL PRIVILEGES ON messages TO authenticated;
GRANT ALL PRIVILEGES ON friendships TO authenticated;
GRANT ALL PRIVILEGES ON post_media TO authenticated;
-- RLS策略示例(posts表)
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 查看公开动态
CREATE POLICY "View public posts" ON posts
FOR SELECT USING (visibility = 'public');
-- 查看好友动态
CREATE POLICY "View friends posts" ON posts
FOR SELECT USING (
visibility = 'friends' AND
user_id IN (
SELECT friend_id FROM friendships
WHERE user_id = auth.uid() AND status = 'accepted'
)
);
-- 用户只能修改自己的动态
CREATE POLICY "Users can update own posts" ON posts
FOR UPDATE USING (user_id = auth.uid());
-- 用户只能删除自己的动态
CREATE POLICY "Users can delete own posts" ON posts
FOR DELETE USING (user_id = auth.uid());
6. 状态管理设计
6.1 Zustand Store结构
// 用户状态
interface UserStore {
currentUser: User | null;
isAuthenticated: boolean;
login: (credentials) => Promise<void>;
logout: () => void;
updateProfile: (data) => Promise<void>;
}
// 动态状态
interface PostStore {
posts: Post[];
currentPost: Post | null;
isLoading: boolean;
fetchPosts: (page: number) => Promise<void>;
createPost: (data) => Promise<void>;
likePost: (postId: string) => void;
addComment: (postId: string, content: string) => void;
}
// 消息状态
interface MessageStore {
conversations: Conversation[];
currentChat: Message[];
unreadCount: number;
fetchConversations: () => Promise<void>;
fetchChatHistory: (userId: string) => Promise<void>;
sendMessage: (receiverId: string, content: string) => void;
markAsRead: (messageId: string) => void;
}
// 好友状态
interface FriendStore {
friends: User[];
pendingRequests: User[];
searchResults: User[];
fetchFriends: () => Promise<void>;
sendFriendRequest: (userId: string) => void;
acceptRequest: (requestId: string) => void;
searchUsers: (query: string) => Promise<void>;
}
7. 实时功能实现
7.1 Supabase Realtime配置
// 消息实时订阅
const subscribeToMessages = (userId: string) => {
return supabase
.channel('messages')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'messages',
filter: `receiver_id=eq.${userId}` },
(payload) => {
// 处理新消息
messageStore.addMessage(payload.new);
}
)
.subscribe();
};
// 动态实时更新
const subscribeToPosts = () => {
return supabase
.channel('posts')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'posts' },
(payload) => {
// 添加新动态到列表
postStore.addPost(payload.new);
}
)
.subscribe();
};
8. 性能优化策略
8.1 前端优化
- 虚拟滚动:动态列表使用react-window实现虚拟滚动
- 图片懒加载:使用Intersection Observer实现图片懒加载
- 代码分割:按路由进行代码分割,减少首屏加载时间
- 缓存策略:利用Zustand持久化存储用户数据和常用状态
8.2 数据库优化
- 索引优化:为常用查询字段创建复合索引
- 分页查询:使用游标分页避免深度分页性能问题
- 数据预加载:提前加载用户可能访问的数据
- 连接池配置:合理配置数据库连接池参数
20大项目拆解:从PRD到架构 文章被收录于专栏
想独立做出一个完整的项目却不知从何下手?本专栏是你的终极路线图。我们由浅入深,通过20个经典项目案例,手把手带你走过产品构思、需求撰写、功能设计、技术选型、架构搭建的全过程。从“音乐播放器”到“企业后台”,你将逐步建立对软件系统的完整认知,完成从理论到实践、从单一技能到复合能力的飞跃。