fix(友链): 修复申请「通过不了/删不掉」;feat(评论): 通知按文章作者分派
## 友链自助申请(通过不了 / 删除不掉)
根因:admin.js 全局事件委托把 data-id 一律 parseInt,
而友链申请 id 是字符串(lamus5uptzcdam)→ NaN → JSON 成 {"id":null}
→ 后端 String(null||'') 为空 → 400 id and action required,查看/通过/拒绝全失效。
引入于 299ab57e(10-04 归档 rss-robot 时;后台只有友链申请用字符串 id)。
- admin.js:纯数字才转数字,其余原样(评论/用户/站点按钮请求完全不变)
- admin.js:待审卡片加「删除」按钮
- links.ts:新增 action:'delete'(不受「已处理过」限制,处理过的也能删)
- links.ts:approve 改为先写友链再改状态 + URL 去重(重试幂等)
- links.ts:已是目标状态时返回 {ok:true,already:true},不再 409
—— 否则网络抖动后重试会让用户以为「怎么点都通不过」
## 评论通知按文章作者分派
编辑角色(女朋友)写的文章,评论通知改发给她,不再打扰博主。
不需要「文章→作者」同步表:Hugo 模板把 author_id 注入 artalkConfig,
artalk.js 已有的 fetch 拦截器把它塞进评论提交体,Worker 直接读。
- artalk.html:artalkConfig 增 pageAuthorId(老文章 0)
- artalk.js:提交评论时带上 author_id(读 window.artalkConfig,防 PJAX 过期)
- comments.ts:createComment 解析 author_id 并传给通知
- mail.ts:收件人改为「这篇文章的主人」——作者非管理员且开了邮件则发给他,
否则回退博主;已被回复通知过 / 作者本人评论自己的文章都不重复发
- mail.ts:增一行收件人决策日志,便于线上排查
验证:Worker tsc 通过;Hugo 构建通过;artalk.js 语法通过;
友链本地跑通(通过 200 → 再通过 already:true → 友链仅 1 条 → 删除 200 → 再删 404)。
This commit is contained in:
1 parent
24f68040c2
commit
57bd4ea737
6 files changed
+124
-25
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import type { Env, CommentRow, UserRow } from '../types';
|
||||
import { findUserById } from './db';
|
||||
import { formatDateCN } from './util';
|
||||
import { md5Lower } from './md5';
|
||||
import { renderMarkdown } from './md';
|
||||
@@ -404,6 +405,11 @@ export interface NotifyCtx {
|
||||
siteUrl: string;
|
||||
pageTitle: string;
|
||||
pageUrl: string;
|
||||
/**
|
||||
* 当前页文章作者的 user id(拿不到则是 0/undefined)。
|
||||
* 文章作者不是博主时(例如「编辑」角色写的文章),新评论通知改发给他。
|
||||
*/
|
||||
pageAuthorId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,12 +453,26 @@ export async function notifyByEmail(env: Env, c: NotifyCtx): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// --- 管理员(用 MAIL_ADMIN,不复用 ADMIN_EMAIL)
|
||||
// --- 这篇文章的主人(默认博主;文章作者另有其人时发给他)
|
||||
// 背景:编辑角色(女朋友)也有发布权限,她文章下的评论不该再来打扰博主。
|
||||
// pageAuthorId 由前端提交评论时带上(Hugo 模板 → artalkConfig → fetch 拦截器),
|
||||
// 这样不需要任何「文章 → 作者」的同步表。
|
||||
// 只在作者确实是「另一位写作者」时才改派:管理员 / 没开邮件 / 邮箱非法一律回退给博主,
|
||||
// 免得把通知发丢了。
|
||||
const adminTo = (env.MAIL_ADMIN || '').trim();
|
||||
let ownerTo = adminTo;
|
||||
let ownerNick = '博主';
|
||||
if (c.pageAuthorId) {
|
||||
const u = await findUserById(env, c.pageAuthorId);
|
||||
if (u && !u.is_admin && u.receive_email && u.email && u.email.includes('@')) {
|
||||
ownerTo = u.email;
|
||||
ownerNick = u.name || '作者';
|
||||
}
|
||||
}
|
||||
if (
|
||||
adminTo.includes('@') &&
|
||||
adminTo.toLowerCase() !== c.author.email.toLowerCase() &&
|
||||
(!c.parentAuthor || c.parentAuthor.email.toLowerCase() !== adminTo.toLowerCase())
|
||||
ownerTo.includes('@') &&
|
||||
ownerTo.toLowerCase() !== c.author.email.toLowerCase() &&
|
||||
(!c.parentAuthor || c.parentAuthor.email.toLowerCase() !== ownerTo.toLowerCase())
|
||||
) {
|
||||
const input: AdminMailInput = {
|
||||
siteName: c.siteName,
|
||||
@@ -462,10 +482,10 @@ export async function notifyByEmail(env: Env, c: NotifyCtx): Promise<void> {
|
||||
comment: c.newComment,
|
||||
commenterNick: c.author.name,
|
||||
commenterEmail: c.author.email,
|
||||
adminNick: '博主',
|
||||
adminNick: ownerNick,
|
||||
};
|
||||
targets.push({
|
||||
to: adminTo,
|
||||
to: ownerTo,
|
||||
subject: adminMailSubject(input),
|
||||
html: adminMailHtml(input),
|
||||
fromName,
|
||||
@@ -474,6 +494,14 @@ export async function notifyByEmail(env: Env, c: NotifyCtx): Promise<void> {
|
||||
|
||||
if (!targets.length) return;
|
||||
|
||||
// 排查用:一条日志看清「这封通知发给了谁、为什么」——文章作者另有其人时
|
||||
// 收件人会是作者本人而不是博主,出问题时先看这里。
|
||||
console.log(
|
||||
'[mail] 收件人 =', targets.map((t) => t.to).join(', '),
|
||||
'| 文章作者 id =', c.pageAuthorId || 0,
|
||||
'| 本地通知收信人 =', ownerTo || '(空)',
|
||||
);
|
||||
|
||||
for (const t of targets) {
|
||||
if (!(await mailQuotaOk(env))) {
|
||||
console.warn('[mail] 已达当日发信上限,跳过');
|
||||
|
||||
Reference in new issue
Block a user