无法实现正确编辑JS对象的算法:书籍类流媒体Web应用月度阅读页数统计需求
解决方案:基于历史最高进度的新增页数计算
核心思路是跟踪用户对单本书的历史最高阅读页码,而不是依赖当月累计或简单的当前页对比。只有当用户当前阅读的页码超过历史最高时,才将差值计入当月新增页数,这样就能完美解决回翻不计数、跳页正确统计的问题。
步骤拆解
1. 定义关键数据指标
我们需要从数据库和前端请求中获取三个核心值:
current_pages:前端传来的用户当前阅读到的总页码(比如首次请求30,次月请求55)user_max_pages:数据库中记录的该用户对这本书的历史最高阅读页码(对应现有结构中的script.max_pages)book_total_pages:书籍的总页码(对应script.full_pages)
2. 计算有效新增页数
首先对前端传来的current_pages做合法性校验(避免超过书籍总页数或负数),然后计算新增页数:
// 合法性校验:限制在0到书籍总页数之间 const valid_current_pages = Math.max(0, Math.min(current_pages, book_total_pages)); // 计算新增页数:只有当前页码超过历史最高时才计入 const added_pages = Math.max(0, valid_current_pages - user_max_pages);
3. 更新数据库记录
根据added_pages的值决定是否更新:
- 如果
added_pages > 0:- 更新
script.max_pages为valid_current_pages(更新历史最高进度) - 定位到当前年份和月份的记录(如果对应的年份/月份不存在,需要先创建)
- 将该月份的
pages字段加上added_pages - 同步更新
vpc字段(阅读百分比,公式:(user_max_pages / book_total_pages) * 100)
- 更新
- 如果
added_pages = 0:说明用户在回翻或未阅读新内容,无需更新任何记录
场景验证
我们用你的例子逐一验证:
- 首次阅读(5月,30页):
user_max_pages初始为0,added_pages=30-0=30,更新max_pages为30,5月pages设为30,正确。 - 次月阅读到55页:
user_max_pages是30,added_pages=55-30=25,更新max_pages为55,当月pages设为25,正确。 - 回翻场景(从30到29):
valid_current_pages=29 < user_max_pages=30,added_pages=0,不计数,避免错误扣减。 - 跳页场景(10→15→14→16):
- 10→15:added_pages=5,计入当月,max_pages更新为15
- 15→14:added_pages=0,不计数
- 14→16:added_pages=1,计入当月,max_pages更新为16
完全符合需求,既不会漏记跳页的新增,也不会回翻错误计数。
数据库操作示例(JavaScript/MongoDB)
假设我们用MongoDB操作,伪代码如下:
// 假设获取到用户ID、书籍scriptID、当前日期 const userId = "CCYSYXf"; const scriptId = "-VQD0"; const now = new Date(); const currentYear = now.getFullYear(); const currentMonth = now.getMonth(); // 注意:JS中月份是0-11,和数据库中的num字段对应 // 1. 查询用户对应的书籍记录 const userRecord = await User.findOne({ user_id: userId, "scripts.script_id": scriptId }); const script = userRecord.scripts.find(s => s.script_id === scriptId); const userMaxPages = script.max_pages; const bookTotalPages = script.full_pages; // 2. 计算新增页数 const validCurrentPages = Math.max(0, Math.min(current_pages, bookTotalPages)); const addedPages = Math.max(0, validCurrentPages - userMaxPages); if (addedPages > 0) { // 3. 更新历史最高页数 script.max_pages = validCurrentPages; // 4. 定位或创建当前年份的记录 let yearRecord = script.data.find(y => y.year === currentYear); if (!yearRecord) { yearRecord = { year: currentYear, months: Array.from({length:12}, (_, i) => ({ num: i, pages: 0, vpc: 0 })) }; script.data.push(yearRecord); } // 5. 更新当月页数和百分比 const monthRecord = yearRecord.months.find(m => m.num === currentMonth); monthRecord.pages += addedPages; monthRecord.vpc = (script.max_pages / bookTotalPages) * 100; // 6. 保存到数据库 await userRecord.save(); }
这样就能实现完全符合需求的业务逻辑,同时覆盖所有边缘场景。
内容的提问来源于stack exchange,提问作者Michal Gally
相关产品推荐
相关产品推荐

