feat(lbs): 大神真实 5km 即时匹配与接单心跳
- 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 用例全绿
这个提交包含在:
@@ -115,6 +115,9 @@ export async function initDatabase(): Promise<void> {
|
||||
audit_status VARCHAR(32) DEFAULT '已通过',
|
||||
id_card_masked VARCHAR(32),
|
||||
tags JSON,
|
||||
latitude DECIMAL(10,7) DEFAULT NULL,
|
||||
longitude DECIMAL(10,7) DEFAULT NULL,
|
||||
last_active_at DATETIME DEFAULT NULL,
|
||||
apply_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`);
|
||||
@@ -132,6 +135,15 @@ export async function initDatabase(): Promise<void> {
|
||||
try {
|
||||
await conn.query("ALTER TABLE companions ADD COLUMN voice_intro_url VARCHAR(255) NOT NULL DEFAULT '' AFTER voice_title");
|
||||
} catch (_) {}
|
||||
try {
|
||||
await conn.query('ALTER TABLE companions ADD COLUMN latitude DECIMAL(10,7) DEFAULT NULL AFTER tags');
|
||||
} catch (_) {}
|
||||
try {
|
||||
await conn.query('ALTER TABLE companions ADD COLUMN longitude DECIMAL(10,7) DEFAULT NULL AFTER latitude');
|
||||
} catch (_) {}
|
||||
try {
|
||||
await conn.query('ALTER TABLE companions ADD COLUMN last_active_at DATETIME DEFAULT NULL AFTER longitude');
|
||||
} catch (_) {}
|
||||
|
||||
// 4. 订单表
|
||||
await conn.query(`
|
||||
@@ -796,6 +808,7 @@ export async function initDatabase(): Promise<void> {
|
||||
['arbitrations', 'idx_arb_order', 'order_id'],
|
||||
['companions', 'idx_comp_user', 'user_id'],
|
||||
['companions', 'idx_comp_status', 'status'],
|
||||
['companions', 'idx_comp_active', 'status, last_active_at'],
|
||||
['companions', 'idx_comp_audit', 'audit_status'],
|
||||
['payment_refunds', 'idx_pr_order', 'order_id'],
|
||||
];
|
||||
|
||||
在新工单中引用
屏蔽一个用户