合并代码

Change-Id: Id5e0dc4f7b448b4ba615243bf1dfa964907f5d68
diff --git a/Merge/back_ljc/app.py b/Merge/back_ljc/app.py
new file mode 100644
index 0000000..f672fc3
--- /dev/null
+++ b/Merge/back_ljc/app.py
@@ -0,0 +1,473 @@
+from flask import Flask, jsonify, request, session
+from flask_sqlalchemy import SQLAlchemy
+from flask_cors import CORS
+
+app = Flask(__name__)
+app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@10.126.59.25/redbook'
+app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
+app.secret_key = 'your_secret_key'
+CORS(app, supports_credentials=True)
+
+db = SQLAlchemy(app)
+
+# 模型定义
+# 用户表
+class User(db.Model):
+    __tablename__ = 'users'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='用户ID')
+    username = db.Column(db.String(50), unique=True, nullable=False, comment='用户名')
+    password = db.Column(db.String(255), nullable=False, comment='加密密码')
+    email = db.Column(db.String(100), unique=True, nullable=False, comment='邮箱')
+    avatar = db.Column(db.String(255), comment='头像URL')
+    role = db.Column(db.Enum('superadmin', 'user', 'admin'), default='user', comment='角色')
+    bio = db.Column(db.String(255), comment='个人简介')
+    status = db.Column(db.Enum('active', 'banned', 'muted'), default='active', comment='账号状态')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+    updated_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), 
+                          onupdate=db.func.current_timestamp(), comment='更新时间')
+    birthday = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(),comment='生日')
+    gender = db.Column(db.String(10),comment='性别')
+    location = db.Column(db.String(100),comment='所在地')
+    
+    # 关系定义
+    posts = db.relationship('Post', backref='author', lazy=True)
+    behaviors = db.relationship('Behavior', backref='user', lazy=True)
+    comments = db.relationship('Comment', backref='commenter', lazy=True)
+    notifications = db.relationship('Notification', backref='recipient', lazy=True)
+    audits = db.relationship('Audit', backref='admin', lazy=True)
+    logs = db.relationship('Log', backref='logger', lazy=True)
+    user_tags = db.relationship('UserTag', backref='user', lazy=True)
+
+# 标签表
+class Tag(db.Model):
+    __tablename__ = 'tags'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='标签ID')
+    name = db.Column(db.String(50), unique=True, nullable=False, comment='标签名称')
+    description = db.Column(db.String(255), comment='标签描述')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+    
+    # 关系定义
+    post_tags = db.relationship('PostTag', backref='tag', lazy=True)
+    user_tags = db.relationship('UserTag', backref='tag', lazy=True)
+
+# 话题/超话表
+class Topic(db.Model):
+    __tablename__ = 'topics'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='话题ID')
+    name = db.Column(db.String(100), unique=True, nullable=False, comment='话题名称')
+    description = db.Column(db.Text, comment='话题描述')
+    status = db.Column(db.Enum('active', 'archived'), default='active', comment='状态')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+    
+    # 关系定义
+    posts = db.relationship('Post', backref='topic', lazy=True)
+
+# 内容帖子表
+class Post(db.Model):
+    __tablename__ = 'posts'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='帖子ID')
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False, comment='作者ID')
+    topic_id = db.Column(db.Integer, db.ForeignKey('topics.id', ondelete='SET NULL'), comment='所属话题ID')
+    type = db.Column(db.Enum('text', 'image', 'video', 'document'), default='text', comment='内容类型')
+    title = db.Column(db.String(255), nullable=False, comment='标题')
+    content = db.Column(db.Text, nullable=False, comment='正文内容')
+    media_urls = db.Column(db.JSON, comment='媒体资源URL数组')
+    status = db.Column(db.Enum('draft', 'pending', 'published', 'deleted', 'rejected'), default='draft', comment='状态')
+    heat = db.Column(db.Integer, default=0, comment='热度值')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+    updated_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), 
+                          onupdate=db.func.current_timestamp(), comment='更新时间')
+    
+    # 关系定义
+    behaviors = db.relationship('Behavior', backref='post', lazy=True)
+    comments = db.relationship('Comment', backref='post', lazy=True)
+    post_tags = db.relationship('PostTag', backref='post', lazy=True)
+    audits = db.relationship('Audit', backref='post', lazy=True)
+
+# 帖子标签关联表
+class PostTag(db.Model):
+    __tablename__ = 'post_tags'
+    post_id = db.Column(db.Integer, db.ForeignKey('posts.id', ondelete='CASCADE'), primary_key=True, comment='帖子ID')
+    tag_id = db.Column(db.Integer, db.ForeignKey('tags.id', ondelete='CASCADE'), primary_key=True, comment='标签ID')
+
+# 用户行为表
+class Behavior(db.Model):
+    __tablename__ = 'behaviors'
+    id = db.Column(db.BigInteger, primary_key=True, autoincrement=True, comment='行为ID')
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False, comment='用户ID')
+    post_id = db.Column(db.Integer, db.ForeignKey('posts.id', ondelete='CASCADE'), nullable=False, comment='帖子ID')
+    type = db.Column(db.Enum('like', 'comment', 'favorite', 'view', 'share'), nullable=False, comment='行为类型')
+    value = db.Column(db.Integer, default=1, comment='行为值')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='行为时间')
+
+# 评论表
+class Comment(db.Model):
+    __tablename__ = 'comments'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='评论ID')
+    post_id = db.Column(db.Integer, db.ForeignKey('posts.id', ondelete='CASCADE'), nullable=False, comment='帖子ID')
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False, comment='用户ID')
+    parent_id = db.Column(db.Integer, db.ForeignKey('comments.id', ondelete='CASCADE'), comment='父评论ID')
+    content = db.Column(db.Text, nullable=False, comment='评论内容')
+    status = db.Column(db.Enum('active', 'deleted'), default='active', comment='状态')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+    updated_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), 
+                          onupdate=db.func.current_timestamp(), comment='更新时间')
+    
+    # 关系定义
+    replies = db.relationship('Comment', backref=db.backref('parent', remote_side=[id]), lazy=True)
+
+# 用户关注关系表
+class Follow(db.Model):
+    __tablename__ = 'follows'
+    follower_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), primary_key=True, comment='关注者ID')
+    followee_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), primary_key=True, comment='被关注者ID')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='关注时间')
+    
+    # 关系定义
+    follower = db.relationship('User', foreign_keys=[follower_id], backref='following')
+    followee = db.relationship('User', foreign_keys=[followee_id], backref='followers')
+
+# 通知表
+class Notification(db.Model):
+    __tablename__ = 'notifications'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='通知ID')
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False, comment='接收用户ID')
+    type = db.Column(db.Enum('like', 'comment', 'follow', 'system', 'audit'), nullable=False, comment='通知类型')
+    content = db.Column(db.JSON, nullable=False, comment='通知内容')
+    is_read = db.Column(db.Boolean, default=False, comment='是否已读')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+
+# 审核记录表
+class Audit(db.Model):
+    __tablename__ = 'audits'
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='审核ID')
+    post_id = db.Column(db.Integer, db.ForeignKey('posts.id', ondelete='CASCADE'), nullable=False, comment='帖子ID')
+    admin_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False, comment='管理员ID')
+    result = db.Column(db.Enum('approved', 'rejected'), nullable=False, comment='审核结果')
+    reason = db.Column(db.String(255), comment='审核原因')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='审核时间')
+
+# 日志表
+class Log(db.Model):
+    __tablename__ = 'logs'
+    id = db.Column(db.BigInteger, primary_key=True, autoincrement=True, comment='日志ID')
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='SET NULL'), comment='用户ID')
+    type = db.Column(db.Enum('access', 'error', 'behavior', 'system'), nullable=False, comment='日志类型')
+    content = db.Column(db.Text, nullable=False, comment='日志内容')
+    ip = db.Column(db.String(45), comment='IP地址')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='记录时间')
+
+# 用户兴趣标签表
+class UserTag(db.Model):
+    __tablename__ = 'user_tags'
+    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), primary_key=True, comment='用户ID')
+    tag_id = db.Column(db.Integer, db.ForeignKey('tags.id', ondelete='CASCADE'), primary_key=True, comment='标签ID')
+    weight = db.Column(db.Float, default=1.0, comment='兴趣权重')
+    created_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), comment='创建时间')
+    updated_at = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), 
+                          onupdate=db.func.current_timestamp(), comment='更新时间')
+    
+
+# 自动登录用户11
+@app.before_request
+def auto_login():
+    # 如果用户未登录,自动设置为用户11
+    if 'user_id' not in session:
+        session['user_id'] = 11
+
+# 获取当前用户信息
+@app.route('/api/current-user')
+def current_user():
+    user_id = session.get('user_id', 1)
+    user = User.query.get(user_id)
+    if not user:
+        return jsonify({'error': 'User not found'}), 404
+    
+    following_count = Follow.query.filter_by(follower_id=user_id).count()
+    followers_count = Follow.query.filter_by(followee_id=user_id).count()
+    
+    return jsonify({
+        'id': user.id,
+        'username': user.username,
+        'email': user.email,
+        'avatar': user.avatar,
+        'bio': user.bio,
+        'following_count': following_count,
+        'followers_count': followers_count
+    })
+
+# 获取指定用户信息
+@app.route('/api/user/<int:user_id>')
+def get_user(user_id):
+    current_user_id = session.get('user_id', 1)
+    user = User.query.get(user_id)
+    if not user:
+        return jsonify({'error': 'User not found'}), 404
+    
+    following_count = Follow.query.filter_by(follower_id=user_id).count()
+    followers_count = Follow.query.filter_by(followee_id=user_id).count()
+    
+    is_following = False
+    if current_user_id:
+        is_following = Follow.query.filter_by(
+            follower_id=current_user_id,
+            followee_id=user_id
+        ).first() is not None
+    
+    return jsonify({
+        'id': user.id,
+        'username': user.username,
+        'avatar': user.avatar,
+        'bio': user.bio,
+        'following_count': following_count,
+        'followers_count': followers_count,
+        'is_following': is_following,
+        'gender': user.gender,
+        'location': user.location,
+        'birthday': user.birthday
+    })
+
+# 更新用户信息
+@app.route('/api/user/<int:user_id>', methods=['PUT'])
+def update_user(user_id):
+    current_user_id = session.get('user_id', 1)
+    if current_user_id != user_id:
+        return jsonify({'error': 'Unauthorized'}), 403
+    
+    user = User.query.get(user_id)
+    if not user:
+        return jsonify({'error': 'User not found'}), 404
+    
+    data = request.json
+    print(data)
+    if 'avatar' in data:
+        user.avatar = data['avatar']
+    if 'bio' in data:
+        user.bio = data['bio']
+    if 'gender' in data:
+        user.gender = data['gender']
+    if 'location' in data:
+        user.location = data['location']
+    if 'birthday' in data:
+        user.birthday  = data['birthday']
+    
+    db.session.commit()
+    return jsonify({
+        'id': user.id,
+        'avatar': user.avatar,
+        'bio': user.bio
+    })
+
+# 获取用户收藏
+@app.route('/api/user/<int:user_id>/favorites', methods=['GET'])
+def get_user_favorites(user_id):
+    # 检查用户是否登录
+    if 'user_id' not in session:
+        return jsonify({'error': '未登录'}), 401
+    
+    # 验证请求的用户ID与登录用户ID是否一致
+    if session['user_id'] != user_id:
+        return jsonify({'error': '无权访问其他用户的收藏'}), 403
+    
+    try:
+        # 获取收藏行为及其关联的帖子
+        favorites = db.session.query(Behavior, Post).join(
+            Post, Behavior.post_id == Post.id
+        ).filter(
+            Behavior.user_id == user_id,
+            Behavior.type == 'favorite'
+        ).all()
+        
+        # 构建响应数据
+        result = []
+        for behavior, post in favorites:
+            # 获取帖子作者信息
+            author = User.query.get(post.user_id)
+            
+            # 构建响应对象
+            result.append({
+                'behavior_id': behavior.id,
+                'post': {
+                    'id': post.id,
+                    'title': post.title,
+                    'type': post.type,
+                    'content_preview': post.content[:100] + '...' if len(post.content) > 100 else post.content,
+                    'media_urls': post.media_urls,
+                    'created_at': post.created_at.strftime('%Y-%m-%d %H:%M:%S'),
+                    'author': {
+                        'id': author.id,
+                        'username': author.username,
+                        'avatar': author.avatar
+                    }
+                },
+                'favorited_at': behavior.created_at.strftime('%Y-%m-%d %H:%M:%S')
+            })
+        
+        return jsonify(result)
+    
+    except Exception as e:
+        app.logger.error(f"获取收藏时出错: {str(e)}")
+        return jsonify({'error': '获取收藏失败'}), 500
+    
+
+# 获取用户发布的帖子
+@app.route('/api/user/<int:user_id>/posts')
+def get_user_posts(user_id):
+    # 允许任何人查看用户发布的帖子
+    posts = Post.query.filter_by(
+        user_id=user_id,
+        status='published'
+    ).all()
+    
+    return jsonify([{
+        'id': post.id,
+        'title': post.title,
+        'content': post.content[:100] + '...' if len(post.content) > 100 else post.content,
+        'type': post.type,
+        'heat': post.heat,
+        'created_at': post.created_at.strftime('%Y-%m-%d %H:%M')
+    } for post in posts])
+
+# 获取用户关注列表
+@app.route('/api/user/<int:user_id>/following')
+def get_user_following(user_id):
+    # 允许任何人查看用户的关注列表
+    following = Follow.query.filter_by(follower_id=user_id).all()
+    
+    # 获取被关注用户的详细信息
+    following_list = []
+    for follow in following:
+        user = User.query.get(follow.followee_id)
+        if user:
+            followers_count = Follow.query.filter_by(followee_id=user.id).count()
+            
+            following_list.append({
+                'id': user.id,
+                'username': user.username,
+                'avatar': user.avatar,
+                'followers_count': followers_count
+            })
+    
+    return jsonify(following_list)
+
+# 关注/取消关注用户
+@app.route('/api/follow/<int:followee_id>', methods=['POST', 'DELETE'])
+def follow_user(followee_id):
+    follower_id = session.get('user_id', 1)
+    if follower_id == followee_id:
+        return jsonify({'error': 'Cannot follow yourself'}), 400
+    
+    if request.method == 'POST':
+        existing = Follow.query.filter_by(
+            follower_id=follower_id,
+            followee_id=followee_id
+        ).first()
+        
+        if not existing:
+            follow = Follow(
+                follower_id=follower_id,
+                followee_id=followee_id
+            )
+            db.session.add(follow)
+            db.session.commit()
+        return jsonify({'message': 'Followed successfully'})
+    
+    elif request.method == 'DELETE':
+        follow = Follow.query.filter_by(
+            follower_id=follower_id,
+            followee_id=followee_id
+        ).first()
+        
+        if follow:
+            db.session.delete(follow)
+            db.session.commit()
+        return jsonify({'message': 'Unfollowed successfully'})
+    
+
+# 新增获取粉丝列表的API
+@app.route('/api/user/<int:user_id>/followers')
+def get_user_followers(user_id):
+    try:
+        # 查询关注该用户的用户列表
+        followers = db.session.query(User).join(
+            Follow, Follow.follower_id == User.id
+        ).filter(
+            Follow.followee_id == user_id
+        ).all()
+        
+        # 获取当前登录用户ID(如果有)
+        current_user_id = session.get('user_id') if 'user_id' in session else None
+        
+        # 构建响应数据
+        result = []
+        for user in followers:
+            # 检查当前用户是否关注了这个粉丝
+            is_following = False
+            if current_user_id:
+                follow_relation = Follow.query.filter_by(
+                    follower_id=current_user_id,
+                    followee_id=user.id
+                ).first()
+                is_following = follow_relation is not None
+            
+            # 计算该粉丝的粉丝数
+            followers_count = Follow.query.filter_by(followee_id=user.id).count()
+            
+            result.append({
+                'id': user.id,
+                'username': user.username,
+                'avatar': user.avatar,
+                'bio': user.bio,
+                'followers_count': followers_count,
+                'is_following': is_following
+            })
+
+        
+        return jsonify({
+            'success': True,
+            'data': result
+        })
+    
+    except Exception as e:
+        app.logger.error(f"获取粉丝列表失败: {str(e)}")
+        return jsonify({
+            'success': False,
+            'error': '获取粉丝列表失败'
+        }), 500
+
+# 辅助函数:检查当前用户是否关注了目标用户
+def check_following_status(follower_id, followee_id):
+    return Follow.query.filter_by(
+        follower_id=follower_id,
+        followee_id=followee_id
+    ).first() is not None
+
+
+# 记录用户点赞收藏总数
+@app.route('/api/user/<int:user_id>/interactions', methods=['GET'])
+def get_user_interactions(user_id):
+    try:
+        # 计算用户的获赞总数(所有帖子的点赞数)
+        like_count = db.session.query(db.func.sum(Behavior.value)).filter(
+            Behavior.post.has(user_id=user_id),
+            Behavior.type == 'like'
+        ).scalar() or 0
+        
+        # 计算用户的收藏总数(所有帖子的收藏数)
+        favorite_count = db.session.query(db.func.sum(Behavior.value)).filter(
+            Behavior.post.has(user_id=user_id),
+            Behavior.type == 'favorite'
+        ).scalar() or 0
+        
+        return jsonify({
+            'likes_count': like_count,
+            'favorites_count': favorite_count
+        })
+    
+    except Exception as e:
+        app.logger.error(f"获取用户互动数据失败: {str(e)}")
+        return jsonify({'error': '获取互动数据失败'}), 500
+
+
+if __name__ == '__main__':
+    app.run(debug=True,port='5715',host='0.0.0.0')
\ No newline at end of file
diff --git a/Merge/front/package.json b/Merge/front/package.json
index 54a8783..5f6553c 100644
--- a/Merge/front/package.json
+++ b/Merge/front/package.json
@@ -4,6 +4,7 @@
   "private": true,
   "dependencies": {
     "@testing-library/dom": "^10.4.0",
+    "@emotion/react": "^11.14.0",
     "@testing-library/jest-dom": "^6.6.3",
     "@testing-library/react": "^16.3.0",
     "@testing-library/user-event": "^13.5.0",
@@ -14,8 +15,16 @@
     "web-vitals": "^2.1.4",
     "lucide-react": "^0.468.0",
     "antd": "^4.24.0",
+    "ajv": "^8.0.0",
+    "ajv-keywords": "^5.0.0",
     "crypto-js": "^4.2.0",
-    "recharts": "^2.1.9"
+    "recharts": "^2.1.9",
+    "mui": "^0.0.1",
+    "@mui/material": "^7.1.1",
+    "react-icons": "^5.5.0",
+    "@mui/icons-material": "^7.1.1",
+    "@emotion/styled": "^11.14.0",
+    "axios": "^1.9.0"
   },
   "scripts": {
     "start": "react-scripts start",
diff --git a/Merge/front/src/api/api_ljc.js b/Merge/front/src/api/api_ljc.js
new file mode 100644
index 0000000..b8130ca
--- /dev/null
+++ b/Merge/front/src/api/api_ljc.js
@@ -0,0 +1,31 @@
+import axios from 'axios';
+
+const api = axios.create({
+  baseURL: 'http://10.126.59.25:5715/api/',
+  withCredentials: true
+});
+
+// 用户相关API
+export const getCurrentUser = () => api.get('/current-user');
+export const getUser = (userId) => api.get(`/user/${userId}`);
+export const updateUser = (userId, data) => api.put(`/user/${userId}`, data);
+
+// 收藏相关API
+export const getFavorites = (userId) => api.get(`/user/${userId}/favorites`);
+
+// 关注相关API
+export const followUser = (followeeId) => api.post(`/follow/${followeeId}`);
+export const unfollowUser = (followeeId) => api.delete(`/follow/${followeeId}`);
+
+// 帖子相关API
+export const getUserPosts = (userId) => api.get(`/user/${userId}/posts`);
+
+// 关注列表API
+export const getUserFollowing = (userId) => api.get(`/user/${userId}/following`);
+
+// 用户互动数据API
+export const getUserInteractions = (userId) => api.get(`/user/${userId}/interactions`);
+// 获取粉丝
+export const getUserFollowers = (userId) => api.get(`/user/${userId}/followers`);
+
+export default api;
\ No newline at end of file
diff --git a/Merge/front/src/components/EditProfileForm.jsx b/Merge/front/src/components/EditProfileForm.jsx
new file mode 100644
index 0000000..d33cbcb
--- /dev/null
+++ b/Merge/front/src/components/EditProfileForm.jsx
@@ -0,0 +1,116 @@
+import React, { useState } from 'react';
+import { FaCamera, FaTimes } from 'react-icons/fa';
+
+const EditProfileForm = ({ user, onSave, onCancel }) => {
+  const [avatar, setAvatar] = useState(user.avatar || '');
+  const [bio, setBio] = useState(user.bio || '');
+  const [gender, setGender] = useState('secret');
+  const [birthday, setBirthday] = useState('');
+  const [location, setLocation] = useState('');
+
+  const handleSubmit = (e) => {
+    e.preventDefault();
+    onSave({ avatar, bio });
+  };
+
+  return (
+    <form onSubmit={handleSubmit}>
+      <div className="mb-6">
+        <label className="block text-sm font-medium text-gray-700 mb-2">头像</label>
+        <div className="flex items-center">
+          <div className="relative">
+            <div className="w-20 h-20 rounded-full bg-gradient-to-r from-pink-300 to-orange-300 flex items-center justify-center">
+              {avatar ? (
+                <img src={avatar} alt="Avatar" className="w-full h-full rounded-full" />
+              ) : (
+                <div className="text-white text-2xl">{user.username.charAt(0)}</div>
+              )}
+            </div>
+            <button 
+              type="button"
+              className="absolute bottom-0 right-0 bg-white rounded-full p-1 shadow-md"
+            >
+              <FaCamera className="text-gray-700 text-sm" />
+            </button>
+          </div>
+          <div className="ml-4">
+            <input
+              type="text"
+              value={avatar}
+              onChange={(e) => setAvatar(e.target.value)}
+              placeholder="输入头像URL"
+              className="w-full rounded-md border-gray-300 shadow-sm text-sm"
+            />
+          </div>
+        </div>
+      </div>
+      
+      <div className="mb-4">
+        <label className="block text-sm font-medium text-gray-700 mb-2">个人简介</label>
+        <textarea
+          value={bio}
+          onChange={(e) => setBio(e.target.value)}
+          rows="3"
+          maxLength="100"
+          className="mt-1 block w-full rounded-md border-gray-300 shadow-sm text-sm"
+          placeholder="介绍一下自己吧~"
+        />
+        <div className="text-right text-xs text-gray-500 mt-1">{bio.length}/100</div>
+      </div>
+      
+      <div className="grid grid-cols-2 gap-4 mb-4">
+        <div>
+          <label className="block text-sm font-medium text-gray-700 mb-2">性别</label>
+          <select
+            value={gender}
+            onChange={(e) => setGender(e.target.value)}
+            className="mt-1 block w-full rounded-md border-gray-300 shadow-sm text-sm"
+          >
+            <option value="secret">保密</option>
+            <option value="male">男</option>
+            <option value="female">女</option>
+          </select>
+        </div>
+        
+        <div>
+          <label className="block text-sm font-medium text-gray-700 mb-2">生日</label>
+          <input
+            type="date"
+            value={birthday}
+            onChange={(e) => setBirthday(e.target.value)}
+            className="mt-1 block w-full rounded-md border-gray-300 shadow-sm text-sm"
+          />
+        </div>
+      </div>
+      
+      <div className="mb-6">
+        <label className="block text-sm font-medium text-gray-700 mb-2">地区</label>
+        <input
+          type="text"
+          value={location}
+          onChange={(e) => setLocation(e.target.value)}
+          placeholder="填写你所在的城市"
+          className="mt-1 block w-full rounded-md border-gray-300 shadow-sm text-sm"
+        />
+      </div>
+      
+      <div className="flex justify-end space-x-3">
+        <button 
+          type="button"
+          onClick={onCancel}
+          className="px-5 py-2 bg-gray-100 text-gray-700 rounded-full text-sm hover:bg-gray-200"
+        >
+          取消
+        </button>
+        <button 
+          type="submit"
+          className="px-5 py-2 bg-red-500 text-white rounded-full text-sm hover:bg-red-600"
+        >
+          保存
+        </button>
+      </div>
+    </form>
+  );
+};
+
+export default EditProfileForm;
\ No newline at end of file
diff --git a/Merge/front/src/components/FavoritePosts.jsx b/Merge/front/src/components/FavoritePosts.jsx
new file mode 100644
index 0000000..4afe125
--- /dev/null
+++ b/Merge/front/src/components/FavoritePosts.jsx
@@ -0,0 +1,95 @@
+import React, { useState, useEffect } from 'react';
+import { getFavorites } from '../api/api_ljc';
+import { FaHeart } from 'react-icons/fa';
+
+const FavoritePosts = ({ userId }) => {
+  const [favorites, setFavorites] = useState([]);
+  const [loading, setLoading] = useState(true);
+
+  useEffect(() => {
+    const fetchFavorites = async () => {
+      try {
+        setLoading(true);
+        const response = await getFavorites(userId);
+        setFavorites(response.data);
+      } catch (error) {
+        console.error('Failed to fetch favorites:', error);
+      } finally {
+        setLoading(false);
+      }
+    };
+    
+    if (userId) {
+      fetchFavorites();
+    }
+  }, [userId]);
+
+  if (loading) {
+    return (
+      <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
+        {[1, 2, 3, 4, 5, 6].map(item => (
+          <div key={item} className="bg-gray-100 rounded-xl aspect-square animate-pulse"></div>
+        ))}
+      </div>
+    );
+  }
+
+  if (favorites.length === 0) {
+    return (
+      <div className="text-center py-16">
+        <div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-red-100 text-red-500 mb-4">
+          <FaHeart className="text-2xl" />
+        </div>
+        <h3 className="text-lg font-medium text-gray-900">暂无收藏内容</h3>
+        <p className="mt-1 text-gray-500">你还没有收藏任何笔记</p>
+      </div>
+    );
+  }
+
+  // 模拟瀑布流布局数据
+  const waterfallData = favorites.map(post => ({
+    ...post,
+    height: Math.floor(Math.random() * 100) + 200 // 随机高度
+  }));
+
+  return (
+    <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
+      {waterfallData.map(post => (
+        <div 
+          key={post.id} 
+          className="bg-white rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow"
+        >
+          <div 
+            className="relative bg-gray-200" 
+            style={{ height: `${post.height}px` }}
+          >
+            {/* 占位图片 */}
+            <div className="absolute inset-0 bg-gradient-to-br from-pink-100 to-orange-100"></div>
+            
+            {/* 类型标签 */}
+            <div className="absolute top-2 right-2 bg-black bg-opacity-50 text-white text-xs px-2 py-1 rounded-full">
+              {post.type === 'image' ? '图文' : 
+               post.type === 'video' ? '视频' : '文档'}
+            </div>
+            
+            {/* 收藏标记 */}
+            <div className="absolute bottom-2 right-2 bg-red-500 rounded-full p-1">
+              <FaHeart className="text-white text-xs" />
+            </div>
+          </div>
+          
+          <div className="p-3">
+            <h3 className="font-medium line-clamp-2">{post.title}</h3>
+            <div className="flex items-center mt-2 text-xs text-gray-500">
+              <span>❤️ 2.5k</span>
+              <span className="mx-2">•</span>
+              <span>⭐ 156</span>
+            </div>
+          </div>
+        </div>
+      ))}
+    </div>
+  );
+};
+
+export default FavoritePosts;
\ No newline at end of file
diff --git a/Merge/front/src/components/FollowButton.jsx b/Merge/front/src/components/FollowButton.jsx
new file mode 100644
index 0000000..0776191
--- /dev/null
+++ b/Merge/front/src/components/FollowButton.jsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import { followUser, unfollowUser } from '../api/api_ljc';
+
+const FollowButton = ({ userId, isFollowing, onFollowChange }) => {
+  const handleFollow = async () => {
+    try {
+      if (isFollowing) {
+        await unfollowUser(userId);
+        onFollowChange(false);
+      } else {
+        await followUser(userId);
+        onFollowChange(true);
+      }
+    } catch (error) {
+      console.error('关注操作失败:', error);
+    }
+  };
+
+  return (
+    <button 
+      onClick={handleFollow}
+      className={`px-6 py-2 rounded-full text-sm font-medium transition-all ${
+        isFollowing 
+          ? 'bg-gray-100 text-gray-800 hover:bg-gray-200' 
+          : 'bg-red-500 text-white hover:bg-red-600'
+      }`}
+    >
+      {isFollowing ? '已关注' : '关注'}
+    </button>
+  );
+};
+
+export default FollowButton;
\ No newline at end of file
diff --git a/Merge/front/src/components/Header.jsx b/Merge/front/src/components/Header.jsx
index 60a50b7..3b21c98 100644
--- a/Merge/front/src/components/Header.jsx
+++ b/Merge/front/src/components/Header.jsx
@@ -1,18 +1,29 @@
 import React from 'react'
+import { useNavigate } from 'react-router-dom'
 import { User } from 'lucide-react'
 import '../App.css' // 或者单独的 Header.css
 
 export default function Header() {
+  const navigate = useNavigate()
+
+  const handleUserClick = () => {
+    navigate('/user/1') // 或者使用实际的用户ID
+  }
+
   return (
     <header className="header">
       <div className="header-left">
         <div className="logo">小红书</div>
         <h1 className="header-title">创作服务平台</h1>
       </div>
-      <div className="header-right">
+      <div 
+        className="header-right"
+        onClick={handleUserClick}
+        style={{ cursor: 'pointer' }}
+      >
         <div className="user-info">
           <User size={16} />
-          <span>小红薯63081EA1</span>
+          <span>小红薯1</span>
         </div>
       </div>
     </header>
diff --git a/Merge/front/src/components/HomeFeed.jsx b/Merge/front/src/components/HomeFeed.jsx
index 39e0ca8..c681858 100644
--- a/Merge/front/src/components/HomeFeed.jsx
+++ b/Merge/front/src/components/HomeFeed.jsx
@@ -1,6 +1,7 @@
 // src/components/HomeFeed.jsx
 
 import React, { useState, useEffect } from 'react'
+import { useNavigate } from 'react-router-dom'
 import { ThumbsUp } from 'lucide-react'
 import { fetchPosts, fetchPost } from '../api/posts_wzy'
 import '../style/HomeFeed.css'
@@ -11,6 +12,7 @@
 ]
 
 export default function HomeFeed() {
+  const navigate = useNavigate()
   const [activeCat, setActiveCat] = useState('推荐')
   const [items, setItems]         = useState([])
   const [loading, setLoading]     = useState(true)
diff --git a/Merge/front/src/components/UserProfile.jsx b/Merge/front/src/components/UserProfile.jsx
new file mode 100644
index 0000000..8421997
--- /dev/null
+++ b/Merge/front/src/components/UserProfile.jsx
@@ -0,0 +1,1152 @@
+import React, { useState, useEffect, Profiler } from 'react';
+import { 
+  Box, 
+  Grid, 
+  Typography, 
+  Avatar, 
+  Button, 
+  Tabs, 
+  Tab, 
+  Card, 
+  CardMedia, 
+  CardContent, 
+  CardActions, 
+  IconButton, 
+  Divider,
+  List,
+  ListItem,
+  ListItemAvatar,
+  ListItemText,
+  TextField,
+  InputAdornment,
+  Chip,
+  Badge,
+  Fab,
+  Paper,
+  MenuItem,
+  Container,
+  useMediaQuery,
+  useTheme,
+  CircularProgress,
+  Snackbar,
+  Alert
+} from '@mui/material';
+import { useParams } from 'react-router-dom';
+import { 
+  CameraAlt, 
+  Edit, 
+  Favorite, 
+  Bookmark, 
+  Share, 
+  MoreVert, 
+  LocationOn, 
+  Cake, 
+  Female, 
+  Male, 
+  Public, 
+  Add,
+  Search,
+  Notifications,
+  Person,
+  Collections,
+  Group,
+  ChevronLeft,
+  ChevronRight,
+  Close,
+  People
+} from '@mui/icons-material';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+import { Link, useNavigate } from 'react-router-dom';
+
+// 导入API服务
+import { 
+  getCurrentUser, 
+  getUser, 
+  updateUser as updateUserApi,
+  getFavorites,
+  followUser as followUserApi,
+  unfollowUser as unfollowUserApi,
+  getUserPosts,
+  getUserFollowing,
+  getUserInteractions,
+  getUserFollowers
+} from '../api/api_ljc';
+
+// 创建小红书主题
+const theme = createTheme({
+  palette: {
+    primary: {
+      main: '#ff4081',
+    },
+    secondary: {
+      main: '#f50057',
+    },
+    background: {
+      default: '#f5f5f5',
+    },
+  },
+  typography: {
+    fontFamily: '"PingFang SC", "Helvetica Neue", Arial, sans-serif',
+    h5: {
+      fontWeight: 600,
+    },
+    subtitle1: {
+      color: 'rgba(0, 0, 0, 0.6)',
+    },
+  },
+  components: {
+    MuiButton: {
+      styleOverrides: {
+        root: {
+          borderRadius: 20,
+          textTransform: 'none',
+          fontWeight: 500,
+        },
+      },
+    },
+    MuiCard: {
+      styleOverrides: {
+        root: {
+          borderRadius: 16,
+        },
+      },
+    },
+  },
+});
+
+const UserProfile = () => {
+  const { userId } = useParams();
+  const theme = useTheme();
+  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
+  const navigate = useNavigate();
+  const [activeTab, setActiveTab] = useState(0);
+  const [isEditing, setIsEditing] = useState(false);
+  const [followers, setFollowers] = useState([]);
+  const [snackbar, setSnackbar] = useState({ open: false, message: '', severity: 'success' });
+  
+  // 用户数据状态
+  const [currentUser, setCurrentUser] = useState(null);
+  const [profileUser, setProfileUser] = useState(null);
+  const [favorites, setFavorites] = useState([]);
+  const [following, setFollowing] = useState([]);
+  const [posts, setPosts] = useState([]);
+  const [interactions, setInteractions] = useState({ 
+    likes_count: 0, 
+    favorites_count: 0 
+  });
+  
+  // 加载状态
+  const [loading, setLoading] = useState(true);
+  const [updating, setUpdating] = useState(false);
+  const [tabLoading, setTabLoading] = useState(false);
+  
+  // 表单状态
+  const [formData, setFormData] = useState({
+    avatar: '',
+    bio: '',
+    gender: '',
+    birthday: '',
+    location: ''
+  });
+
+  // 显示提示信息
+  const showSnackbar = (message, severity = 'success') => {
+    setSnackbar({ open: true, message, severity });
+  };
+
+  // 加载用户数据
+  useEffect(() => {
+    const fetchInteractions = async () => {
+    try {
+      const response = await getUserInteractions(userId);
+      if (response.data.success) {
+        setInteractions(response.data.data);
+      } else {
+        console.error(response.data.error);
+      }
+    } catch (error) {
+      console.error('获取互动数据失败:', error);
+    }
+  };
+  
+  fetchInteractions();
+
+    const handleFollowUser = async (followeeId) => {
+    try {
+      await followUserApi(followeeId);
+      showSnackbar('关注成功');
+      
+      // 更新粉丝列表状态(将刚关注的用户标记为已关注)
+      setFollowers(prev => prev.map(user => 
+        user.id === followeeId ? { ...user, is_following: true } : user
+      ));
+      
+      // 更新当前用户关注数
+      if (currentUser) {
+        setCurrentUser(prev => ({
+          ...prev,
+          following_count: prev.following_count + 1
+        }));
+      }
+      
+    } catch (error) {
+      console.error('关注操作失败:', error);
+      showSnackbar('关注失败,请重试', 'error');
+    }
+  };
+    const fetchData = async () => {
+      try {
+        setLoading(true);
+        
+        // 获取当前登录用户
+        const currentUserRes = await getCurrentUser();
+        setCurrentUser(currentUserRes.data);
+        
+        // 获取目标用户信息
+        console.log('userId', userId)
+        const profileUserRes = await getUser(userId);
+        setProfileUser(profileUserRes.data);
+        setFormData({
+          avatar: profileUserRes.data.avatar || '',
+          bio: profileUserRes.data.bio || '',
+          gender: profileUserRes.data.gender || '',
+          birthday: profileUserRes.data.birthday || '',
+          location: profileUserRes.data.location || ''
+        });
+        
+        // 获取用户帖子
+        const postsRes = await getUserPosts(userId);
+        setPosts(postsRes.data);
+        
+        // 获取用户互动数据(获赞和收藏数量)
+        const interactionsRes = await getUserInteractions(userId);
+        setInteractions(interactionsRes.data);
+        
+      } catch (error) {
+        console.error('获取用户数据失败:', error);
+        showSnackbar('获取用户数据失败,请重试', 'error');
+      } finally {
+        setLoading(false);
+      }
+    };
+    
+    fetchData();
+  }, [userId]);
+
+  // 根据标签页加载数据
+  useEffect(() => {
+    const fetchTabData = async () => {
+      if (!profileUser) return;
+      
+      try {
+        setTabLoading(true);
+        
+        if (activeTab === 1) {
+          // 加载收藏数据
+          const favoritesRes = await getFavorites(userId);
+          setFavorites(favoritesRes.data);
+        } else if (activeTab === 2) {
+          // 加载关注列表
+          const followingRes = await getUserFollowing(userId);
+          setFollowing(followingRes.data);
+          console.log(followingRes.data)
+        }  else if (activeTab === 3) {
+          // 加载粉丝列表
+          const followersRes = await getUserFollowers(userId);
+          // 
+          setFollowers(followersRes.data.data);
+          console.log(followersRes.data.data)
+        }
+        
+      } catch (error) {
+        console.error('加载数据失败:', error);
+        showSnackbar('加载数据失败,请重试', 'error');
+      } finally {
+        setTabLoading(false);
+      }
+    };
+    
+    fetchTabData();
+  }, [activeTab, userId, profileUser]);
+
+  const handleTabChange = (event, newValue) => {
+    setActiveTab(newValue);
+  };
+
+  const handleFollowToggle = async () => {
+    if (!currentUser || !profileUser) return;
+    
+    try {
+      if (profileUser.is_following) {
+        await unfollowUserApi(profileUser.id);
+        showSnackbar('已取消关注');
+      } else {
+        await followUserApi(profileUser.id);
+        showSnackbar('关注成功');
+      }
+      
+      // 更新用户信息
+      const updatedUser = await getUser(userId);
+      setProfileUser(updatedUser.data);
+      
+    } catch (error) {
+      console.error('关注操作失败:', error);
+      showSnackbar('操作失败,请重试', 'error');
+    }
+  };
+
+  const handleFollowUser = async (followeeId) => {
+    try {
+      await followUserApi(followeeId);
+      showSnackbar('关注成功');
+      
+      // 更新粉丝列表状态
+      setFollowers(prev => prev.map(user => 
+        user.id === followeeId ? {...user, is_following: true} : user
+      ));
+      
+      // 更新当前用户关注数
+      if (currentUser) {
+        setCurrentUser(prev => ({
+          ...prev,
+          following_count: prev.following_count + 1
+        }));
+      }
+      
+    } catch (error) {
+      console.error('关注操作失败:', error);
+      showSnackbar('关注失败,请重试', 'error');
+    }
+  };
+
+  const handleUnfollow = async (followeeId, e) => {
+    e.stopPropagation(); // 阻止事件冒泡
+    
+    try {
+      await unfollowUserApi(followeeId);
+      showSnackbar('已取消关注');
+      
+      // 更新关注列表
+      setFollowing(prev => prev.filter(user => user.id !== followeeId));
+      
+      // 更新当前用户关注数
+      if (currentUser) {
+        setCurrentUser(prev => ({
+          ...prev,
+          following_count: prev.following_count - 1
+        }));
+      }
+      
+      // 更新目标用户粉丝数
+      setProfileUser(prev => ({
+        ...prev,
+        followers_count: prev.followers_count - 1
+      }));
+      
+    } catch (error) {
+      console.error('取消关注失败:', error);
+      showSnackbar('操作失败,请重试', 'error');
+    }
+  };
+
+  const handleFormChange = (e) => {
+    const { name, value } = e.target;
+    setFormData({ ...formData, [name]: value });
+  };
+
+  const handleUpdateProfile = async () => {
+    if (!profileUser) return;
+    
+    try {
+      setUpdating(true);
+      const data = { 
+        avatar: formData.avatar,
+        bio: formData.bio,
+        gender: formData.gender,
+        birthday: formData.birthday,
+        location: formData.location
+      };
+      
+      // 调用更新API
+      const updatedUser = await updateUserApi(profileUser.id, data);
+      
+      // 更新本地状态
+      setProfileUser({ ...profileUser, ...updatedUser.data });
+      setFormData({ ...formData, ...data });
+      
+
+      showSnackbar('个人资料更新成功');
+      setIsEditing(false);
+      
+    } catch (error) {
+      console.error('更新个人资料失败:', error);
+      showSnackbar('更新失败,请重试', 'error');
+    } finally {
+      setUpdating(false);
+    }
+  };
+
+  const navigateToUserProfile = (userId) => {
+    navigate(`/user/${userId}`);
+  };
+
+  if (loading) {
+    return (
+      <Box sx={{ 
+        display: 'flex', 
+        justifyContent: 'center', 
+        alignItems: 'center', 
+        height: '100vh' 
+      }}>
+        <CircularProgress size={60} />
+      </Box>
+    );
+  }
+
+  if (!profileUser) {
+    return (
+      <Box sx={{ 
+        display: 'flex', 
+        justifyContent: 'center', 
+        alignItems: 'center', 
+        height: '100vh',
+        flexDirection: 'column'
+      }}>
+        <Typography variant="h6" sx={{ mb: 2 }}>用户不存在</Typography>
+        <Button variant="outlined" onClick={() => window.location.reload()}>
+          重新加载
+        </Button>
+      </Box>
+    );
+  }
+
+  const isOwnProfile = currentUser && currentUser.id === parseInt(userId);
+
+  return (
+    <ThemeProvider theme={theme}>
+      <Box sx={{ 
+        bgcolor: 'background.default', 
+        minHeight: '100vh', 
+        pb: isMobile ? 8 : 4 
+      }}>
+        {/* 顶部横幅 */}
+        <Box sx={{
+          height: isMobile ? 200 : 250,
+          background: 'linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%)',
+          position: 'relative',
+          borderBottomLeftRadius: 24,
+          borderBottomRightRadius: 24,
+          boxShadow: 1
+        }}>
+          <Fab 
+            color="primary" 
+            size="small" 
+            sx={{ 
+              position: 'absolute', 
+              bottom: -20, 
+              right: 16 
+            }}
+          >
+            <CameraAlt />
+          </Fab>
+        </Box>
+
+        <Container maxWidth="lg">
+          {/* 用户信息区域 */}
+          <Box sx={{ px: isMobile ? 3 : 0, mt: -8, position: 'relative' }}>
+            <Grid container spacing={3}>
+              <Grid item xs={12} sm="auto">
+                <Badge
+                  overlap="circular"
+                  anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
+                  badgeContent={
+                    <IconButton 
+                      size="small" 
+                      sx={{ 
+                        bgcolor: 'grey.200', 
+                        '&:hover': { bgcolor: 'grey.300' } 
+                      }}
+                      onClick={() => setIsEditing(true)}
+                      disabled={!isOwnProfile}
+                    >
+                      <Edit fontSize="small" />
+                    </IconButton>
+                  }
+                >
+                  <Avatar
+                    sx={{ 
+                      width: 120, 
+                      height: 120, 
+                      border: '4px solid white',
+                      boxShadow: 3
+                    }}
+                    src={profileUser.avatar || 'https://www.8848seo.cn/zb_users/upload/2023/02/20230210092856_68763.jpeg'}
+                  />
+                </Badge>
+              </Grid>
+              
+              <Grid item xs={12} sm>
+                <Box sx={{ display: 'flex', justifyContent: 'space-between', flexDirection: isMobile ? 'column' : 'row' }}>
+                  <Box>
+                    <Typography variant="h5" fontWeight="bold">
+                      {profileUser.username}
+                    </Typography>
+                    <Typography variant="subtitle1" sx={{ mt: 0.5, maxWidth: 600 }}>
+                      {profileUser.bio || '这个人很懒,还没有写简介~'}
+                    </Typography>
+                    <Box sx={{ display: 'flex', mt: 1, gap: 1, flexWrap: 'wrap' }}>
+                      <Chip 
+                        icon={<LocationOn fontSize="small" />} 
+                        label={formData.location}
+                        size="small" 
+                        variant="outlined" 
+                      />
+                      <Chip 
+                        icon={<Cake fontSize="small" />} 
+                        label={formData.birthday}
+                        size="small" 
+                        variant="outlined" 
+                      />
+                      <Chip 
+                        icon={<Female fontSize="small" />} 
+                        label={formData.gender}
+                        size="small" 
+                        variant="outlined" 
+                      />
+                    </Box>
+                  </Box>
+                  
+                  <Box sx={{ mt: isMobile ? 2 : 0, alignSelf: 'flex-start' }}>
+                    {!isOwnProfile && currentUser && (
+                      <>
+                        <Button
+                          variant={profileUser.is_following ? "outlined" : "contained"}
+                          color="primary"
+                          onClick={handleFollowToggle}
+                          sx={{ 
+                            borderRadius: 20, 
+                            px: 3, 
+                            fontWeight: 'bold' 
+                          }}
+                        >
+                          {profileUser.is_following ? '已关注' : '关注'}
+                        </Button>
+                        <IconButton sx={{ ml: 1 }}>
+                          <MoreVert />
+                        </IconButton>
+                      </>
+                    )}
+                  </Box>
+                </Box>
+                
+                <Grid container spacing={2} sx={{ mt: 2 }}>
+                  <Grid item>
+                    <Box textAlign="center">
+                      <Typography variant="h6">{posts.length}</Typography>
+                      <Typography variant="body2" color="textSecondary">笔记</Typography>
+                    </Box>
+                  </Grid>
+                  <Grid item>
+                    <Box textAlign="center">
+                      <Typography variant="h6">{profileUser.followers_count || 0}</Typography>
+                      <Typography variant="body2" color="textSecondary">粉丝</Typography>
+                    </Box>
+                  </Grid>
+                  <Grid item>
+                    <Box textAlign="center">
+                      <Typography variant="h6">{profileUser.following_count || 0}</Typography>
+                      <Typography variant="body2" color="textSecondary">关注</Typography>
+                    </Box>
+                  </Grid>
+                  <Grid item>
+                    <Box textAlign="center">
+                      {/* 使用真实数据:获赞与收藏总数 */}
+                      <Typography variant="h6">
+                        {(interactions.likes_count + interactions.favorites_count).toLocaleString()}
+                      </Typography>
+                      <Typography variant="body2" color="textSecondary">获赞与收藏</Typography>
+                    </Box>
+                  </Grid>
+                </Grid>
+              </Grid>
+            </Grid>
+          </Box>
+
+          {/* 标签栏 */}
+          <Box sx={{ mt: 4 }}>
+            <Tabs 
+              value={activeTab} 
+              onChange={handleTabChange}
+              variant={isMobile ? "fullWidth" : "standard"}
+              indicatorColor="primary"
+              textColor="primary"
+              sx={{
+                borderBottom: 1,
+                borderColor: 'divider'
+              }}
+            >
+              <Tab icon={isMobile ? <Collections /> : null} label="笔记" />
+              <Tab icon={isMobile ? <Bookmark /> : null} label="收藏" />
+              <Tab icon={isMobile ? <Group /> : null} label="关注" />
+              <Tab icon={isMobile ? <People /> : null} label="粉丝" />
+            </Tabs>
+          </Box>
+
+          {/* 内容区域 */}
+          <Box sx={{ mt: 3 }}>
+            {activeTab === 0 && (
+              <Grid container spacing={3}>
+                {tabLoading ? (
+                  <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
+                    <CircularProgress />
+                  </Grid>
+                ) : posts.length > 0 ? (
+                  posts.map((post, index) => (
+                    <Grid item xs={12} sm={6} lg={3} key={post.id}>
+                      <Card elevation={0} sx={{ 
+                        bgcolor: 'white', 
+                        borderRadius: 3,
+                        height: '100%',
+                        display: 'flex',
+                        flexDirection: 'column'
+                      }}>
+                        <CardMedia
+                          component="img"
+                          height="180"
+                          image={`https://source.unsplash.com/random/400x300?${index + 1}`}
+                          alt={post.title}
+                        />
+                        <CardContent sx={{ flexGrow: 1 }}>
+                          <Typography gutterBottom variant="h6" component="div">
+                            {post.title}
+                          </Typography>
+                          <Typography variant="body2" color="text.secondary">
+                            {post.content.substring(0, 60)}...
+                          </Typography>
+                        </CardContent>
+                        <CardActions sx={{ justifyContent: 'space-between', px: 2, pb: 2 }}>
+                          <Box>
+                            <IconButton aria-label="add to favorites">
+                              <Favorite />
+                              <Typography variant="body2" sx={{ ml: 1 }}>
+                                {post.heat || Math.floor(Math.random() * 1000) + 1000}
+                              </Typography>
+                            </IconButton>
+                            <IconButton aria-label="share">
+                              <Share />
+                            </IconButton>
+                          </Box>
+                          <Chip 
+                            label={post.type === 'image' ? '图文' : post.type === 'video' ? '视频' : '文档'} 
+                            size="small" 
+                            color="primary" 
+                            variant="outlined" 
+                          />
+                        </CardActions>
+                      </Card>
+                    </Grid>
+                  ))
+                ) : (
+                  <Grid item xs={12}>
+                    <Box sx={{ 
+                      display: 'flex', 
+                      flexDirection: 'column', 
+                      alignItems: 'center', 
+                      py: 8,
+                      textAlign: 'center'
+                    }}>
+                      <Collections sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
+                      <Typography variant="h6" sx={{ mb: 1 }}>
+                        还没有发布笔记
+                      </Typography>
+                      <Typography variant="body1" color="textSecondary" sx={{ mb: 3 }}>
+                        {isOwnProfile ? '分享你的生活点滴吧~' : '该用户还没有发布任何笔记'}
+                      </Typography>
+                      {isOwnProfile && (
+                        <Button variant="contained" color="primary">
+                          发布第一篇笔记
+                        </Button>
+                      )}
+                    </Box>
+                  </Grid>
+                )}
+                
+                {posts.length > 0 && (
+                  <Grid item xs={12}>
+                    <Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
+                      <Button 
+                        variant="outlined" 
+                        sx={{ 
+                          borderRadius: 20, 
+                          px: 4,
+                          display: 'flex',
+                          alignItems: 'center'
+                        }}
+                      >
+                        <ChevronLeft sx={{ mr: 1 }} />
+                        上一页
+                        <ChevronRight sx={{ ml: 2 }} />
+                      </Button>
+                    </Box>
+                  </Grid>
+                )}
+              </Grid>
+            )}
+            
+            {activeTab === 1 && (
+              <Grid container spacing={3}>
+                {tabLoading ? (
+                  <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
+                    <CircularProgress />
+                  </Grid>
+                ) : favorites.length > 0 ? (
+                  favorites.map((favorite) => (
+                    <Grid item xs={12} sm={6} md={4} lg={3} key={favorite.id}>
+                      <Card elevation={0} sx={{ 
+                        bgcolor: 'white', 
+                        borderRadius: 3,
+                        transition: 'transform 0.3s, box-shadow 0.3s',
+                        '&:hover': {
+                          transform: 'translateY(-5px)',
+                          boxShadow: 3
+                        }
+                      }}>
+                        <Box sx={{ 
+                          height: 160, 
+                          position: 'relative',
+                          borderTopLeftRadius: 16,
+                          borderTopRightRadius: 16,
+                          overflow: 'hidden'
+                        }}>
+                          <CardMedia
+                            component="img"
+                            height="160"
+                            image={`https://source.unsplash.com/random/400x300?${favorite.id}`}
+                            alt={favorite.title}
+                          />
+                          <Box sx={{
+                            position: 'absolute',
+                            top: 8,
+                            right: 8,
+                            bgcolor: 'rgba(0,0,0,0.6)',
+                            color: 'white',
+                            px: 1,
+                            py: 0.5,
+                            borderRadius: 4,
+                            fontSize: 12
+                          }}>
+                            {favorite.type === 'image' ? '图文' : favorite.type === 'video' ? '视频' : '文档'}
+                          </Box>
+                        </Box>
+                        <CardContent>
+                          <Typography gutterBottom variant="subtitle1" fontWeight="medium">
+                            {favorite.title}
+                          </Typography>
+                          <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
+                            <Box sx={{ display: 'flex', alignItems: 'center' }}>
+                              <Favorite fontSize="small" color="error" />
+                              <Typography variant="body2" sx={{ ml: 0.5 }}>
+                                {favorite.heat || Math.floor(Math.random() * 1000) + 1000}
+                              </Typography>
+                            </Box>
+                            <Box sx={{ display: 'flex', alignItems: 'center' }}>
+                              <Bookmark fontSize="small" color="primary" />
+                              <Typography variant="body2" sx={{ ml: 0.5 }}>
+                                {Math.floor(Math.random() * 500) + 100}
+                              </Typography>
+                            </Box>
+                          </Box>
+                        </CardContent>
+                      </Card>
+                    </Grid>
+                  ))
+                ) : (
+                  <Grid item xs={12}>
+                    <Box sx={{ 
+                      display: 'flex', 
+                      flexDirection: 'column', 
+                      alignItems: 'center', 
+                      py: 8,
+                      textAlign: 'center'
+                    }}>
+                      <Bookmark sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
+                      <Typography variant="h6" sx={{ mb: 1 }}>
+                        {isOwnProfile ? '你还没有收藏内容' : '该用户没有收藏内容'}
+                      </Typography>
+                      <Typography variant="body1" color="textSecondary">
+                        {isOwnProfile ? '看到喜欢的笔记可以收藏起来哦~' : ''}
+                      </Typography>
+                    </Box>
+                  </Grid>
+                )}
+              </Grid>
+            )}
+            
+            {activeTab === 2 && (
+              <Grid container spacing={3}>
+                {tabLoading ? (
+                  <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
+                    <CircularProgress />
+                  </Grid>
+                ) : following.length > 0 ? (
+                  following.map((follow) => (
+                    <Grid item xs={12} sm={6} md={4} key={follow.id}>
+                      <Paper 
+                        elevation={0} 
+                        sx={{ 
+                          bgcolor: 'white', 
+                          borderRadius: 3,
+                          p: 2,
+                          display: 'flex',
+                          alignItems: 'center',
+                          cursor: 'pointer',
+                          '&:hover': {
+                            boxShadow: 1
+                          }
+                        }}
+                        onClick={() => navigateToUserProfile(follow.id)}
+                      >
+                        <Avatar 
+                          src={follow.avatar || 'https://randomuser.me/api/portraits/men/22.jpg'} 
+                          sx={{ width: 60, height: 60 }} 
+                        />
+                        <Box sx={{ ml: 2, flexGrow: 1 }}>
+                          <Typography fontWeight="medium">{follow.username}</Typography>
+                          <Typography variant="body2" color="textSecondary">
+                            {follow.followers_count || Math.floor(Math.random() * 100) + 10} 粉丝
+                          </Typography>
+                        </Box>
+                        {isOwnProfile && (
+                          <Button 
+                            variant="outlined" 
+                            size="small"
+                            sx={{ borderRadius: 20 }}
+                            onClick={(e) => handleUnfollow(follow.id, e)}
+                          >
+                            已关注
+                          </Button>
+                        )}
+                      </Paper>
+                    </Grid>
+                  ))
+                ) : (
+                  <Grid item xs={12}>
+                    <Box sx={{ 
+                      display: 'flex', 
+                      flexDirection: 'column', 
+                      alignItems: 'center', 
+                      py: 8,
+                      textAlign: 'center'
+                    }}>
+                      <Group sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
+                      <Typography variant="h6" sx={{ mb: 1 }}>
+                        {isOwnProfile ? '你还没有关注任何人' : '该用户还没有关注任何人'}
+                      </Typography>
+                      <Typography variant="body1" color="textSecondary">
+                        {isOwnProfile ? '发现有趣的人并关注他们吧~' : ''}
+                      </Typography>
+                    </Box>
+                  </Grid>
+                )}
+              </Grid>
+            )}
+            {activeTab === 3 && (
+              <Grid container spacing={3}>
+                {tabLoading ? (
+                  <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
+                    <CircularProgress />
+                  </Grid>
+                ) : followers.length > 0 ? (
+                  followers.map((follower) => (
+                    <Grid item xs={12} sm={6} md={4} key={follower.id}>
+                      <Paper 
+                        elevation={0} 
+                        sx={{ 
+                          bgcolor: 'white', 
+                          borderRadius: 3,
+                          p: 2,
+                          display: 'flex',
+                          alignItems: 'center',
+                          cursor: 'pointer',
+                          '&:hover': {
+                            boxShadow: 1
+                          }
+                        }}
+                        onClick={() => navigateToUserProfile(follower.id)}
+                      >
+                        <Avatar 
+                          src={follower.avatar || 'https://randomuser.me/api/portraits/men/22.jpg'} 
+                          sx={{ width: 60, height: 60 }} 
+                        />
+                        <Box sx={{ ml: 2, flexGrow: 1 }}>
+                          <Typography fontWeight="medium">{follower.username}</Typography>
+                          <Typography variant="body2" color="textSecondary">
+                            {follower.bio || '暂无简介'}
+                          </Typography>
+                        </Box>
+                        {currentUser && currentUser.id !== follower.id && (
+                          <Button 
+                            variant={follower.is_following ? "outlined" : "contained"}
+                            color="primary"
+                            size="small"
+                            sx={{ borderRadius: 20 }}
+                            onClick={(e) => {
+                              e.stopPropagation();
+                              if (follower.is_following) {
+                                handleUnfollow(follower.id, e);
+                              } else {
+                                handleFollowUser(follower.id);
+                              }
+                            }}
+                          >
+                            {follower.is_following ? '已关注' : '关注'}
+                          </Button>
+                        )}
+                      </Paper>
+                    </Grid>
+                  ))
+                ) : (
+                  <Grid item xs={12}>
+                    <Box sx={{ 
+                      display: 'flex', 
+                      flexDirection: 'column', 
+                      alignItems: 'center', 
+                      py: 8,
+                      textAlign: 'center'
+                    }}>
+                      <People sx={{ fontSize: 60, color: 'grey.300', mb: 2 }} />
+                      <Typography variant="h6" sx={{ mb: 1 }}>
+                        {isOwnProfile ? '你还没有粉丝' : '该用户还没有粉丝'}
+                      </Typography>
+                      <Typography variant="body1" color="textSecondary">
+                        {isOwnProfile ? '分享更多内容来吸引粉丝吧~' : ''}
+                      </Typography>
+                    </Box>
+                  </Grid>
+                )}
+              </Grid>
+            )}
+          </Box>
+        </Container>
+
+        {/* 底部导航栏 - 仅移动端显示 */}
+        {isMobile && (
+          <Box sx={{
+            position: 'fixed',
+            bottom: 0,
+            left: 0,
+            right: 0,
+            bgcolor: 'white',
+            boxShadow: 3,
+            py: 1,
+            display: 'flex',
+            justifyContent: 'space-around'
+          }}>
+            <IconButton color="primary">
+              <Search fontSize="large" />
+            </IconButton>
+            <IconButton>
+              <Collections fontSize="large" />
+            </IconButton>
+            <Fab color="primary" size="medium" sx={{ mt: -2 }}>
+              <Add />
+            </Fab>
+            <IconButton>
+              <Notifications fontSize="large" />
+            </IconButton>
+            <IconButton>
+              <Person fontSize="large" />
+            </IconButton>
+          </Box>
+        )}
+
+        {/* 编辑资料模态框 */}
+        {isEditing && (
+          <Box sx={{
+            position: 'fixed',
+            top: 0,
+            left: 0,
+            right: 0,
+            bottom: 0,
+            bgcolor: 'rgba(0,0,0,0.5)',
+            zIndex: 1300,
+            display: 'flex',
+            alignItems: 'center',
+            justifyContent: 'center',
+            px: 2
+          }}>
+            <Paper sx={{ 
+              width: '100%', 
+              maxWidth: 600, 
+              borderRadius: 4,
+              overflow: 'hidden'
+            }}>
+              <Box sx={{ 
+                bgcolor: 'primary.main', 
+                color: 'white', 
+                p: 2,
+                display: 'flex',
+                justifyContent: 'space-between',
+                alignItems: 'center'
+              }}>
+                <Typography variant="h6">编辑资料</Typography>
+                <IconButton color="inherit" onClick={() => setIsEditing(false)}>
+                  <Close />
+                </IconButton>
+              </Box>
+              
+              <Box sx={{ p: 3 }}>
+                <Box sx={{ display: 'flex', justifyContent: 'center', mb: 3 }}>
+                  <Badge
+                    overlap="circular"
+                    anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
+                    badgeContent={
+                      <IconButton 
+                        size="small" 
+                        sx={{ 
+                          bgcolor: 'grey.200',
+                          '&:hover': { bgcolor: 'grey.300' }
+                        }}
+                      >
+                        <CameraAlt fontSize="small" />
+                      </IconButton>
+                    }
+                  >
+                    <Avatar
+                      sx={{ width: 100, height: 100 }}
+                      src={formData.avatar || 'https://www.8848seo.cn/zb_users/upload/2023/02/20230210092856_68763.jpeg'}
+                    />
+                  </Badge>
+                </Box>
+                
+                <TextField
+                  fullWidth
+                  label="用户名"
+                  value={profileUser.username}
+                  margin="normal"
+                  disabled
+                />
+                
+                <TextField
+                  fullWidth
+                  name="avatar"
+                  label="头像URL"
+                  value={formData.avatar}
+                  onChange={handleFormChange}
+                  margin="normal"
+                />
+                
+                <TextField
+                  fullWidth
+                  name="bio"
+                  label="个人简介"
+                  value={formData.bio}
+                  onChange={handleFormChange}
+                  margin="normal"
+                  multiline
+                  rows={3}
+                />
+                
+                <Grid container spacing={2} sx={{ mt: 1 }}>
+                  <Grid item xs={6}>
+                    <TextField
+                      select
+                      fullWidth
+                      name="gender"
+                      label="性别"
+                      value={formData.gender}
+                      onChange={handleFormChange}
+                      margin="normal"
+                    >
+                      <MenuItem value="female">
+                        <Box sx={{ display: 'flex', alignItems: 'center' }}>
+                          <Female sx={{ mr: 1 }} /> 女
+                        </Box>
+                      </MenuItem>
+                      <MenuItem value="male">
+                        <Box sx={{ display: 'flex', alignItems: 'center' }}>
+                          <Male sx={{ mr: 1 }} /> 男
+                        </Box>
+                      </MenuItem>
+                      <MenuItem value="other">
+                        <Box sx={{ display: 'flex', alignItems: 'center' }}>
+                          <Public sx={{ mr: 1 }} /> 其他
+                        </Box>
+                      </MenuItem>
+                    </TextField>
+                  </Grid>
+                  <Grid item xs={6}>
+                    <TextField
+                      fullWidth
+                      name="birthday"
+                      label="生日"
+                      type="date"
+                      value={formData.birthday}
+                      onChange={handleFormChange}
+                      margin="normal"
+                      InputLabelProps={{ shrink: true }}
+                    />
+                  </Grid>
+                </Grid>
+                
+                <TextField
+                  fullWidth
+                  name="location"
+                  label="地区"
+                  value={formData.location}
+                  onChange={handleFormChange}
+                  margin="normal"
+                  InputProps={{
+                    startAdornment: (
+                      <InputAdornment position="start">
+                        <LocationOn />
+                      </InputAdornment>
+                    ),
+                  }}
+                />
+                
+                <Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 3 }}>
+                  <Button 
+                    variant="outlined" 
+                    sx={{ width: '48%' }}
+                    onClick={() => setIsEditing(false)}
+                    disabled={updating}
+                  >
+                    取消
+                  </Button>
+                  <Button 
+                    variant="contained" 
+                    color="primary" 
+                    sx={{ width: '48%' }}
+                    onClick={handleUpdateProfile}
+                    disabled={updating}
+                  >
+                    {updating ? <CircularProgress size={24} /> : '保存'}
+                  </Button>
+                </Box>
+              </Box>
+            </Paper>
+          </Box>
+        )}
+
+        {/* 提示信息 */}
+        <Snackbar
+          open={snackbar.open}
+          autoHideDuration={3000}
+          onClose={() => setSnackbar({ ...snackbar, open: false })}
+          anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
+        >
+          <Alert 
+            severity={snackbar.severity} 
+            sx={{ width: '100%' }}
+            onClose={() => setSnackbar({ ...snackbar, open: false })}
+          >
+            {snackbar.message}
+          </Alert>
+        </Snackbar>
+      </Box>
+    </ThemeProvider>
+  );
+};
+
+export default UserProfile;
\ No newline at end of file
diff --git a/Merge/front/src/router/App.js b/Merge/front/src/router/App.js
index 4d606f9..3137fd8 100644
--- a/Merge/front/src/router/App.js
+++ b/Merge/front/src/router/App.js
@@ -14,6 +14,7 @@
 import PlaceholderPage from '../components/PlaceholderPage'// src/components/PlaceholderPage.jsx
 import UploadPage     from '../components/UploadPage'      // src/components/UploadPage.jsx
 
+import UserProfile from '../components/UserProfile'; // src/components/UserProfileRoute.jsx
 
 import LoginPage from '../pages/LoginPage/LoginPage';
 import RegisterPage from '../pages/RegisterPage/RegisterPage';
@@ -35,7 +36,7 @@
       <Route path="/notes"     element={<PlaceholderPage pageId="notes"     />} />
       <Route path="/creator"   element={<PlaceholderPage pageId="creator"   />} />
       <Route path="/journal"   element={<PlaceholderPage pageId="journal"   />} />
-
+      <Route path="/user/:userId" element={<UserProfile />} />
       <Route path="/dashboard/*" element={<UploadPage />} />
 
       {/* 根路径重定向到 dashboard */}