perf(user): 关注结算异步化并去除冗余勋章评估
This commit is contained in:
@@ -1,34 +1,33 @@
|
||||
## 背景结论(回答"为什么没接入")
|
||||
## 目标
|
||||
|
||||
Toast 系统(notyf)其实已在所有前台页面全局加载(handle `aksrt-notyf`,`assets/js/notyf.js` 暴露 `window.notyf(message, type)`),公开主页上举报、面板加载失败也都在用。真正的缺口:
|
||||
把"点关注"从同步跑完整结算链(积分+勋章×3遍+等级,约几十条 SQL)优化为:接口只写关注表立即返回,结算在响应送达客户端之后执行。
|
||||
|
||||
1. **关注/取消关注成功时零反馈**:`assets/js/follow.js:40-42` 成功后只翻转按钮状态,不调用 `notyf()`(对比文章页点赞/收藏 `article.js:225/250` 成功失败都有提示)——这是"页面没接 Toast"观感的来源。
|
||||
2. **依赖声明不规范**:`author.js` 调用了 7 处 `notyf()`,但 handle `aksrt-author`(`ScriptsPart1b.php:335`)只声明 `['loader_js']`,靠全局加载碰巧可用。
|
||||
3. **相邻 bug**:`data-aksrt-follow` 按钮在文章页作者栏(`single-author-bar.php:116`、`aksrt-single-render.php:442`)、WidgetSystem 用户卡(`UserRenderer.php:102`)、身份铭牌(`aksrt-identity.php:226`)等多处渲染,但 `follow.js` 只在用户中心/公开主页路由注册 → 这些位置按钮是死的(用户已确认一并修复)。
|
||||
## 改动内容(3 个文件)
|
||||
|
||||
## 改动内容
|
||||
### 1. `src/User/Metrics.php` — 删除冗余订阅
|
||||
`on_user_followed()`(Metrics.php:93-98)只做 `reevaluate_medals(following_id)`,而 `BadgeAutoAward::on_follow` 已经评估过该用户——这是同一请求内的第 3 遍重复评估。删除该方法和它的 `add_action` 注册(Metrics.php:34)。`reevaluate_medals` 方法本身保留(点赞/浏览等其他钩子仍在用)。
|
||||
|
||||
### 1. `assets/js/follow.js` — 补齐成功 Toast(核心)
|
||||
成功分支(`updateFollowButton(...)` 之后)增加:
|
||||
```js
|
||||
notyf(isFollowing ? '关注成功' : '已取消关注', 'success');
|
||||
```
|
||||
遵循 article.js 点赞/收藏既有惯例:客户端写死文案、两种状态都用 `success`(后端 `follow_toggle` 不返回 message,与点赞/收藏接口一致)。
|
||||
### 2. `src/User/BadgeAutoAward.php` — 删除对"关注者"的无效评估
|
||||
`on_follow()`(BadgeAutoAward.php:61-68)同时评估关注者和被关注者,但 `Badges::metric_value` 的全部指标分支(registration_time/checkin/new_post/comment/**followed(被关注数)**/like/views/pay_income/pay_rebate)没有任何一个依赖"关注了多少人"——关注者评估必然零产出。改为只评估 `$following_id`(保留双参数签名以兼容钩子,`unset($follower_id)`)。
|
||||
|
||||
### 2. `src/Core/ScriptsPart1b.php` + `src/Core/ScriptsPart1c.php` — follow.js 提升为全局注册
|
||||
- 删除 `ScriptsPart1b.php:318-328` `$is_profile_page` 块内的 `aksrt-follow` 注册;
|
||||
- 在 `ScriptsPart1c.php` 全局栈(`aksrt-runtime` 注册之后,约 165 行处)全局注册,依赖 `['aksrt-notyf', 'aksrt-runtime']`——显式声明依赖 `aksrt-runtime` 是因为 `aksrtData`(REST 地址 + nonce,follow.js IIFE 解析期就要读)localize 在该 handle 上,把目前"靠 footer 打印顺序碰巧正确"变为确定的依赖顺序。
|
||||
- 效果:文章页作者栏、任意位置的用户卡片关注按钮恢复可用,并获得同样的 Toast 反馈。脚本仅 ~100 行、单个委托点击监听,全局加载成本可忽略(与已全局加载的 notyf/runtime/core modules 一致)。
|
||||
### 3. `src/User/Follow.php` — 结算钩子延迟到响应之后
|
||||
`follow()` 里的 `do_action('aksrt_user_followed', ...)`(Follow.php:50)改为经 `register_shutdown_function` 延迟执行:关闭回调里先调 `fastcgi_finish_request()`(PHP-FPM 下存在)把响应立即送达客户端,再触发钩子跑积分/勋章/等级结算。新增一个 `private static function defer_action(string $hook, int ...$args)` 辅助方法。
|
||||
|
||||
### 3. `src/Core/ScriptsPart1b.php:335` — aksrt-author 显式声明 notyf 依赖
|
||||
`['loader_js']` → `['loader_js', 'aksrt-notyf']`。
|
||||
- 非-FPM 环境(无 `fastcgi_finish_request`):退化为 shutdown 时机同步执行,行为与现状等价,无回归。
|
||||
- 不用 `wp_schedule_single_event`:WP-Cron 粒度不可控(禁用循环回执的站点要等系统 cron,积分勋章到账会延迟数分钟),shutdown 方案在所有环境都能即时结算。
|
||||
- `aksrt_user_followed` 仅 Follow.php:50 一处触发,4 个订阅者全部按传入 ID 工作、不依赖请求上下文,延迟执行安全。
|
||||
- 效果:关注接口响应路径只剩 WP REST 启动 + 1 次 SELECT + 1 次 INSERT + 1 次 COUNT(全部命中索引),勋章评估从 3 遍降为 1 遍且不再阻塞响应。
|
||||
|
||||
## 不在本次范围
|
||||
|
||||
前端乐观更新(点击瞬间翻转按钮、失败回滚)——上轮标注为可选项,用户未明确要求;异步化后反馈延迟已大幅下降,且与全站点赞/收藏的交互模式保持一致。需要可后续单独做。
|
||||
|
||||
## 验证
|
||||
|
||||
- `php -l` 检查两个改动的 PHP 文件。
|
||||
- 浏览器实测(桌面 + 移动):公开主页关注/取消关注弹出 success Toast、按钮翻转、粉丝数更新;未登录/网络失败路径弹 danger Toast;文章页作者栏关注按钮可点击且有提示;Tab 无刷新切换不受影响。
|
||||
- `node --test tests/widget-system/post-visual-contract.test.cjs` 确认无回归(未改标记,应通过)。
|
||||
- `php -l` 检查 3 个改动文件。
|
||||
- 浏览器实测:关注点击后按钮/Toast 应明显变快(仅剩接口往返);稍后刷新可见积分/勋章/等级照常到账(结算仍在同一请求生命周期内完成,只是后置)。
|
||||
- 取消关注路径不受影响(本就无钩子)。
|
||||
|
||||
## 提交
|
||||
|
||||
单条提交,遵循仓库 Conventional Commit 风格:`fix(frontend): 关注操作接入 notyf 成功提示并将关注脚本改为全局加载`。
|
||||
单条提交:`perf(user): 关注结算异步化并去除冗余勋章评估`。
|
||||
Reference in New Issue
Block a user