行为型任务的判定窗口:need_seconds=30 与 max_gap_ms=15000 是怎么配合的
成长体系里最常见的任务是「打开某页停留 N 秒」。它没有回调、没有按钮,做没做由服务端根据心跳判。要脚本化,第一步是把任务对象的真实字段读出来——因为「30 秒」这句话里藏着两个参数。
一、原始返回长这样
GET https://harmonybp.developer.huaweicloud.cn/api/growth/tasks
{
"task_key": "case-view-daily",
"name": "每日浏览一个案例",
"description": "打开任意案例详情页并保持浏览 30 秒",
"evaluator": "dwell",
"period": "DAILY",
"period_key": "2026-11-04",
"points_hint": 10,
"configured": true, "award_enabled": true, "logged_in": true,
"today_status": "done", "record_status": "done",
"completed_at": 1793747113230,
"need_seconds": 30, "max_gap_ms": 15000, "elapsed_seconds": 0
}三个细节值得单拎出来。
其一,max_gap_ms 才是难度所在。need_seconds=30 是累计停留时长,max_gap_ms=15000 是相邻两次心跳允许的最大间隔。也就是说 30 秒必须是「连续的」:每 15 秒内至少上报一次才算数。脚本里只 sleep 30 然后发一次心跳、或者中途因为一次接口重试卡了 20 秒,都会出现「时长够但窗口断」,读回的状态永远不动。稳妥的排法是拿上限的一半以内当地心,我这边实际按 5 秒一次排(need // 5 + 5 次),留出一整个重试预算也不会破窗。
其二,elapsed_seconds 不等于「今天累计」。我做完之后回头读,它是 0,而 today_status 已经是 done——说明累计量是判完就清,真正的账本在 record_status 和 completed_at。所以脚本里别拿 elapsed_seconds 当进度条,它是过程量。
其三,period_key 是账期,不是日期格式统一的东西。日任务给 2026-11-04,周任务给 2026-W45。跨零点跑的任务如果按本地日期自己算账期,会出现「脚本认为是昨天、账本认为是今天」的错位;直接用接口回的 period_key 存状态最省事。
二、三种 evaluator,别用同一套等待逻辑
同一份任务列表里出现了三种判定方式,它们决定你该等多久、该信什么:
dwell 本站心跳累计,几秒内就能读到 done
external_check 去第三方核对(例如 GitCode 上的 Star),当天可能一直是 todo
external_report 要外部系统上报,我这边这条甚至没有对应的积分卡片第三种那次读回来是「云端实践 / weekly / points_hint=100」,但在任务中心那边找不到对应卡片,也就是说它记不记账跟这个页面无关。这种「站点列表里有、账本里没有」的差集,只有把两边的数据都结构化拉出来做集合差才能发现,靠看页面很容易以为做了白工。
三、落到脚本上的三条约束
第一,心跳间隔用 max_gap_ms 推导,不要写死;第二,判完成只读状态位,读回未登录或 unknown 时不能当作未完成(那是另一篇文章要讲的坑);第三,等待窗口要短于账期切换,跨零点跑的行为类任务最容易「做了一半掉进昨天」。
- 点赞
- 收藏
- 关注作者
评论(0)