匿名论坛技术文档

一、项目概述

1.1 项目简介

匿名论坛是一个支持用户注册登录和匿名发帖的社区平台,提供帖子发布、回复、点赞、收藏、私信、通知等完整社交功能,并配备管理后台进行内容审核和用户管理。

1.2 核心特性

  • 双模式身份:支持注册用户和匿名访客
  • 完整社交功能:发帖、回复、点赞、收藏、私信
  • 楼中楼回复:支持嵌套回复和@提及
  • 实时通知:新回复、点赞通知
  • 管理后台:用户/内容管理、操作日志
  • 安全防护:XSS过滤、速率限制、敏感词过滤

二、技术栈详解

2.1 前端技术栈

技术版本用途
React18.3.1核心框架,函数组件 + Hooks
TypeScript类型安全
React Router DOMlatest客户端路由,SPA 导航
Vite6.3.5构建工具,HMR 热更新
Tailwind CSS原子化 CSS 框架
Radix UI多个组件无障碍 UI 原语组件
Axios1.13.2HTTP 客户端
Sonner2.0.3Toast 通知
Lucide React0.487.0图标库
React MarkdownlatestMarkdown 渲染
React Syntax Highlighterlatest代码高亮
date-fnslatest日期处理
next-themes0.4.6主题切换(明/暗)

2.2 后端技术栈

技术版本用途
Node.js运行时环境
Express.js4.18.2Web 框架
TypeScript5.3.3类型安全
MySQL23.6.5数据库驱动(Promise API)
bcryptjs3.0.3密码加密(bcrypt 算法)
UUID9.0.1唯一标识符生成
Helmet7.1.0HTTP 安全头
CORS2.8.5跨域资源共享
express-rate-limit7.1.5速率限制
express-validator7.0.1请求参数验证
XSS1.0.14XSS 过滤
Multer1.4.5-lts.1文件上传
Sharp0.33.1图片压缩优化
Winston3.11.0日志框架
winston-daily-rotate-file4.7.1日志轮转
Compression1.7.4Gzip 压缩

2.3 数据库

技术版本配置
MySQL8.xInnoDB 引擎
字符集utf8mb4支持 emoji
排序规则utf8mb4_unicode_ciUnicode 排序
连接池20 连接mysql2 连接池

2.4 部署环境

组件配置
服务器腾讯云 CVM (101.32.242.75)
操作系统Linux
Web 服务器Nginx(反向代理 + 静态文件)
进程管理PM2
域名forum.zcc609.online
前端路径/home/anonymous-forum/frontend
后端路径/home/anonymous-forum/backend
后端端口3001

三、项目结构详解

3.1 完整目录结构

