feat: 高德IoT v5 API升级、电子围栏管理、设备绑定自动考勤

- 前向地理编码升级为高德IoT v5 API (POST restapi.amap.com/v5/position/IoT)
- 修复LBS定位偏差: 添加network=LTE参数区分4G/2G, bts格式补充cage字段
- 新增电子围栏管理模块 (circle/polygon/rectangle), 支持地图绘制和POI搜索
- 新增设备-围栏多对多绑定 (DeviceFenceBinding/DeviceFenceState)
- 围栏自动考勤引擎 (fence_checker.py): haversine距离、ray-casting多边形判定、容差机制、防抖
- TCP位置上报自动检测围栏进出, 生成考勤记录并WebSocket广播
- 前端围栏页面: 绑定设备弹窗、POI搜索定位、左侧围栏面板
- 新增fence_attendance WebSocket topic

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
2026-03-27 13:04:11 +00:00
parent cde5146bfe
commit 1d06cc5415
17 changed files with 2303 additions and 187 deletions

View File

@@ -3,7 +3,8 @@ Device Service - 设备管理服务
Provides CRUD operations and statistics for badge devices.
"""
from datetime import datetime, timezone
from datetime import datetime
from app.config import now_cst
from sqlalchemy import func, select, or_
from sqlalchemy.ext.asyncio import AsyncSession
@@ -158,7 +159,7 @@ async def update_device(
for field, value in update_fields.items():
setattr(device, field, value)
device.updated_at = datetime.now(timezone.utc)
device.updated_at = now_cst()
await db.flush()
await db.refresh(device)
return device
@@ -245,7 +246,7 @@ async def batch_update_devices(
devices = await get_devices_by_ids(db, device_ids)
found_map = {d.id: d for d in devices}
update_fields = update_data.model_dump(exclude_unset=True)
now = datetime.now(timezone.utc)
now = now_cst()
results = []
for device_id in device_ids: