/** * 地图工具函数 */ 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) => { const info = findStatusInfo(STATUS_DICT[type], value) return info ? `${type}_${value}` : null } /** * 根据字典数据获取设备最高优先级状态 */ export const getHighestPriorityStatus = (markerData: MarkerData): keyof typeof STATUS_PRIORITY => { const statuses: Array = [] // 检查各种状态 const gasStatus = getStatusMapping('gas', String(markerData.gasStatus)) const batteryStatus = getStatusMapping('battery', String(markerData.batteryStatus)) const fenceStatus = getStatusMapping('fence', String(markerData.fenceStatus)) const onlineStatus = String(markerData.onlineStatus) === '0' ? 'offline' : null // 收集非正常状态 if (gasStatus && markerData.gasStatus !== 0) statuses.push(gasStatus as keyof typeof STATUS_PRIORITY) if (batteryStatus && markerData.batteryStatus !== 0) statuses.push(batteryStatus as keyof typeof STATUS_PRIORITY) if (fenceStatus && markerData.fenceStatus !== 0) statuses.push(fenceStatus as keyof typeof STATUS_PRIORITY) if (onlineStatus) statuses.push(onlineStatus) // 如果没有报警状态,则为正常 if (statuses.length === 0) return 'normal' // 返回优先级最高的状态 return statuses.reduce((prev, current) => STATUS_PRIORITY[prev] < STATUS_PRIORITY[current] ? prev : current ) } /** * 根据字典数据获取状态颜色 */ export const getStatusColor = (status: keyof typeof STATUS_PRIORITY): string => { if (status === 'normal') return '#67c23a' if (status === 'offline') return STATUS_DICT.online[0].cssClass 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: keyof typeof STATUS_PRIORITY): string => { if (status === 'normal') return '正常' if (status === 'offline') return STATUS_DICT.online[0].label const [type, value] = status.split('_') as [keyof typeof STATUS_DICT, string] const info = findStatusInfo(STATUS_DICT[type], value) return info?.label || '正常' } /** * 创建位置图标SVG */ export const createLocationIconSVG = (color: string, size: number = 24) => { return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(` `)}` } /** * 创建标记样式 */ export const createMarkerStyle = ( markerData: MarkerData | keyof typeof STATUS_PRIORITY, isCluster: boolean = false, clusterSize?: number ) => { // 如果是字符串,说明是状态值 const status: keyof typeof STATUS_PRIORITY = typeof markerData === 'string' ? (markerData as keyof typeof STATUS_PRIORITY) : getHighestPriorityStatus(markerData) const color = getStatusColor(status) 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(color, 24), scale: 1, anchor: [0.5, 1], // 锚点设置在底部中心 anchorXUnits: 'fraction', anchorYUnits: 'fraction' }) }) } } /** * 生成探测器列表项HTML */ export const createDetectorListItem = (detector: DetectorInfo) => `
${detector.name}
${detector.statusLabel}
` /** * 生成聚合标记弹窗HTML */ export const createClusterPopupHTML = (detectorList: DetectorInfo[]) => { const detectorListHTML = detectorList.map(createDetectorListItem).join('') return `
${detectorListHTML}
` } /** * 获取聚合标记数据 */ export const getClusterMarkerData = (features: Feature[]): keyof typeof STATUS_PRIORITY => { // 收集所有标记的状态 const allStatuses: Array = [] features.forEach((feature) => { const markerData = feature.get('markerData') as MarkerData if (markerData) { const status = getHighestPriorityStatus(markerData) allStatuses.push(status) } }) // 返回优先级最高的状态 if (allStatuses.length === 0) return 'normal' return allStatuses.reduce((prev, current) => STATUS_PRIORITY[prev] < STATUS_PRIORITY[current] ? prev : current ) } /** * 按优先级排序探测器列表 */ 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 }) }