匿名论坛/
├── .env.development              # 开发环境变量
├── .env.production               # 生产环境变量
├── .gitignore                    # Git 忽略规则
├── index.html                    # 入口 HTML
├── package.json                  # 前端依赖
├── package-lock.json             # 依赖锁定
├── vite.config.ts                # Vite 配置
├── nginx-forum.conf              # Nginx 配置模板
├── deploy-to-server.sh           # 部署脚本
├── server-start.sh               # 服务启动脚本
├── 上传到服务器.sh                # 上传脚本
├── 部署文档.md                    # 部署说明
│
├── src/                          # 前端源码
│   ├── main.tsx                  # 应用入口
│   ├── App.tsx                   # 根组件 + 路由配置
│   ├── index.css                 # Tailwind 样式
│   │
│   ├── components/               # 通用组件 (25个)
│   │   ├── ForumHeader.tsx       # 顶部导航栏
│   │   ├── ForumSidebar.tsx      # 侧边栏(分类、热帖)
│   │   ├── MobileBottomNav.tsx   # 移动端底部导航
│   │   ├── MobileSidebar.tsx     # 移动端侧边栏
│   │   ├── PostCard.tsx          # 帖子卡片
│   │   ├── PostCardSkeleton.tsx  # 帖子骨架屏
│   │   ├── ReplyItem.tsx         # 回复项(支持楼中楼)
│   │   ├── CreatePostDialog.tsx  # 发帖对话框
│   │   ├── MarkdownEditor.tsx    # Markdown 编辑器
│   │   ├── EmojiPicker.tsx       # 表情选择器
│   │   ├── ImageUploader.tsx     # 图片上传组件
│   │   ├── ImageViewer.tsx       # 图片查看器
│   │   ├── ImageGallery.tsx      # 图片画廊
│   │   ├── NotificationDropdown.tsx  # 通知下拉
│   │   ├── MessageDropdown.tsx   # 消息下拉
│   │   ├── UserCard.tsx          # 用户信息卡片
│   │   ├── ThemeToggle.tsx       # 主题切换
│   │   ├── SortSelector.tsx      # 排序选择器
│   │   ├── EmptyState.tsx        # 空状态
│   │   ├── LoadMoreIndicator.tsx # 加载更多指示器
│   │   ├── ErrorBoundary.tsx     # 错误边界
│   │   ├── ProtectedRoute.tsx    # 路由守卫
│   │   └── KeyboardShortcutsDialog.tsx  # 快捷键帮助
│   │
│   ├── pages/                    # 页面组件 (15个)
│   │   ├── PostListPage.tsx      # 帖子列表(首页)
│   │   ├── PostDetailPage.tsx    # 帖子详情
│   │   ├── SearchResultPage.tsx  # 搜索结果
│   │   ├── LoginPage.tsx         # 登录页
│   │   ├── RegisterPage.tsx      # 注册页
│   │   ├── ProfilePage.tsx       # 个人资料
│   │   ├── MyPostsPage.tsx       # 我的帖子
│   │   ├── MyRepliesPage.tsx     # 我的回复
│   │   ├── MyFavoritesPage.tsx   # 我的收藏
│   │   ├── MyLikesPage.tsx       # 我的点赞
│   │   ├── DraftsPage.tsx        # 草稿箱
│   │   ├── Messages.tsx          # 私信列表
│   │   ├── MessageConversation.tsx  # 私信对话
│   │   ├── NotificationPage.tsx  # 通知页面
│   │   └── admin/                # 管理后台
│   │       ├── AdminDashboard.tsx    # 管理仪表盘
│   │       ├── AdminUsers.tsx        # 用户管理
│   │       ├── AdminPosts.tsx        # 帖子管理
│   │       └── AdminLogs.tsx         # 操作日志
│   │
│   ├── hooks/                    # 自定义 Hooks
│   │   ├── useInfiniteScroll.ts  # 无限滚动
│   │   └── useKeyboardShortcuts.ts  # 快捷键
│   │
│   ├── lib/                      # 工具库
│   │   ├── api.ts                # API 封装(帖子、回复、互动)
│   │   ├── apiClient.ts          # Axios 实例配置
│   │   ├── auth.ts               # 认证工具(登录状态管理)
│   │   ├── messageApi.ts         # 私信 API
│   │   ├── notificationApi.ts    # 通知 API
│   │   ├── storage.ts            # 本地存储工具
│   │   ├── constants.ts          # 常量定义
│   │   ├── utils.ts              # 通用工具函数
│   │   ├── portal.ts             # Portal 容器
│   │   └── mockData.ts           # 模拟数据(开发用)
│   │
│   ├── types/                    # 类型定义
│   │   ├── index.ts              # 业务类型(Post, Reply 等)
│   │   └── auth.ts               # 认证类型
│   │
│   └── styles/                   # 样式
│       └── globals.css           # 全局样式
│
├── backend/                      # 后端源码
│   ├── .env                      # 开发环境变量
│   ├── .env.production           # 生产环境变量
│   ├── package.json              # 后端依赖
│   ├── tsconfig.json             # TypeScript 配置
│   ├── backup-db.sh              # 数据库备份脚本
│   ├── repair-db.sh              # 数据库修复脚本
│   ├── reset-admin.sh            # 管理员密码重置
│   │
│   ├── src/
│   │   ├── index.ts              # 应用入口
│   │   │
│   │   ├── config/               # 配置
│   │   │   ├── database.ts       # 数据库连接池
│   │   │   └── logger.ts         # Winston 日志配置
│   │   │
│   │   ├── middleware/           # 中间件
│   │   │   ├── auth.ts           # 认证中间件
│   │   │   │   ├── authenticate()     # 强制登录验证
│   │   │   │   ├── optionalAuth()     # 可选登录验证
│   │   │   │   └── requireAdmin()     # 管理员权限验证
│   │   │   │
│   │   │   ├── security.ts       # 安全中间件
│   │   │   │   ├── sanitizeInput()    # XSS 过滤
│   │   │   │   ├── generalLimiter     # 通用速率限制
│   │   │   │   ├── createLimiter      # 创建内容限制
│   │   │   │   ├── uploadLimiter      # 上传限制
│   │   │   │   ├── filterSensitiveWords()  # 敏感词过滤
│   │   │   │   ├── logOperation()     # 操作日志
│   │   │   │   ├── validateId()       # ID 格式验证
│   │   │   │   └── errorHandler()     # 全局错误处理
│   │   │   │
│   │   │   └── validation.ts     # 参数验证
│   │   │       ├── validateCreatePost     # 创建帖子验证
│   │   │       ├── validateCreateReply    # 创建回复验证
│   │   │       ├── validateGetPosts       # 获取帖子验证
│   │   │       ├── validateSearch         # 搜索验证
│   │   │       ├── validateToggleLike     # 点赞验证
│   │   │       ├── validateSendMessage    # 私信验证
│   │   │       └── validateSaveDraft      # 草稿验证
│   │   │
│   │   ├── controllers/          # 控制器
│   │   │   ├── authController.ts      # 认证控制器
│   │   │   ├── postController.ts      # 帖子控制器
│   │   │   ├── replyController.ts     # 回复控制器
│   │   │   ├── userController.ts      # 用户控制器
│   │   │   ├── interactionController.ts  # 互动控制器
│   │   │   ├── uploadController.ts    # 上传控制器
│   │   │   └── adminController.ts     # 管理控制器
│   │   │
│   │   ├── routes/               # 路由
│   │   │   ├── index.ts          # 路由汇总
│   │   │   ├── auth.ts           # 认证路由
│   │   │   ├── posts.ts          # 帖子路由
│   │   │   ├── replies.ts        # 回复路由
│   │   │   ├── users.ts          # 用户路由
│   │   │   ├── interactions.ts   # 互动路由
│   │   │   ├── upload.ts         # 上传路由
│   │   │   └── admin.ts          # 管理路由
│   │   │
│   │   └── types/                # 类型定义
│   │       ├── auth.ts           # 认证类型
│   │       └── express.d.ts      # Express 类型扩展
│   │
│   ├── database/                 # SQL 脚本
│   │   ├── schema.sql            # 主表结构
│   │   ├── auth_migration.sql    # 认证相关表
│   │   ├── add_login_fields.sql  # 登录字段迁移
│   │   └── add_profile_fields.sql  # 个人资料字段
│   │
│   ├── dist/                     # 编译输出
│   ├── uploads/                  # 上传文件存储
│   └── logs/                     # 日志文件
│
├── build/                        # 前端构建产物
│   ├── index.html
│   └── assets/
│       ├── index-*.css
│       └── index-*.js
│
└── scripts/                      # 部署脚本
    ├── start-services.sh         # 启动服务
    └── stop-services.sh          # 停止服务

