最新动态 v1.4.2:一行播报「谁下载了、谁加入了、谁登录了、谁访问了」


它只占一行(桌面 38px、手机 34px),把站点上刚刚发生的四类事按时间倒序滚出来。不轮询数据库、不加页面骨架、装上就有,是资源站最便宜的那种「让人感觉这站是活的」。整包 28874 字节、8 个文件。

v1.4.2这一版干了两件事:把明亮模式的品牌色全部撤掉(文字回归正文色,层级改由字号和字重承担),以及把左侧那枚小圆点强化成三层叠加的呼吸灯——它是整条里唯一的品牌色落点。为什么这么改,第九节讲。

一、它长什么样

首页上就一行:

最新动态  Z z***e · 刚刚 下载了《宝塔面板从零部署网站源码》    今日 1,286 次

四个细节让它不像一块死板的信息牌:

  1. 一条一条滚。旧条往上滑出、新条从下方弹入,滑到六成时过冲一点再回落——就是那下「跳」的手感。两行绝对定位叠在同一个窗口里,所以看着是连续的滚动带,不是内容在刷新。
  2. 四类事一起播。下载、注册、登录、访问混在同一条时间轴上按先后滚,不用切换页签,也不分区块。
  3. 左右两端是活的。左边那枚圆点是呼吸灯(缩放 + 透明度 + 向外扩散的柔光晕,2 秒一轮);右边「今日 1,286 次」在数据刷新且数字变化时会弹一下(520ms)。
  4. 点得动。播报里只有下载这类带资源页,整行是链接,点进去就是那个资源——播报本身就是个入口。注册 / 登录 / 访问没有落地页,保持纯文本,不做无意义的可点区域。

悬停会暂停轮播(鼠标移开继续);页面切到后台时完全不动画,省电,也避免切回来时一次性连跳好几条。

窄屏(≤767px)自动收窄:前缀文字和「今日」二字藏起来只留呼吸点与数字,行高降到 34px,字号 13px,把宽度全让给资源名。

二、四类动态,数据从哪来

这是装之前最该搞清楚的一张表。四类事件的数据来源完全不同,其中「访问」是最特殊的一个:

事件 文案 数据来源 说明
download 下载了《…》 钩子 guaqi_count_updated 官方下载入口触发;只认 type === 'resource',浏览量等其它计数走同一个 action,必须过滤掉
register 加入了本站 钩子 user_register 第三方聚合登录首次建号时同样会触发,不需要额外对接
login 登录了 钩子 wp_login 账号密码登录与第三方授权登录都走到这里;同一用户 30 分钟内只记一次
visit 访问了本站 只读官方签到表 {prefix}guaqi_checkins 不自己记录,直接读官方数据;官方已按「每人每天一条」去重,天然不刷屏

四类事写进同一张自建表 {prefix}guaqi_download_feed(访问类除外,它在官方表里),查询时两个来源各自带着时间窗查出来,在 PHP 侧合并排序,不做 SQL UNION。这样两边都能走自己的索引,时间语义也不用在 SQL 里绕。

三、为什么「访问」要去读官方签到表

这一节是给想自己造轮子的人看的,它解释了一个很容易踩空的坑。

正常的 WordPress 站点要记「有人访问了一页」,挂 wp 或 template_redirect 就行了。但瓜奇这套是 headless:前端是 Nuxt,WordPress 只提供 GraphQL 接口,并不 serve 页面。也就是说真实访客打开网页时,WordPress 那几个钩子根本不会触发——挂上去会得到永远为空的记录,而且很难看出是错的。

那前端访问时到底留下了什么?前端每次页面访问会调一个 gqPageVisit mutation,登录用户会落进 {prefix}guaqi_checkins,官方已经按「每人每天一条」帮你去重了。那就是「今天谁来过」的权威数据——再自己记一份只是重复劳动。

代价也要说清楚:官方那张表只存了 frontend_url,没存 path。所以拿不到「访问了哪一页」,只能得到「今天谁来过」。这个限制在代码里、在调试接口里都明写着,不是漏做。

