diff --git a/banban-mini/src/pages/location/index.tsx b/banban-mini/src/pages/location/index.tsx index 1851df6..e1fbe1b 100644 --- a/banban-mini/src/pages/location/index.tsx +++ b/banban-mini/src/pages/location/index.tsx @@ -2,9 +2,7 @@ import { View, Text, Map } from '@tarojs/components' import { useState } from 'react' import Taro, { useDidShow } from '@tarojs/taro' import { getToken } from '@/services/auth' -import { DEVICE_UNAVAILABLE_MESSAGE } from '@/services/api' import { loadCurrentChildBindingContext } from '@/services/binding' -import { getDeviceOnlineStatus } from '@/services/device' import { getCurrentDeviceLocation, getDeviceTrajectory, @@ -187,18 +185,11 @@ export default function Location() { return } - const onlineStatus = await getDeviceOnlineStatus(resolvedDeviceId) - if (onlineStatus && !onlineStatus.online) { - setDeviceLocation(null) - setTrajectory([]) - setSelectedPoint(null) - setCoordinates(DEFAULT_COORDINATES) - setLocationNotice(onlineStatus.message || '设备不在线或暂时无法上报位置') - return - } - const currentLocation = await getCurrentDeviceLocation(resolvedDeviceId) setDeviceLocation(currentLocation) + if (currentLocation?.stale || currentLocation?.realtime === false) { + setLocationNotice('已显示最近一次定位') + } const nextCoordinates = currentLocation ? { @@ -249,9 +240,7 @@ export default function Location() { } setLoading(false) console.error('[location] load failed:', error) - const message = error?.message === DEVICE_UNAVAILABLE_MESSAGE - ? '设备不在线或处于休眠中,暂时无法获取位置' - : error?.message || '位置更新失败' + const message = error?.status === 408 ? '暂时无法刷新定位' : error?.message || '位置更新失败' Taro.showToast({ title: message, icon: 'none', diff --git a/banban-mini/src/services/location.ts b/banban-mini/src/services/location.ts index 2d5948d..c3cbe37 100644 --- a/banban-mini/src/services/location.ts +++ b/banban-mini/src/services/location.ts @@ -17,6 +17,8 @@ export interface DeviceLocation { device_time: string server_time: string updated_at: string + stale?: boolean + realtime?: boolean } export interface DeviceTrajectoryPoint extends DeviceLocation { diff --git a/talkingq-url/banban/routers/devices.py b/talkingq-url/banban/routers/devices.py index 48076e4..3b6b11f 100644 --- a/talkingq-url/banban/routers/devices.py +++ b/talkingq-url/banban/routers/devices.py @@ -202,7 +202,12 @@ def _row_to_ai_conversation_item(row: Mapping) -> DeviceAiConversationItem: ) -def _row_to_current_location_response(row: Mapping) -> DeviceLocationCurrentResponse: +def _row_to_current_location_response( + row: Mapping, + *, + stale: bool = False, + realtime: bool = True, +) -> DeviceLocationCurrentResponse: return DeviceLocationCurrentResponse( child_id=int(row["child_id"]), child_name=row.get("child_name"), @@ -219,6 +224,8 @@ def _row_to_current_location_response(row: Mapping) -> DeviceLocationCurrentResp device_time=row["device_time"], server_time=row["server_time"], updated_at=row["updated_at"], + stale=stale, + realtime=realtime, ) @@ -681,10 +688,21 @@ async def get_current_device_location( await asyncio.sleep(1) - if row is None: - raise HTTPException(status_code=408, detail="GPS数据上报超时") + if row is not None: + logger.info( + "device stale location returned", + extra={ + "event": "device_stale_location", + "request_id": getattr(request.state, "request_id", None), + "user_id": current_user_id, + "device_id": device_id, + "child_id": int(row["child_id"]), + "location_updated_at": row.get("updated_at"), + }, + ) + return _row_to_current_location_response(row, stale=True, realtime=False) - raise HTTPException(status_code=408, detail="GPS数据未刷新") + raise HTTPException(status_code=408, detail="GPS数据上报超时") except Exception as e: raise HTTPException(status_code=408, detail=f"GPS数据上报失败: {e}") diff --git a/talkingq-url/banban/schemas/location.py b/talkingq-url/banban/schemas/location.py index bbb412c..7d79ed7 100644 --- a/talkingq-url/banban/schemas/location.py +++ b/talkingq-url/banban/schemas/location.py @@ -35,6 +35,8 @@ class DeviceLocationPoint(BaseModel): class DeviceLocationCurrentResponse(DeviceLocationPoint): updated_at: datetime + stale: bool = False + realtime: bool = True class DeviceLocationReportResponse(DeviceLocationCurrentResponse):