四、功能模块详解

4.1 用户认证模块

功能列表

功能接口说明
注册POST /api/auth/register用户名+密码+邮箱(可选)
登录POST /api/auth/login返回 Session Token
登出POST /api/auth/logout删除会话
获取当前用户GET /api/auth/me返回用户信息
修改密码POST /api/auth/change-password需验证旧密码
匿名模式POST /api/auth/anonymous生成临时匿名ID

认证流程

1. 用户注册
   ├── 验证用户名长度(3-20)、密码长度(>=6)
   ├── 检查用户名/邮箱唯一性
   ├── bcrypt 加密密码 (cost=10)
   ├── 生成 UUID 用户ID
   ├── 生成匿名昵称 "用户_${username}"
   ├── 插入 users 表
   ├── 创建 session (30天有效期)
   └── 返回 token + 用户信息

2. 用户登录
   ├── 查询用户
   ├── 检查账号激活状态
   ├── bcrypt 比对密码
   ├── 更新登录信息 (login_count, last_login_at, last_login_ip)
   ├── 创建新 session
   └── 返回 token + 用户信息

3. 请求鉴权 (authenticate 中间件)
   ├── 从 Authorization Header 提取 Bearer Token
   ├── 查询 sessions 表 (JOIN users)
   ├── 验证 token 有效性和过期时间
   ├── 检查账号激活状态
   ├── 注入 req.user, req.userId, req.anonymousName
   └── 调用 next()

