从 0 到 1:我的小说阅读平台开发之旅
最近基于 FastAPI 构建异步后端、SQLite 轻量化存储、Dify 赋能 AI 辅助能力,同时优化阅读体验、解决 TXT 解析、AI 输出处理等方面完成了一个简易的小说阅读平台的开发,想和大家分享一下整个开发过程中的收获与思考。。
一、缘起:为什么要做这个项目?
作为一个小说爱好者,我一直觉得市面上的阅读平台要么广告太多,要么阅读体验不够个性化。同时,作为一个写作者,我也希望有更好的工具来辅助创作。
于是,我决定自己动手,打造一个集阅读与创作于一体的小说平台。核心目标很简单:
- 为读者:提供干净、舒适的阅读体验
- 为作者:提供智能的写作辅助工具
- 为自己:实践全栈开发能力
二、技术选型
后端框架:FastAPI
选择 FastAPI 的原因:
- 异步支持:对于 IO 密集型的应用场景(如数据库查询、AI 调用)更高效
- 类型提示:配合 Pydantic,代码更健壮,调试更方便
- 自动文档:自动生成 Swagger UI,API 调试事半功倍
数据库:SQLite + SQLAlchemy
考虑到这是一个单体应用,且需要轻量化部署,我选择了 SQLite:
- 零配置:开箱即用,无需额外安装数据库服务
- 文件存储:数据以文件形式保存,便于备份和迁移
- ORM 层:SQLAlchemy 提供数据访问抽象
AI 引擎:Dify
这是项目最核心的亮点之一。我选择了 Dify 作为 AI 引擎:
- 双模式支持:Workflow(结构化分析)+ Chatflow(开放式对话)
- 低代码配置:可视化配置工作流,无需复杂 API 调用
- 私有化部署:数据安全可控
认证方案:JWT + pbkdf2_sha256
使用 python-jose 签发 JWT 令牌,passlib 库的 pbkdf2_sha256 算法进行密码加密。
三、项目架构
我采用了经典的分层架构:
┌─────────────────────────────────────────────────────────┐
│ 前端层 (Frontend) │
│ HTML / CSS / JavaScript / 静态资源 │
│ 首页 | 书城 | 阅读页 | AI写作 | 管理后台 │
└──────────────────────────────┬──────────────────────────┘
│ HTTP/JSON
▼
┌─────────────────────────────────────────────────────────┐
│ API 层 (FastAPI) │
│ Auth 认证 │ Novels 小说 │ AI 助手 │ Carousel 轮播 │
└──────────────────────────────┬──────────────────────────┘
│ 依赖注入
▼
┌─────────────────────────────────────────────────────────┐
│ 业务层 (Services) │
│ auth_service 用户认证 │ dify_service AI 交互 │
└──────────────────────────────┬──────────────────────────┘
│ SQLAlchemy
▼
┌─────────────────────────────────────────────────────────┐
│ 数据层 (CRUD) │
│ User │ Novel │ Chapter │ Favorite │ Comment │ Carousel │
└──────────────────────────────┬──────────────────────────┘
│ SQLite
▼
┌─────────────────────────────────────────────────────────┐
│ AI 引擎层 (Dify) │
│ Workflow (小说分析) │ Chatflow (AI辅助写作) │
└─────────────────────────────────────────────────────────┘
四、数据库设计
核心实体关系
User (用户) ──1:N──▶ Novel (小说)
Novel (小说) ──1:N──▶ Chapter (章节)
User (用户) ──1:N──▶ Favorite (收藏)
User (用户) ──1:N──▶ Comment (评论)
User (用户) ──1:N──▶ ReadingHistory (阅读历史)
Novel (小说) ──1:N──▶ CarouselItem (轮播项)
数据表清单
| 表名 | 核心字段 | 说明 |
|---|---|---|
users |
id, username, email, hashed_password, is_admin | 用户信息 |
novels |
id, title, author_id, author_name, genre, description, views, word_count, reader_target, status | 小说信息 |
chapters |
id, novel_id, title, chapter_number, content | 章节内容 |
reading_history |
id, user_id, novel_id, chapter_id, last_read_at | 阅读记录 |
favorites |
id, user_id, novel_id, added_at | 收藏记录 |
comments |
id, user_id, novel_id, content, created_at | 评论信息 |
carousel_items |
id, item_type, display_order, title, cover_url | 轮播项目 |
carousel_config |
id, config_key, config_value | 轮播配置 |
数据库索引优化
为提升查询性能,在以下字段添加了索引:
novels 表:author_id, author_name, genre, status, views, reader_target, created_at, updated_at
chapters 表:novel_id, title, chapter_number, created_at
reading_history 表:user_id, novel_id, chapter_id, last_read_at
favorites 表:user_id, novel_id, added_at
comments 表:user_id, novel_id, created_at
五、核心功能详解
5.1 用户认证模块
使用 JWT 进行身份验证,支持用户注册、登录、权限控制:
# 密码加密使用 pbkdf2_sha256
pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto")
# JWT 令牌生成
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
权限分为两级:
- 普通用户:浏览、阅读、收藏、评论
- 管理员:小说管理、轮播管理、上传小说
5.2 小说管理模块
支持小说的 CRUD 操作,以及 TXT 文件批量上传:
# TXT 文件上传接口
@router.post("/upload-novel/")
async def upload_novel(
title: str = Form(...),
file: UploadFile = File(...),
separator: str = Form("第.*章"),
...
):
# 文件大小限制(10MB)
MAX_FILE_SIZE = 10 * 1024 * 1024
# 章节数限制(5000章)
MAX_CHAPTERS = 5000
# 读取文件内容
text = content.decode('utf-8', errors='replace')
# 按分隔符解析章节
chapters = parse_novel_chapters(text, separator)
章节解析逻辑使用正则表达式,支持用户自定义分隔符(默认按 “第x章” 分割)。
5.3 阅读体验模块
阅读器提供了丰富的个性化设置:
| 设置项 | 可选值 | 说明 |
|---|---|---|
| 字体大小 | 12px ~ 36px | 步进 1px |
| 阅读主题 | 默认 / 夜间 / 护眼 / 粉色 / 蓝色 / 护眼黄 | 背景色 + 文字色 |
| 行间距 | 1.5 ~ 3.0 | 步进 0.1 |
| 字体样式 | 系统默认 / 宋体 / 黑体 / 楷体 | CSS font-family |
| 翻页方式 | 点击翻页 / 滑动翻页 | 交互模式 |
所有设置保存在 localStorage,下次打开自动恢复。
键盘快捷键支持:
→/空格:下一页/下一章←:上一页/上一章Esc:返回小说详情+/-:调整字体大小T:打开设置面板
5.4 用户交互模块
- 收藏功能:添加/取消收藏,检查是否已收藏
- 评论系统:发表评论,查看评论列表
- 阅读历史:自动记录阅读进度,按时间倒序排列
- 离线阅读:支持下载小说到本地,无网络时也可阅读
5.5 AI 小说分析模块(Workflow)
通过 Dify Workflow 实现小说深度分析,支持对话历史记录:
# 发送 6 个变量到 Dify Workflow
inputs = {
"query": request.query,
"novel_title": novel_info["title"],
"novel_author": novel_info["author"],
"novel_description": novel_info["description"],
"novel_genre": novel_info["genre"],
"chapter_content": chapter_content[:5000]
}
# 调用 Workflow API,支持 conversation_id 传递
result = await dify_client.run_workflow(inputs, user=str(current_user.id))
return result # 返回 answer 和 conversation_id
Workflow 会按照预设的流程,调用 LLM 进行结构化分析,返回分析报告。
5.6 AI 辅助写作模块(Chatflow)
通过 Dify Chatflow 提供四种写作辅助模式:
| 模式 | 接口 | 必填参数 | 说明 |
|---|---|---|---|
| 续写 | continue_writing |
context, style | 基于前文继续创作 |
| 大纲生成 | generate_outline |
title, genre, description | 生成故事大纲 |
| 角色设计 | design_character |
context | 设计人物设定 |
| 文本润色 | polish_text |
text, style | 提升文字质量 |
# 前端路由分发
if mode == "continue":
answer = await dify_client.continue_writing(request.context, request.style or "")
elif mode == "outline":
answer = await dify_client.generate_outline(request.title, request.genre or "", request.description or "")
elif mode == "character":
answer = await dify_client.design_character(request.context)
elif mode == "polish":
answer = await dify_client.polish_text(request.text, request.style or "")
5.7 轮播管理模块
支持两种轮播类型:
- 名人堂(hall_of_fame):展示作家信息,包括代表作、经典语录、创作理念
- 巅峰榜(top_list):展示热门小说排行
管理员可通过后台管理轮播项目和配置显示数量。
5.8 书城筛选模块
提供多维度的筛选功能:
读者筛选:全部 / 男生 / 女生
分类筛选:全部 / 主题 / 角色 / 情节(根据读者选择动态变化)
状态筛选:全部 / 已完结 / 连载中
字数筛选:全部 / 30万以下 / 30-50万 / 50-100万 / 100-200万 / 200万以上
六、性能优化
6.1 数据库查询优化
问题:N+1 查询问题,循环查询作者信息导致性能下降。
解决方案:使用 SQLAlchemy 的 joinedload 预加载关联数据:
def get_novels_with_author(db: Session, skip: int = 0, limit: int = 100):
return db.query(Novel).options(
joinedload(Novel.author)
).order_by(Novel.updated_at.desc()).offset(skip).limit(limit).all()
6.2 雪花特效性能优化
问题:雪花特效动态创建/删除 DOM 元素,性能消耗大。
解决方案:使用对象池复用 DOM 元素:
const snowflakePool = [];
const MAX_SNOWFLAKES = 30;
let snowflakeIndex = 0;
function getSnowflakeElement() {
let el;
if (snowflakePool.length < MAX_SNOWFLAKES) {
el = document.createElement('div');
el.className = 'snowflake';
snowflakePool.push(el);
} else {
el = snowflakePool[snowflakeIndex % MAX_SNOWFLAKES];
snowflakeIndex++;
}
return el;
}
七、遇到的挑战与解决方案
挑战一:TXT 文件章节分割
问题:用户上传的 TXT 文件格式不一,章节标题格式多样。
解决方案:使用正则表达式配合用户自定义分隔符:
def parse_novel_chapters(text: str, separator: str) -> list:
pattern = re.compile(rf'({separator})')
parts = pattern.split(text)
# 遍历分割结果,提取章节标题和内容
for i, part in enumerate(parts):
if re.match(rf'^{separator}$', part.strip()):
# 匹配到章节标题
...
else:
# 章节内容
...
默认分隔符为 第.*章,用户也可以自定义,如 第.*节、第.*回 等。
挑战二:AI 输出格式处理
问题:Dify 返回的内容带有 Markdown 格式符号,需要清洗后展示。
解决方案:
function cleanMarkdown(text) {
if (!text) return '';
return text
.replace(/^#{1,6}\s+/gm, '') // 移除标题标记
.replace(/\*\*(.+?)\*\*/g, '$1') // 移除粗体
.replace(/\*(.+?)\*/g, '$1') // 移除斜体
.replace(/`(.+?)`/g, '$1') // 移除代码标记
.replace(/^[-*+]\s+/gm, '• ') // 无序列表转圆点
.replace(/^\d+\.\s+/gm, '') // 有序列表
.replace(/^\s*[-*_]{3,}\s*$/gm, '') // 分隔线
.replace(/^\s*>\s+/gm, '') // 引用标记
.replace(/\*/g, '') // 移除剩余星号
.trim();
}
挑战三:异步 AI 调用
问题:AI 调用可能耗时较长(最长 120 秒超时),需要异步处理。
解决方案:
# 使用 httpx.AsyncClient 进行异步 HTTP 请求
async with httpx.AsyncClient(timeout=120.0) as client:
response = await client.post(
self.workflow_url,
json=payload,
headers=self.workflow_headers
)
挑战四:Workflow 与 Chatflow 的区分
问题:Dify 的 Workflow 和 Chatflow 返回格式不同,需要分别处理。
解决方案:
# Workflow 返回格式:data.outputs.answer
if "data" in data and "outputs" in data["data"]:
if "answer" in data["data"]["outputs"]:
result = data["data"]["outputs"]["answer"]
# Chatflow 返回格式:answer
data.get("answer", "抱歉,没有收到回复")
八、API 端点一览
用户认证
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /token |
登录获取 JWT 令牌 |
| POST | /users/ |
用户注册 |
| GET | /users/me/ |
获取当前用户信息 |
小说管理
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /novels/ |
获取小说列表(分页) |
| GET | /novels/search/ |
搜索小说 |
| GET | /novels/filter/ |
按条件筛选小说 |
| GET | /novels/top/ |
热门小说排行 |
| GET | /novels/top-authors/ |
热门作者排行 |
| GET | /novels/{id} |
获取小说详情 |
| POST | /novels/ |
创建小说(管理员) |
| PUT | /novels/{id} |
更新小说(管理员) |
| DELETE | /novels/{id} |
删除小说(管理员) |
| POST | /upload-novel/ |
上传 TXT 小说(管理员) |
| GET | /genres/ |
获取所有小说类型 |
章节
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /novels/{id}/chapters/ |
获取章节列表 |
| GET | /chapters/{id} |
阅读章节(需登录) |
| POST | /novels/{id}/chapters/ |
添加章节 |
收藏与阅读历史
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /reading-history/ |
获取阅读历史 |
| POST | /favorites/{novel_id} |
收藏小说 |
| DELETE | /favorites/{novel_id} |
取消收藏 |
| GET | /favorites/ |
获取收藏列表 |
| GET | /favorites/check/{novel_id} |
检查是否已收藏 |
评论
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /novels/{id}/comments/ |
获取小说评论 |
| POST | /novels/{id}/comments/ |
发表评论 |
AI 助手
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /dify/chat |
AI 小说分析(Workflow) |
| POST | /dify/writing |
AI 辅助写作(Chatflow) |
| POST | /dify/summary/{novel_id} |
生成小说简介 |
轮播图
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /carousel/items/ |
获取轮播项目 |
| POST | /carousel/items/ |
创建轮播项目(管理员) |
| PUT | /carousel/items/{id} |
更新轮播项目(管理员) |
| DELETE | /carousel/items/{id} |
删除轮播项目(管理员) |
| GET | /carousel/config/{key} |
获取轮播配置 |
| PUT | /carousel/config/{key} |
更新轮播配置(管理员) |
封面上传
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /novels/{id}/cover |
上传小说封面(管理员) |
| POST | /carousel/items/{id}/cover |
上传轮播封面(管理员) |
九、总结与感悟
技术亮点
- AI 与传统业务的结合:将 Dify 的 Workflow 和 Chatflow 无缝集成到小说平台中
- 阅读体验优化:6 种阅读主题、字体大小/行间距/字体样式可调,支持键盘快捷键
- 书城多维筛选:读者、分类、状态、字数四级筛选
- 双轮播系统:名人堂展示作家风采,巅峰榜展示热门小说
- 性能优化:数据库查询优化(解决 N+1 问题)、雪花特效对象池复用
- 对话历史记录:AI 分析支持多轮对话上下文保持
技术难点
- Workflow vs Chatflow 的选择:Workflow 适合结构化的小说分析任务,Chatflow 适合开放式的写作辅助对话,两者的 API 返回格式不同,需要分别处理
- TXT 章节智能分割:支持用户自定义分隔符,兼容多种章节标题格式
- AI 输出清洗:对 Markdown 内容进行多层清洗,确保前端展示整洁
- 异步超时处理:AI 调用设置 120 秒超时,避免长时间阻塞
- 数据库性能优化:使用 joinedload 预加载关联数据,添加数据库索引提升查询效率
未来规划
- 支持 EPUB/MOBI 格式导入
- 添加社交分享功能
- 实现个性化推荐算法
- 支持更多功能
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)