personal page

Change-Id: I893fc586bd501f1067844ca4812be740aa8ed4ec
diff --git a/xiaohongshu-upload-platform/src/ljc/back_end/app.py b/xiaohongshu-upload-platform/src/ljc/back_end/app.py
new file mode 100644
index 0000000..cb62a4d
--- /dev/null
+++ b/xiaohongshu-upload-platform/src/ljc/back_end/app.py
@@ -0,0 +1,460 @@
+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='更新时间')
+    
+    # 关系定义
+    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
+    })
+
+# 更新用户信息
+@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
+    if 'avatar' in data:
+        user.avatar = data['avatar']
+    if 'bio' in data:
+        user.bio = data['bio']
+    
+    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)
\ No newline at end of file