Session 表结构

sql

CREATE TABLE sessions (
    id VARCHAR(36) PRIMARY KEY,
    user_id VARCHAR(36) NOT NULL,
    token VARCHAR(255) NOT NULL UNIQUE,
    expires_at TIMESTAMP NOT NULL,
    user_agent VARCHAR(500),
    ip_address VARCHAR(45),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

4.2 帖子模块

功能列表

功能接口说明
获取帖子列表GET /api/posts支持分类、排序、分页
获取帖子详情GET /api/posts/:id自动增加浏览量
创建帖子POST /api/posts需登录
删除帖子DELETE /api/posts/:id作者或管理员
搜索帖子GET /api/posts/search全文搜索
热门帖子GET /api/posts/hot按热度算法排序
我的帖子GET /api/posts/user/my-posts当前用户的帖子

帖子分类

typescript

type PostCategory = 'tech' | 'life' | 'help' | 'other';

// 分类映射
const CATEGORIES = {
  tech: '技术交流',
  life: '生活杂谈',
  help: '求助问答',
  other: '其他'
};

排序方式

typescript

type SortType = 'latest' | 'most_replies' | 'recent_reply';

// 排序 SQL
switch (sort) {
  case 'most_replies':
    ORDER BY reply_count DESC, created_at DESC
  case 'recent_reply':
    ORDER BY COALESCE(last_reply_at, created_at) DESC
  case 'latest':
  default:
    ORDER BY created_at DESC
}

热度算法

sql

hot_score = reply_count * 0.7 + like_count * 0.3
-- 取最近 24 小时内的帖子,按 hot_score 降序

4.3 回复模块

功能列表

功能接口说明
获取回复列表GET /api/replies/post/:postId按时间升序
创建回复POST /api/replies/post/:postId支持楼中楼
删除回复DELETE /api/replies/:id作者或管理员
我的回复GET /api/replies/user/my-replies包含帖子信息

楼中楼回复

typescript

interface Reply {
  id: string;
  post_id: string;
  user_id: string;
  content: string;
  parent_reply_id: string | null;    // 父回复ID
  parent_floor_number: number | null; // 父回复楼层
  parent_username: string | null;     // 被回复用户名
  created_at: Date;
}

回复通知逻辑

创建回复时:
├── 如果是楼中楼 (有 parent_reply_id)
│   └── 给被回复用户发送通知
└── 如果是直接回复
    └── 给帖子作者发送通知

通知内容: "${回复者匿名名} 回复了你的${帖子/评论}"

4.4 互动模块

功能列表

功能接口说明
点赞/取消点赞POST /api/interactions/like/:idtype: post/reply
收藏/取消收藏POST /api/interactions/favorite/:postId帖子收藏
获取收藏列表GET /api/interactions/favorites当前用户
获取点赞帖子GET /api/interactions/liked-posts当前用户
获取获赞数GET /api/interactions/user-likes收到的总赞数
发送私信POST /api/interactions/messages用户间私信
获取对话列表GET /api/interactions/conversations私信会话
获取对话详情GET /api/interactions/conversation/:userId与某用户的对话
未读消息数GET /api/interactions/unread-count未读私信数

点赞逻辑

点赞切换:
├── 查询是否已点赞
├── 如果已点赞
│   ├── 删除 likes 记录
│   └── 更新 posts.like_count - 1
└── 如果未点赞
    ├── 插入 likes 记录
    ├── 更新 posts.like_count + 1
    └── 发送点赞通知给作者

4.5 通知模块

通知类型

sql

type ENUM('new_reply', 'like', 'system')

类型触发场景
new_reply帖子/回复被回复
like帖子/回复被点赞
system系统通知

通知表结构

sql

CREATE TABLE notifications (
    id VARCHAR(36) PRIMARY KEY,
    user_id VARCHAR(36) NOT NULL,
    type ENUM('new_reply', 'like', 'system') NOT NULL,
    title VARCHAR(100) NOT NULL,
    content VARCHAR(500) NOT NULL,
    post_id VARCHAR(36) NULL,        -- 关联帖子(可点击跳转)
    is_read TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

4.6 管理后台模块

功能列表

功能接口说明
获取用户列表GET /api/admin/users分页、搜索
启用/禁用用户PATCH /api/admin/users/:userId/status切换激活状态
删除用户DELETE /api/admin/users/:userId不能删除管理员
获取帖子列表GET /api/admin/posts分页、搜索、分类
删除帖子DELETE /api/admin/posts/:postId管理员删除
删除回复DELETE /api/admin/replies/:replyId管理员删除
获取操作日志GET /api/admin/logs管理员操作记录

操作日志记录

typescript

// 记录的操作类型
type AdminAction = 
  | 'enable_user'    // 启用用户
  | 'disable_user'   // 禁用用户
  | 'delete_user'    // 删除用户
  | 'delete_post'    // 删除帖子
  | 'delete_reply';  // 删除回复

// 日志表结构
CREATE TABLE admin_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    admin_id VARCHAR(36) NOT NULL,
    action VARCHAR(50) NOT NULL,
    target_type VARCHAR(50),        -- user/post/reply
    target_id VARCHAR(36),
    description TEXT,
    ip_address VARCHAR(45),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

4.7 文件上传模块

功能列表

功能接口说明
单图上传POST /api/upload/image返回图片 URL
多图上传POST /api/upload/images批量上传

图片处理

typescript

// 使用 Sharp 进行图片优化
const processImage = async (file) => {
  return sharp(file.buffer)
    .resize(1920, 1080, { fit: 'inside', withoutEnlargement: true })
    .jpeg({ quality: 80 })
    .toBuffer();
};

// 文件命名: optimized_${uuid}.${ext}
// 存储路径: backend/uploads/
// 访问路径: /uploads/optimized_xxx.jpg

五、数据库设计

5.1 ER 图(文字描述)

                            ┌──────────────┐
                            │    users     │
                            │──────────────│
                            │ id (PK)      │
                            │ username     │
                            │ password_hash│
                            │ email        │
                            │ anonymous_name│
                            │ role         │
                            │ is_active    │
                            └──────┬───────┘
                                   │
       ┌───────────────────────────┼───────────────────────────┐
       │                           │                           │
       ▼                           ▼                           ▼
┌──────────────┐            ┌──────────────┐            ┌──────────────┐
│    posts     │            │   sessions   │            │ admin_logs   │
│──────────────│            │──────────────│            │──────────────│
│ id (PK)      │            │ id (PK)      │            │ id (PK)      │
│ user_id (FK) │◄───────────│ user_id (FK) │            │ admin_id (FK)│
│ title        │            │ token        │            │ action       │
│ content      │            │ expires_at   │            │ target_type  │
│ category     │            └──────────────┘            │ description  │
│ reply_count  │                                        └──────────────┘
│ like_count   │
│ view_count   │
└──────┬───────┘
       │
       ├───────────────────────────┬───────────────────────────┐
       │                           │                           │
       ▼                           ▼                           ▼
┌──────────────┐            ┌──────────────┐            ┌──────────────┐
│   replies    │            │  favorites   │            │    images    │
│──────────────│            │──────────────│            │──────────────│
│ id (PK)      │            │ id (PK)      │            │ id (PK)      │
│ post_id (FK) │            │ user_id (FK) │            │ related_type │
│ user_id (FK) │            │ post_id (FK) │            │ related_id   │
│ content      │            └──────────────┘            │ url          │
│ parent_reply_id│                                      └──────────────┘
└──────┬───────┘
       │
       ▼
┌──────────────┐            ┌──────────────┐            ┌──────────────┐
│    likes     │            │  messages    │            │ notifications│
│──────────────│            │──────────────│            │──────────────│
│ id (PK)      │            │ id (PK)      │            │ id (PK)      │
│ user_id (FK) │            │ from_user_id │            │ user_id (FK) │
│ target_type  │            │ to_user_id   │            │ type         │
│ target_id    │            │ content      │            │ title        │
└──────────────┘            │ is_read      │            │ post_id      │
                            └──────────────┘            │ is_read      │
                                                        └──────────────┘

5.2 核心表详细设计

users 表

sql

CREATE TABLE users (
    id VARCHAR(36) PRIMARY KEY,              -- UUID
    username VARCHAR(50) UNIQUE,             -- 用户名(可为空,匿名用户)
    password_hash VARCHAR(255),              -- bcrypt 加密密码
    email VARCHAR(100) UNIQUE,               -- 邮箱
    phone VARCHAR(20),                       -- 手机号
    avatar VARCHAR(500),                     -- 头像 URL
    anonymous_name VARCHAR(50) NOT NULL,     -- 显示名称
    role ENUM('user', 'admin') DEFAULT 'user',
    is_active BOOLEAN DEFAULT TRUE,          -- 账号状态
    login_count INT DEFAULT 0,               -- 登录次数
    last_login_at TIMESTAMP,                 -- 最后登录时间
    last_login_ip VARCHAR(45),               -- 最后登录 IP
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_username (username),
    INDEX idx_email (email),
    INDEX idx_role (role)
);

posts 表

sql

CREATE TABLE posts (
    id VARCHAR(36) PRIMARY KEY,
    title VARCHAR(200) NOT NULL,
    content TEXT NOT NULL,
    category ENUM('tech', 'life', 'help', 'other') NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    anonymous_name VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    reply_count INT DEFAULT 0,               -- 冗余字段,提升查询性能
    like_count INT DEFAULT 0,                -- 冗余字段
    view_count INT DEFAULT 0,
    last_reply_at TIMESTAMP NULL,            -- 最后回复时间
    is_deleted TINYINT(1) DEFAULT 0,         -- 软删除
    
    INDEX idx_user_id (user_id),
    INDEX idx_category (category),
    INDEX idx_created_at (created_at),
    INDEX idx_last_reply_at (last_reply_at),
    FULLTEXT INDEX idx_search (title, content)  -- 全文索引
);

replies 表

sql

CREATE TABLE replies (
    id VARCHAR(36) PRIMARY KEY,
    post_id VARCHAR(36) NOT NULL,
    user_id VARCHAR(36) NOT NULL,
    anonymous_name VARCHAR(50) NOT NULL,
    content TEXT NOT NULL,
    parent_reply_id VARCHAR(36) NULL,        -- 楼中楼父回复
    parent_floor_number INT NULL,            -- 父回复楼层号
    parent_username VARCHAR(50) NULL,        -- 被回复用户名
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    like_count INT DEFAULT 0,
    is_deleted TINYINT(1) DEFAULT 0,
    
    INDEX idx_post_id (post_id),
    INDEX idx_user_id (user_id),
    INDEX idx_parent_reply_id (parent_reply_id),
    FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE
);

sessions 表

sql

CREATE TABLE sessions (
    id VARCHAR(36) PRIMARY KEY,
    user_id VARCHAR(36) NOT NULL,
    token VARCHAR(255) NOT NULL UNIQUE,
    expires_at TIMESTAMP NOT NULL,
    user_agent VARCHAR(500),
    ip_address VARCHAR(45),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_token (token),
    INDEX idx_user_id (user_id),
    INDEX idx_expires_at (expires_at),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

六、API 接口详解

6.1 认证接口

POST /api/auth/register
Request:
{
  "username": "testuser",
  "password": "123456",
  "email": "test@example.com"  // 可选
}
Response:
{
  "success": true,
  "message": "注册成功",
  "user": { id, username, email, anonymous_name, role, is_active, created_at },
  "token": "uuid_timestamp_random"
}

POST /api/auth/login
Request:
{
  "username": "testuser",
  "password": "123456"
}
Response:
{
  "success": true,
  "message": "登录成功",
  "user": { ... },
  "token": "..."
}

POST /api/auth/logout
Headers: Authorization: Bearer <token>
Response:
{
  "success": true,
  "message": "登出成功"
}

GET /api/auth/me
Headers: Authorization: Bearer <token>
Response:
{
  "success": true,
  "user": { ... }
}

POST /api/auth/change-password
Headers: Authorization: Bearer <token>
Request:
{
  "currentPassword": "oldpass",
  "newPassword": "newpass"
}
Response:
{
  "success": true,
  "message": "密码修改成功"
}

6.2 帖子接口

GET /api/posts?category=tech&sort=latest&page=1&limit=20
Response:
{
  "posts": [
    {
      "id": "uuid",
      "title": "帖子标题",
      "content": "帖子内容",
      "category": "tech",
      "user_id": "uuid",
      "anonymous_name": "用户_xxx",
      "user_avatar": null,
      "created_at": "2025-01-01T00:00:00.000Z",
      "reply_count": 5,
      "like_count": 10,
      "view_count": 100,
      "is_liked": false,
      "is_favorited": true,
      "images": ["url1", "url2"]
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 100,
    "totalPages": 5
  }
}

GET /api/posts/:id
Response:
{
  "id": "uuid",
  "title": "...",
  "content": "...",
  ...
}

POST /api/posts
Headers: Authorization: Bearer <token>
Request:
{
  "title": "帖子标题",
  "content": "帖子内容",
  "category": "tech",
  "images": ["url1", "url2"]
}
Response:
{
  "id": "uuid",
  "title": "...",
  ...
}

DELETE /api/posts/:id
Headers: Authorization: Bearer <token>
Response:
{
  "message": "删除成功"
}

GET /api/posts/search?q=关键词&page=1&limit=20
Response:
{
  "posts": [...]
}

GET /api/posts/hot?hours=24&limit=5
Response:
[{ ... }, { ... }]

6.3 回复接口

GET /api/replies/post/:postId
Response:
[
  {
    "id": "uuid",
    "post_id": "uuid",
    "user_id": "uuid",
    "anonymous_name": "用户_xxx",
    "user_avatar": null,
    "content": "回复内容",
    "parent_reply_id": null,
    "parent_floor_number": null,
    "parent_username": null,
    "created_at": "...",
    "like_count": 5,
    "is_liked": false,
    "images": []
  }
]

POST /api/replies/post/:postId
Headers: Authorization: Bearer <token>
Request:
{
  "content": "回复内容",
  "parentReplyId": "uuid",        // 可选,楼中楼
  "parentFloorNumber": 3,         // 可选
  "parentUsername": "用户_xxx",   // 可选
  "images": []
}
Response:
{
  "id": "uuid",
  ...
}

DELETE /api/replies/:id
Headers: Authorization: Bearer <token>
Response:
{
  "message": "删除成功"
}

6.4 互动接口

POST /api/interactions/like/:id
Headers: Authorization: Bearer <token>
Request:
{
  "type": "post"  // 或 "reply"
}
Response:
{
  "liked": true,
  "message": "点赞成功"
}

POST /api/interactions/favorite/:postId
Headers: Authorization: Bearer <token>
Response:
{
  "favorited": true,
  "message": "收藏成功"
}

GET /api/interactions/favorites
Headers: Authorization: Bearer <token>
Response:
[{ post1 }, { post2 }]

POST /api/interactions/messages
Headers: Authorization: Bearer <token>
Request:
{
  "toUserId": "uuid",
  "content": "私信内容"
}
Response:
{
  "id": "uuid",
  "from_user_id": "...",
  "to_user_id": "...",
  "content": "...",
  ...
}

GET /api/interactions/conversations
Headers: Authorization: Bearer <token>
Response:
[
  {
    "other_user_id": "uuid",
    "other_user_name": "用户_xxx",
    "other_user_avatar": null,
    "last_message": "最后一条消息",
    "last_message_time": "...",
    "unread_count": 3
  }
]

七、安全设计

7.1 认证安全

措施实现
密码加密bcrypt (cost=10)
Token 格式UUID + 时间戳 + 随机串
Token 存储数据库 sessions 表
Token 有效期30 天
会话管理修改密码后其他设备登出

7.2 请求安全

措施实现
XSS 防护xss 库过滤所有输入
SQL 注入参数化查询 (mysql2)
CORS限制 origin
HTTP 安全头Helmet 中间件
速率限制express-rate-limit

7.3 速率限制配置

typescript

// 通用 API: 5000 次/分钟 (开发模式)
generalLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 5000
});

// 创建内容: 1000 次/分钟 (开发模式)
createLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 1000
});

