- companions 新增 latitude/longitude/last_active_at 与 idx_comp_active;切换接单中立即刷新活跃时间 - 新增 /api/companions/heartbeat(鉴权)与 /api/companions/match(真实注册+审核通过+接单中+10分钟心跳,Haversine 5km 过滤与距离排序,不返回精确坐标) - 工作台/接单大厅/雷达前台每 60s 心跳,离开停止;首页即时匹配改为服务端 LBS 匹配并展示真实距离 - 线上实测:2010 匹配排除自己,仅命中 280m 的 8 号;匿名命中 9 号 10m、8 号 280m;北京 5km 为 0;118 套件/771 用例全绿
62 行
1.6 KiB
JavaScript
62 行
1.6 KiB
JavaScript
// 大神接单心跳:工作台/接单大厅/雷达页在前台时每 60 秒上报一次
|
||
// 服务端以 last_active_at 判断是否真实在线(10 分钟无心跳自动移出匹配池)
|
||
import { getUserLocation } from './location.js';
|
||
import { sendCompanionHeartbeat, normalizeUserId } from './api.js';
|
||
|
||
let timer = null;
|
||
let inFlight = false;
|
||
let lastSentAt = 0;
|
||
let coords = null;
|
||
let coordsAt = 0;
|
||
|
||
const COORD_TTL_MS = 5 * 60 * 1000;
|
||
|
||
async function resolveCoords() {
|
||
if (coords && Date.now() - coordsAt < COORD_TTL_MS) return coords;
|
||
try {
|
||
const pos = await getUserLocation();
|
||
coords = { lat: pos.latitude, lng: pos.longitude };
|
||
coordsAt = Date.now();
|
||
return coords;
|
||
} catch (_) {
|
||
// 用户拒绝定位时仍上报活跃时间,只是没有距离信息
|
||
return coords;
|
||
}
|
||
}
|
||
|
||
export async function sendHeartbeat(force = false) {
|
||
if (inFlight) return;
|
||
if (!force && Date.now() - lastSentAt < 45 * 1000) return;
|
||
if (!normalizeUserId()) return;
|
||
inFlight = true;
|
||
try {
|
||
const pos = await resolveCoords();
|
||
await sendCompanionHeartbeat(pos || {});
|
||
lastSentAt = Date.now();
|
||
} catch (_) {
|
||
} finally {
|
||
inFlight = false;
|
||
}
|
||
}
|
||
|
||
export function startHeartbeat(intervalMs = 60 * 1000) {
|
||
if (timer) return;
|
||
void sendHeartbeat(true);
|
||
timer = setInterval(() => {
|
||
void sendHeartbeat();
|
||
}, Math.max(30 * 1000, Number(intervalMs) || 60 * 1000));
|
||
if (timer && typeof timer.unref === 'function') timer.unref();
|
||
}
|
||
|
||
export function stopHeartbeat() {
|
||
if (timer) {
|
||
clearInterval(timer);
|
||
timer = null;
|
||
}
|
||
}
|
||
|
||
export function resetHeartbeatLocation() {
|
||
coords = null;
|
||
coordsAt = 0;
|
||
}
|