顺带一个容易误判的点:官方有一张看起来很合适的表 {prefix}guaqi_feed(Common/Feed 模块),但它其实是内容动态流——kind 只收 publication / comment,且强制要求 postId >= 1。注册、登录、访问这三类没有 postId 的事件根本塞不进去。所以自建表是正解,别再试着去接官方 Feed 了。

四、装它:三步,加一次验收

  1. 装包。瓜奇 builder → 插件 → 安装 guaqi-download-feed-1.4.2.zip。
  2. 拖模块。把「最新动态」拖到想要的位置——首页顶部、资源列表上方、侧栏都行。它只有一行,放哪都不挤,也不绑定首页,任意页面都能拖。
  3. 点发布。
第 3 步最容易忘。这套站是 Nuxt SSR,builder 里改了不点「发布」,前台一个字都不会变。改完样式、改完设置之后同样要重新发布。

验收方法:用一个非管理员账号去下载一个资源,几秒之内首页那条播报应该就出现了。别用管理员账号测——原因见第七节的「噪音过滤」,而且站长的登录/访问本来就被特意过滤掉了。

刚装完是空的,这是正常的。因为「谁下载了什么」这个数据在官方那边根本不存在(原因见第六节),历史补不回来,动态从装上的那一刻开始积累。前几小时可能只有一两条,甚至什么都没有——别急着判断它坏了,先看第二节那张表确认钩子类型,或者直接打第十节的调试接口。

五、设置项速查(11 项)

模块设置里能改的都在 builder 右侧面板:

设置 范围 默认 说明
播报条前缀文字 文本(40 字内) 最新动态 左边那句,留空则只留呼吸点
轮播池条数 3–20 8 池子越大,同一条再出现的间隔越长
播报间隔(秒) 2–15 4 太快看不清,太慢没有动态感,4 秒是试出来最舒服的
显示今日动态条数 开 / 关 开 关掉右边会清爽,但也少了一半「活」的观感
播报「谁下载了」 开 / 关 开 四类事件独立开关。全关掉会自动退回只看下载,避免请求落空
播报「谁注册了」 开 / 关 开
播报「谁登录了」 开 / 关 开
播报「谁访问了」 开 / 关 开
用户名脱敏 开 / 关 开 zenghe → z***e。建议保持开
显示资源标题 开 / 关 开 关掉只剩「某人下载了」,适合极度保守的场景
数据刷新间隔(秒) 0–600(0 = 关) 60 刷新时游标按条目 id 跟随当前那条,不会跳回第一条

