如何比对客户端API坐标与数据库存储活动坐标实现签到校验
实现步骤
1. 修正EJS中活动坐标的变量定义
原代码中eventCoords被包裹成了字符串,实际需要直接输出数值数组方便后续计算,同时注意GeoJSON默认存储的坐标顺序为[经度, 纬度],修改后的EJS代码如下:
<% layout('layouts/boilerplate') %> <h1>Prompt</h1> <script> // 去掉外层引号,直接输出为数组格式 const eventCoords = <%- JSON.stringify(event.geometry.coordinates) %> const eventID = '<%- event.id %>'; </script> <script src="/javascripts/guestValidate.js"></script>
2. 实现坐标比对+上报逻辑(修改guestValidate.js)
使用Haversine公式计算两个经纬度点的球面距离,设置合理的误差阈值(可根据业务场景调整,示例为500米),匹配成功后通过fetch请求上报结果到后端接口:
// 计算两个经纬度点的球面距离,返回结果单位为米 function calculateDistance(lat1, lon1, lat2, lon2) { const earthRadius = 6371e3; // 地球半径,单位:米 const rad1 = lat1 * Math.PI / 180; const rad2 = lat2 * Math.PI / 180; const diffRadLat = (lat2 - lat1) * Math.PI / 180; const diffRadLon = (lon2 - lon1) * Math.PI / 180; const a = Math.sin(diffRadLat / 2) * Math.sin(diffRadLat / 2) + Math.cos(rad1) * Math.cos(rad2) * Math.sin(diffRadLon / 2) * Math.sin(diffRadLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return earthRadius * c; } if(confirm('Compare 需要获取你的当前位置完成签到,是否授权?')) { navigator.geolocation.getCurrentPosition(async function (position) { const userLat = position.coords.latitude; const userLon = position.coords.longitude; // 拆分活动坐标,注意GeoJSON顺序是[经度, 纬度] const eventLon = eventCoords[0]; const eventLat = eventCoords[1]; // 比对距离,阈值可自行调整 const distance = calculateDistance(userLat, userLon, eventLat, eventLon); const isMatch = distance <= 500; if (isMatch) { // 上报匹配结果到后端,路由地址替换为你的实际业务路由 try { const res = await fetch('/api/activity/checkin', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ eventId: eventID, checkinResult: true, userLocation: [userLon, userLat] }) }); const respData = await res.json(); if (res.ok) { alert('签到成功'); } else { alert('签到失败,请稍后重试'); } } catch (err) { console.error('上报请求异常', err); alert('网络错误,请检查网络后重试'); } } else { alert('你当前不在活动范围内,无法完成签到'); } }) } else { console.log("位置授权被拒绝"); alert('需要授权位置权限才能完成签到'); }
3. 后端配套路由参考(Express示例)
你需要在后端新增对应接口接收上报数据,更新数据库记录,示例代码如下:
app.post('/api/activity/checkin', async (req, res) => { const { eventId, checkinResult, userLocation } = req.body; try { // 此处编写你的数据库更新逻辑,比如写入签到记录 // await Activity.updateOne({_id: eventId}, {$push: {checkinList: {location: userLocation, createTime: new Date()}}}) res.json({ code: 0, msg: '签到成功' }) } catch (err) { res.status(500).json({ code: 1, msg: '服务器异常' }) } })
内容的提问来源于stack exchange,提问作者econobro
相关产品推荐
相关产品推荐

