BNDSForum 是一套轻量级的博客与知识分享平台。它基于 Flask 3 构建,内置 Markdown 写作体验、类别/班级双标签体系以及与 BNDS Online Judge (BNDSOJ) 的账号集成。
- 支持 Markdown 写作、实时预览、代码高亮与 KaTeX 数学公式渲染。
- 与 BNDSOJ 共用账号体系;远程校验成功后自动同步真实姓名并更新本地缓存。
- 文章、评论均支持 Markdown;评论区具备轻量工具栏和实时校验。
- 采用 SQLite 存储,自动初始化数据库并兼容旧版 JSON 文件结构。
- 管理后台提供类别、班级、固定标签及用户管理,可一键同步 BNDSOJ 小组。
- 首页支持班级多选、类别单选与关键词过滤,快速找到目标文章。
- 全量静态资源本地化,无需依赖外部 CDN,可直接离线部署。
- 后端:Flask 3、Flask-Login
- 数据层:SQLite 3 本地文件数据库,使用 WAL 模式与外键约束
- 认证集成:
requests驱动的 BNDSOJ 登录流程封装 - Markdown & 富文本:markdown-it、mdit-py-plugins、CodeMirror、highlight.js、KaTeX
- 前端样式:自定义响应式布局,支持深浅配色与移动端导航
BNDSForum/
├── app/ # Flask 应用主包
│ ├── __init__.py # 应用工厂与全局上下文
│ ├── admin.py # 管理后台蓝图
│ ├── auth.py # 登录 / 登出 / 注册入口(注册已禁用)
│ ├── blog.py # 文章、评论与用户主页
│ ├── datastore.py # SQLite 数据访问层及业务逻辑
│ ├── oj_client.py # BNDSOJ 登录校验客户端
│ ├── tag.py # 旧版标签树展示(默认未启用,兼容保留)
│ ├── static/ # 本地化静态资源与样式
│ └── templates/ # Jinja2 模板
├── data/ # 默认数据目录(forum.sqlite3)
├── run.py # 入口脚本(开发服务器)
├── requirements.txt # Python 依赖列表
└── COPYING # GPL-3.0 许可文本
- Python ≥ 3.8(建议 3.11+,与 Flask 3 官方支持保持一致)
- SQLite 3(随 Python 内置)
- 可选:访问 BNDSOJ 登录页的出站网络权限
# 1. 创建并激活虚拟环境
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2. 安装依赖
pip install --upgrade pip
pip install -r requirements.txt
# 3. (可选) 配置环境变量
export SECRET_KEY="change-me"
export OJ_BASE_URL="https://onlinejudge.bnds.cn"
# 4. 启动开发服务器
python run.py # 监听 0.0.0.0:6001首轮启动会自动在 data/forum.sqlite3 创建数据库,并初始化用户名为 admin、密码为 admin123 的管理员帐号。请立即登录后台修改密码。
浏览器访问 http://localhost:6001 即可进入首页。
| 变量名 | 默认值 | 说明 |
|---|---|---|
SECRET_KEY |
dev-secret-key |
Flask 会话密钥,部署时必须修改 |
OJ_BASE_URL |
https://onlinejudge.bnds.cn |
BNDSOJ 入口地址 |
OJ_TIMEOUT |
10(秒) |
BNDSOJ 请求超时时间 |
OJ_VERIFY_SSL |
false(任何非真值均视作否) |
true 强制校验证书,false 关闭校验 |
提示:生产环境应显式设置
SECRET_KEY,并根据部署网络状况决定是否开启OJ_VERIFY_SSL。
- 默认数据位于
data/forum.sqlite3;可通过设置DATA_PATH(修改app/__init__.py)定制存储位置。 datastore.py会自动启用 SQLiteWAL模式、外键约束与适配的性能配置。- 首次启动若检测到旧版 JSON 数据(
users.json、tags.json、tag_tree.json、posts.json或posts/*.json),会执行一次性迁移;迁移完成后写入data/.sqlite_migrated哨兵文件防止重复导入。 - 所有写操作均在线程安全的
RLock范围内完成,可安全用于 Flask 内置开发服务器与 Gunicorn 等 WSGI 容器。
- BNDSOJ 联合登录:登录表单优先向 BNDSOJ 发起校验;成功后自动同步真实姓名并缓存密码哈希以支持离线登录。
- 离线回退:当 BNDSOJ 不可用或账号不存在时,退回本地 SQLite 校验。
- 角色体系:
admin:访问管理后台、调整用户角色与固定/类别/班级标签。user:撰写文章、评论、按标签筛选阅读内容。
- 注册入口:面向普通用户注册已关闭,模板按钮用于管理员批量创建时保留。可在
auth.register中重新开启。
- Markdown 编辑器:基于 CodeMirror,提供常用语法快捷按钮、键盘列表缩进、实时预览面板。
- KaTeX 数学公式:在 Markdown 中使用
$...$或$$...$$即可渲染;编辑器会自动转义大括号避免冲突。 - Callout 块:支持
:::info/:::success/:::warning/:::error容器语法,预览和渲染均保持提示框样式。 - 语法高亮:内置 highlight.js,无需额外配置即可对代码块进行高亮。
- 评论区:表单采用紧凑模式,与文章编辑器共享渲染逻辑,提交前校验空内容并给出提示。
- 类别标签:管理员维护的扁平列表,文章必须选择一个类别。
- 班级标签:支持本地维护与 BNDSOJ 小组同步,文章必须选择一个班级标签,可在首页按班级多选过滤。
- 固定标签:为用户全局配置的标签,系统会在该用户的所有文章中自动附加。
- 筛选体验:首页左侧提供班级多选、类别单选以及关键词搜索,右侧实时展示符合条件的文章卡片。
- 类别标签、班级标签(含 OJ 同步)、固定标签维护。
- 用户筛选(用户名、真实姓名、固定标签)与批量编辑(真实姓名、角色、固定标签)。
- 保护策略:强制至少保留一名管理员;普通用户无法访问后台路由。
仓库提供 scripts/perf_test.py 用于压力与性能测试,涵盖首页筛选、文章详情、登录、写作、评论、后台等典型操作。脚本会在运行前自动备份 data/forum.sqlite3,测试结束(无论成功与否)都会恢复原始数据库,确保测试数据不污染现有环境。
执行示例:
python scripts/perf_test.py \
--base-url http://localhost:6001 \
--duration 60 \
--concurrency 8常用参数:
--base-url:目标服务地址,默认为本地开发服务器。--username/--password:登录账号,默认使用内置管理员,可通过环境变量PERF_USERNAME/PERF_PASSWORD覆盖。--duration:压力测试持续时间(秒)。--concurrency:并发工作线程数量。--timeout:单次请求超时时间(秒)。--seed-posts:测试前额外创建的种子文章数量,保证读取与编辑操作有数据可用。--seed:随机种子,便于复现压测场景。
测试完成后会在终端输出各操作的吞吐(TPS)与时延(平均值、p95、max 等),可据此评估不同功能的性能表现。