想改呼吸灯的颜色(默认品牌橙 #FF4612),在主题 CSS 里覆盖两个变量——光晕色得一起改,因为十六进制换不出 rgba:

:root {
  --gq-dlfeed-accent: #FF4612;
  --gq-dlfeed-accent-glow: rgba(255, 70, 18, 0.45);
}

另外还有 --gq-dlfeed-edge(左侧竖条)、--gq-dlfeed-avatar-fg(头像字色)、--gq-dlfeed-skel(骨架条)三个中性色变量,以及 --gq-dlfeed-row-h(行高,默认 38px)——改高度只改这一个变量就够,切换动画用的是绝对定位 + 百分比位移,不吃行高。

六、一个必须先说的坏消息:历史补不回来

如果你以为「我站早有下载记录了,装上直接就能看到历史」,这盆冷水得先泼:官方没有「谁下载了什么」这个数据,历史补不回来。

我翻过官方源码,下载成功后它只做两件事(入口在 ResourceDownload::mutateAndGetPayload()):

官方写下的数据 表 / 字段 能算出什么
当日配额扣减 {prefix}guaqi_daily_downloads 某人某天下了几次(只有次数,没有对象)
资源计数自增 post_meta.guaqi_count.resource 某资源被下过几次(只有总数,没有对象)

两边都没有「谁在什么时候下了哪一篇」。合起来能算总量,拆不出明细。所以这插件的动态从装上的那一刻开始积累。

顺带纠正一个常见误解:下载走的是每日次数配额,不扣积分。所以积分流水里同样捞不到下载记录——别去那边找。

七、我替你定的六个取舍

决定 为什么
30 秒缓存,不做「写入即失效」 首页 QPS 最高,不能让每个访客都打一次库。而缓存键里含条数与开关,没法枚举删除;若改用自增版本号做键,每次事件都会新增一个 transient,高流量下会把 options 表撑大。30 秒自然过期 + 前端自己刷新,体感已经够低。
只有「今日计数」那一档缓存会在写入时主动清掉,因为它最需要即时。
同一个人只留最新一条 否则有人连下 5 个源码,整屏都是他一个人。
7 天时效窗 首页挂着「30 天前」的播报,比不显示更显冷清。超窗的记录只在库里留着,不参与展示。
登录 / 访问排除管理员,下载 / 注册保留 登录和访问是高频、低信息量的事件,站长天天登后台会把它整条淹没;下载和注册是低频、高信息量的,站长偶尔出现一次反而更真实。
细节:去重打标只在通过过滤之后做——站长的登录被跳过后,他更早的那条下载仍然有机会出现在播报里。
用户名默认脱敏 zenghe → z***e,两字名 阿伟 → 阿***。下载行为被公开本身就是隐私暴露,脱敏是最低成本的体面。设置里可以关。
后台 90 天自动清理 每天跑一次 cron,单次最多删 5000 行,表不会无限涨。

八、三次线上事故的根因(这节最值钱)

下面三条都是真在线上炸过的,也都已经修在包里。如果你在用别人的插件,或者自己写类似的东西,这三条大概能帮你省一个晚上。

8.1 升级之后,下载动态整块消失,只剩「谁登录了」

现象:1.2.0 上线后,播报条只轮播登录事件,下载类一条都不剩。而 1.1.0 是好的。

排查一遍:钩子和签名都对、客户端没做二次过滤、三端事件白名单一致。唯一变的是查询条件——1.1.0 是 WHERE created_at >= X AND post_id > 0,根本不看 event_type;1.2.0 扩成四类事件后变成 WHERE created_at >= X AND event_type IN (...)。

根因:event_type 这一列是 1.2.0 新加的,靠 dbDelta 的 ADD COLUMN 给存量行补默认值。但 dbDelta 解析 CREATE TABLE 时会 trim 掉行尾的引号,生成的 ALTER 可能不带 DEFAULT——存量行于是停在空字符串,被新查询整批挡掉。老数据全在那儿,只是查不出来了。

修法:表结构版本 2 → 3,升级时无条件跑一次归类(幂等,全是合法值时更新 0 行):

UPDATE {prefix}guaqi_download_feed SET event_type = 'download'
WHERE event_type IS NULL
   OR event_type NOT IN ('download','register','login','visit')
这个坑的教训是通用的:用 dbDelta 给存量表加列,别指望默认值一定落到老行上。加了列又用它做过滤条件,就得自己补一次回填。
另外,升级逻辑挂在「表结构版本」的门闩上——只递增版本号才能让已装旧版的站点重跑一遍,光改代码不涨版本号是没用的。

8.2 点播报跳去了后端域名

现象:首页播报里点「谁下载了《瓜奇文字格子广告插件》」,跳进了 www.q0di.top/瓜奇文字格子广告插件.html——后端 WordPress 的文章页,而不是前站的资源页。

根因:取链接用了 get_permalink($post)。它是按后端 WordPress 域生成的(后端域/中文标题.html 那种形态),而前站是另一个域、路由是 /article/{id}——两条完全不同的路,域名和结构都对不上。

修法:改用官方 guaqi_get_single_slug($post)——官方给前站卡片写 url 用的就是这个函数,会带语言前缀、遵循站点的 slug 结构,那才是「文章 → 前站地址」的权威映射。取到的路径统一裁成站内相对路径,拿不到时兜底 /article/{id},再拿不到就返回空串(干脆不生成链接,保持纯文本)。

一条能复用的结论:瓜奇 headless 场景下,凡是「文章 → 前站可点地址」,一律用 guaqi_get_single_slug(),绝不要用 get_permalink()。
还有个附带好处:url 是渲染时实时查的、不入库,所以历史记录会被一起修正,不需要清表。

8.3 空数据永远卡在骨架条上

现象:站点冷启动时播报条一直转圈,看起来像坏了。

根因:原代码只判断了「请求是否失败」,没区分「还在加载」和「加载完了但确实没数据」。少这一个分支,空态就永远等不到。

修法:把三种状态拆开——首屏加载中给骨架条;拿到响应但没有条目(或请求失败)给空态文案「暂时没有新的动态」;有数据才渲染行。现在这三种情况在代码里是三个明确的返回分支,测试也专门盯着这条。

九、为什么整条只有一个橙点

v1.4.2 把明亮模式里的品牌色全撤了,只留左侧一枚呼吸灯。这不是审美偏好,是算过对比度的:

  • 品牌橙 #FF4612 落在白底上,对比度只有 3.4,达不到 13–15px 正文要求的 4.5 门槛。拿它写字,看着「品牌感很足」,实际读起来发飘——这个问题在手机小字号上尤其明显。
  • 所以文字全部改成 color: inherit,直接跟随站点正文色。层级改由字号 + 字重 + 透明度承担:前缀 13px/600、名字 500、相对时间 12px/0.5 透明度、今日数字 15px/600。
  • 整条唯一的品牌色落点就是那枚 7px 呼吸灯。它的职责是「正在发生」的信号,靠三层叠加把注意力拽过去:本体 scale(1 → 0.8) + 透明度 1 → 0.5 + 一圈从 0 0 0 0 扩散到 0 0 0 6px 的柔光晕。
  • 竖条、头像、骨架条全部走中性灰——保留结构感,但不跟呼吸灯抢色。

文字用 inherit 还有个额外红利:站点如果靠 class 或属性切深色主题,它也会自动跟着变,不再只认系统的 prefers-color-scheme。

另外,系统开启「减弱动态效果」时:呼吸灯关掉动画但保留一圈静态柔光(「正在发生」的信号不该彻底消失),数字不跳,行的切换从位移改成 300ms 淡入淡出。

十、装上没显示?先打这个接口

这插件对外只有两个 action:plugin.guaqi.downloadFeed.list 负责取播报数据,plugin.guaqi.downloadFeed.debug 是排障入口。后者带一个密钥保护,一次性告诉你:表建没建、各类事件各有多少行、钩子挂上没有、当前身份是谁、签到表读得到多少、最近 10 条原始流水。密钥只存在于服务端,不会下发到浏览器。

mutation {
  gqDownloadFeedDebug(input: { key: "gqfeed-diag-9f3c1a7b24e8" }) {
    result
  }
}

返回值里看几个关键字段就能定位卡在哪:

字段 含义 异常时怎么办
table.exists 流水表建好了没 false → 插件没真正启用,或数据库用户没建表权限
table.dbVersion 表结构版本 不是 3 → 升级没跑,回看 8.1
table.byEvent 各类事件各多少行 出现空键且行数很多 → 还有别的写入路径没打上 event_type
hooks.guaqi_count_updated 下载钩子挂上了没 false → 插件没加载,或下载走的不是官方入口
identity.user_id 后端认出的用户 为 0 → 这次请求没带上登录态,流水压根不会记
visitSource.recentRows 签到表 7 天内的行数 0 → 前端没有上报访问,或 frontend_url 对不上
latest 最近 10 条原始流水 有记录但前台不显示 → 记录超了 7 天时效窗,或被去重/噪音过滤挡了

十一、想自己改?四个扩展点

1)排除某些用户,不让他们出现在播报里(最常见的是排除管理员、或排除某个测试号):

