博主 1.29日~2.4日 BUG修复清单

1) 首页异步分页 + 智能滚动(移动端“丝滑”修复)
改动点
前端改成走 GET /api/articles 拉数据,再 history.pushState() 更新地址栏(伪静态体验)。
Bug 现象
手机端点击侧边栏分类/分页后,页面滚动出现“跳动/不滚动/突然回顶部”。
触发位置
/mnt/data/index.ejs 的 loadData()(AJAX 成功回调里)
关键代码:setTimeout(() => $('html, body').animate(...), delayTime)
触发原因(机制级)
移动端侧边栏收起动画期间,body 会短暂处于“滚动锁定/布局变动”状态;滚动指令($('html, body').animate)过早执行会被浏览器忽略或滚动到错误位置。
修复方案
用 window.innerWidth <= 736 判定移动端,设置 delayTime = 600ms,PC 端 150ms:
移动端等侧边栏动画结束 + 解锁滚动后再执行 animate
PC只需要等待内容淡出/重绘即可
2) 首页“首页 5 篇 + 后续 6 篇”智能分页(避免重复/漏文章)
触发位置
/mnt/data/server.js → getArticlesData(req, callback)
核心变量:limitPage1 = 5、limitOther = 6
触发原因
如果首页与后续页 LIMIT 不一致,但仍用传统 offset=(page-1)*limit,会导致 分页重复或跳过文章。
修复方案(算法)
page=1:limit=limitPage1、offset=0
page>=2:limit=limitOther、offset=limitPage1 + (page-2)*limitOther
同时按 priority DESC, id DESC 排序,保证“置顶优先 + 新文优先”的稳定顺序。
3) 文章摘要“HTML 实体乱码”( “ 等)修复
Bug 现象
首页摘要出现 、“、& 等“代码符号”,影响阅读。
触发位置
/mnt/data/server.js → function stripHtml(html)
摘要来源:processedArticles = articles.map(... preview: stripHtml(art.content))
触发原因
仅做了“去标签”(/<[^>]+>/g),但富文本内容里还有大量 HTML 实体(entities),不会自动变成正常字符。
修复方案
在 stripHtml() 内新增实体替换链:
-> 空格
“ ” -> 中文引号
& -> &(放最后防二次替换)
再做 \s+ 合并空格并截断 150 字输出 ...
4) 评论“楼中楼断链”问题:软删除 + 留坑(is_deleted)
Bug 现象
删除一条主评论后,子回复(parent_id 指向它的评论)在页面结构里“消失/错乱”。
触发位置
数据表:comments
/mnt/data/server.js:
启动迁移:ALTER TABLE comments ADD COLUMN is_deleted INTEGER DEFAULT 0
删除逻辑:UPDATE comments SET is_deleted = 1 WHERE id = ?
渲染时说明:即使 is_deleted=1 也查出来,再在前端/模板层替换显示
触发原因
物理删除(DELETE)会导致回复链 parent_id 悬空,树结构无法构建,表现成“子评论没了”。
修复方案
用 is_deleted 做软删除:
删除改 UPDATE 不改 DELETE
渲染时检测 is_deleted=1,把 content 替换为“🗑️ 该评论已删除”,保留楼层结构与审计能力
5) 回复“@某人”名字显示为空(回复指向不清晰)
Bug 现象
回复时 UI 中 “@xxx” 后面名字不显示,用户不知道在回复谁。
触发位置
评论渲染逻辑(在 post.ejs/后端组装评论树处)
触发原因
旧逻辑为了防“套娃/重复显示”,对某些父级节点做了隐藏昵称判断(类似 “如果 parent 是楼主就不显示”),结果误伤正常回复显示。
修复方案
去掉/放宽这类条件判断:只要是回复(parent_id!=0)就显示被回复者昵称,确保对话链清晰。
6) 个人中心:改昵称后历史评论仍显示旧名(comments.name 快照未同步)
Bug 现象
用户资料里昵称已更新,但历史评论依然显示旧昵称。
触发位置
/mnt/data/server.js → /profile/update(资料更新接口)
关联字段:comments.name、comments.user_id
触发原因
评论表会存一个 name 快照;用户表 users.nickname 更新不会自动回写历史评论。
修复方案
在资料更新事务里追加同步 SQL:
UPDATE comments SET name = ? WHERE user_id = ?
这样即使某些页面仍用 comments.name 渲染,也不会出现旧昵称残留。
7) 历史评论“无主数据”导致个人中心查不到(user_id=0/NULL)
Bug 现象
早期评论没有绑定账号,个人中心按 user_id 查询时无法展示“老评论”。
触发位置
/mnt/data/server.js 启动期“自动迁移/关联修复” SQL
关键条件:WHERE (user_id = 0 OR user_id IS NULL) AND email IN (SELECT email FROM users)
触发原因
早期只记录了 comments.email,没有写 comments.user_id,导致后续“按用户维度聚合/展示”缺少主键关联。
修复方案
迁移脚本用 email 反查 users.id,批量补齐 comments.user_id:
SET user_id = (SELECT id FROM users WHERE users.email = comments.email)
迁移后个人中心能完整展示历史互动记录。
8) 投稿分类“前端限制可绕过”——后端二次校验 allow_submit
Bug 现象
普通用户可能通过改 POST 参数把文章投到“不允许投稿”的分类里(前端下拉框限制不够)。
触发位置
/mnt/data/server.js → POST /article/submit
校验点:SELECT allow_submit FROM categories WHERE value = ?
触发原因
仅靠前端 select 做限制无法防篡改;用户可直接构造请求。
修复方案
后端强校验 allow_submit === 1 才允许继续写入;否则 alert + history.back() 拦截。
同时 GET /article/submit 对普通用户只查询 allow_submit=1 的分类列表,减少误操作入口。
9) 后台分类管理:allow_submit 无法编辑(纯文本展示)
Bug 现象
后台分类表只能看,不能修改“允许投稿”状态。
触发位置
/mnt/data/admin.ejs 分类表格
/mnt/data/server.js → POST /admin/categories/add、POST /admin/categories/update/:id
关键字段:allow_submit(checkbox → req.body.allow_submit === 'on' ? 1 : 0)
触发原因
原分类表格缺少 <input type="checkbox"> + 缺少 form 绑定,提交不到后端。
修复方案
前端表格嵌入 checkbox,并用 HTML5 form="xxx" 把表格控件绑定到操作按钮
后端把 allow_submit 入库与更新逻辑补齐。
10) 后台文章编辑报错:缺路由/缺 categories(模板渲染缺参)
Bug 现象
点击“编辑”报错、打不开、或渲染分类下拉时报错。
触发位置
/mnt/data/server.js:GET /admin/edit/:id、POST /admin/edit/:id
/mnt/data/edit.ejs:需要 categories 来渲染下拉
触发原因
常见是只查 articles 没查 categories,模板引用变量时报错;或路由缺失导致跳转/404。
修复方案
补齐 REST 风格编辑路由,并确保 res.render('edit', { article, categories }) 两个都传。
11) 严重崩溃:ReferenceError: saveCompressedImage is not defined
Bug 现象
发文章/上传封面时,Node 进程直接崩(ReferenceError)。
触发位置
/mnt/data/server.js 多处调用:例如投稿/后台编辑的 await saveCompressedImage(req.file.buffer, req.file.originalname)
函数定义:async function saveCompressedImage(fileBuffer, originalName)
触发原因
在多次合并修改过程中,函数定义被误删/移动,但调用点还在,导致运行时找不到符号。
修复方案
把 saveCompressedImage() 统一放回 server.js(可被所有路由复用)
采用 sharp:resize({width:1920}) + jpeg压缩,输出到 public/uploads
12) 分享系统:/api/share + share_cache(低带宽优化)
新增点
/api/share/:id 输出文章分享信息;/share/qr/:id.png 和 /share/poster/:id.jpg 生成二维码/海报
触发位置
/mnt/data/server.js:
shareDir = path.join(__dirname, 'share_cache')
常量:SHARE_POSTER_W/H、SHARE_QR_SIZE、SHARE_JPEG_QUALITY
设计原因(性能/安全)
分享素材生成成本高,所以落地到 share_cache 做缓存;并且不放 public 下,避免静态资源绕过后续鉴权设计。
海报采用较低 SHARE_JPEG_QUALITY,降低服务器带宽占用。
💬 留言板 (0)
还没有人留言,快来抢沙发吧~
登录后参与评论
加入讨论,与博主互动
去登录 / 注册