介绍一个多人划线标记功能
想法
灵感来源于某次逛公众号文章的时候,在文章中偶然看到了一个下划线,经过它时还会显示多少人划线标记。感觉这个功能其实对博文也挺方便的,因为都有评论系统,感觉可以通过评论用户信息做一个多人划线标记功能,自己留作标记的同时也方便其他浏览文章的博友发现和标记文章主要相关内容。
众所周知我目前用的平台是 wordpress,所以该功能也是基于 php 环境下进行开发的,由于标记数据储存在本地而非数据库中,可以灵活应用于各类基于php框架的博客系统上(如typecho、zblog、emlog等)。唯一一点是使用了 wordpress 的文章 id 来区分不同文章页面(关于这点其实可以使用加密 location.pathname
发送到后端作为文章别名区分,后续版本可能以此更新 已更新(默认url别名),执行标记后请勿随意修改url:*切换请求标识符(postID)可能导致清空本地记录继而误删远程数据),故若使用其他平台需要修改前端请求中的pid参数(现可选携带参数:postId
初始化,默认 location.pathname
)
功能简介
划线标记功能结构由文章—用户—标记三部分组成,通过wordpress文章id区分:同一篇文章下可以理论上可以存在不限量标记,但同一个用户(md5邮件区分)默认情况下仅能存在3个标记(可携带自定义参数初始化标记)。而同一个标记(内容)仅能在该文章中存在一次。(若通过某种手段重复标记某段已存在于远程记录时,后端会返回标记已存在的错误信息),另若当前选中文本在当前段落中存在多个相同字符时,前端会阻止用户提交标记。
本着只要能把功能复现就行的想法,在持续一周左右的时间后正式开始测试,目前该功能已集成到2BLOG主题最新的 #v1.3.9.2
版本中,后续将对其进行持续迭代更新,下面讲下简单实现思路。
实现思路
前端直接用的 getSelection api 执行选中标记操作(之前本想做跨浏览器兼容,后面想想太麻烦,先实现可以用了再说,反正又不是上线的东西 后面可以慢慢迭代无所叼谓),用户信息存了本地cookie(刚开始做的内容储存,后来改为用户本地校验内容)。
后端用的东西基本和我之前那篇实现gpt的思路基本是一致的,都是本地储存。唯一只是多了部分用户校验,因为涉及到用户新增和删除操作问题(毕竟所有人在评论后都可以对文章进行标记或删除)暂时只能先这么弄(虽然目前配置了文章标记次数限制,不过并没有做黑白名单限制)。
WordPress 简单实现 chatGPT 文章摘要
灵感来源于之前在浏览 HEO 博文时候偶然看到文章前有一段 AI 摘要,第三人称以打字形式来简述文章内容还是蛮酷的~ 于是拟了个把这个功能集成到 2BLOG ...
用户校验
目前做了两个信息校验,
一个是最基本的邮件mail(明文验证,其实刚开始的方案是有md5来做,后来因为新增了显示标记用户 gravatar 头像的需求所以不得不放弃该方案,取而代之的只能是远程明文对比验证。但是,为了防止出现邮件明文暴露后造成伪造请求的情况,在执行部分敏感操作时必须携带储存在用户本地的 timestamp 时间戳(明文)与储存在远程服务器中的ts(加密,防止远程ts暴露后获取到对应的本地ts明文)进行校验,通过后再放行相关操作。
但ts交互验证有一个明显的坏处就是:如果标记浏览器与执行操作的浏览器环境不同(即本地cookie无相关ts记录)哪怕当前是用户本人操作也无法通过远程ts验证,目前应对这种情况目前做了用户操作提示与浏览器user-agent记录(可查看对比记录),暂无具体替代解决方案。
其他
这个功能目前处于测试阶段,使用过程中有任何bug欢迎反馈哟/doge。(*另附一些常用的初始化参数如下(所有参数值均为默认值!具体参数等内容可前往 github 查看)
// 携带参数初始化
new marker.init({
static: {
postId: window.location.pathname, // 页面标识符(可选,文章唯一ID)
apiUrl: "mark.php", // 后端 mark.php 文件地址(可选,缺省同一目录)
md5Url: "md5.js", // 用户 mid 初始化 md5 资源(可选,缺省同一目录)
avatar: "//gravatar.cn/", // 用户头像 cdn(可选,默认 cravatar)
},
class: {
blackList: ['chatGPT','article_index','ibox'], //'', 'chatGPT,article_index',
},
element: {
effectsArea: document.querySelector('.content'), // 可选区域(可配合 blackList 使用)
commentArea: document.querySelector('#vcomments textarea'), // 评论区域
commentInfo: {
userNick: document.querySelector('input[name=nick]'), // 评论用户
userMail: document.querySelector('input[name=mail]'), // 评论邮箱
}
},
});
插件
现已集成插件到 github:
2Broear/marker: a local-storage(php) based original javascript api marking-off plugin. (github.com)
todos
一些預計添加或修復的待辦事項
約束後端請求頻率,(新增延迟文件锁),修復并發請求失敗但返回已完成問題。问了一圈 gpt 没解决,暂时在前端做请求限制与延时。- 使用 localStorage 修复了授权用户操作失败(弱网、并发)后再次访问时自动更新本地/远程记录。bug:
标记后立即刷新页面会导致本地记录(已记录)无法匹配远程(等待返回)被删除,后续刷新页面后导致远程记录(已返回)无法匹配本地记录(已删除)被删除。(可在切换评论系统后,通过读取本地记录仍可执行标记删除等操作) - 更新方案(v1.3.9.5):标记或删除后等待远程响应,返回后再写入(补全)或删除(更新)本地记录,对应逻辑如下:
- 新增标记:(未响应,新增本地记录)—>刷新页面(未响应,删除本地记录)—>返回数据(已响应,对比本地记录)—>远程记录中 未找到 本地记录—>新增本地记录
- 删除标记:(未响应,删除本地记录)—>刷新页面(未响应,新增本地记录)—>返回数据(已响应,对比本地记录)—>本地记录中 不存在 远程记录—>删除本地记录
- 使用 localStorage 修复了授权用户操作失败(弱网、并发)后再次访问时自动更新本地/远程记录。bug:
- 修复本地、远程标记请求上限多步验证。
- 新增更多自定义初始化携带参数配置。
- 新增自定义标记文本注释功能。
- 支持多人重复(未注释)标记,并显示(前三)标记用户头像。
- 更新UI/UE,更好的适配暗黑模式
- 支持 SSE 服务端 api 推流(递增显示标记动画)bug: 每次接收数据后输出时未即使更新data