// 写入前拦截:返回 true 即不记这条流水
add_filter( 'guaqi_download_feed_skip', function ( $skip, $user_id, $post_id ) {
    if ( $user_id === 7 ) return true;                          // 排除某个具体用户
    return user_can( $user_id, 'manage_options' );              // 或者排除全部管理员
}, 10, 3 );

2)让管理员也出现在登录/访问播报里(单人站点会想让页面显得更热闹):

add_filter( 'guaqi_download_feed_exclude_admin_noise', '__return_false' );

3)在别的插件里复用同一份流水(比如自己再做一个「下载排行」):

// 表:{prefix}guaqi_download_feed
// 一行 = 一次事件:event_type / user_id / post_id / resource_index / created_at
// 注意 created_at 是 GMT,排序算龄要用 UTC 口径

// 或者挂官方钩子做别的事:
add_action( 'guaqi_count_updated', function ( $post_id, $type ) {
    if ( $type !== 'resource' ) return;   // 浏览等计数也走这个 action,必须过滤
    // 你的逻辑
}, 30, 4 );

4)把播报条塞进别的页面。模块本身不绑定首页,任意页面都能拖,也可以一个页面放多条。

十二、常见问题

Q:装了,但一直是「暂时没有新的动态」。
先打第十节那个接口看 table.byEvent。如果确实全是 0,检查三件事:① 测试时是不是未登录状态(游客不记流水);② 是不是管理员(登录/访问被过滤掉了,用非管理员账号测);③ 你那几次下载是不是被权限或配额拦下来了(被拦的下载不算)。

