/** * 地图工具函数 */ import { Style, Text, Circle, Fill, Stroke, Icon } from 'ol/style' import { Feature } from 'ol' import type { MarkerData, DetectorInfo } from '../types/map.types' import { STATUS_DICT, STATUS_PRIORITY, STATUS_ORDER } from '../constants/map.constants' /** * 从字典中查找状态信息 */ export const findStatusInfo = ( dict: (typeof STATUS_DICT)[keyof typeof STATUS_DICT], value: string ) => { return dict?.find((item) => item.value === value) } /** * 获取状态映射 */ export const getStatusMapping = (type: keyof typeof STATUS_DICT, value: string): string => { const info = findStatusInfo(STATUS_DICT[type], value) return info ? `${type}_${value}` : '' } // 获取状态优先级,越小优先级越高 export const getStatusPriority = (statusStr: string | keyof typeof STATUS_PRIORITY): number => { return STATUS_PRIORITY[statusStr] || 0 } /** * 根据字典数据获取设备最高优先级状态 */ export const getHighestPriorityStatus = (markerData: { gasStatus?: number batteryStatus?: number fenceStatus?: number onlineStatus?: number }): keyof typeof STATUS_PRIORITY => { const onlineStatus = String(markerData.onlineStatus) !== '1' ? 'offline' : null if (onlineStatus === 'offline') { return 'offline' } const statuses: string[] = [] // 收集非正常状态 if (markerData.gasStatus === 1) { const gasStatusStr = getStatusMapping('gasStatus', String(markerData.gasStatus)) gasStatusStr && statuses.push(gasStatusStr) } if (markerData.batteryStatus === 1) { const batteryStatusStr = getStatusMapping('batteryStatus', String(markerData.batteryStatus)) statuses.push(batteryStatusStr) } if (markerData.fenceStatus === 1) { const fenceStatusStr = getStatusMapping('fenceStatus', String(markerData.fenceStatus)) fenceStatusStr && statuses.push(fenceStatusStr) } // console.log('statuses', statuses) // 如果没有报警状态,则为正常 if (statuses.length === 0) return 'normal' // 返回优先级最高的状态 return statuses.reduce((prev, current) => STATUS_PRIORITY[prev] < STATUS_PRIORITY[current] ? prev : current ) as keyof typeof STATUS_PRIORITY } /** * 根据字典数据获取状态颜色 */ export const getStatusColor = (status: string | keyof typeof STATUS_PRIORITY): string => { if (status === 'normal') return '#67c23a' if (status === 'offline') return STATUS_DICT.onlineStatus[0].cssClass // 安全校验,确保状态字符串格式正确 if (!status.includes('_')) return '' const [type, value] = status.split('_') as [keyof typeof STATUS_DICT, string] const info = findStatusInfo(STATUS_DICT[type], value) return info?.cssClass || '#67c23a' } /** * 根据字典数据获取状态标签 */ export const getStatusLabel = (status: string | keyof typeof STATUS_PRIORITY): string => { if (status === 'normal') return '正常' if (status === 'offline') return STATUS_DICT.onlineStatus[0].label // 安全校验,确保状态字符串格式正确 if (!status.includes('_')) return '' const [type, value] = status.split('_') as [keyof typeof STATUS_DICT, string] const info = findStatusInfo(STATUS_DICT[type], value) return info?.label || '正常' } export const getLabelWithTypeValue = (type: string, value: number | undefined): string => { if (value === undefined) return '-' const info = findStatusInfo(STATUS_DICT[type], String(value)) return info?.label || '-' } /** * 创建开始位置图标SVG */ export const createStartIconSVG = (size: number = 24, color: string = '#1296db') => { return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(` `)}` } /** * 创建结束位置图标SVG */ export const createEndIconSVG = (size: number = 24, color: string = '#dd4e3b') => { return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(` `)}` } /** * 创建位置图标SVG */ export const createLocationIconSVG = (size: number = 24,color: string='#1296db') => { return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(` `)}` } /** * 创建标记样式 */ export const createMarkerStyle = ( color: string, isCluster: boolean = false, clusterSize?: number ) => { if (isCluster && clusterSize) { // 聚合标记样式 return new Style({ image: new Circle({ radius: Math.min(20 + clusterSize * 2, 40), fill: new Fill({ color: color + '80' // 添加透明度 }), stroke: new Stroke({ color: color, width: 2 }) }), text: new Text({ text: clusterSize.toString(), fill: new Fill({ color: '#ffffff' }), font: 'bold 14px Arial' }) }) } else { // 单个标记样式 - 使用位置图标 return new Style({ image: new Icon({ src: createLocationIconSVG(24,color), scale: 1, anchor: [0.5, 0.8], // 锚点设置在底部中心 anchorXUnits: 'fraction', anchorYUnits: 'fraction' }) }) } } /** * 生成探测器列表项HTML */ export const createDetectorListItem = (detector: DetectorInfo) => `
${detector.name}
${detector.statusLabel}
` export const createDetectorListItem2 = (type: string, label: string, count: number) => { if (count === 0) return '' return `
${label}
${count}
` } /** * 生成聚合标记弹窗HTML */ export const createClusterPopupHTML = (detectorList: DetectorInfo[]) => { let detectorListHTML = '' if (detectorList.length > 5) { // 正常探测器数量 const normalCount = detectorList.filter((detector) => detector.status === 'normal').length // if (normalCount === detectorList.length) return '' // 气体报警数量 const gasAlarmCount = detectorList.filter( (detector) => detector.status === 'gasStatus_1' ).length // 围栏报警 const fenceAlarmCount = detectorList.filter( (detector) => detector.status === 'fenceStatus_1' ).length // 低电量数量 const lowBatteryCount = detectorList.filter( (detector) => detector.status === 'batteryStatus_1' ).length // 离线探测器数量 const offlineCount = detectorList.filter((detector) => detector.status === 'offline').length detectorListHTML = createDetectorListItem2('gasAlarm', '气体报警', gasAlarmCount) + createDetectorListItem2('fenceAlarm', '围栏报警', fenceAlarmCount) + createDetectorListItem2('lowBattery', '低电量', lowBatteryCount) + createDetectorListItem2('offline', '离线', offlineCount) + createDetectorListItem2('normal', '正常', normalCount) // ` //
//
气体报警${gasAlarmCount}个
//
围栏报警${fenceAlarmCount}个
//
离线${offlineCount}个
//
低电量${lowBatteryCount}个
//
正常${normalCount}个
//
// ` } else { detectorListHTML = detectorList.map(createDetectorListItem).join('') } return `
${detectorListHTML}
` } /** * 获取聚合标记数据 */ export const getClusterMarkerData = (features: Feature[]): keyof typeof STATUS_PRIORITY => { // 收集所有标记的状态 const allStatuses: string[] = [] features.forEach((feature) => { const markerData = feature.get('markerData') as MarkerData if (markerData) { const status = markerData.statusStr || '' allStatuses.push(status) } }) // 返回优先级最高的状态 if (allStatuses.length === 0) return 'normal' return allStatuses.reduce((prev, current) => STATUS_PRIORITY[prev] < STATUS_PRIORITY[current] ? prev : current ) as keyof typeof STATUS_PRIORITY } /** * 按优先级排序探测器列表 */ export const sortDetectorsByPriority = (detectorList: DetectorInfo[]): DetectorInfo[] => { return detectorList.sort((a, b) => { const aPriority = STATUS_ORDER.indexOf(a.status as keyof typeof STATUS_PRIORITY) const bPriority = STATUS_ORDER.indexOf(b.status as keyof typeof STATUS_PRIORITY) return aPriority - bPriority }) }