feat(comments): 匿名评论 + 表情最近使用;fix: 自动填充聚焦提示 & 邮件模板回退原版 & 返回顶部改 CSS 动画
- 匿名评论:comments.is_anonymous 列;对外昵称/头像/网址/徽标/等级/IP归属全部脱敏, 真实身份留 users 表(回复通知照发、autofill 不受污染);邮件昵称也用「匿名」防泄露 - 表情包最近使用:面板顶部「最近」栏,localStorage 记录 8 个,零侵入复用 Artalk 插入逻辑 - 匿名开关插在 textarea 与底栏之间独立一行,不挤移动端底栏 - 自动填充:提示改 focusin 触发(原 input+sessionStorage 一次性门导致永不触发); 已填昵称/网址时不覆盖并弹提示 - 邮件模板 UI 回退原版深色气泡设计,保留表情内联尺寸/主题文案等逻辑修复 - 返回顶部:rAF 自绘改 CSS scroll-behavior(滚动期临时挂类),修移动端掉帧
This commit is contained in:
1 parent
090262d278
commit
215929a67f
11 files changed
+587
-207
No files matched your search
@@ -3,9 +3,11 @@
|
||||
*
|
||||
* 场景:很多人隔几个月来评论一次,早忘了上次填的昵称/网址,每次都重新想。
|
||||
* 这个模块做两件事:
|
||||
* 1. 访客开始在昵称框打字时,弹一次 toast 提示「填邮箱可以自动带回来」;
|
||||
* 1. 昵称框一获得焦点就弹 toast 提示「填邮箱可以自动带回来」(90 秒冷却,
|
||||
* 防止反复点进点出刷屏);
|
||||
* 2. 邮箱填完(失焦或格式完整)就问后端:这个邮箱上次评论用的什么昵称/网址,
|
||||
* 拿到后回填到空着的输入框,让老朋友少打几个字。
|
||||
* 拿到后回填到空着的输入框;如果框里已经有内容就不覆盖,也会弹一条
|
||||
* 「欢迎回来」让 TA 知道系统认出了 TA。
|
||||
*
|
||||
* 隐私红线:后端 /comments/lookup **只回昵称和网址,永远不回邮箱**;
|
||||
* 邮箱只作为查询参数发给评论后端(跟提交评论本身一样),不在本地落任何存储,
|
||||
@@ -18,7 +20,7 @@
|
||||
if (window.__atkAutofillReady) return; // PJAX 重复执行防抖
|
||||
window.__atkAutofillReady = true;
|
||||
|
||||
var HINT_KEY = 'atk_friend_hint'; // sessionStorage:提示只弹一次
|
||||
var HINT_COOLDOWN = 90000; // 同一编辑器 90 秒内不重复弹提示
|
||||
var asked = {}; // 查过的邮箱 → 结果,避免重复请求
|
||||
var timer = null;
|
||||
|
||||
@@ -52,12 +54,16 @@
|
||||
}
|
||||
|
||||
function showHint(editor) {
|
||||
try {
|
||||
if (sessionStorage.getItem(HINT_KEY)) return;
|
||||
sessionStorage.setItem(HINT_KEY, '1');
|
||||
} catch (e) { return; } // 存储被禁用就别弹了,宁缺毋滥
|
||||
// 邮箱已经填了就不用提示(提示了也没东西可带出)
|
||||
var email = fieldIn(editor, 'email');
|
||||
if (email && email.value.trim()) return; // 已经填了邮箱,不用提示
|
||||
if (email && email.value.trim()) return;
|
||||
// 冷却门:同一编辑器 90 秒只弹一次,反复点进点出不刷屏。
|
||||
// (曾经用 sessionStorage 做「整个会话只弹一次」,结果很多人再也见不到——弃用)
|
||||
try {
|
||||
var last = editor.__atkHintAt || 0;
|
||||
if (Date.now() - last < HINT_COOLDOWN) return;
|
||||
editor.__atkHintAt = Date.now();
|
||||
} catch (e) { return; }
|
||||
toast('老朋友?填一下邮箱,昵称和网址会自动帮你带回来 ✨', 'info', 4500);
|
||||
}
|
||||
|
||||
@@ -70,20 +76,28 @@
|
||||
if (!name) return;
|
||||
|
||||
var filled = [];
|
||||
var kept = []; // 查到了,但框里已经有 TA 自己填的内容 → 不抢,口头告知
|
||||
// 昵称:空着,或者只打了历史昵称的开头(说明 TA 正在凭印象敲同一个名字)
|
||||
// 才替 TA 补全 —— 已经敲了一个完全不同的名字就别抢,那是故意的。
|
||||
// 才替 TA 补全 —— 已经敲了一个完全不同的名字就别动,那是故意的。
|
||||
if (nick) {
|
||||
var cur = nick.value.trim();
|
||||
var lower = cur.toLowerCase();
|
||||
var lowerName = name.toLowerCase();
|
||||
if (!cur || lowerName.indexOf(lower) === 0) {
|
||||
if (cur !== name) { setVal(nick, name); filled.push('昵称'); }
|
||||
} else {
|
||||
kept.push('昵称');
|
||||
}
|
||||
}
|
||||
if (link && !link.value.trim() && url) { setVal(link, url); filled.push('网址'); }
|
||||
if (url) {
|
||||
if (link && !link.value.trim()) { setVal(link, url); filled.push('网址'); }
|
||||
else if (link && link.value.trim() && link.value.trim() !== url) kept.push('网址');
|
||||
}
|
||||
|
||||
if (filled.length) {
|
||||
toast('欢迎回来,' + name + '!已帮你填好' + filled.join('和') + ' 👋', 'success', 4000);
|
||||
} else if (kept.length) {
|
||||
toast('欢迎回来,' + name + '!你已填好' + kept.join('和') + ',就不帮你改动啦', 'info', 4000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,16 +126,22 @@
|
||||
}
|
||||
|
||||
// ── 事件委托(capture:Artalk 内部可能 stopPropagation)──────────────
|
||||
|
||||
// 昵称框获得焦点就提示(focusin 比 focus 冒泡,靠委托才能一把抓住反复重建的编辑器)
|
||||
document.addEventListener('focusin', function (e) {
|
||||
var el = e.target;
|
||||
if (!el || el.tagName !== 'INPUT' || el.name !== 'nick') return;
|
||||
var editor = editorOf(el);
|
||||
if (!editor) return; // 只管 Artalk 的评论框
|
||||
showHint(editor);
|
||||
}, true);
|
||||
|
||||
document.addEventListener('input', function (e) {
|
||||
var el = e.target;
|
||||
if (!el || el.tagName !== 'INPUT' || !el.name) return;
|
||||
var editor = editorOf(el);
|
||||
if (!editor) return; // 只管 Artalk 的评论框
|
||||
|
||||
if (el.name === 'nick') {
|
||||
if (el.value.trim()) showHint(editor); // 打了第一个字就开始提示
|
||||
return;
|
||||
}
|
||||
if (el.name === 'email') {
|
||||
var v = el.value.trim();
|
||||
if (isEmail(v)) {
|
||||
|
||||
Reference in new issue
Block a user