Q:播报里出现了我自己测试的下载记录。
正常,下载和注册不排除管理员(故意的,测试痕迹留着更真实)。用第十一节的 filter 排除掉,或者等它过了 7 天自动出窗。

Q:只有 1 条的时候看着怪怪的。
1 条时不滚动、静止显示,这是有意设计的——省掉无意义的空转。等池子攒到 2 条以上就正常滚了。

Q:首页变慢了吗?
不该。列表和今日计数共用一份 30 秒缓存,首页自己的渲染不吃库;真实数据是客户端挂载后才拉的。如果你的首页本来就重,先查别的地方。

Q:能显示游客的下载吗?
不能,也不建议。游客没有稳定身份,做出来就是「某位用户下载了」,没有社交证明价值。同理,游客访问也不进播报——签到表里本来就只有登录用户。

Q:访问动态为什么没有具体页面?
官方签到表只存了来源域名、没存页面路径。详见第三节。想记具体页面得在前端另做上报,那是另一个插件的活。

Q:会不会把访客的名字暴露出去?
默认脱敏(z***e),且登录、访问这两类还会额外过滤掉管理员。想更保守:把「显示资源标题」关掉,或干脆关掉某个事件类型。

十三、还能怎么玩

  • 配排行榜。同一张表按 post_id 聚合就是「本周下载榜」,按 user_id 聚合就是「下载狂人榜」,按 event_type 分组就是「今日活跃构成」。数据都是现成的。
  • 做「实时热度」角标。某资源 24 小时内被下载超过 N 次,就在列表页给它盖一个热门标记。查表就行,不用改这个插件。
  • 注册播报当增长看板。把 register 单独聚合,按天画一条注册曲线——比翻后台用户列表直观得多。
  • 换前缀文案做氛围区分。考研站写「本站动态」、游戏站写「刚刚发生」、社区写「热乎的」——同一个模块,前缀一改气质就变了。
  • 给播报加音效。资源站戏太多会显廉价;但如果是游戏站或直播站,切换时来一声轻响,「活着」的感觉会翻倍。

附录 A:文件清单

guaqi-download-feed-1.4.2.zip          安装包(28874 字节 / 8 个文件)
├─ manifest.json                       模块声明(1 个模块 / 2 个 action / 11 项设置)
├─ wordpress/plugin.php                建表升级 / 四类事件采集 / 合并查询 / GraphQL / 90 天清理
├─ node/server/index.mjs               action 翻译 + SSR 骨架壳
├─ node/client/components/0/index.js   单行播报组件(零依赖,纯展示)
├─ node/client/components/0/style.css  样式(中性底 + 一枚呼吸灯)
├─ i18n/zh-hans.json                   中文词条
├─ i18n/en.json                        英文词条
└─ i18n/es.json                        西语词条

