Files
akmon/utils/locationService.uts
2026-01-20 08:04:15 +08:00

553 lines
13 KiB
Plaintext

/**
* 手环位置服务 - 处理基站ID、位置信息、围栏功能
*/
import type { AkReqResponse } from '@/uni_modules/ak-req/index.uts'
// 基础坐标类型
export type LocationCoordinate = {
longitude: number
latitude: number
}
// 估算位置类型
export type EstimatedLocation = {
longitude: number
latitude: number
accuracy: number
}
// 围栏中心点类型
export type FenceCenter = {
longitude: number
latitude: number
}
// 基站信息类型
export type BaseStationInfo = {
/** 基站ID */
id: string
/** 基站名称 */
name: string
/** 基站位置描述 */
location: string
/** 经度 */
longitude: number
/** 纬度 */
latitude: number
/** 信号强度 */
signalStrength: number
/** 是否在线 */
isOnline: boolean
/** 覆盖范围(米) */
range: number
}
// 位置信息类型
export type LocationInfo = {
/** 设备ID */
deviceId: string
/** 当前连接的基站 */
baseStation: BaseStationInfo | null
/** 估算位置 */
estimatedLocation: EstimatedLocation | null
/** 最后更新时间 */
lastUpdate: string
/** 位置状态 */
status: 'online' | 'offline' | 'unknown'
}
// 围栏信息类型
export type FenceInfo = {
/** 围栏ID */
id: string
/** 围栏名称 */
name: string
/** 围栏类型 */
type: 'circle' | 'polygon'
/** 围栏中心点(圆形围栏) */
center?: FenceCenter
/** 围栏半径(米,圆形围栏) */
radius?: number
/** 围栏顶点(多边形围栏) */
points?: Array<LocationCoordinate>
/** 是否激活 */
isActive: boolean
/** 围栏事件类型 */
eventType: 'enter' | 'exit' | 'both'
/** 创建时间 */
createdAt: string
}
// 位置历史记录类型
export type LocationHistoryItem = {
/** 记录ID */
id: string
/** 设备ID */
deviceId: string
/** 基站信息 */
baseStation: BaseStationInfo
/** 记录时间 */
timestamp: string
/** 持续时间(秒) */
duration: number
/** 位置类型 */
locationType: 'basestation' | 'estimated'
}
// 围栏事件类型
export type FenceEvent = {
/** 事件ID */
id: string
/** 设备ID */
deviceId: string
/** 围栏信息 */
fence: FenceInfo
/** 事件类型 */
eventType: 'enter' | 'exit'
/** 事件时间 */
timestamp: string
/** 触发位置 */
location: LocationCoordinate
/** 是否已读 */
isRead: boolean
}
// FenceInfo 的手动 Partial 类型
export type PartialFenceInfo = {
id?: string
name?: string
type?: 'circle' | 'polygon'
center?: FenceCenter
radius?: number
points?: Array<LocationCoordinate>
isActive?: boolean
eventType?: 'enter' | 'exit' | 'both'
createdAt?: string
}
// mock generic AkReqResponse for array data
export function mockAkArrayResponse<T>(data: T[], status: number = 200): AkReqResponse<Array<T>> {
return {
status,
data,
headers: {} as UTSJSONObject,
error: null,
total: data.length,
page: 1,
limit: data.length,
hasmore: false,
origin: null,
};
}
/**
* 位置服务工厂函数
*/
export function createLocationResponse<T>(status: number, message: string, data: T[]): AkReqResponse<Array<T>> {
return mockAkArrayResponse<T>(data, status);
}
/**
* 位置服务错误响应工厂函数
*/
export function createLocationErrorResponse<T>(message: string): AkReqResponse<Array<T>> {
return createLocationResponse<T>(500, message, [])
}
/**
* 手环位置服务类
*/
export class LocationService {
/**
* 获取设备当前位置信息
*/
static async getCurrentLocation(deviceId: string): Promise<AkReqResponse<LocationInfo>> {
try {
// 模拟API调用延迟
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 1000)
})
// 模拟数据
const mockBaseStation: BaseStationInfo = {
id: 'BS001',
name: '教学楼A栋基站',
location: '教学楼A栋1层',
longitude: 116.397428,
latitude: 39.90923,
signalStrength: -45,
isOnline: true,
range: 50
}
const mockLocation: LocationInfo[] = [{
deviceId: deviceId,
baseStation: mockBaseStation,
estimatedLocation: {
longitude: 116.397428,
latitude: 39.90923,
accuracy: 15
},
lastUpdate: new Date().toISOString(),
status: 'online'
}]
return createLocationResponse(200, '获取位置成功', mockLocation)
} catch (error) {
console.error('获取设备位置失败:', error)
return createLocationErrorResponse('获取位置信息失败')
}
}
/**
* 获取可用基站列表
*/
static async getBaseStations(): Promise<AkReqResponse<BaseStationInfo[]>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 800)
})
const mockBaseStations: BaseStationInfo[] = [
{
id: 'BS001',
name: '教学楼A栋基站',
location: '教学楼A栋1层',
longitude: 116.397428,
latitude: 39.90923,
signalStrength: -45,
isOnline: true,
range: 50
},
{
id: 'BS002',
name: '教学楼B栋基站',
location: '教学楼B栋2层',
longitude: 116.398428,
latitude: 39.91023,
signalStrength: -52,
isOnline: true,
range: 45
},
{
id: 'BS003',
name: '操场基站',
location: '学校操场',
longitude: 116.399428,
latitude: 39.91123,
signalStrength: -38,
isOnline: true,
range: 100
},
{
id: 'BS004',
name: '宿舍楼基站',
location: '学生宿舍1号楼',
longitude: 116.396428,
latitude: 39.90823,
signalStrength: -60,
isOnline: false,
range: 40
}
]
return createLocationResponse(200, '获取基站列表成功', mockBaseStations)
} catch (error) {
console.error('获取基站列表失败:', error)
return createLocationErrorResponse('获取基站列表失败')
}
}
/**
* 获取围栏列表
*/
static async getFences(deviceId: string): Promise<AkReqResponse<FenceInfo[]>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 600)
})
const mockFences: FenceInfo[] = [ {
id: 'FENCE001',
name: '校园安全区域',
type: 'circle',
center: {
longitude: 116.397928,
latitude: 39.90973
},
radius: 200,
isActive: true,
eventType: 'exit',
createdAt: '2024-01-15T10:00:00Z'
},
{
id: 'FENCE002',
name: '教学区域',
type: 'polygon',
points: [
{ longitude: 116.397000, latitude: 39.909000 },
{ longitude: 116.398000, latitude: 39.909000 },
{ longitude: 116.398000, latitude: 39.910000 },
{ longitude: 116.397000, latitude: 39.910000 }
],
isActive: true,
eventType: 'both',
createdAt: '2024-01-16T14:30:00Z'
},
{
id: 'FENCE003',
name: '危险区域',
type: 'circle',
center: {
longitude: 116.395428,
latitude: 39.90723
},
radius: 30,
isActive: true,
eventType: 'enter',
createdAt: '2024-01-17T09:15:00Z'
}
]
console.log(mockFences)
return createLocationResponse<FenceInfo>(200, '获取围栏列表成功', mockFences)
} catch (error) {
console.error('获取围栏列表失败:', error)
return createLocationErrorResponse('获取围栏列表失败')
}
}
/**
* 获取位置历史记录
*/
static async getLocationHistory(deviceId: string, startDate: string, endDate: string): Promise<AkReqResponse<LocationHistoryItem[]>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 1200)
})
const mockHistory: LocationHistoryItem[] = [
{
id: 'HIST001',
deviceId: deviceId,
baseStation: {
id: 'BS001',
name: '教学楼A栋基站',
location: '教学楼A栋1层',
longitude: 116.397428,
latitude: 39.90923,
signalStrength: -45,
isOnline: true,
range: 50
},
timestamp: '2024-01-20T08:30:00Z',
duration: 3600,
locationType: 'basestation'
},
{
id: 'HIST002',
deviceId: deviceId,
baseStation: {
id: 'BS003',
name: '操场基站',
location: '学校操场',
longitude: 116.399428,
latitude: 39.91123,
signalStrength: -38,
isOnline: true,
range: 100
},
timestamp: '2024-01-20T10:00:00Z',
duration: 2400,
locationType: 'basestation'
},
{
id: 'HIST003',
deviceId: deviceId,
baseStation: {
id: 'BS002',
name: '教学楼B栋基站',
location: '教学楼B栋2层',
longitude: 116.398428,
latitude: 39.91023,
signalStrength: -52,
isOnline: true,
range: 45
},
timestamp: '2024-01-20T14:20:00Z',
duration: 5400,
locationType: 'basestation'
}
]
return createLocationResponse(200, '获取位置历史成功', mockHistory)
} catch (error) {
console.error('获取位置历史失败:', error)
return createLocationErrorResponse('获取位置历史失败')
}
}
/**
* 获取围栏事件记录
*/
static async getFenceEvents(deviceId: string, limit: number = 10): Promise<AkReqResponse<FenceEvent[]>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 900)
})
const mockEvents: FenceEvent[] = [ {
id: 'EVENT001',
deviceId: deviceId,
fence: {
id: 'FENCE001',
name: '校园安全区域',
type: 'circle',
center: {
longitude: 116.397928,
latitude: 39.90973
},
radius: 200,
isActive: true,
eventType: 'exit',
createdAt: '2024-01-15T10:00:00Z'
},
eventType: 'enter',
timestamp: '2024-01-20T07:45:00Z',
location: {
longitude: 116.397528,
latitude: 39.90943
},
isRead: false
},
{
id: 'EVENT002',
deviceId: deviceId,
fence: {
id: 'FENCE002',
name: '教学区域',
type: 'polygon',
points: [
{ longitude: 116.397000, latitude: 39.909000 },
{ longitude: 116.398000, latitude: 39.909000 },
{ longitude: 116.398000, latitude: 39.910000 },
{ longitude: 116.397000, latitude: 39.910000 }
],
isActive: true,
eventType: 'both',
createdAt: '2024-01-16T14:30:00Z'
},
eventType: 'enter',
timestamp: '2024-01-20T08:30:00Z',
location: {
longitude: 116.397500,
latitude: 39.909500
},
isRead: true
}
]
return createLocationResponse(200, '获取围栏事件成功', mockEvents)
} catch (error) {
console.error('获取围栏事件失败:', error)
return createLocationErrorResponse('获取围栏事件失败')
}
}
/**
* 创建围栏
*/
static async createFence(fence: PartialFenceInfo): Promise<AkReqResponse<FenceInfo>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 1500)
})
const newFence: FenceInfo[] = [{
id: `FENCE${Date.now()}`,
name: fence.name ?? '新围栏',
type: fence.type ?? 'circle',
center: fence.center,
radius: fence.radius,
points: fence.points,
isActive: fence.isActive ?? true,
eventType: fence.eventType ?? 'both',
createdAt: new Date().toISOString()
}]
return createLocationResponse(200, '创建围栏成功', newFence)
} catch (error) {
console.error('创建围栏失败:', error)
return createLocationErrorResponse('创建围栏失败')
}
}
/**
* 更新围栏
*/
static async updateFence(fenceId: string, updates: PartialFenceInfo): Promise<AkReqResponse<FenceInfo>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 1200)
})
// 模拟更新成功
const updatedFence: FenceInfo[] = [{
id: fenceId,
name: updates.name ?? '更新的围栏',
type: updates.type ?? 'circle',
center: updates.center,
radius: updates.radius,
points: updates.points,
isActive: updates.isActive ?? true,
eventType: updates.eventType ?? 'both',
createdAt: '2024-01-15T10:00:00Z'
}]
return createLocationResponse(200, '更新围栏成功', updatedFence)
} catch (error) {
console.error('更新围栏失败:', error)
return createLocationErrorResponse('更新围栏失败')
}
}
/**
* 删除围栏
*/
static async deleteFence(fenceId: string): Promise<AkReqResponse<Array<boolean>>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 800)
})
return createLocationResponse(200, '删除围栏成功', [true])
} catch (error) {
console.error('删除围栏失败:', error)
return createLocationErrorResponse('删除围栏失败')
}
}
/**
* 标记围栏事件为已读
*/
static async markEventAsRead(eventId: string): Promise<AkReqResponse<Array<boolean>>> {
try {
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve()
}, 500)
})
return createLocationResponse(200, '标记事件成功', [true])
} catch (error) {
console.error('标记事件失败:', error)
return createLocationErrorResponse('标记事件失败')
}
}
}