// 文件上传: 10 次/分钟
uploadLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 10
});

7.4 敏感词过滤

typescript

// 敏感词等级
type SensitiveLevel = 'low' | 'medium' | 'high';

// 处理逻辑
if (level === 'high') {
  // 拒绝发布
  return res.status(400).json({ error: '内容包含敏感词' });
} else {
  // 记录日志,允许发布
  await logOperation(...);
}

八、日志系统

8.1 Winston 配置

typescript

// 日志级别: error, warn, info, debug
// 日志格式: [YYYY-MM-DD HH:mm:ss] LEVEL: message

// 输出目标:
// 1. 控制台 (带颜色)
// 2. error-YYYY-MM-DD.log (仅错误)
// 3. combined-YYYY-MM-DD.log (所有日志)

// 日志轮转:
// - 每日轮转
// - 单文件最大 20MB
// - 保留 14 天

8.2 操作日志

typescript

// 记录到 operation_logs 表
await logOperation(userId, action, targetType, targetId, req);

// 记录内容:
// - user_id: 操作用户
// - action: 操作类型 (create_post, delete_reply, like, etc.)
// - target_type: 目标类型 (post, reply, user)
// - target_id: 目标 ID
// - ip_address: 客户端 IP
// - user_agent: 浏览器信息

九、部署架构