三语词典必须与代码里的兜底文案逐字一致——宿主缺词条时会原样返回 key,这时候就得靠内置中文兜底,两边不一样会闪一下。

附录 B:数据表与索引

表:{prefix}guaqi_download_feed

event_type      事件类型:download / register / login / visit
user_id         事件主体
post_id         关联资源(注册/登录/访问为 0)
resource_index  该资源里的第几个下载项
frontend_scope  前端作用域(多站点/多域名区分用)
created_at      事件时间(GMT,与官方签到表同轴)

索引
idx_time       按时间窗查
idx_type_time  按事件类型 + 时间查
idx_post_time  按资源聚合(做下载榜)
idx_user_time  按人查(去重与排查)
时间基准是 GMT。官方签到表的 created_at 是 GMT,为了让两张表能放在同一条时间轴上排序,本表也统一存 GMT,升级时会把老数据平移一次。所谓「今日」则是按站点本地日期算出来的,比较前会先把本地零点换算成 GMT。

附录 C:版本演进

版本 做了什么
1.0.0 初始版本,只播报下载
1.1.0 改成单行滚动播报条;修空数据卡骨架
1.2.0 从「下载动态」扩成四类事件的站点动态流;表加 event_type,时间基准统一为 GMT
1.3.0 修升级后下载动态整块消失(补 event_type 归类回填,表结构版本 2 → 3)
1.4.0 视觉重做:品牌色锚定方案
1.4.1 修下载条目跳去后端域名(改用官方 slug 映射)
1.4.2 明亮模式去品牌色、呼吸灯强化(当前版本)

安装包:guaqi-download-feed-1.4.2.zip(28874 字节 / 8 文件)。文中数值均取自 wordpress/plugin.php 的常量声明。

下载点可用性1 个下载点,1 个已验证可用
  • 本地下载已验证可用

可用性由站点定时核验,最近一次 2026-10-12 09:42。若某个下载点不可用,可在评论区告知,我们会尽快替换。

本文已于 2026-10-12 提交 百度、IndexNow 的收录通道,以缩短收录周期。
低风险

源码安全检测报告

已检测
100/100
检测引擎 srcscan/1.3-php报告编号 SC-20261012-432423检测时间 2026-10-12 09:43:29内容发布 2026-10-12 09:41:38最新动态 v1.4.2:一行播报「谁下载了、谁加入了、谁登录了、谁访问了」
0高危
1中危
0低危
0提示
结构概览文件 8体积 83.4 KB代码文件 1代码行 1,312
按类别来源情报 1不扣分
后门特征排查8 项特征全部未发现
  • 请求参数直接进入执行函数未发现
  • 请求参数直接进入文件包含未发现
  • 变量函数执行请求参数未发现
  • 请求参数批量覆盖变量未发现
  • 编码载荷后执行(混淆特征)未发现
  • 回连裸 IP 地址未发现
  • 配置预加载文件(隐蔽后门手法)未发现
  • 向文件写入 PHP 代码未发现
命中明细共 1 项
来源情报不扣分
  • 第三方二次打包 / 转发站标记wordpress/plugin.php:807

    包内存在第三方源码站的引流文件、水印页或导流文案。说明这不是原厂原始包,而是被搬运方重新打包过。二次打包是投毒最高发的环节,且无法与官方包比对校验,因此来源可信度必须下调,交付前应逐文件核对。

    第三方转发站标记 / 引流文件:wordpress/plugin.php

    建议:清掉第三方引流文件与标记文件,然后通读一遍被改动过的核心文件,确认除标记之外没有夹带别的改动。

仅「风险项」参与评分,加固建议与来源情报只作呈现

本报告由 8号码库源码安全检测引擎(srcscan)静态扫描生成,用于上架前风险筛查,不构成安全保证。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注