实时自习室社区平台
系统流程图
1 | flowchart TD |
数据库
我用的是navicate mysql8,先确定我需要的表和每个表设计的字段,以下是初步拟写的表:
但是我的语句未在navicate中运行,我想做成写在后端,后端帮我在数据库自动建表的玩法
数据库表
– 1. 用户主表:整合基础信息与社区积分
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘用户唯一标识’,
username VARCHAR(50) NOT NULL UNIQUE COMMENT ‘登录账号(学号/管理员名)’,
password VARCHAR(255) NOT NULL COMMENT ‘加密存储的密码’,
nickname VARCHAR(50) DEFAULT ‘新用户’ COMMENT ‘用户昵称’,
avatar VARCHAR(255) DEFAULT NULL COMMENT ‘头像URL路径’,
role ENUM(‘admin’, ‘student’) DEFAULT ‘student’ COMMENT ‘角色权限:admin-管理员, student-学生 ‘,
points INT DEFAULT 0 COMMENT ‘社区总积分(用于排行榜) ‘,
status TINYINT DEFAULT 1 COMMENT ‘账号状态:1-启用, 0-封禁 ‘,
last_login DATETIME DEFAULT NULL COMMENT ‘最后登录时间’,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘注册时间’,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘信息更新时间’
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’用户权限与积分表’;
– 2. 操作日志表:满足“管理端操作日志记录”个人任务
CREATE TABLE admin_logs (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘日志ID’,
admin_id INT NOT NULL COMMENT ‘执行操作的管理员ID’,
action_type VARCHAR(50) NOT NULL COMMENT ‘操作类型:如 封禁用户、审核帖子’,
target_table VARCHAR(50) COMMENT ‘被操作的数据表名’,
target_id INT COMMENT ‘被操作的数据ID’,
detail TEXT COMMENT ‘具体操作描述(记录修改前后的变化)’,
ip_address VARCHAR(45) COMMENT ‘操作者IP’,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘记录时间’,
FOREIGN KEY (admin_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’管理员操作审计日志表’;
– 3. 社区帖子表:包含审核状态流转
CREATE TABLE posts (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘帖子ID’,
user_id INT NOT NULL COMMENT ‘发帖人ID’,
title VARCHAR(255) NOT NULL COMMENT ‘标题’,
content LONGTEXT NOT NULL COMMENT ‘帖子正文内容’,
status TINYINT DEFAULT 0 COMMENT ‘审核状态:0-待审核, 1-审核通过, 2-违规退回 ‘,
view_count INT DEFAULT 0 COMMENT ‘浏览量’,
like_count INT DEFAULT 0 COMMENT ‘点赞数’,
comment_count INT DEFAULT 0 COMMENT ‘评论总数’,
is_top TINYINT DEFAULT 0 COMMENT ‘是否置顶:1-是, 0-否’,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT ‘发布时间’,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’社区帖子表’;
– 4. 社区评论表
CREATE TABLE comments (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘评论ID’,
post_id INT NOT NULL COMMENT ‘所属帖子ID’,
user_id INT NOT NULL COMMENT ‘评论人ID’,
content TEXT NOT NULL COMMENT ‘评论内容’,
status TINYINT DEFAULT 1 COMMENT ‘状态:1-显示, 0-因违规隐藏’,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’社区评论表’;
– 5. 点赞记录表:防止重复点赞,用于数据统计
CREATE TABLE post_likes (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
post_id INT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY idx_user_post (user_id, post_id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (post_id) REFERENCES posts(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’帖子点赞记录表’;
– 6. 内容举报表:管理端内容审核的重要数据源
CREATE TABLE reports (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘举报ID’,
reporter_id INT NOT NULL COMMENT ‘举报人ID’,
target_type ENUM(‘post’, ‘comment’) NOT NULL COMMENT ‘举报对象类型 ‘,
target_id INT NOT NULL COMMENT ‘被举报的对象ID’,
reason VARCHAR(255) NOT NULL COMMENT ‘举报理由(如垃圾广告、人身攻击)’,
status TINYINT DEFAULT 0 COMMENT ‘处理状态:0-待处理, 1-已处理 ‘,
handle_result VARCHAR(255) COMMENT ‘处理结论(如 忽略、删除内容并扣分)’,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (reporter_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’内容举报处理表’;
– 7. 敏感词库表:支撑“敏感词过滤”功能
CREATE TABLE sensitive_words (
id INT PRIMARY KEY AUTO_INCREMENT,
word VARCHAR(100) NOT NULL UNIQUE COMMENT ‘违禁词条’,
category VARCHAR(50) COMMENT ‘分类:政治、色情、暴力等’,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’敏感词过滤词库’;
建后端
npm install express cors mysql2 dotenv bcryptjs jsonwebtoken express-validator express-rate-limit helmet morgan multers
express: Node.js 最流行的Web框架,用于构建Web应用和API。
cors: 中间件,用于处理跨域资源共享(CORS),允许或限制不同域的请求。
mysql2: MySQL数据库的Node.js驱动,用于连接和操作MySQL数据库。相比mysql包,mysql2性能更好,并且支持Promise。
dotenv: 零依赖模块,将环境变量从.env文件加载到process.env中,便于管理配置。
bcryptjs: 用于密码哈希的库,将密码加密后存储,增强安全性。注意:这是纯JavaScript实现,不依赖C++编译,因此兼容性更好。
jsonwebtoken: 用于生成和验证JSON Web Tokens(JWT),常用于用户认证和授权。
express-validator: 用于验证和清理用户输入数据,防止无效或恶意数据进入应用。
express-rate-limit: 用于限制重复请求,防止暴力攻击,可以限制来自同一IP的请求频率。
helmet: 通过设置HTTP头来增强应用的安全性,防止一些常见的攻击(如XSS、点击劫持等)。
morgan: HTTP请求日志中间件,用于记录请求的详细信息,便于调试和监控。
multer: 用于处理multipart/form-data类型(即文件上传)的中间件。
连接数据库
使用基于Sequelize(Node.js 最流行的对象关系映射框架)的开发流程,用写js对象的方式操作数据库,而不是用SQL语句
流程:启动服务器 → 加载 .env → 初始化 Sequelize → 连接 MySQL → 导入所有模型 → 执行 sync() → 自动建表
.env文件配置环境
执行流程:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
191. 系统启动
↓
2. Node.js 加载 server.ts
↓
3. 执行 require('dotenv').config() ⭐ 【关键】
↓ 读取 .env 文件,解析内容
↓ 将所有变量注入到 process.env
↓
4. 之后的 require/import 可以访问 process.env
↓
5. 导入 database.ts
↓
const sequelize = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASSWORD
)
↓
6. 连接数据库成功入口文件server.ts
要先require('dotenv').config();因为node.js的导入是同步执行的,必须先加载.env文件,不然会导致环境变量为undefined,导致连接失败(我在数据库连接这卡了很久)数据库配置:database.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41// 第一步:创建 Sequelize 实例(还没有连接到数据库)
export const sequelize = new Sequelize(
process.env.DB_NAME || "study_platform",
process.env.DB_USER || "root",
process.env.DB_PASSWORD || "root",
{
host: process.env.DB_HOST || "localhost",
port: parseInt(process.env.DB_PORT || "3306"),
dialect: "mysql",
logging: console.log, // 打印所有 SQL 语句
pool: { max: 10, min: 0, acquire: 30000, idle: 10000 }
}
);
// 第二步:connectDB 函数(这是神奇的地方)
export const connectDB = async () => {
try {
// 1:测试数据库连接
await sequelize.authenticate();
console.log("MySQL connected successfully");
// 2:动态导入所有模型
// 这里用 require() 是关键,避免文件最开头的 import 导致循环依赖
const User = require("../models/user.model").default;
const Post = require("../models/post.model").default;
const Comment = require("../models/comment.model").default;
const Report = require("../models/report.model").default;
const AdminLog = require("../models/admin-log.model").default;
const PostLike = require("../models/post-like.model").default;
const SensitiveWord = require("../models/sensitive-word.model").default;
// 3:调用 sync() 自动建表,核心
await sequelize.sync({ alter: true });
console.log("Database tables synchronized");
return sequelize;
} catch (error) {
console.error("MySQL connection failed:", error);
process.exit(1);
}
};sync() 创建缺少的表,但不删除现有表
sync({ alter: true }) 修改现有表结构以匹配模型定义
sync({ force: true }) 删除所有表后重新创建有危险模型定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import { DataTypes, Model } from "sequelize";
import { sequelize } from "../config/database"; // ⚠️ 关键导入
// 定义数据类
export class User extends Model {
public id!: number;
public username!: string;
public password!: string;
// ... 其他字段
}
// 初始化模型,告诉 Sequelize 这个类如何映射到表
User.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING(255),
allowNull: false,
},
// ... 其他字段定义
},
{
sequelize, // 关键!告诉这个模型用哪个 Sequelize 实例
modelName: "User",
tableName: "users", // 数据库表名
timestamps: true,
createdAt: "created_at",
updatedAt: "updated_at",
}
);
export default User;
建前端
1 | npm create vite@latest study-com-platform-fe -- --template react-ts |
性能优化
会报警告
1 | const loadPermissions = async () => { |
react建议优化为:
但是这样处理还是会报”在Effect中同步调用setState”的警告
useCallback 稳定了函数引用,但它没有改变 fetchPermissions() 的异步执行速度和时机。
关键的时间线:
组件渲染 → React 执行 useEffect (同步步骤)
useEffect 调用 loadPermissions() (同步调用)
loadPermissions 内部的 await fetchPermissions() 如果瞬间完成(例如命中缓存、本地Mock、极速的开发服务器),那么 setData 就会几乎立即执行。
在 React 看来,这次 setData 仍然发生在上一步(useEffect 的同步执行流)的“余波”中,因此抛出警告。
简单来说:useCallback 解决了函数依赖问题,但解决不了“异步请求太快以至于看起来像同步”这个触发警告的根本条件。尤其是在 React.StrictMode 下,组件会渲染两次,更容易触发此场景。
最后优化为:
1 | const loadPermissions = async () => { |
实时通信
实时通道:WebSocket(推荐 Socket.IO)或 SSE。需要双向时选 WebSocket。
在线人数:后端维护“在线会话集合”(按用户ID/连接ID),定时心跳与断线清理。
新帖通知:发帖成功后向在线会话广播事件。
认证:沿用现有 JWT,在握手/连接时校验。
扩展:多实例时用 Redis 共享在线状态与广播。
实现思路(不写代码)
前端进入社区页时建立 WebSocket 连接并携带 token。
后端验证 token,加入在线集合,向所有连接广播在线人数。
前端监听“在线人数更新”事件,实时显示。
前端定时心跳,断线自动重连;后端超时清理。
发布帖子接口成功后,后端向所有在线用户广播“新帖提示”事件;前端收到后弹提示。
发帖后仅在“发布成功且通过审核”的帖子时广播提示。
当前用户名发帖不会收到提示。
打开两个不同浏览器(或一个无痕窗口 + 一个普通窗口),分别登录不同账号。
同时进入社区首页,右侧“在线用户”应同步变化
同一浏览器的多个窗口不行,因为它们共享同一个 localStorage,只能保留一个 token,登录会互相覆盖。
要模拟多用户,建议:
不同浏览器;或
普通窗口 + 无痕窗口(无痕有独立存储)
帖子推荐
1 | graph TD |



