import mapConfig from "../../baseSetting/config/mapConfig.js";
import {
    base_sources,
    business_layers,
    business_sources,
    Dark_Layers,
    Dark_Sources,
    Image_Layers,
    LayerConfig,
    Light_Layers,
    Light_Sources,
    Vector_Layers,
} from "../../baseSetting/gis-data/sources_layers.js";
import {
    Dark_Style,
    Light_Style,
} from "../../baseSetting/style/DevMapConfig.js";
import TokenUtils from "../../baseSetting/utils/TokenUtils.js";
import {Scene, Mapbox} from '@antv/l7'

// 图标资源
const point_icon = require('../../baseSetting/images/map/point.png');
const img_todo = require('../../baseSetting/images/map/todo.png');
const img_done = require('../../baseSetting/images/map/done.png');
const img_invalid = require('../../baseSetting/images/map/invalid.png');
const img_error = require('../../baseSetting/images/map/error.png');
let map = null
let antV7Scene = null
let pendingRequests = new Set();
const throttleDelay = 300; // 300ms 内相同瓦片不重复请求

// 颜色配置 TODO: 是否增加亮色/暗色的配置
const actual_color = '#7ed321';
const plan_color_valid = '#3a6bdb';
const plan_color_invalid = '#9b9b9b';

export default {
    workspace: mapConfig.workspace,
    mapType: mapConfig.mapType || "vector",
    vectorSignalStr: ['vec', 'cva'],
    imageSignalStr: ['img', 'cia'],
    map_srid: mapConfig.map_srid,
    business_srid: mapConfig.business_srid,
    mapgisMap: null,
    mbMap: null,
    rootUrl: window.location.protocol + '//' + window.location.host + '/gisserver',
    styleUrl: window.location.protocol + '//' + window.location.host + '/gisserver/style',
    sceneConfig: mapConfig.sceneConfig,
    opts: {},

    /**
     * 创建地图实例
     * theme = 'dark'时 将使用离线暗色底图瓦片,将mapConfig中的isOnline设置为false,此时默认使用文件服务器上的暗色瓦片资源
     * theme = 'light'时 将使用在线亮色底图瓦片,将mapConfig中的isOnline设置为true,此时默认使用天地图资源
     * theme = 'light'时 将使用在线亮色底图瓦片,将mapConfig中的isOnline设置为false,此时默认使用文件服务器上的亮色瓦片资源
     * @param opts
     * @param callback
     */
    create: function (opts, callback) {
        this.opts = opts
        if (mapConfig.noMap) {
            this.$message.info("未配置地图")
            alert("未配置地图")
            return
        } else {
            if (typeof zondy == 'undefined') {
                // 使用 Promise 确保资源加载完成后再执行后续逻辑
                this.loadMapGISResources().then(() => {
                    this.initMap(opts, callback);
                }).catch((error) => {
                    console.error("地图资源加载失败:", error);
                    callback && callback();
                });
            } else {
                // 如果 zondy 已经存在，直接初始化地图
                console.log('MapGIS 资源已加载，直接初始化地图');
                this.initMap(opts, callback);
            }
        }
    },

    /**
     * 添加图标资源
     * @param map
     */
    addImageSource: function (map) {
        // 添加图标到地图
        if (!map.hasImage('img_done')) {
            map.loadImage(img_done, (error, image) => {
                if (error) throw error;
                map.addImage('img_done', image);
            });
        }

        if (!map.hasImage('img_error')) {
            map.loadImage(img_error, (error, image) => {
                if (error) throw error;
                map.addImage('img_error', image);
            });
        }

        if (!map.hasImage('img_invalid')) {
            map.loadImage(img_invalid, (error, image) => {
                if (error) throw error;
                map.addImage('img_invalid', image);
            });
        }

        if (!map.hasImage('img_todo')) {
            map.loadImage(img_todo, (error, image) => {
                if (error) throw error;
                map.addImage('img_todo', image);
            });
        }
    },

    /**
     * 加载 MapGIS 资源
     * @returns {Promise<unknown>}
     */
    loadMapGISResources: function () {
        window.MapConfig = mapConfig
        return new Promise((resolve, reject) => {
            const script = document.createElement("script");
            script.src = mapConfig.mapUrl + "/mapgis-libs/include-lib-local-upgrade.js";

            // 根据需要加载的引擎类型添加 include 属性
            script.setAttribute("include", "engine:mapboxgl");

            let scriptLoaded = false;

            script.onload = () => {
                console.log('include-lib-local-upgrade.js 加载完成，等待依赖初始化...');
                scriptLoaded = true;
                this.checkDependenciesReady().then(() => {
                    console.log('MapGIS 资源加载完成');
                    resolve();
                }).catch(reject);
            };

            script.onerror = () => reject(new Error("MapGIS Client JS 加载失败"));

            document.head.appendChild(script);
        });
    },

    /**
     * 检查依赖是否就绪
     * @returns {Promise<unknown>}
     */
    checkDependenciesReady: function () {
        return new Promise((resolve, reject) => {
            const check = () => {
                if (typeof zondy !== 'undefined' &&
                        typeof zondy.Map !== 'undefined' &&
                        typeof window.createView === 'function') {
                    console.log('MapGIS 核心依赖已就绪');
                    resolve();
                    return true;
                }
                return false;
            };

            // 立即检查一次
            if (check()) {
                return;
            }

            // 如果还没就绪，轮询检查（最多等待10秒）
            let attempts = 0;
            const maxAttempts = 100; // 100 * 100ms = 10秒
            const pollInterval = setInterval(() => {
                attempts++;
                if (check()) {
                    clearInterval(pollInterval);
                } else if (attempts >= maxAttempts) {
                    clearInterval(pollInterval);
                    reject(new Error("MapGIS 依赖初始化超时"));
                }
            }, 100);
        });
    },

    /**
     * 初始化地图
     * @param opts
     * @param callback
     */

    initMap: function (opts, callback) {
        const {Map} = zondy
        let baseSources = {}, baseLayers = [];

        // 底图注入
        if (mapConfig.isOnline) {
            const basemapType = mapConfig.map_srid === 'EPSG:3857' ? 'w' : 'c';

            baseSources = {};
            baseLayers = [];

            this.vectorSignalStr.forEach(signal => {
                baseLayers.push({
                    name: 'tdt_vec_' + signal + '_tiles',
                    url: 'http://t0.tianditu.gov.cn/' + signal + '_' + basemapType + '/wmts',
                    visible: true
                })

            })

            this.imageSignalStr.forEach(signal => {
                baseLayers.push({
                    name: 'tdt_img_' + signal + '_tiles',
                    url: 'http://t0.tianditu.gov.cn/' + signal + '_' + basemapType + '/wmts',
                    visible: true
                })
            })

        } else {
            baseLayers = opts.theme === "dark" ? Dark_Layers : Light_Layers;
        }

        // const businessLayers = opts.theme === "dark" ? business_layers : business_layers;
        const businessLayers = opts.theme === "dark" ? [] : [];
        const mapId = opts.mapId;

        mapboxgl.accessToken = TokenUtils.MapboxGL_AccessToken;
        console.log('baseSources, baseLayers', baseSources, baseLayers);
        mapboxgl.config.MAX_PARALLEL_IMAGE_REQUESTS = 256;

        this.mapgisMap = new Map() // mapgis Map对象

        // 初始化地图视图对象
        window.gisView = createView(mapId, this.mapgisMap, this.opts)

        this.initBaseDataLayers(baseLayers)

        this._innerViewCreatedHandler(gisView,callback)
    },

    // 创建事件处理函数并保存引用
    _innerViewCreatedHandler(result,callback) {
        const innerView = result.getInnerView()
        console.log('innerView-created', innerView);
        map = innerView;
        const customStyle = this.opts.theme === "dark" ? Dark_Style : Light_Style;

        this.setStyle(map);
        this.addImageSource(map)
        map._customStyle = customStyle

        if (this.sceneConfig.useAntVL7Scene) {
            antV7Scene = this.createAntVL7Scene(this.opts.mapId)
            window.antV7Scene = antV7Scene;
        }

        this.hideLogo(map)
        map.resize()
        callback && callback(map, antV7Scene, this.mapgisMap, gisView);
    },

    initBaseDataLayers(baseLayers) {
        let bLayers = []
        if (MapConfig.isOnline) {
            bLayers = baseLayers.map(layer => {
                return new zondy.layer.WMTSLayer({
                    id: layer.name,
                    url: layer.url,
                    visible: layer.visible,
                    // 天地图必须加token，且token名为tk
                    tokenKey: 'tk',
                    // token请在天地图官网申请
                    tokenValue: TokenUtils.TDT_token,
                    // 瓦片显示策略
                    tileDisplayStrategy: 'hide', // 'stretch'拉伸 'hide'隐藏
                    minScale: this.getScaleBySridAndLevel(mapConfig.map_srid_code,mapConfig.minZoom),
                    maxScale: this.getScaleBySridAndLevel(mapConfig.map_srid_code,mapConfig.maxOnlineZoom)
                })
            })
        } else {
            bLayers = baseLayers.map(layer => {
                return new zondy.layer.IGSTileLayer({
                    name: layer.name,
                    url: layer.url,
                    visible: layer.visible
                })
            })
        }

        // 初始化图层管理容器
        this.mapgisMap.basemap = new zondy.Basemap({
            // 设置图层到底图集合中
            baseLayers: new zondy.Collection(bLayers)
        })
    },

    /* 地图 */
    // 增加瓦片范围判断
    isValidTile(z, x, y, url) {
        // 在这里写你的判断逻辑
        // 例如：mapConfig.origin.maxBounds获取地图的经纬度范围从而判断z,x,y是否在有效范围内,如果是返回正确的url,否则返回一个空的图片
        const mapBounds = mapConfig.origin.maxBounds;
        const tileBounds = this.tile2lonlat(x, y, z);
        if (this.boundsIntersect(tileBounds, mapBounds)) {
            return {
                url: url
            }
        } else {
            // 返回一个空的透明图片 Data URL，阻止实际的网络请求
            return {
                url: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
            };
        }
    },

    /**
     * 瓦片坐标转经纬度
     * @param x
     * @param y
     * @param z
     * @returns {number[]}
     */
    tile2lonlat(x, y, z) {
        // 计算瓦片左上角的经纬度
        const n = Math.pow(2, z);
        const lon1 = (x / n) * 360 - 180;
        const lat1 = Math.atan(Math.sinh(Math.PI * (1 - 2 * y / n))) * (180 / Math.PI);

        // 计算瓦片右下角的经纬度
        const lon2 = ((x + 1) / n) * 360 - 180;
        const lat2 = Math.atan(Math.sinh(Math.PI * (1 - 2 * (y + 1) / n))) * (180 / Math.PI);

        // Mapbox GL JS 使用 TMS 方案，y 轴是反的，需要转换
        // 如果你的服务是 XYZ 方案，请注释下面的 lat 转换
        const tileSize = 256;
        const tileCount = Math.pow(2, z);
        const yTMS = tileCount - 1 - y;

        // 重新计算 TMS 对应的经纬度
        const lat1TMS = Math.atan(Math.sinh(Math.PI * (1 - 2 * yTMS / n))) * (180 / Math.PI);
        const lat2TMS = Math.atan(Math.sinh(Math.PI * (1 - 2 * (yTMS + 1) / n))) * (180 / Math.PI);

        return [lon1, lat2TMS, lon2, lat1TMS];
    },

    /**
     * 判断两个边界框是否相交
     * @param bounds1
     * @param bounds2
     * @returns {boolean}
     */
    boundsIntersect(bounds1, bounds2) {
        // bounds 格式: [minLng, minLat, maxLng, maxLat]
        return !(
                bounds1[0] > bounds2[2] || // 左 > 右
                bounds1[2] < bounds2[0] || // 右 < 左
                bounds1[1] > bounds2[3] || // 下 > 上
                bounds1[3] < bounds2[1]    // 上 < 下
        );
    },

    /**
     * 更新底图可见性
     * @param {String} type - 底图类型：'vector' 或 'image'
     */
    updateBaseMapVisibility: function (type) {
        if (!this.mapgisMap || !mapConfig.isOnline) return;

        const vecLayerIds = this.vectorSignalStr.map(signal => 'tdt_vec_' + signal + '_tiles');
        const imgLayerIds = this.imageSignalStr.map(signal => 'tdt_img_' + signal + '_tiles');

        vecLayerIds.forEach(layerId => {
            const layer = this.mapgisMap.findLayerById(layerId)
            if (layer) {
                const visible = type === 'vector';
                layer.visible = visibility;
            }
        });

        imgLayerIds.forEach(layerId => {
            const layer = this.mapgisMap.findLayerById(layerId)
            if (layer) {
                const visible = type === 'image';
                layer.visible = visibility;
            }
        });
    },

    /**
     * 获取要素(点选)
     * @param e
     */
    getFeature: function (e) {
        // 获取点击位置的要素
        const features = map.queryRenderedFeatures(e.point);

        if (features.length > 0) {
            const feature = features[0];
            console.log('点击的要素:', feature.properties);
            return feature
        }
    },

    /**
     * 隐藏MapBoxgl logo
     */
    hideLogo: function () {
        console.log('logo is hidden')
        let controls = map._controls;
        controls.forEach(control => {
            // 去除logo控件
            if ('_updateLogo' in control) {
                map.removeControl(control)
            }

            // 去除attribute控件
            if ('_attribHTML' in control) {
                map.removeControl(control)
            }
        })
    },

    /**
     * 切换底图
     * @param {String} type -目标底图类型
     */
    changeMap: function (type) {
        if (!map || type === this.mapType) return;

        if (mapConfig.isOnline) {
            this.updateBaseMapVisibility(type);
        } else {
            let changedLayers = null;
            switch (type) {
                case 'vector':
                    changedLayers = Vector_Layers;
                    break;
                case 'image':
                    changedLayers = Image_Layers;
                    break;
                default:
                    return;
            }

            changedLayers.forEach(layer => {
                if (map.getLayer(layer.id)) {
                    map.setLayoutProperty(layer.id, 'visibility', layer.visibility);
                }
            });
        }

        this.mapType = type;
    },

    /**
     * 重置地图中心点和缩放级别
     * @param map
     */
    resetCenterAndZoom: function (map) {
        if (!map) return;
        map.jumpTo({center: mapConfig.center, zoom: mapConfig.zoom});
        console.log('地图已重置到默认中心点和缩放级别');
    },

    /**
     * 定位到当前位置
     */
    placePoint: function (map, location, callback) {
        if (!map) return;
        if (Array.isArray(location) && location.length === 2) {
            map.setCenter(location)
            map.setZoom(mapConfig.zoom);
        } else {
            navigator.geolocation.getCurrentPosition(
                    (position) => {
                        console.log('navigator.geolocation', position);
                        const point = {
                            lng: position.coords.longitude,
                            lat: position.coords.latitude
                        };

                        map.setCenter([point.lng, point.lat]);
                        map.setZoom(mapConfig.maxZoom);
                        callback && callback(point);
                    },
                    (error) => {
                        switch (error.code) {
                            case error.PERMISSION_DENIED:
                                console.error("用户拒绝了位置请求");
                                break;
                            case error.POSITION_UNAVAILABLE:
                                console.error("位置信息不可用");
                                break;
                            case error.TIMEOUT:
                                console.error("请求超时");
                                break;
                            default:
                                console.error("未知错误", error.message);
                        }
                        // 默认定位到地图中心点
                        const point = {lng: mapConfig.center[0], lat: mapConfig.center[1]};
                        map.setCenter([point.lng, point.lat]);
                        map.setZoom(mapConfig.maxZoom);
                        callback && callback(point);
                    },
                    {
                        enableHighAccuracy: true, // 高精度（可能更耗电）
                        timeout: 10000,           // 10秒超时
                        maximumAge: 30000         // 允许使用30秒内的缓存位置
                    }
            );
        }
    },

    /**
     * @param data
     * @param customIcon (require结构的url)
     * @param customIconName
     */
    addMarker: function (data, customIcon, customIconName) {
        console.log('addMarker>>>>>>')
        // 清除之前的标记图层和数据源
        if (map.getLayer('marker-point')) {
            map.removeLayer('marker-point');
        }
        if (map.getSource('marker-point')) {
            map.removeSource('marker-point');
        }

        if (data.longitude && data.latitude) {
            // 确保图标已加载到地图中
            if (!map.hasImage('add_marker_icon')) {
                map.loadImage(point_icon, (error, image) => {
                    if (error) throw error;
                    map.addImage('add_marker_icon', image);
                });
            }

            if (!map.hasImage('custom-icon')) {
                map.loadImage(customIcon, (error, image) => {
                    if (error) throw error;
                    map.addImage(customIconName || 'custom-icon', image);
                });
            }

            // 创建GeoJSON数据源
            const geojson = {
                type: 'FeatureCollection',
                features: [{
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [data.longitude, data.latitude]
                    },
                    properties: {}
                }]
            };

            // 添加数据源
            map.addSource('marker-point', {
                type: 'geojson',
                data: geojson
            });

            // 添加图层显示标记点（使用自定义图标）
            map.addLayer({
                id: 'marker-point',
                type: 'symbol',
                source: 'marker-point',
                layout: {
                    'icon-image': customIconName || 'add_marker_icon',
                    'icon-size': 1,
                    'icon-offset': [4, -19]
                }
            });

            // 设置地图中心点和缩放级别
            map.setCenter([data.longitude, data.latitude]);
            map.setZoom(data.zoom || mapConfig.maxZoom || 18);
        }
    },

    /**
     * 设置地图样式
     */
    setStyle: function (map) {
        if (!map) return;

        // 独立设置需要的mapbox内置样式
        // 默认的base64 png图片 并进行addImage操作 iVBORw0KGgoAAAANSUhEUgAAAAsAAAArCAYAAABm8CLRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqkld9LAlEUxr93Z3fHXV1bE1JLMoheIh/6B/oHIiilICjohR76A4KgHnroTwh6CIKgICIzKCvNMnVdXd3ZnbnndIcZZ3bWEPoNDnfuOed855tzzz1XGGNgGIbxf8DpdF5omoZer/eXpmmYTCaIRCJot9vwer3wer0wmUwAgFarhXa7jXa7jVarhXa7jU6ng263i16vh36/DwAYDAaIRCKIRCJE0zQMDAzAarWCZVlgjIFSCkopKKXgeR6CICAIAjiOA8dxIIQAQghIkoQkSSBJEkRRhCiKEEURPM+DYRgwDAOGYUBRFCiKAkVRoKoqVFUFpRSapkHzPGiapnnDMAzDMAzDMIzf8M8BXq8XPp8PPp8Poij+9Xg8hkajgXq9jkajgXq9jnq9jmazCUIIGGOglILneQiCAEEQIAgCOI4Dx3EQBAEcxyEQCECWZUiShEAgALvdDovFAovFApvNBovFAkmSIEmSJEnSNVmW/1JV9Zym6XOaptc0TT/QNP1A0/QDTdMPNE0/0DR9T9P0PU3TdzRN39I0fUPT9DVN01c0TV/SNH1B0/Q5TdOnNE2f0DR9TNP0EU3ThzRNH9A0vU/T9B5N07s0Te/SNL1D0/Q2TdNbNE1v0jS9QdP0Ok3TazRNr9I0vULT9DJN00s0TS/SNL1A0/Q8TdNzNE3P0jQ9Q9P0NE3TUzRN/6Rp+jhN00c0TR/SNH1A0/Q+TdN7NE3v0jS9Q9P0Nk3TWzRNb9I0vUHT9DpN02s0Ta/SNL1C0/QyTdNLNE0v0jS9QNP0PE3TczRNz9I0PUMmk0kkEgnE43HE43HE43HEYjFomgZKKSilIIQAAARBAM/zEAQBgiCA53nwPA+e58HzPHiehyAI4DgOHMeB53lwHAeO48BxHHiehyAI4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOPM+D53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB/wD/BGAAuJZK3XZCtKsAAAAASUVORK5CYII=
        // 添加基于base64的自定义图片资源
        if (!map.hasImage('custom_circle_icon')) {
            const img = new Image();
            img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAArCAYAAABm8CLRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqkld9LAlEUxr93Z3fHXV1bE1JLMoheIh/6B/oHIiilICjohR76A4KgHnroTwh6CIKgICIzKCvNMnVdXd3ZnbnndIcZZ3bWEPoNDnfuOed855tzzz1XGGNgGIbxf8DpdF5omoZer/eXpmmYTCaIRCLot9vwer3wer0wmUwAgFarhXa7jXa7jVarhXa7jU6ng263i16vh36/DwAYDAaIRCKIRCJE0zQMDAzAarWCZVlgjIFSCkopKKXgeR6CICAIAjiOA8dxIIQAQghIkoQkSSBJEkRRhCiKEEURPM+DYRgwDAOGYUBRFCiKAkVRoKoqVFUFpRSapkHzPGiapnnDMAzDMIzDMIzf8M8BXq8PPp8PPp8Poij+9Xg8hkajgXq9jkajgXq9jnq9jmazCUIIGGOglILneQiCAEEQIAgCOI4Dx3EQBAEcxyEQCECWZUiShEAgALvdDovFAovFApvNBovFAkmSIEmSJEnSNVmW/1JV9Zym6XOaptc0TT/QNP1A0/QDTdMPNE0/0DR9T9P0PU3TdzRN39I0fUPT9DVN01c0TV/SNH1B0/Q5TdOnNE2f0DR9TNP0EU3ThzRNH9A0vU/T9B5N07s0Te/SNL1D0/Q2TdNbNE1v0jS9QdP0Ok3TazRNr9I0vULT9DJN00s0TS/SNL1A0/Q8TdNzNE3P0jQ9Q9P0NE3TUzRN/6Rp+jhN00c0TR/SNH1A0/Q+TdN7NE3v0jS9Q9P0Nk3TWzRNb9I0vUHT9DpN02s0Ta/SNL1C0/QyTdNLNE0v0jS9QNP0PE3TczRNz9I0PUMmk0kkEgnE43HE43HEYjFomgZKKSilIIQAAARBAM/zEAQBgiCA53nwPA+e58HzPHiehyAI4DgOHMeB53lwHAeO48BxHHiehyAI4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOPM+D53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB53nwPA9BECAIAjiOA8dx4DgOHMeB/wD/BGAAuJZK3XZCtKsAAAAASUVORK5CYII=';
            img.onload = () => {
                map.addImage('custom_circle_icon', img);
            };
        }

        // Mapbox GL JS使用不同的样式设置方式
        // 这里可以设置预定义样式或自定义样式
        // map.setStyle('mapbox://styles/mapbox/streets-v11');
    },

    /**
     * 设置地图缩放级别和中心点
     */
    setZoom: function (map, points, zoomLevel = null) {
        if (!map || !points || points.length === 0) return;

        let coordinates;
        if (typeof points[0] === 'number' && points.length % 2 === 0) {
            // 处理扁平数组格式
            coordinates = [];
            for (let i = 0; i < points.length; i += 2) {
                coordinates.push([points[i], points[i + 1]]);
            }
        } else {
            // 处理对象数组格式
            coordinates = points.map(p => [p.longitude, p.latitude]);
        }

        // 计算所有坐标的边界框
        const bounds = coordinates.reduce(
                (bbox, coord) => {
                    return [
                        Math.min(bbox[0], coord[0]), // 最小经度
                        Math.min(bbox[1], coord[1]), // 最小纬度
                        Math.max(bbox[2], coord[0]), // 最大经度
                        Math.max(bbox[3], coord[1])  // 最大纬度
                    ];
                },
                [Infinity, Infinity, -Infinity, -Infinity] // 初始边界
        );

        if (zoomLevel) {
            const center = [
                (bounds[0] + bounds[2]) / 2,
                (bounds[1] + bounds[3]) / 2
            ];
            map.setCenter(center);
            map.setZoom(zoomLevel);
        } else {
            map.fitBounds(
                    [[bounds[0], bounds[1]], [bounds[2], bounds[3]]],
                    {
                        padding: 80,
                        maxZoom: 16,
                        duration: 800
                    }
            );
        }
    },

    /**
     * 绘制巡检任务
     */
    drawPatrolTask: function (map, data) {
        if (!map || !data) return;

        const points = data.patrolPointDetailDTOs || [];
        const lines = data.patrolTaskPlanPaths || [];

        if (!points.length || !lines.length) return;

        this.setZoom(map, points);

        // 清除之前的图层
        if (map.getLayer('patrol-points')) map.removeLayer('patrol-points');
        if (map.getSource('patrol-points')) map.removeSource('patrol-points');
        if (map.getLayer('patrol-lines')) map.removeLayer('patrol-lines');
        if (map.getSource('patrol-lines')) map.removeSource('patrol-lines');

        // 添加点数据
        const pointFeatures = points.map(po => ({
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: [po.longitude, po.latitude]
            },
            properties: {
                ...po
            }
        }));

        map.addSource('patrol-points', {
            type: 'geojson',
            data: {
                type: 'FeatureCollection',
                features: pointFeatures
            }
        });

        // 根据状态设置不同图标
        map.addLayer({
            id: 'patrol-points',
            type: 'circle',
            source: 'patrol-points',
            paint: {
                'circle-radius': 6,
                'circle-color': [
                    'match',
                    ['get', 'status'],
                    '正常', '#7ed321',
                    '异常', '#ff0000',
                    '未检', '#9b9b9b',
                    '#3a6bdb' // 默认颜色
                ],
                'circle-stroke-width': 2,
                'circle-stroke-color': '#ffffff'
            }
        });

        // 添加点标签
        map.addLayer({
            id: 'patrol-point-labels',
            type: 'symbol',
            source: 'patrol-points',
            layout: {
                'text-field': ['get', 'patrolPoint'],
                'text-offset': [0, 1.5],
                'text-anchor': 'top'
            },
            paint: {
                'text-color': '#0093ff'
            }
        });

        // 添加线数据
        if (lines.length >= 2) {
            const lineFeatures = [];
            for (let i = 0; i < lines.length - 1; i++) {
                lineFeatures.push({
                    type: 'Feature',
                    geometry: {
                        type: 'LineString',
                        coordinates: [
                            [lines[i].longitude, lines[i].latitude],
                            [lines[i + 1].longitude, lines[i + 1].latitude]
                        ]
                    },
                    properties: {
                        validate: lines[i].validate
                    }
                });
            }

            map.addSource('patrol-lines', {
                type: 'geojson',
                data: {
                    type: 'FeatureCollection',
                    features: lineFeatures
                }
            });

            map.addLayer({
                id: 'patrol-lines',
                type: 'line',
                source: 'patrol-lines',
                paint: {
                    'line-color': [
                        'match',
                        ['get', 'validate'],
                        'valid', plan_color_valid,
                        plan_color_invalid
                    ],
                    'line-width': 4
                }
            });
        }
    },

    /**
     * 绘制巡检路径
     */
    drawPatrol: function (map, data, pointField) {
        if (!map || !data) return;
        const taskUniqueId = data.id || data.patrolTaskId;
        if (!taskUniqueId) return;

        const points = data.patrolTaskPointTrackDTOs || [];
        const lines = data.patrolTaskPlanPaths || [];
        if (!points.length || !lines.length) return;

        this.setZoom(map, points);

        // 定义动态唯一ID
        const pointSourceId = `patrol-track-points-${taskUniqueId}`;
        const pointIconLayerId = `patrol-track-points-icons-${taskUniqueId}`;
        const pointLabelLayerId = `patrol-track-point-labels-${taskUniqueId}`;
        const lineSourceId = `patrol-track-lines-${taskUniqueId}`;
        const lineLayerId = `patrol-track-lines-${taskUniqueId}`;

        // 清除旧图层/数据源（使用动态ID）
        if (map.getLayer(pointIconLayerId)) map.removeLayer(pointIconLayerId);
        if (map.getLayer(pointLabelLayerId)) map.removeLayer(pointLabelLayerId);
        if (map.getSource(pointSourceId)) map.removeSource(pointSourceId);
        if (map.getLayer(lineLayerId)) map.removeLayer(lineLayerId);
        if (map.getSource(lineSourceId)) map.removeSource(lineSourceId);

        // 添加点数据
        const pointFeatures = points.map(po => ({
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: [po.longitude, po.latitude]
            },
            properties: {
                ...po
            }
        }));

        // 在 addSource 中添加图标属性
        map.addSource(pointSourceId, {
            type: 'geojson',
            data: {
                type: 'FeatureCollection',
                features: pointFeatures.map(feature => {
                    let icon;
                    const status = feature.properties.status;
                    switch (status) {
                        case '正常':
                            icon = 'img_done';
                            break;
                        case '异常':
                            icon = 'img_error';
                            break;
                        case '未检':
                            icon = 'img_invalid';
                            break;
                        default:
                            icon = 'img_todo';
                            break;
                    }
                    return {
                        ...feature,
                        properties: {...feature.properties, icon: icon}
                    };
                })
            }
        });

        // 在图层中使用图标
        map.addLayer({
            id: pointIconLayerId,
            type: 'symbol',
            source: pointSourceId,
            layout: {
                'icon-image': ['get', 'icon'],
                'icon-size': 1,
                'icon-anchor': 'bottom'
            }
        });

        // 添加点标签
        map.addLayer({
            id: pointLabelLayerId,
            type: 'symbol',
            source: pointSourceId,
            layout: {
                'text-field': ['get', 'patrolPointName'],
                'text-offset': [0, 1.5],
                'text-anchor': 'top'
            },
            paint: {'text-color': '#0093ff'}
        });

        // 添加线数据,绑定任务信息到 properties
        if (lines.length >= 2) {
            const lineFeatures = [];
            for (let i = 0; i < lines.length - 1; i++) {
                lineFeatures.push({
                    type: 'Feature',
                    geometry: {
                        type: 'LineString',
                        coordinates: [
                            [lines[i].longitude, lines[i].latitude],
                            [lines[i + 1].longitude, lines[i + 1].latitude]
                        ]
                    },
                    properties: {
                        validate: lines[i].validate,
                        taskId: taskUniqueId,
                        taskInfo: {
                            name: data.name,
                            executeStatus: data.executeStatus,
                            startTime: data.startTime,
                            endTime: data.endTime,
                            faultCount: data.faultCount,
                            patrolPointCount: data.patrolPointCount,
                            inspectedCount: data.inspectedCount,
                            planPathLength: data.planPathLength,
                            validPathLength: data.validPathLength
                        }
                    }
                });
            }

            map.addSource(lineSourceId, {
                type: 'geojson',
                data: {type: 'FeatureCollection', features: lineFeatures}
            });

            map.addLayer({
                id: lineLayerId,
                type: 'line',
                source: lineSourceId,
                paint: {
                    'line-color': ['match', ['get', 'validate'], 'valid', plan_color_valid, plan_color_invalid],
                    'line-width': 4,
                    'line-dasharray': [2, 2]
                },
                interactive: true // 开启线图层点击交互
            });
        }

        // console.log('当前地图图层ID列表:', map.getStyle().layers.map(layer => layer.id));
    },

    /**
     * 绘制巡检任务(高德)
     */
    drawPatrolTaskInGaoDe: function (map, data) {
        if (!map || !data) return;

        const points = data.patrolPointDetailDTOs || [];
        const lines = data.patrolTaskPlanPaths || [];

        if (!points.length || !lines.length) return;

        this.setZoom(map, points);

        // 清除之前的图层
        if (map.getLayer('patrol-points')) map.removeLayer('patrol-points');
        if (map.getSource('patrol-points')) map.removeSource('patrol-points');
        if (map.getLayer('patrol-lines')) map.removeLayer('patrol-lines');
        if (map.getSource('patrol-lines')) map.removeSource('patrol-lines');

        // 添加点数据
        // 返回高德结果时需要进行wgs84转gcj02
        points.forEach(po => {
            [po.longitude, po.latitude] = SpatialRefUtils.wgs84toGcj02([po.longitude, po.latitude])
        })
        const pointFeatures = points.map(po => ({
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: [po.longitude, po.latitude]
            },
            properties: {
                ...po
            }
        }));

        map.addSource('patrol-points', {
            type: 'geojson',
            data: {
                type: 'FeatureCollection',
                features: pointFeatures
            }
        });

        // 根据状态设置不同图标
        map.addLayer({
            id: 'patrol-points',
            type: 'circle',
            source: 'patrol-points',
            paint: {
                'circle-radius': 6,
                'circle-color': [
                    'match',
                    ['get', 'status'],
                    '正常', '#7ed321',
                    '异常', '#ff0000',
                    '未检', '#9b9b9b',
                    '#3a6bdb' // 默认颜色
                ],
                'circle-stroke-width': 2,
                'circle-stroke-color': '#ffffff'
            }
        });

        // 添加点标签
        map.addLayer({
            id: 'patrol-point-labels',
            type: 'symbol',
            source: 'patrol-points',
            layout: {
                'text-field': ['get', 'patrolPoint'],
                'text-offset': [0, 1.5],
                'text-anchor': 'top'
            },
            paint: {
                'text-color': '#0093ff'
            }
        });

        // 添加线数据
        if (lines.length >= 2) {
            const lineFeatures = [];
            for (let i = 0; i < lines.length - 1; i++) {
                lineFeatures.push({
                    type: 'Feature',
                    geometry: {
                        type: 'LineString',
                        coordinates: [
                            [lines[i].longitude, lines[i].latitude],
                            [lines[i + 1].longitude, lines[i + 1].latitude]
                        ]
                    },
                    properties: {
                        validate: lines[i].validate
                    }
                });
            }

            map.addSource('patrol-lines', {
                type: 'geojson',
                data: {
                    type: 'FeatureCollection',
                    features: lineFeatures
                }
            });

            map.addLayer({
                id: 'patrol-lines',
                type: 'line',
                source: 'patrol-lines',
                paint: {
                    'line-color': [
                        'match',
                        ['get', 'validate'],
                        'valid', plan_color_valid,
                        plan_color_invalid
                    ],
                    'line-width': 4
                }
            });
        }
    },

    /**
     * 绘制巡检路径(高德)
     */
    drawPatrolInGaoDe: function (map, data, pointField) {
        if (!map || !data) return;
        const taskUniqueId = data.id || data.patrolTaskId;
        if (!taskUniqueId) return;

        const points = data.patrolTaskPointTrackDTOs || [];
        const lines = data.patrolTaskPlanPaths || [];
        if (!points.length || !lines.length) return;

        this.setZoom(map, points);

        // 定义动态唯一ID
        const pointSourceId = `patrol-track-points-${taskUniqueId}`;
        const pointIconLayerId = `patrol-track-points-icons-${taskUniqueId}`;
        const pointLabelLayerId = `patrol-track-point-labels-${taskUniqueId}`;
        const lineSourceId = `patrol-track-lines-${taskUniqueId}`;
        const lineLayerId = `patrol-track-lines-${taskUniqueId}`;

        // 清除旧图层/数据源（使用动态ID）
        if (map.getLayer(pointIconLayerId)) map.removeLayer(pointIconLayerId);
        if (map.getLayer(pointLabelLayerId)) map.removeLayer(pointLabelLayerId);
        if (map.getSource(pointSourceId)) map.removeSource(pointSourceId);
        if (map.getLayer(lineLayerId)) map.removeLayer(lineLayerId);
        if (map.getSource(lineSourceId)) map.removeSource(lineSourceId);

        // 添加点数据
        // 返回高德结果时需要进行wgs84转gcj02
        points.forEach(po => {
            [po.longitude, po.latitude] = SpatialRefUtils.wgs84toGcj02([po.longitude, po.latitude])
        })
        const pointFeatures = points.map(po => ({
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: [po.longitude, po.latitude]
            },
            properties: {
                ...po
            }
        }));

        // 在 addSource 中添加图标属性
        map.addSource(pointSourceId, {
            type: 'geojson',
            data: {
                type: 'FeatureCollection',
                features: pointFeatures.map(feature => {
                    let icon;
                    const status = feature.properties.status;
                    switch (status) {
                        case '正常':
                            icon = 'img_done';
                            break;
                        case '异常':
                            icon = 'img_error';
                            break;
                        case '未检':
                            icon = 'img_invalid';
                            break;
                        default:
                            icon = 'img_todo';
                            break;
                    }
                    return {
                        ...feature,
                        properties: {...feature.properties, icon: icon}
                    };
                })
            }
        });

        // 在图层中使用图标
        map.addLayer({
            id: pointIconLayerId,
            type: 'symbol',
            source: pointSourceId,
            layout: {
                'icon-image': ['get', 'icon'],
                'icon-size': 1,
                'icon-anchor': 'bottom'
            }
        });

        // 添加点标签
        map.addLayer({
            id: pointLabelLayerId,
            type: 'symbol',
            source: pointSourceId,
            layout: {
                'text-field': ['get', 'patrolPointName'],
                'text-offset': [0, 1.5],
                'text-anchor': 'top'
            },
            paint: {'text-color': '#0093ff'}
        });

        // 添加线数据,绑定任务信息到 properties
        if (lines.length >= 2) {
            const lineFeatures = [];
            for (let i = 0; i < lines.length - 1; i++) {
                lineFeatures.push({
                    type: 'Feature',
                    geometry: {
                        type: 'LineString',
                        coordinates: [
                            [lines[i].longitude, lines[i].latitude],
                            [lines[i + 1].longitude, lines[i + 1].latitude]
                        ]
                    },
                    properties: {
                        validate: lines[i].validate,
                        taskId: taskUniqueId,
                        taskInfo: {
                            name: data.name,
                            executeStatus: data.executeStatus,
                            startTime: data.startTime,
                            endTime: data.endTime,
                            faultCount: data.faultCount,
                            patrolPointCount: data.patrolPointCount,
                            inspectedCount: data.inspectedCount,
                            planPathLength: data.planPathLength,
                            validPathLength: data.validPathLength
                        }
                    }
                });
            }

            map.addSource(lineSourceId, {
                type: 'geojson',
                data: {type: 'FeatureCollection', features: lineFeatures}
            });

            map.addLayer({
                id: lineLayerId,
                type: 'line',
                source: lineSourceId,
                paint: {
                    'line-color': ['match', ['get', 'validate'], 'valid', plan_color_valid, plan_color_invalid],
                    'line-width': 4,
                    'line-dasharray': [2, 2]
                },
                interactive: true // 开启线图层点击交互
            });
        }

        // console.log('当前地图图层ID列表:', map.getStyle().layers.map(layer => layer.id));
    },

    /**
     * 添加搜索功能
     * @param {string} containerId - 搜索输入框的容器ID
     * @param {Array} bounds - 搜索边界范围
     * @param {Function} callback - 回调函数
     */
    addSearch: function (containerId, bounds = [], callback) {
        // 检查容器ID是否存在
        if (!containerId) return;

        // 通过容器ID获取输入框元素
        const inputElement = document.getElementById(containerId);
        inputElement.setAttribute('placeholder', '请输入搜索内容并通过↩︎进行查询')
        if (!inputElement) {
            console.error(`未找到ID为 ${containerId} 的输入框元素`);
            return;
        }

        // 创建搜索结果容器并插入到输入框下方
        let resultListContainer = document.getElementById(`${containerId}-results`);
        if (!resultListContainer) {
            resultListContainer = document.createElement('div');
            resultListContainer.id = `${containerId}-results`;
            resultListContainer.className = 'search-results-container';
            inputElement.parentNode.insertBefore(resultListContainer, inputElement.nextSibling);
        }

        // 默认隐藏搜索结果容器
        resultListContainer.style.display = 'none';

        // 监听输入事件，当输入为空时清空并隐藏结果列表
        inputElement.addEventListener('input', (event) => {
            const keyword = event.target.value.trim();
            if (!keyword) {
                // 清空并隐藏搜索结果列表
                this.clearSearchResults(containerId);
            }
        });

        inputElement.addEventListener('keydown', (event) => {
            if (event.key === 'Enter') {
                event.preventDefault();
                const keyword = inputElement.value.trim();
                if (keyword) {
                    this.executeSearch(containerId, bounds, (poiList) => {
                        // 展示搜索结果列表
                        this.showSearchResults(containerId, poiList);
                        callback && callback(poiList);
                    });
                } else {
                    // 如果输入为空，清空并隐藏结果列表
                    this.clearSearchResults(containerId);
                }
            }
        });

        // 添加输入框失去焦点时隐藏结果列表的事件
        inputElement.addEventListener('blur', () => {
            // 延迟隐藏，确保点击列表项时不会立即隐藏
            setTimeout(() => {
                if (resultListContainer) {
                    resultListContainer.style.display = 'none';
                }
            }, 200);
        });

        // 添加输入框获得焦点时显示结果列表的事件（如果有结果）
        inputElement.addEventListener('focus', () => {
            if (resultListContainer && resultListContainer.children.length > 0) {
                resultListContainer.style.display = 'block';
            }
        });
    },

    /**
     * 清空并隐藏搜索结果列表
     * @param {string} containerId - 搜索输入框的容器ID
     */
    clearSearchResults: function (containerId) {
        const resultListContainer = document.getElementById(`${containerId}-results`);
        if (resultListContainer) {
            resultListContainer.innerHTML = '';
            resultListContainer.style.display = 'none';
        }

        // 同时清除地图上的POI结果
        this.clearPOIResults();
    },

    /**
     * 展示搜索结果列表
     * @param {string} containerId - 搜索输入框的容器ID
     * @param {Array} poiList - POI结果列表
     */
    showSearchResults: function (containerId, poiList) {
        const resultListContainer = document.getElementById(`${containerId}-results`);
        if (!resultListContainer) return;

        // 清空容器内容
        resultListContainer.innerHTML = '';

        if (!poiList || poiList.length === 0) {
            resultListContainer.innerHTML = '<div class="no-results">未找到相关结果</div>';
            resultListContainer.style.display = 'block';
            return;
        }

        // 创建结果列表
        const resultList = document.createElement('ul');
        resultList.className = 'search-result-list';

        // 为每个POI创建列表项
        poiList.forEach((poi, index) => {
            const listItem = document.createElement('li');
            listItem.className = 'search-result-item';
            listItem.dataset.index = index;

            // 设置列表项内容
            listItem.innerHTML = `
            <div class="result-item-header">
                <span class="result-item-name">${poi.name || '未知名称'}</span>
                ${poi.type ? `<span class="result-item-type">${poi.type}</span>` : ''}
            </div>
            ${poi.address ? `<div class="result-item-address">${poi.address}</div>` : ''}
            ${poi.tel ? `<div class="result-item-tel">电话: ${poi.tel}</div>` : ''}
        `;

            // 绑定点击事件，实现定位功能
            listItem.addEventListener('mousedown', (e) => {
                // 使用mousedown而不是click，避免blur事件先触发
                e.preventDefault();
                this.focusOnPOI(poi);
            });

            resultList.appendChild(listItem);
        });

        resultListContainer.appendChild(resultList);
        resultListContainer.style.display = 'block';
    },

    /**
     * 定位到指定POI
     * @param {Object} poi - POI对象
     */
    focusOnPOI: function (poi) {
        if (!map || !poi || !poi.longitude || !poi.latitude) return;

        // 移动地图到POI位置
        map.flyTo({
            center: [poi.longitude, poi.latitude],
            zoom: 18,
            essential: true // 动画不受 prefers-reduced-motion 影响
        });

        // 高亮显示该POI（如果地图上已有POI结果图层）
        if (map.getSource('poi-results')) {
            // 创建临时标记
            const popup = new mapboxgl.Popup({
                closeButton: false,
                className: 'poi-focus-popup'
            })
                    .setLngLat([poi.longitude, poi.latitude])
                    .setHTML(`<div class="poi-focus-content">${poi.name}</div>`)
                    .addTo(map);

            // 3秒后自动关闭弹窗
            setTimeout(() => {
                if (popup.isOpen()) {
                    popup.remove();
                }
            }, 3000);
        }
    },

    executeSearch: function (containerId, bounds = [], callback) {
        // 通过容器ID获取输入框元素
        const inputElement = document.getElementById(containerId);
        if (!inputElement) {
            console.error(`未找到ID为 ${containerId} 的输入框元素`);
            return;
        }
        // 获取输入框的值作为搜索关键词
        const keyword = inputElement.value.trim();
        if (!keyword) return;

        // 天地图POI搜索API URL (使用注释中的v2/search接口)
        const baseUrl = mapConfig.TDT_query_url;

        // 构建请求参数 (按照注释中的格式)
        const postStr = {
            keyWord: keyword,
            level: 12,
            queryType: 1,
            start: 0,
            count: 100
        };

        // 如果提供了搜索范围，则添加边界参数
        if (bounds && bounds.length === 4) {
            postStr.mapBound = `${bounds[0]},${bounds[1]},${bounds[2]},${bounds[3]}`;
        } else {
            postStr.mapBound = `${mapConfig.mapExtent[0]},${mapConfig.mapExtent[1]},${mapConfig.mapExtent[2]},${mapConfig.mapExtent[3]}`;
        }

        // 构建完整的请求URL
        const params = new URLSearchParams({
            postStr: JSON.stringify(postStr),
            type: 'query',
            tk: TokenUtils.TDT_token
        });

        // 发送请求
        fetch(`${baseUrl}?${params.toString()}`)
                .then(response => response.json())
                .then(data => {
                    if (data.pois) {
                        // 处理返回的数据，转换为统一格式
                        const poiList = data.pois.map(item => ({
                            id: item.lonlat ? item.lonlat.split(',')[1] : '', // 使用lonlat生成ID
                            name: item.name,
                            address: item.address || '',
                            longitude: item.lonlat ? parseFloat(item.lonlat.split(',')[0]) : 0,
                            latitude: item.lonlat ? parseFloat(item.lonlat.split(',')[1]) : 0,
                            tel: item.phone || '',
                            type: item.type || ''
                        }));

                        // 使用Mapbox绘制POI结果
                        this.drawPOIResults(poiList);

                        callback && callback(poiList);
                    } else {
                        this.clearPOIResults();
                        callback && callback([]);
                    }
                })
                .catch(error => {
                    console.error('天地图POI搜索失败:', error);
                    this.clearPOIResults();
                    callback && callback([]);
                });
    },

    /**
     * 绘制POI搜索结果到地图上
     * @param {Array} poiList - POI结果列表
     */
    drawPOIResults: function (poiList) {
        if (!map || !poiList || !poiList.length) return;

        // 清除之前的结果图层
        this.clearPOIResults();

        // 创建GeoJSON数据
        const geojson = {
            type: 'FeatureCollection',
            features: poiList.map(poi => ({
                type: 'Feature',
                geometry: {
                    type: 'Point',
                    coordinates: [poi.longitude, poi.latitude]
                },
                properties: {
                    id: poi.id,
                    name: poi.name,
                    address: poi.address,
                    tel: poi.tel,
                    type: poi.type
                }
            }))
        };

        // 添加数据源
        map.addSource('poi-results', {
            type: 'geojson',
            data: geojson
        });

        // 添加点图层
        map.addLayer({
            id: 'poi-results',
            type: 'circle',
            source: 'poi-results',
            paint: {
                'circle-radius': 8,
                'circle-color': '#ff6b35',
                'circle-stroke-width': 2,
                'circle-stroke-color': '#ffffff'
            }
        });

        // 添加标签图层
        map.addLayer({
            id: 'poi-labels',
            type: 'symbol',
            source: 'poi-results',
            layout: {
                'text-field': ['get', 'name'],
                'text-offset': [0, 1.5],
                'text-anchor': 'top',
                'text-size': 12
            },
            paint: {
                'text-color': '#333333',
                'text-halo-color': '#ffffff',
                'text-halo-width': 1
            }
        });

        // 添加点击事件
        map.on('click', 'poi-results', (e) => {
            const feature = e.features[0];
            new mapboxgl.Popup({offset: [0, -15]})
                    .setLngLat(feature.geometry.coordinates)
                    .setHTML(`                <div style="padding: 10px;">
                    <h3 style="margin: 0 0 5px 0;">${feature.properties.name}</h3>
                    <p style="margin: 5px 0;"><strong>地址:</strong> ${feature.properties.address || '无'}</p>
                    <p style="margin: 5px 0;"><strong>电话:</strong> ${feature.properties.tel || '无'}</p>
                    <p style="margin: 5px 0;"><strong>类型:</strong> ${feature.properties.type || '未知'}</p>
                </div>
            `)
                    .addTo(map);
        });

        // 设置鼠标悬停效果
        map.on('mouseenter', 'poi-results', () => {
            map.getCanvas().style.cursor = 'pointer';
        });

        map.on('mouseleave', 'poi-results', () => {
            map.getCanvas().style.cursor = '';
        });
    },

    /**
     * 清除POI搜索结果
     */
    clearPOIResults: function () {
        if (!map) return;

        if (map.getLayer('poi-results')) {
            map.removeLayer('poi-results');
        }
        if (map.getLayer('poi-labels')) {
            map.removeLayer('poi-labels');
        }
        if (map.getSource('poi-results')) {
            map.removeSource('poi-results');
        }

        // 移除事件监听器
        map.off('click', 'poi-results');
        map.off('mouseenter', 'poi-results');
        map.off('mouseleave', 'poi-results');
    },

    /**
     * 转换数据点为地图点
     */
    getMapboxPoints: function (data) {
        if (!data) return [];
        return data.map(item => [item.longitude, item.latitude]);
    },

    /**
     * 标记点位并支持拖拽移动
     * @param {Object} map - 地图实例
     * @param {Array|Object} points - 点位数据
     * @param {Boolean} disableDrag - 是否禁用拖拽功能
     * @param {Function} onDragEnd - 拖拽结束回调函数，返回更新后的点位信息
     */
    hitPoint: function (map, points, disableDrag = true, onDragEnd) {
        if (!map) return;

        let pointsArray = Array.isArray(points) ? points : [points];

        // 创建点数据源 - 改进数据验证逻辑，允许坐标值为0
        const features = pointsArray
                .filter(point =>
                        typeof point.longitude !== 'undefined' &&
                        typeof point.latitude !== 'undefined' &&
                        point.longitude !== null &&
                        point.latitude !== null
                )
                .map((point, idx) => ({
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [point.longitude, point.latitude]
                    },
                    properties: {
                        id: point.id,
                        patrolPoint: point.patrolPoint
                    }
                }));

        // 添加数据源和图层
        if (!map.getSource('hit-points')) {
            map.addSource('hit-points', {
                type: 'geojson',
                data: {
                    type: 'FeatureCollection',
                    features: features
                }
            });

            map.addLayer({
                id: 'hit-points',
                type: 'circle',
                source: 'hit-points',
                minzoom: 5,
                maxZoom: 19,
                layout: {
                    'visibility': 'visible'  // 显式设置图层可见性
                },
                paint: {
                    'circle-radius': 6,
                    'circle-color': '#3a6bdb',
                    'circle-stroke-width': 2,
                    'circle-stroke-color': '#ffffff'
                }
            });

            // 添加标签
            map.addLayer({
                id: 'hit-point-labels',
                type: 'symbol',
                source: 'hit-points',
                minzoom: 5,
                maxZoom: 19,
                layout: {
                    "text-font": ["Microsoft YaHei"],
                    'text-field': ['get', 'patrolPoint'],
                    'text-offset': [0, 1.5],
                    'text-anchor': 'top',
                    'visibility': 'visible'  // 显式设置图层可见性
                },
                paint: {
                    'text-color': '#0093ff'
                }
            });

            // 确保图层在最上层显示
            const layers = map.getStyle().layers;
            const lastLayerId = layers.length > 0 ? layers[layers.length - 1].id : undefined;
            if (lastLayerId) {
                map.moveLayer('hit-points', lastLayerId);
                map.moveLayer('hit-point-labels', lastLayerId);
            }

            // 如果不禁用拖拽，则添加拖拽功能
            if (!disableDrag) {
                this._enablePointDragging(map, onDragEnd);
            }

            // 将 disableDrag 状态存储在图层上，便于后续更新时判断
            map.getLayer('hit-points')._disableDrag = disableDrag;
        } else {
            // 更新数据
            map.getSource('hit-points').setData({
                type: 'FeatureCollection',
                features: features
            });

            // 确保图层可见
            map.setLayoutProperty('hit-points', 'visibility', 'visible');
            map.setLayoutProperty('hit-point-labels', 'visibility', 'visible');

            // 检查是否需要更新拖拽功能状态
            const hitPointsLayer = map.getLayer('hit-points');
            if (hitPointsLayer && hitPointsLayer._disableDrag !== disableDrag) {
                if (!disableDrag) {
                    // 启用拖拽功能
                    this._enablePointDragging(map, onDragEnd);
                } else {
                    // 禁用拖拽功能，移除相关事件监听器
                    map.off('mousedown', 'hit-points');
                    map.off('mouseenter', 'hit-points');
                    map.off('mouseleave', 'hit-points');
                }
                // 更新状态
                hitPointsLayer._disableDrag = disableDrag;
            }
        }

        // 调试日志
        console.log('_hitPoint_ executed with features:', features);
        console.log('Current zoom level:', map.getZoom());
        console.log('Layer visibility:',
                map.getLayoutProperty('hit-points', 'visibility'),
                map.getLayoutProperty('hit-point-labels', 'visibility')
        );
    },

    /**
     * 启用点位拖拽功能
     * @param {Object} map - 地图实例
     * @param {Function} onDragEnd - 拖拽结束回调函数
     */
    _enablePointDragging: function (map, onDragEnd) {
        let isDragging = false;
        let dragTarget = null;
        let originalPosition = null;
        let tooltip = null; // 添加tooltip变量

        // 鼠标按下事件 - 开始拖拽
        map.on('mousedown', 'hit-points', (e) => {
            this.enableScrollWheelZoom(false)
            map.dragPan.disable();
            isDragging = true;
            dragTarget = e.features[0];
            originalPosition = dragTarget.geometry.coordinates.slice();

            // 设置鼠标样式
            map.getCanvas().style.cursor = 'grabbing';

            // 为dragTarget增加一个tooltip
            tooltip = new mapboxgl.Popup({
                closeButton: false,
                closeOnClick: false,
                className: 'drag-tooltip'
            })
                    .setLngLat(dragTarget.geometry.coordinates)
                    .setHTML('<div>拖拽中...</div>')
                    .addTo(map);
        });

        // 鼠标移动事件 - 执行拖拽
        map.on('mousemove', (e) => {
            if (!isDragging || !dragTarget) return;

            // 更新点位位置
            const updatedFeatures = map.getSource('hit-points')._data.features.map(feature => {
                if (feature.properties.id === dragTarget.properties.id) {
                    return {
                        ...feature,
                        geometry: {
                            ...feature.geometry,
                            coordinates: [e.lngLat.lng, e.lngLat.lat]
                        }
                    };
                }
                return feature;
            });

            // 更新数据源
            map.getSource('hit-points').setData({
                type: 'FeatureCollection',
                features: updatedFeatures
            });

            // 更新tooltip位置
            if (tooltip) {
                tooltip.setLngLat([e.lngLat.lng, e.lngLat.lat]);
            }
        });

        // 鼠标释放事件 - 结束拖拽
        map.on('mouseup', () => {
            // 移除tooltip
            if (tooltip) {
                tooltip.remove();
                tooltip = null;
            }
            if (isDragging && dragTarget) {
                isDragging = false;

                // 获取更新后的点位数据
                const updatedFeatures = map.getSource('hit-points')._data.features;
                const updatedPoint = updatedFeatures.find(
                        feature => feature.properties.id === dragTarget.properties.id
                );

                // 调用回调函数返回更新后的点位信息
                if (onDragEnd && updatedPoint) {
                    onDragEnd({
                        id: updatedPoint.properties.id,
                        patrolPoint: updatedPoint.properties.patrolPoint,
                        longitude: updatedPoint.geometry.coordinates[0],
                        latitude: updatedPoint.geometry.coordinates[1],
                        originalLongitude: originalPosition[0],
                        originalLatitude: originalPosition[1]
                    });
                }

                dragTarget = null;
                originalPosition = null;

                this.enableScrollWheelZoom()
                map.dragPan.enable();
            }

            // 恢复鼠标样式
            map.getCanvas().style.cursor = '';
        });

        // 鼠标离开地图时也结束拖拽
        map.on('mouseleave', () => {
            if (isDragging) {
                isDragging = false;
                dragTarget = null;
                originalPosition = null;

                // 移除tooltip
                if (tooltip) {
                    tooltip.remove();
                    tooltip = null;
                }

                map.getCanvas().style.cursor = '';
            }
        });

        // 设置鼠标悬停样式
        map.on('mouseenter', 'hit-points', () => {
            map.getCanvas().style.cursor = 'grab';
        });

        map.on('mouseleave', 'hit-points', () => {
            if (!isDragging) {
                map.getCanvas().style.cursor = '';
            }
        });
    },

    /**
     * 绘制线段
     * @param map - 地图实例
     * @param points - 点位数据
     * @param options - 绘制选项
     * @returns {*|null} 绘制的线对象
     */
    renderLine: function (map, points, options) {
        if (!map || !points || points.length < 2) return null;

        const coordinates = points.map(p => [p.lng, p.lat]);

        const config = {
            enableEditing: false,
            enableClicking: true,
            strokeWeight: 5,
            strokeOpacity: 0.65,
            color: '#3a6bdb',
            ...options
        };

        // 创建线数据源
        if (!map.getSource('custom-line')) {
            map.addSource('custom-line', {
                type: 'geojson',
                data: {
                    type: 'Feature',
                    geometry: {
                        type: 'LineString',
                        coordinates: coordinates
                    },
                    properties: {
                        id: options.id || Date.now()
                    }
                }
            });

            map.addLayer({
                id: 'custom-line',
                type: 'line',
                source: 'custom-line',
                paint: {
                    'line-color': config.color,
                    'line-width': config.strokeWeight,
                    'line-opacity': config.strokeOpacity
                }
            });
        } else {
            // 更新数据
            let existingData = map.getSource('custom-line')._data;
            let isFeatureObj = existingData.hasOwnProperty('features')
            let geomData = null
            if  (isFeatureObj) {
                geomData = map.getSource('custom-line')._data.features[0]
            } else {
                geomData = map.getSource('custom-line')._data;
            }
            geomData.geometry.coordinates = coordinates;
            geomData.properties = {
                ...geomData.properties,
                ...options.properties
            };

            map.getSource('custom-line').setData(geomData);
        }

        // 获取更新后的feature
        const updatedFeature = map.getSource('custom-line')._data.hasOwnProperty('features') ? map.getSource('custom-line')._data.features[0]: map.getSource('custom-line')._data;

        // 如果启用编辑功能
        if (config.enableEditing) {
            this._enableLineEditing(map, 'custom-line', config);
        }

        return updatedFeature;
    },

    /**
     * 启用线段编辑功能
     */
    _enableLineEditing: function (map, sourceId, config) {
        let editingVertexIndex = -1;
        let isVertexDragging = false;

        // 创建顶点图层以便编辑
        if (!map.getSource('line-vertices')) {
            map.addSource('line-vertices', {
                type: 'geojson',
                data: {
                    type: 'FeatureCollection',
                    features: []
                }
            });

            map.addLayer({
                id: 'line-vertices',
                type: 'circle',
                source: 'line-vertices',
                filter: ['==', '$type', 'Point'],
                paint: {
                    'circle-radius': 6,
                    'circle-color': '#ff0000',
                    'circle-stroke-width': 2,
                    'circle-stroke-color': '#ffffff'
                }
            });
        }

        // 更新顶点显示
        const updateVertices = () => {
            const lineData = map.getSource(sourceId)._data;
            const coordinates = lineData.features[0].geometry.coordinates;

            const vertices = coordinates.map((coord, index) => ({
                type: 'Feature',
                geometry: {
                    type: 'Point',
                    coordinates: coord
                },
                properties: {
                    vertexIndex: index
                }
            }));

            map.getSource('line-vertices').setData({
                type: 'FeatureCollection',
                features: vertices
            });
        };

        // 鼠标按下事件 - 开始拖拽顶点
        map.on('mousedown', 'line-vertices', (e) => {
            if (!config.enableEditing) return;

            this.enableScrollWheelZoom(false);
            map.dragPan.disable();
            editingVertexIndex = e.features[0].properties.vertexIndex;
            isVertexDragging = true;

            // 设置鼠标样式
            map.getCanvas().style.cursor = 'grabbing';
        });

        // 鼠标移动事件 - 拖拽顶点
        map.on('mousemove', (e) => {
            if (!isVertexDragging || editingVertexIndex === -1 || !config.enableEditing) return;

            // 更新线段坐标
            const source = map.getSource(sourceId);
            const data = source._data;
            const coordinates = data.features[0].geometry.coordinates;

            // 更新对应顶点的坐标
            coordinates[editingVertexIndex] = [e.lngLat.lng, e.lngLat.lat];

            source.setData(data);

            // 更新顶点显示
            updateVertices();
        });

        // 鼠标释放事件 - 结束拖拽
        map.on('mouseup', () => {
            if (isVertexDragging) {
                isVertexDragging = false;
                editingVertexIndex = -1;

                // 触发编辑完成回调
                if (config.onEditComplete) {
                    const updatedFeature = map.getSource(sourceId)._data.features[0];
                    config.onEditComplete(updatedFeature);
                }

                this.enableScrollWheelZoom();
                map.dragPan.enable();
            }

            // 恢复鼠标样式
            map.getCanvas().style.cursor = '';
        });

        // 鼠标进入顶点区域 - 更改光标样式
        map.on('mouseenter', 'line-vertices', () => {
            if (config.enableEditing) {
                map.getCanvas().style.cursor = 'crosshair';
            }
        });

        map.on('mouseleave', 'line-vertices', () => {
            if (config.enableEditing) {
                map.getCanvas().style.cursor = '';
            }
        });

        // 初始显示顶点
        if (config.enableEditing) {
            updateVertices();
        }
    },


    /**
     * 绘制点
     * @param map 地图实例
     * @param point 点对象
     * @param options 绘制配置项
     * @returns {*|null} 绘制的点对象
     */
    renderPoint: function (map, point, options) {
        if (!map || !point || typeof point.lng === 'undefined' || typeof point.lat === 'undefined') return null;

        const coordinates = [point.lng, point.lat];

        const config = {
            enableEditing: false,
            enableClicking: true,
            radius: 6,
            color: '#3a6bdb',
            strokeColor: '#ffffff',
            strokeWidth: 2,
            ...options
        };

        // 创建点数据源
        if (!map.getSource('custom-point')) {
            map.addSource('custom-point', {
                type: 'geojson',
                data: {
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: coordinates
                    },
                    properties: {
                        id: point.id || Date.now()
                    }
                }
            });

            map.addLayer({
                id: 'custom-point',
                type: 'circle',
                source: 'custom-point',
                paint: {
                    'circle-radius': config.radius,
                    'circle-color': config.color,
                    'circle-stroke-width': config.strokeWidth,
                    'circle-stroke-color': config.strokeColor
                }
            });
        } else {
            // 更新数据
            const existingData = map.getSource('custom-point')._data;
            existingData.features[0].geometry.coordinates = coordinates;
            existingData.features[0].properties = {
                ...existingData.features[0].properties,
                ...point.properties
            };

            map.getSource('custom-point').setData(existingData);
        }

        // 获取更新后的feature
        const updatedFeature = map.getSource('custom-point')._data.features[0];

        // 如果启用编辑功能
        if (config.enableEditing) {
            this._enablePointEditing(map, 'custom-point', config);
        }

        return updatedFeature;
    },

    /**
     * 启用点编辑功能
     */
    _enablePointEditing: function (map, sourceId, config) {
        let isDragging = false;
        let dragStartPos = null;

        // 鼠标按下事件 - 开始拖拽
        map.on('mousedown', sourceId, (e) => {
            if (!config.enableEditing) return;

            this.enableScrollWheelZoom(false);
            map.dragPan.disable();
            isDragging = true;
            dragStartPos = e.lngLat;

            // 设置鼠标样式
            map.getCanvas().style.cursor = 'grabbing';
        });

        // 鼠标移动事件 - 执行拖拽
        map.on('mousemove', (e) => {
            if (!isDragging || !config.enableEditing) return;

            // 获取原始数据并更新坐标
            const source = map.getSource(sourceId);
            const data = source._data;
            data.features[0].geometry.coordinates = [e.lngLat.lng, e.lngLat.lat];
            source.setData(data);
        });

        // 鼠标释放事件 - 结束拖拽
        map.on('mouseup', () => {
            if (isDragging) {
                isDragging = false;

                // 触发编辑完成回调
                if (config.onEditComplete) {
                    const updatedFeature = map.getSource(sourceId)._data.features[0];
                    config.onEditComplete(updatedFeature);
                }

                this.enableScrollWheelZoom();
                map.dragPan.enable();
            }

            // 恢复鼠标样式
            map.getCanvas().style.cursor = '';
        });

        // 设置鼠标悬停样式
        map.on('mouseenter', sourceId, () => {
            if (config.enableEditing) {
                map.getCanvas().style.cursor = 'grab';
            }
        });

        map.on('mouseleave', sourceId, () => {
            if (!isDragging && config.enableEditing) {
                map.getCanvas().style.cursor = '';
            }
        });
    },

    /**
     * 绘制多边形
     * @param map 地图实例
     * @param points 点对象数组
     * @param options 绘制配置项
     * @returns {*|null} 绘制的多边形对象
     */
    renderPolygon: function (map, points, options) {
        if (!map || !points || points.length < 3) return null;

        // 确保多边形闭合
        const coordinates = [...points.map(p => [p.lng, p.lat])];
        if (coordinates[0][0] !== coordinates[coordinates.length - 1][0] ||
                coordinates[0][1] !== coordinates[coordinates.length - 1][1]) {
            coordinates.push(coordinates[0]); // 闭合多边形
        }

        const config = {
            enableEditing: false,
            enableClicking: true,
            fillColor: '#3a6bdb',
            fillOpacity: 0.4,
            strokeColor: '#3a6bdb',
            strokeWidth: 2,
            ...options
        };

        // 创建多边形数据源
        if (!map.getSource('custom-polygon')) {
            map.addSource('custom-polygon', {
                type: 'geojson',
                data: {
                    type: 'Feature',
                    geometry: {
                        type: 'Polygon',
                        coordinates: [coordinates]
                    },
                    properties: {
                        id: options.id || Date.now()
                    }
                }
            });

            map.addLayer({
                id: 'custom-polygon-fill',
                type: 'fill',
                source: 'custom-polygon',
                paint: {
                    'fill-color': config.fillColor,
                    'fill-opacity': config.fillOpacity
                }
            });

            map.addLayer({
                id: 'custom-polygon-stroke',
                type: 'line',
                source: 'custom-polygon',
                paint: {
                    'line-color': config.strokeColor,
                    'line-width': config.strokeWidth
                }
            });
        } else {
            // 更新数据
            let existingData = map.getSource('custom-polygon')._data;
            let isFeatureObj = existingData.hasOwnProperty('features')
            let geomData = null
            if  (isFeatureObj) {
                geomData = map.getSource('custom-polygon')._data.features[0]
            } else {
                geomData = map.getSource('custom-polygon')._data;
            }
            geomData.geometry.coordinates = coordinates;
            geomData.properties = {
                ...geomData.properties,
                ...options.properties
            };

            map.getSource('custom-polygon').setData(geomData);
        }

        // 获取更新后的feature
        const updatedFeature = map.getSource('custom-polygon')._data.hasOwnProperty('features') ? map.getSource('custom-polygon')._data.features[0]: map.getSource('custom-polygon')._data;


        // 如果启用编辑功能
        if (config.enableEditing) {
            this._enablePolygonEditing(map, 'custom-polygon', config);
        }

        return updatedFeature;
    },

    /**
     * 启用多边形编辑功能
     */
    _enablePolygonEditing: function (map, sourceId, config) {
        let editingVertexIndex = -1;
        let isVertexDragging = false;

        // 创建顶点图层以便编辑
        if (!map.getSource('polygon-vertices')) {
            map.addSource('polygon-vertices', {
                type: 'geojson',
                data: {
                    type: 'FeatureCollection',
                    features: []
                }
            });

            map.addLayer({
                id: 'polygon-vertices',
                type: 'circle',
                source: 'polygon-vertices',
                filter: ['==', '$type', 'Point'],
                paint: {
                    'circle-radius': 6,
                    'circle-color': '#ff0000',
                    'circle-stroke-width': 2,
                    'circle-stroke-color': '#ffffff'
                }
            });
        }

        // 更新顶点显示
        const updateVertices = () => {
            const polygonData = map.getSource(sourceId)._data;
            const coordinates = polygonData.features[0].geometry.coordinates[0]; // 获取外环坐标

            const vertices = coordinates.slice(0, -1).map((coord, index) => ({ // 不包含最后一个重复点
                type: 'Feature',
                geometry: {
                    type: 'Point',
                    coordinates: coord
                },
                properties: {
                    vertexIndex: index
                }
            }));

            map.getSource('polygon-vertices').setData({
                type: 'FeatureCollection',
                features: vertices
            });
        };

        // 鼠标按下事件 - 开始拖拽顶点
        map.on('mousedown', 'polygon-vertices', (e) => {
            if (!config.enableEditing) return;

            this.enableScrollWheelZoom(false);
            map.dragPan.disable();
            editingVertexIndex = e.features[0].properties.vertexIndex;
            isVertexDragging = true;

            // 设置鼠标样式
            map.getCanvas().style.cursor = 'grabbing';
        });

        // 鼠标移动事件 - 拖拽顶点
        map.on('mousemove', (e) => {
            if (!isVertexDragging || editingVertexIndex === -1 || !config.enableEditing) return;

            // 更新多边形坐标
            const source = map.getSource(sourceId);
            const data = source._data;
            const coordinates = data.features[0].geometry.coordinates[0];

            // 更新对应顶点的坐标
            coordinates[editingVertexIndex] = [e.lngLat.lng, e.lngLat.lat];
            // 如果是第一个点，也要更新最后一个点（因为多边形是闭合的）
            if (editingVertexIndex === 0) {
                coordinates[coordinates.length - 1] = [e.lngLat.lng, e.lngLat.lat];
            }

            source.setData(data);

            // 更新顶点显示
            updateVertices();
        });

        // 鼠标释放事件 - 结束拖拽
        map.on('mouseup', () => {
            if (isVertexDragging) {
                isVertexDragging = false;
                editingVertexIndex = -1;

                // 触发编辑完成回调
                if (config.onEditComplete) {
                    const updatedFeature = map.getSource(sourceId)._data.features[0];
                    config.onEditComplete(updatedFeature);
                }

                this.enableScrollWheelZoom();
                map.dragPan.enable();
            }

            // 恢复鼠标样式
            map.getCanvas().style.cursor = '';
        });

        // 鼠标进入顶点区域 - 更改光标样式
        map.on('mouseenter', 'polygon-vertices', () => {
            if (config.enableEditing) {
                map.getCanvas().style.cursor = 'crosshair';
            }
        });

        map.on('mouseleave', 'polygon-vertices', () => {
            if (config.enableEditing) {
                map.getCanvas().style.cursor = '';
            }
        });

        // 初始显示顶点
        if (config.enableEditing) {
            updateVertices();
        }
    },


    /**
     * controls
     */
    /**
     * 启用滚轮缩放
     * @param {boolean} isOpen 是否开启控制
     */
    enableScrollWheelZoom: function (isOpen = true) {
        // 进行mapboxgl的scroll(wheel)事件的控制
        if (!map) return;

        if (isOpen) {
            map.scrollZoom.enable();
        } else {
            map.scrollZoom.disable();
        }
    },

    /**
     * 绘制带中心点标注的经纬度网格
     * @param {Object} map - 地图实例
     * @param {Object} options - 网格配置选项
     */
    _drawGridWithCenterLabels: function (map, options = {}) {
        if (!map) return;

        const {
            interval = 1,
            color = '#0066cc',
            width = 1,
            showLabels = true,
            showCenterLabels = true
        } = options;

        const features = [];
        const labelFeatures = [];
        const centerLabelFeatures = [];

        // 中国范围经纬度网格
        // 73.55, 3.85, 135.08, 53.55
        const minLng = mapConfig.mapExtent[0], maxLng = mapConfig.mapExtent[2];
        const minLat = mapConfig.mapExtent[1], maxLat = mapConfig.mapExtent[3];

        // 经线
        for (let lng = Math.ceil(minLng); lng <= Math.floor(maxLng); lng += interval) {
            const coordinates = [];
            for (let lat = minLat; lat <= maxLat; lat += 0.1) {
                coordinates.push([lng, lat]);
            }
            features.push({
                type: 'Feature',
                geometry: {
                    type: 'LineString',
                    coordinates: coordinates
                },
                properties: {
                    type: 'longitude',
                    value: lng
                }
            });

            // 添加经度标签
            if (showLabels) {
                labelFeatures.push({
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [lng, minLat]
                    },
                    properties: {
                        text: `${lng}°`
                    }
                });
            }
        }

        // 纬线
        for (let lat = Math.ceil(minLat); lat <= Math.floor(maxLat); lat += interval) {
            const coordinates = [];
            for (let lng = minLng; lng <= maxLng; lng += 0.1) {
                coordinates.push([lng, lat]);
            }
            features.push({
                type: 'Feature',
                geometry: {
                    type: 'LineString',
                    coordinates: coordinates
                },
                properties: {
                    type: 'latitude',
                    value: lat
                }
            });

            // 添加纬度标签
            if (showLabels) {
                labelFeatures.push({
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: [minLng, lat]
                    },
                    properties: {
                        text: `${lat}°`
                    }
                });
            }
        }

        // 添加网格中心点标签（显示经纬度区间）
        if (showCenterLabels) {
            for (let lng = Math.ceil(minLng); lng < Math.floor(maxLng); lng += interval) {
                for (let lat = Math.ceil(minLat); lat < Math.floor(maxLat); lat += interval) {
                    // 计算网格中心点
                    const centerLng = lng + interval / 2;
                    const centerLat = lat + interval / 2;

                    // 创建区间标签文本
                    const label = `${lng}°~${lng + interval}°\n${lat}°~${lat + interval}°`;

                    centerLabelFeatures.push({
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: [centerLng, centerLat]
                        },
                        properties: {
                            text: label
                        }
                    });
                }
            }
        }

        // 添加网格线数据源和图层
        if (!map.getSource('longitude-latitude-grid')) {
            map.addSource('longitude-latitude-grid', {
                type: 'geojson',
                data: {
                    type: 'FeatureCollection',
                    features: features
                }
            });

            map.addLayer({
                id: 'longitude-latitude-grid',
                type: 'line',
                source: 'longitude-latitude-grid',
                paint: {
                    'line-color': color,
                    'line-width': width,
                    'line-opacity': 0.6,
                    'line-dasharray': [2, 2]
                }
            });
        } else {
            map.getSource('longitude-latitude-grid').setData({
                type: 'FeatureCollection',
                features: features
            });
        }

        // 添加边界标签数据源和图层
        if (showLabels && labelFeatures.length > 0) {
            if (!map.getSource('grid-labels')) {
                map.addSource('grid-labels', {
                    type: 'geojson',
                    data: {
                        type: 'FeatureCollection',
                        features: labelFeatures
                    }
                });

                map.addLayer({
                    id: 'grid-labels',
                    type: 'symbol',
                    source: 'grid-labels',
                    layout: {
                        'text-field': ['get', 'text'],
                        'text-size': 16,
                        'text-offset': [0, 1]
                    },
                    paint: {
                        'text-color': '#ff6b35',
                        'text-halo-color': '#ffffff',
                        'text-halo-width': 1,
                    }
                });
            } else {
                map.getSource('grid-labels').setData({
                    type: 'FeatureCollection',
                    features: labelFeatures
                });
            }
        }

        // 添加中心点区间标签数据源和图层（仅在层级10及以上显示）
        if (showCenterLabels && centerLabelFeatures.length > 0) {
            if (!map.getSource('grid-center-labels')) {
                map.addSource('grid-center-labels', {
                    type: 'geojson',
                    data: {
                        type: 'FeatureCollection',
                        features: centerLabelFeatures
                    }
                });

                map.addLayer({
                    id: 'grid-center-labels',
                    type: 'symbol',
                    source: 'grid-center-labels',
                    layout: {
                        'text-field': ['get', 'text'],
                        'text-size': 16,
                        'text-offset': [0, 0],
                        'text-anchor': 'center',
                        'text-justify': 'center',
                    },
                    paint: {
                        'text-color': '#ff6b35',
                        'text-halo-color': '#ffffff',
                        'text-halo-width': 1,
                    }
                });
            } else {
                map.getSource('grid-center-labels').setData({
                    type: 'FeatureCollection',
                    features: centerLabelFeatures
                });
            }
        }
    },

    /**
     * 清除经纬度网格（包括中心点标签）
     * @param {Object} map - 地图实例
     */
    clearGridWithCenterLabels: function (map) {
        if (!map) return;

        // 清除网格线
        if (map.getLayer('longitude-latitude-grid')) {
            map.removeLayer('longitude-latitude-grid');
        }
        if (map.getSource('longitude-latitude-grid')) {
            map.removeSource('longitude-latitude-grid');
        }

        // 清除边界标签
        if (map.getLayer('grid-labels')) {
            map.removeLayer('grid-labels');
        }
        if (map.getSource('grid-labels')) {
            map.removeSource('grid-labels');
        }

        // 清除中心点标签
        if (map.getLayer('grid-center-labels')) {
            map.removeLayer('grid-center-labels');
        }
        if (map.getSource('grid-center-labels')) {
            map.removeSource('grid-center-labels');
        }
    },

    /**
     * 计算线段中间点
     * @param start
     * @param end
     * @returns {{lng, lat}}
     */
    countMidFromLine(start, end) {
        return {
            lng: (start.lng + end.lng) / 2,
            lat: (start.lat + end.lat) / 2
        };
    },

    /**
     * 清除所有非底图图层
     */
    clearOverlays: function () {
        // 批量清除所有巡检相关的动态图层（ID包含patrol-track-前缀）
        const layers = map.getStyle().layers;
        layers.forEach(layer => {
            if (layer.id.includes('patrol-track-')) {
                map.removeLayer(layer.id);
                if (layer.source && layer.source.includes('patrol-track-')) {
                    map.removeSource(layer.source);
                }
            }
        });
    },

    /**
     * 创建L7场景
     * @param mapId
     */
    createAntVL7Scene(mapId) {
        let scene = new Scene({
            id: mapId,
            antialias: true, // 👈 关键！启用硬件抗锯齿
            preserveDrawingBuffer: true,
            map: new Mapbox({
                mapInstance: map,
            }),
            WebGLParams: {
                antialias: true
            },
            // 关闭默认 L7 Logo
            logoVisible: false,
        });

        // 立即返回 scene 对象，外部可以通过 scene.on('loaded') 监听加载完成
        return scene;
    },

    /**
     * 销毁地图实例，清理事件监听器
     */
    destroy: function() {
        // 移除 innerView-created 事件监听器
        if (this._innerViewCreatedHandler && gisView) {
            gisView.off('innerView-created', this._innerViewCreatedHandler);
            this._innerViewCreatedHandler = null;
        }

        // 清理全局引用
        window.gisView = null;
        this.mapgisMap = null;
        this.mbMap = null;
        map = null;
        antV7Scene = null;

        console.log('MapGIS 地图实例已销毁');
    },


    /**
     * 根据 SRID 和 level 获取对应的 scale（比例尺）
     * @param {Number} srid - 坐标系 WKID（如 4326, 3857 等）
     * @param {Number} level - LODs 层级（0-22）
     * @returns {Number} 对应的比例尺值，如果未找到则返回 null
     *
     * @description
     * 该方法根据不同的坐标系和缩放层级，返回对应的地图比例尺。
     * 常用于 IGS 图层中根据显示层级计算合适的比例尺参数。
     *
     * @example
     * // 获取 EPSG:4326 坐标系下第 10 级的比例尺
     * const scale = getScaleBySridAndLevel(4326, 10);
     * console.log(scale); // 输出对应比例尺
     *
     * // 获取 EPSG:3857 坐标系下第 15 级的比例尺
     * const scale3857 = getScaleBySridAndLevel(3857, 15);
     * console.log(scale3857);
     */
    getScaleBySridAndLevel: function (srid, level) {
        // 定义不同坐标系下的 LODs 配置
        // 参考 ArcGIS/MapGIS 标准瓦片方案
        const lodsConfig = {
            // WGS84 (EPSG:4326) 坐标系
            4326: [
                { level: 0, resolution: 0.703125, scale: 295829355.45 },
                { level: 1, resolution: 0.3515625, scale: 147914677.73 },
                { level: 2, resolution: 0.17578125, scale: 73957338.86 },
                { level: 3, resolution: 0.087890625, scale: 36978669.43 },
                { level: 4, resolution: 0.0439453125, scale: 18489334.72 },
                { level: 5, resolution: 0.02197265625, scale: 9244667.36 },
                { level: 6, resolution: 0.010986328125, scale: 4622333.68 },
                { level: 7, resolution: 0.0054931640625, scale: 2311166.84 },
                { level: 8, resolution: 0.00274658203125, scale: 1155583.42 },
                { level: 9, resolution: 0.001373291015625, scale: 577791.71 },
                { level: 10, resolution: 0.0006866455078125, scale: 288895.85 },
                { level: 11, resolution: 0.00034332275390625, scale: 144447.93 },
                { level: 12, resolution: 0.000171661376953125, scale: 72223.96 },
                { level: 13, resolution: 0.0000858306884765625, scale: 36111.98 },
                { level: 14, resolution: 0.00004291534423828125, scale: 18055.99 },
                { level: 15, resolution: 0.000021457672119140625, scale: 9028.0 },
                { level: 16, resolution: 0.000010728836059570312, scale: 4514.0 },
                { level: 17, resolution: 0.000005364418029785156, scale: 2257.0 },
                { level: 18, resolution: 0.000002682209014892578, scale: 1128.5 },
                { level: 19, resolution: 0.000001341104507446289, scale: 564.25 },
                { level: 20, resolution: 0.0000006705522537231445, scale: 282.12 }
            ],
            // Web Mercator (EPSG:3857) 坐标系
            3857: [
                { level: 0, resolution: 156543.033928, scale: 591657527.59 },
                { level: 1, resolution: 78271.516964, scale: 295828763.79 },
                { level: 2, resolution: 39135.758482, scale: 147914381.9 },
                { level: 3, resolution: 19567.879241, scale: 73957190.95 },
                { level: 4, resolution: 9783.9396205, scale: 36978595.47 },
                { level: 5, resolution: 4891.96981025, scale: 18489297.74 },
                { level: 6, resolution: 2445.984905125, scale: 9244648.87 },
                { level: 7, resolution: 1222.9924525625, scale: 4622324.43 },
                { level: 8, resolution: 611.49622628125, scale: 2311162.22 },
                { level: 9, resolution: 305.748113140625, scale: 1155581.11 },
                { level: 10, resolution: 152.8740565703125, scale: 577790.55 },
                { level: 11, resolution: 76.43702828515625, scale: 288895.28 },
                { level: 12, resolution: 38.218514142578125, scale: 144447.64 },
                { level: 13, resolution: 19.109257071289062, scale: 72223.82 },
                { level: 14, resolution: 9.554628535644531, scale: 36111.91 },
                { level: 15, resolution: 4.777314267822266, scale: 18055.95 },
                { level: 16, resolution: 2.388657133911133, scale: 9027.98 },
                { level: 17, resolution: 1.1943285669555665, scale: 4513.99 },
                { level: 18, resolution: 0.5971642834777832, scale: 2257.0 },
                { level: 19, resolution: 0.2985821417388916, scale: 1128.5 },
                { level: 20, resolution: 0.1492910708694458, scale: 564.25 },
                { level: 21, resolution: 0.0746455354347229, scale: 282.12 },
                { level: 22, resolution: 0.03732276771736145, scale: 141.06 }
            ],
            // CGCS2000 (EPSG:4490) 坐标系 - 与 4326 类似
            4490: [
                { level: 0, resolution: 0.703125, scale: 295829355.45 },
                { level: 1, resolution: 0.3515625, scale: 147914677.73 },
                { level: 2, resolution: 0.17578125, scale: 73957338.86 },
                { level: 3, resolution: 0.087890625, scale: 36978669.43 },
                { level: 4, resolution: 0.0439453125, scale: 18489334.72 },
                { level: 5, resolution: 0.02197265625, scale: 9244667.36 },
                { level: 6, resolution: 0.010986328125, scale: 4622333.68 },
                { level: 7, resolution: 0.0054931640625, scale: 2311166.84 },
                { level: 8, resolution: 0.00274658203125, scale: 1155583.42 },
                { level: 9, resolution: 0.001373291015625, scale: 577791.71 },
                { level: 10, resolution: 0.0006866455078125, scale: 288895.85 },
                { level: 11, resolution: 0.00034332275390625, scale: 144447.93 },
                { level: 12, resolution: 0.000171661376953125, scale: 72223.96 },
                { level: 13, resolution: 0.0000858306884765625, scale: 36111.98 },
                { level: 14, resolution: 0.00004291534423828125, scale: 18055.99 },
                { level: 15, resolution: 0.000021457672119140625, scale: 9028.0 },
                { level: 16, resolution: 0.000010728836059570312, scale: 4514.0 },
                { level: 17, resolution: 0.000005364418029785156, scale: 2257.0 },
                { level: 18, resolution: 0.000002682209014892578, scale: 1128.5 },
                { level: 19, resolution: 0.000001341104507446289, scale: 564.25 },
                { level: 20, resolution: 0.0000006705522537231445, scale: 282.12 }
            ]
        };

        // 处理常见的 SRID 别名
        const normalizedSrid = (() => {
            switch (srid) {
                case 4214:  // Beijing 1954
                case 4610:  // Xian 1980
                    return 4326;  // 使用 WGS84 的配置
                default:
                    return srid;
            }
        })();

        // 获取对应坐标系的 LODs 配置
        const lods = lodsConfig[normalizedSrid];

        if (!lods) {
            console.warn(`未找到 SRID ${srid} 的 LODs 配置，使用默认配置`);
            // 默认使用 4326 的配置
            return this.getScaleBySridAndLevel(4326, level);
        }

        // 查找对应 level 的配置
        const lod = lods.find(item => item.level === level);

        if (!lod) {
            console.warn(`未找到 level ${level} 的配置`);
            return null;
        }

        return lod.scale;
    },

    /**
     * 根据 SRID 和 scale 反查对应的 level
     * @param {Number} srid - 坐标系 WKID
     * @param {Number} scale - 比例尺值
     * @returns {Number} 对应的层级，如果未找到则返回 null
     *
     * @example
     * // 根据比例尺反查层级
     * const level = getLevelBySridAndScale(4326, 288895.85);
     * console.log(level); // 输出 10
     */
    getLevelBySridAndScale: function (srid, scale) {
        const lodsConfig = {
            4326: [
                { level: 0, scale: 295829355.45 },
                { level: 1, scale: 147914677.73 },
                { level: 2, scale: 73957338.86 },
                { level: 3, scale: 36978669.43 },
                { level: 4, scale: 18489334.72 },
                { level: 5, scale: 9244667.36 },
                { level: 6, scale: 4622333.68 },
                { level: 7, scale: 2311166.84 },
                { level: 8, scale: 1155583.42 },
                { level: 9, scale: 577791.71 },
                { level: 10, scale: 288895.85 },
                { level: 11, scale: 144447.93 },
                { level: 12, scale: 72223.96 },
                { level: 13, scale: 36111.98 },
                { level: 14, scale: 18055.99 },
                { level: 15, scale: 9028.0 },
                { level: 16, scale: 4514.0 },
                { level: 17, scale: 2257.0 },
                { level: 18, scale: 1128.5 },
                { level: 19, scale: 564.25 },
                { level: 20, scale: 282.12 }
            ],
            3857: [
                { level: 0, scale: 591657527.59 },
                { level: 1, scale: 295828763.79 },
                { level: 2, scale: 147914381.9 },
                { level: 3, scale: 73957190.95 },
                { level: 4, scale: 36978595.47 },
                { level: 5, scale: 18489297.74 },
                { level: 6, scale: 9244648.87 },
                { level: 7, scale: 4622324.43 },
                { level: 8, scale: 2311162.22 },
                { level: 9, scale: 1155581.11 },
                { level: 10, scale: 577790.55 },
                { level: 11, scale: 288895.28 },
                { level: 12, scale: 144447.64 },
                { level: 13, scale: 72223.82 },
                { level: 14, scale: 36111.91 },
                { level: 15, scale: 18055.95 },
                { level: 16, scale: 9027.98 },
                { level: 17, scale: 4513.99 },
                { level: 18, scale: 2257.0 },
                { level: 19, scale: 1128.5 },
                { level: 20, scale: 564.25 },
                { level: 21, scale: 282.12 },
                { level: 22, scale: 141.06 }
            ]
        };

        const normalizedSrid = (() => {
            switch (srid) {
                case 4214:
                case 4610:
                case 4490:
                    return 4326;
                default:
                    return srid;
            }
        })();

        const lods = lodsConfig[normalizedSrid];

        if (!lods) {
            console.warn(`未找到 SRID ${srid} 的 LODs 配置`);
            return null;
        }

        // 找到最接近的 level（允许一定的误差范围）
        let closestLod = null;
        let minDiff = Infinity;

        lods.forEach(lod => {
            const diff = Math.abs(lod.scale - scale);
            if (diff < minDiff) {
                minDiff = diff;
                closestLod = lod;
            }
        });

        // 如果差异在 10% 以内，认为匹配成功
        if (closestLod && minDiff / scale < 0.1) {
            return closestLod.level;
        }

        console.warn(`未找到与 scale ${scale} 匹配的 level`);
        return null;
    }
};