鸿蒙签到 App 的位置判定:Haversine 距离、GPS 误差与班次时间规则
做员工签到 App 时,最容易被低估的不是登录注册,而是“这次签到到底算不算数”。我在做一个鸿蒙端云一体签到案例时,把判定拆成三层:位置判定、时间判定、记录策略。每一层都有明确的输入、输出和失败分支,缺一层,签到结果就不可信。
一、位置判定:为什么用 Haversine,而不是直线欧氏距离
员工在手机端点“签到”,端侧先通过 HarmonyOS 定位能力拿到经纬度,再把坐标连同时间一起发给后端。后端拿员工坐标和管理员配置的签到点坐标算距离,小于等于允许半径(例如 200 米)算“范围内”,否则算“超出范围”。
经纬度是球面坐标,直接用欧氏距离算会失真。正确做法是用 Haversine 公式:
function haversine(lat1, lon1, lat2, lon2) {
const R = 6371000; // 地球半径,单位米
const toRad = (d) => (d * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(a));
}
这个函数只做一件事:给两个经纬度,返回米级距离。把它放在后端算,而不是端侧算,好处是判定口径统一:员工改不了本地代码就改不了判定结果。端侧只负责采集和上报,判定权收归服务端。
二、GPS 误差:不要把“超出范围”判得太死
真实定位有误差,室内、地下车库、高楼阴影下误差可能到几十米。如果签到点半径设 100 米、定位误差 80 米,员工站在门口也可能被判“超出范围”。我的做法是分层处理:
| 情况 | 处理 |
|---|---|
| 距离在半径内 | 正常签到 |
| 距离略超半径,但定位精度字段很差 | 返回“定位不准,请到开阔处重试”,不直接记失败 |
| 距离远超半径 | 记“超出范围”,允许管理员事后核查 |
| 拿不到定位 | 不发签到请求,端侧先提示开启定位权限 |
关键是把“定位失败”和“超出范围”分开:前者是采集问题,后者是业务结果。混在一起,管理员看到一堆“超出范围”也分不清是员工没来还是 GPS 不准。
三、时间判定:班次、迟到与周末
位置过了,还要看时间。管理员配置上班时间(例如 9:00),员工签到时间在这个点之前算正常,之后算迟到。实现时注意三点:
- 用服务器时间判定,不要用手机本地时间。手机时间可以改,服务器时间改不了。
- 班次时间要和日期绑定:今天的 9:00 不是明天的 9:00,跨天签到要按签到当天的班次算。
- 周末禁止签到是业务规则,不是技术限制。把它做成可配置项:管理员关掉周末限制,加班日也能签到;打开时,周六周日直接拒绝并给出明确提示,而不是静默失败。
四、记录策略:最早与最晚双记录
一天内员工可能签到多次:早上打卡一次,下午补签一次。只保留最后一次会丢掉“最早到岗”这个信息,只保留第一次又看不到“最晚离岗”。案例里的做法是每天保留两条:最早记录和最晚记录。管理员看列表时,一眼能看到到岗时间和最后签到时间,考勤统计也不用再去翻原始流水。
数据库层面就是三张表:用户表、配置表(签到点、班次、提示语)、签到记录表。签到记录表按 userId + 日期建索引,查询“今天这个人签过几次、最早最晚各是什么时候”都是一条查询的事,不用扫全表。
五、一个容易忽略的安全点:判定接口必须鉴权
签到接口不鉴权,任何人拿到接口地址就能替别人签到。所以签到请求必须带 JWT,服务端先验 token、再取 token 里的 userId,最后才做位置和时间判定。userId 从 token 里取,不要从请求体里取——请求体是客户端传的,可以伪造;token 是服务端签发的,伪造不了。
另外,后端配置里的数据库密码、JWT 密钥只放 .env,不进 Git;生产模式下缺密钥直接拒绝启动(fail closed),而不是用默认值继续跑。演示项目里 admin 默认密码仅供演示,生产环境必须改掉。
六、小结
签到判定可以总结成一条流水线:端侧采集 GPS 与时间 → 服务端验 JWT 取 userId → Haversine 算距离判位置 → 服务端时间判班次与迟到 → 按“最早+最晚”双记录落库。每一层只做一件事,每一层失败都有明确的返回码和提示,管理员才能从签到列表里读出真实情况,而不是一堆无法解释的“失败”。
把判定逻辑收归服务端、把误差和业务失败分开、把时间口径统一到服务器时间,这三点做好,签到系统就具备了最基本的工程可信度。
- 点赞
- 收藏
- 关注作者
评论(0)