You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何比对客户端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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 12:24:08