9.1 Nginx 配置

nginx

server {
    listen 80;
    server_name forum.zcc609.online;
    
    # 前端静态文件
    root /home/anonymous-forum/frontend;
    
    # SPA 路由
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # API 反向代理
    location /api/ {
        proxy_pass http://127.0.0.1:3001/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
    # 图片代理
    location /uploads/ {
        proxy_pass http://127.0.0.1:3001/uploads/;
    }
    
    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
    
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

9.2 PM2 进程管理

bash

# 启动
pm2 start dist/index.js --name anonymous-forum

# 查看日志
pm2 logs anonymous-forum

# 重启
pm2 restart anonymous-forum

# 停止
pm2 stop anonymous-forum

9.3 部署流程

bash

# 1. 本地构建前端
npm run build

# 2. 上传到服务器
scp -r build/* root@server:/home/anonymous-forum/frontend/

# 3. 上传后端代码
scp -r backend/* root@server:/home/anonymous-forum/backend/

# 4. 服务器编译后端
cd /home/anonymous-forum/backend
npm install
npm run build

# 5. 重启服务
pm2 restart anonymous-forum

十、前端路由结构

typescript

// App.tsx 路由配置
<Routes>
  {/* 认证页面 */}
  <Route path="/login" element={<LoginPage />} />
  <Route path="/register" element={<RegisterPage />} />
  
  {/* 管理后台 (需要管理员权限) */}
  <Route path="/admin/*" element={
    <ProtectedRoute requireAuth adminOnly>
      <AdminDashboard />
    </ProtectedRoute>
  } />
  
  {/* 私信对话页面 */}
  <Route path="/messages/:userId" element={<MessageConversation />} />
  
  {/* 主布局页面 (需要登录) */}
  <Route element={<MainLayout />}>
    <Route path="/" element={<PostListPage />} />
    <Route path="/post/:id" element={<PostDetailPage />} />
    <Route path="/search" element={<SearchResultPage />} />
    <Route path="/my-replies" element={<MyRepliesPage />} />
    <Route path="/my-posts" element={<MyPostsPage />} />
    <Route path="/my-favorites" element={<MyFavoritesPage />} />
    <Route path="/my-likes" element={<MyLikesPage />} />
    <Route path="/notifications" element={<NotificationPage />} />
    <Route path="/drafts" element={<DraftsPage />} />
    <Route path="/messages" element={<Messages />} />
    <Route path="/profile" element={<ProfilePage />} />
  </Route>
  
  {/* 404 重定向 */}
  <Route path="*" element={<Navigate to="/" />} />
</Routes>

以上是项目的完整详细信息,涵盖技术栈、项目结构、功能模块、数据库设计、API 接口、安全设计、日志系统和部署架构。

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注