最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3集成Leaflet實現(xiàn)一個功能完整的地圖可視化組件

 更新時間:2026年01月08日 09:59:59   作者:愛健身的小劉同學  
在現(xiàn)代 Web 應用中,地圖可視化是一個常見的需求,無論是展示位置信息、軌跡追蹤,還是數(shù)據(jù)統(tǒng)計分析,地圖都能提供直觀的視覺體驗,本文將詳細介紹如何在 Vue 3 項目中集成 Leaflet 地圖庫,實現(xiàn)一個功能完整的地圖可視化組件,需要的朋友可以參考下

前言

在現(xiàn)代 Web 應用中,地圖可視化是一個常見的需求。無論是展示位置信息、軌跡追蹤,還是數(shù)據(jù)統(tǒng)計分析,地圖都能提供直觀的視覺體驗。本文將詳細介紹如何在 Vue 3 項目中集成 Leaflet 地圖庫,實現(xiàn)一個功能完整的地圖可視化組件。

項目背景

本項目是一個檢測管理系統(tǒng),需要在地圖上展示檢測點的位置信息。主要需求包括:

  • 支持大量標記點的展示
  • 標記點聚合功能,提升性能
  • 多種地圖類型切換(路網(wǎng)圖、衛(wèi)星圖、地形圖)
  • 標記點點擊查看詳情
  • 全屏模式支持
  • 實時統(tǒng)計可見標記數(shù)量

技術棧

  • Vue 3.5.11 - 漸進式 JavaScript 框架
  • Leaflet 1.9.4 - 開源地圖庫
  • leaflet.markercluster 1.5.3 - 標記聚類插件
  • Ant Design Vue 3 - UI 組件庫
  • Vite 5.0 - 構建工具

安裝配置

1. 安裝依賴

npm install leaflet leaflet.markercluster

2. 引入樣式文件

在組件中引入 Leaflet 的 CSS 文件:

import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet.markercluster';
import 'leaflet.markercluster/dist/MarkerCluster.css';
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';

3. 修復圖標路徑問題

Leaflet 在打包后可能會出現(xiàn)圖標路徑問題,需要手動配置:

// 修復 leaflet 默認圖標路徑問題
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
    iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
    iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
    shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
});

核心功能實現(xiàn)

1. 地圖初始化

let map = null;
 
const initMap = () => {
    if (!mapContainer.value) return;
    
    // 如果地圖已存在,先清理
    if (map) {
        map.off('moveend', updateVisibleStats);
        map.off('zoomend', updateVisibleStats);
        map.off('click');
        map.remove();
        map = null;
    }
    
    // 創(chuàng)建地圖實例
    map = L.map(mapContainer.value, {
        zoomControl: true,
        attributionControl: true,
    });
 
    // 將縮放控件移到右上角
    if (map.zoomControl) {
        map.zoomControl.setPosition('topright');
    }
 
    // 添加初始瓦片圖層
    switchMapType('road');
    
    // 等待地圖加載完成后再添加事件監(jiān)聽
    map.whenReady(() => {
        map.on('moveend', updateVisibleStats);
        map.on('zoomend', updateVisibleStats);
        map.on('click', (e) => {
            // 點擊地圖空白處取消高亮
            if (e.originalEvent && e.originalEvent.target) {
                const target = e.originalEvent.target;
                if (!target.closest('.leaflet-popup') && !target.closest('.leaflet-marker-icon')) {
                    clearHighlight();
                }
            }
        });
    });
};

2. 地圖類型切換

支持路網(wǎng)圖、衛(wèi)星圖、地形圖三種類型:

const switchMapType = (type) => {
    if (!map) return;
    
    mapType.value = type || mapType.value;
    
    // 移除舊圖層
    if (currentTileLayer) {
        map.removeLayer(currentTileLayer);
    }
    
    // 根據(jù)類型添加新圖層
    let tileUrl = '';
    let attribution = '';
    
    switch (mapType.value) {
        case 'satellite':
            // 高德地圖衛(wèi)星圖
            tileUrl = 'https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}';
            attribution = '? 高德地圖';
            break;
        case 'terrain':
            // 高德地圖地形圖
            tileUrl = 'https://webst0{s}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}';
            attribution = '? 高德地圖';
            break;
        case 'road':
        default:
            // 高德地圖路網(wǎng)圖
            tileUrl = 'https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}';
            attribution = '? 高德地圖';
            break;
    }
    
    currentTileLayer = L.tileLayer(tileUrl, {
        subdomains: ['1', '2', '3', '4'],
        attribution: attribution,
        maxZoom: 18,
    }).addTo(map);
};

3. 標記點創(chuàng)建

創(chuàng)建自定義圖標:

// 創(chuàng)建默認圖標
const createDefaultIcon = () => {
    return L.icon({
        iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
        iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
        shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
        iconSize: [25, 41],
        iconAnchor: [12, 41],
        popupAnchor: [0, -41]
    });
};
 
// 創(chuàng)建高亮圖標
const createHighlightIcon = () => {
    return L.icon({
        iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
        iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
        shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
        iconSize: [30, 46],
        iconAnchor: [15, 46],
        popupAnchor: [0, -46],
        className: 'highlighted-marker'
    });
};

4. 標記聚合功能

使用 leaflet.markercluster 實現(xiàn)標記聚合:

let markerClusterGroup = null;
 
const renderMarkers = (validData) => {
    clearMarkers();
    
    if (displayMode.value === 'cluster') {
        // 聚合模式
        markerClusterGroup = L.markerClusterGroup({
            maxClusterRadius: 50,
            spiderfyOnMaxZoom: true,
            showCoverageOnHover: true,
            zoomToBoundsOnClick: true,
            iconCreateFunction: function(cluster) {
                const count = cluster.getChildCount();
                let size = 40;
                let fontSize = 14;
                let bgColor = '#1890ff';
                
                // 根據(jù)數(shù)量設置不同顏色和大小
                if (count > 100) {
                    size = 50;
                    fontSize = 16;
                    bgColor = '#ff4d4f';
                } else if (count > 50) {
                    size = 45;
                    fontSize = 15;
                    bgColor = '#fa8c16';
                } else if (count > 20) {
                    size = 42;
                    fontSize = 14;
                    bgColor = '#52c41a';
                }
                
                return L.divIcon({
                    html: `<div style="background-color: ${bgColor}; color: white; border-radius: 50%; width: ${size}px; height: ${size}px; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: ${fontSize}px; border: 3px solid white; box-shadow: 0 2px 8px rgba(0,0,0,0.3);">${count}</div>`,
                    className: 'marker-cluster-custom',
                    iconSize: L.point(size, size)
                });
            }
        });
 
        // 監(jiān)聽聚類點擊事件
        markerClusterGroup.on('clusterclick', function(cluster) {
            const markers = cluster.getAllChildMarkers();
            if (markers && markers.length > 0) {
                const firstMarker = markers[0];
                const latlng = firstMarker.getLatLng();
                const item = validData.find(d => 
                    d.latitude === latlng.lat && d.longitude === latlng.lng
                );
                if (item) {
                    highlightMarker(firstMarker, item);
                }
            }
        });
 
        // 添加標記到聚類組
        validData.forEach(item => {
            const marker = L.marker([item.latitude, item.longitude], {
                icon: createDefaultIcon()
            }).bindPopup(createPopupContent(item));
            
            marker.on('click', function() {
                highlightMarker(this, item);
            });
            
            markerClusterGroup.addLayer(marker);
        });
 
        markerClusterGroup.addTo(map);
    } else {
        // 平鋪模式
        validData.forEach(item => {
            const marker = L.marker([item.latitude, item.longitude], {
                icon: createDefaultIcon()
            })
            .addTo(map)
            .bindPopup(createPopupContent(item));
            
            marker.on('click', function() {
                highlightMarker(this, item);
            });
            
            markers.push(marker);
        });
    }
    
    // 自動調整視圖范圍
    fitBounds(validData);
};

5. 彈窗內容定制

創(chuàng)建豐富的彈窗內容:

const createPopupContent = (item) => {
    // 圖片預覽部分
    const imagesHtml = item.imageList && item.imageList.length > 0
        ? `
            <div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #e8e8e8;">
                <div style="font-weight: bold; margin-bottom: 8px; color: #333;">?? 現(xiàn)場圖片:</div>
                <div style="display: flex; gap: 8px; flex-wrap: wrap;">
                    ${item.imageList.slice(0, 3).map((img, idx) => 
                        `<img src="${img}" style="width: 80px; height: 80px; object-fit: cover; border-radius: 4px; cursor: pointer; border: 1px solid #e8e8e8;" onclick="window.previewImage('${img}')" title="點擊預覽" />`
                    ).join('')}
                </div>
            </div>
        `
        : '';
    
    return `
        <div style="min-width: 280px; max-width: 400px;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 2px solid #1890ff;">
                <h4 style="margin: 0; color: #1890ff; font-size: 16px;">?? ${item.serviceCode || '-'}</h4>
            </div>
            
            <div style="margin-bottom: 8px;">
                <div style="margin-bottom: 8px; display: flex; align-items: flex-start;">
                    <span style="font-weight: bold; min-width: 80px; color: #666;">??? 線路:</span>
                    <span style="flex: 1;">${item.towerNumber || '-'}</span>
                </div>
                <div style="margin-bottom: 8px; display: flex; align-items: flex-start;">
                    <span style="font-weight: bold; min-width: 80px; color: #666;">?? 發(fā)布時間:</span>
                    <span style="flex: 1;">${item.createTime || '-'}</span>
                </div>
            </div>
            
            ${imagesHtml}
            
            <div style="margin-top: 12px; display: flex; gap: 8px; padding-top: 12px; border-top: 1px solid #e8e8e8;">
                <button 
                    onclick="window.viewDetail('${item.id}')"
                    style="flex: 1; padding: 8px 16px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer;">
                    查看詳情
                </button>
                <button 
                    onclick="window.centerMap(${item.latitude}, ${item.longitude})"
                    style="flex: 1; padding: 8px 16px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer;">
                    居中定位
                </button>
            </div>
        </div>
    `;
};

6. 視圖范圍自適應

自動調整地圖視圖以顯示所有標記點:

const fitBounds = (points) => {
    if (points.length === 0 || !map) return;
    
    // 臨時移除事件監(jiān)聽器,避免觸發(fā)統(tǒng)計更新
    map.off('moveend', updateVisibleStats);
    map.off('zoomend', updateVisibleStats);
    
    try {
        if (points.length === 1) {
            const point = points[0];
            map.setView([point.latitude, point.longitude], 13);
        } else {
            const bounds = L.latLngBounds(
                points.map(p => [p.latitude, p.longitude])
            );
            map.fitBounds(bounds, { padding: [50, 50] });
        }
    } catch (e) {
        console.warn('設置地圖視圖失敗:', e);
    } finally {
        // 重新添加事件監(jiān)聽器
        setTimeout(() => {
            if (map) {
                map.on('moveend', updateVisibleStats);
                map.on('zoomend', updateVisibleStats);
            }
        }, 500);
    }
};

7. 可見標記統(tǒng)計

實時統(tǒng)計當前視圖范圍內的標記數(shù)量:

// 防抖函數(shù)
const debounce = (func, wait) => {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
};
 
// 更新可見標記統(tǒng)計(防抖處理)
let updateStatsTimer = null;
const updateVisibleStats = () => {
    if (!map || currentDataList.length === 0) {
        visibleMarkersCount.value = 0;
        return;
    }
    
    if (updateStatsTimer) {
        clearTimeout(updateStatsTimer);
    }
    
    updateStatsTimer = setTimeout(() => {
        try {
            const bounds = map.getBounds();
            if (!bounds) {
                visibleMarkersCount.value = 0;
                return;
            }
            
            // 計算當前視圖范圍內的標記數(shù)
            const visible = currentDataList.filter(item => {
                if (!item.longitude || !item.latitude) return false;
                try {
                    const lat = parseFloat(item.latitude);
                    const lng = parseFloat(item.longitude);
                    if (isNaN(lat) || isNaN(lng)) return false;
                    return bounds.contains([lat, lng]);
                } catch (e) {
                    return false;
                }
            });
            visibleMarkersCount.value = visible.length;
        } catch (e) {
            console.warn('更新可見標記統(tǒng)計失敗:', e);
            visibleMarkersCount.value = 0;
        }
    }, 200);
};

8. 全屏功能

支持全屏查看地圖:

const toggleFullscreen = () => {
    if (!mapContainerRef.value) return;
    
    if (!isFullscreen.value) {
        if (mapContainerRef.value.requestFullscreen) {
            mapContainerRef.value.requestFullscreen();
        } else if (mapContainerRef.value.webkitRequestFullscreen) {
            mapContainerRef.value.webkitRequestFullscreen();
        } else if (mapContainerRef.value.mozRequestFullScreen) {
            mapContainerRef.value.mozRequestFullScreen();
        } else if (mapContainerRef.value.msRequestFullscreen) {
            mapContainerRef.value.msRequestFullscreen();
        }
    } else {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        }
    }
};
 
// 監(jiān)聽全屏狀態(tài)變化
const handleFullscreenChange = () => {
    isFullscreen.value = !!(
        document.fullscreenElement ||
        document.webkitFullscreenElement ||
        document.mozFullScreenElement ||
        document.msFullscreenElement
    );
    
    // 全屏時重新調整地圖大小
    if (map) {
        setTimeout(() => {
            map.invalidateSize();
        }, 100);
    }
};

樣式定制

高亮標記樣式

:deep(.highlighted-marker) {
    filter: drop-shadow(0 0 8px rgba(24, 144, 255, 0.8));
    z-index: 1000 !important;
}

聚類樣式

:deep(.marker-cluster-custom) {
    background-color: transparent !important;
    border: none !important;
}
 
:deep(.marker-cluster-custom div) {
    transition: all 0.3s ease;
}
 
:deep(.marker-cluster-custom:hover div) {
    transform: scale(1.1);
    box-shadow: 0 4px 12px rgba(0,0,0,0.4) !important;
}

組件使用

<template>
    <map-modal ref="mapModalRef" />
    <a-button @click="openMap">打開地圖</a-button>
</template>
<script setup>
import { ref } from 'vue';
import MapModal from '@/components/mapModal.vue';
 
const mapModalRef = ref(null);
 
const openMap = () => {
    const dataList = [
        {
            id: 1,
            latitude: 39.9042,
            longitude: 116.4074,
            serviceCode: 'BJ001',
            towerNumber: '北京-001',
            createTime: '2024-01-01',
            imageList: ['https://example.com/image1.jpg']
        },
        // ... 更多數(shù)據(jù)
    ];
    
    mapModalRef.value?.openMap(dataList);
};
</script>

最佳實踐

1. 性能優(yōu)化

  • 使用標記聚合:當標記點數(shù)量超過 100 個時,建議使用聚合模式
  • 防抖處理:地圖移動和縮放事件使用防抖,避免頻繁計算
  • 延遲加載:大數(shù)據(jù)量時,可以分批加載標記點

2. 內存管理

  • 及時清理:組件卸載時,務必清理地圖實例和事件監(jiān)聽器
  • 避免內存泄漏:使用 onBeforeUnmount 鉤子進行清理
onBeforeUnmount(() => {
    clearMarkers();
    if (map) {
        map.off('moveend', updateVisibleStats);
        map.off('zoomend', updateVisibleStats);
        map.off('click');
        map.remove();
        map = null;
    }
});

3. 錯誤處理

  • 數(shù)據(jù)驗證:添加標記前,驗證經(jīng)緯度數(shù)據(jù)的有效性
  • 異常捕獲:使用 try-catch 包裹可能出錯的操作
const validData = dataList.filter(item => 
    item.longitude && item.latitude && 
    !isNaN(parseFloat(item.longitude)) && 
    !isNaN(parseFloat(item.latitude))
);

常見問題

1. 圖標不顯示

問題:打包后圖標路徑錯誤

解決方案:使用 CDN 地址或配置 webpack/vite 的靜態(tài)資源處理

delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
    iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
    iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
    shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
});

2. 地圖顯示空白

問題:容器未正確初始化或樣式問題

解決方案

  • 確保容器有明確的高度
  • 使用 nextTick 確保 DOM 已渲染
  • 調用 map.invalidateSize() 重新計算尺寸

3. 聚合不生效

問題:未正確引入插件或配置錯誤

解決方案

  • 確保引入了 leaflet.markercluster 及其樣式文件
  • 檢查 markerClusterGroup 是否正確添加到地圖

擴展功能

1. 添加自定義控件

// 創(chuàng)建自定義控件
const CustomControl = L.Control.extend({
    onAdd: function(map) {
        const container = L.DomUtil.create('div', 'custom-control');
        container.innerHTML = '<button>自定義按鈕</button>';
        return container;
    }
});
 
// 添加到地圖
new CustomControl({ position: 'topleft' }).addTo(map);

2. 繪制路線

// 使用 Polyline 繪制路線
const polyline = L.polyline([
    [39.9042, 116.4074],
    [39.9142, 116.4174],
    [39.9242, 116.4274]
], {
    color: 'red',
    weight: 3
}).addTo(map);

3. 添加圓形區(qū)域

// 添加圓形區(qū)域
const circle = L.circle([39.9042, 116.4074], {
    color: 'red',
    fillColor: '#f03',
    fillOpacity: 0.5,
    radius: 500
}).addTo(map);

總結

通過本文的介紹,我們實現(xiàn)了一個功能完整的地圖可視化組件,包括:

  • 地圖初始化和配置
  • 多種地圖類型切換
  • 標記點聚合和平鋪模式
  • 豐富的彈窗內容
  • 實時統(tǒng)計功能
  • 全屏支持
  • 性能優(yōu)化

Leaflet 作為一個輕量級、功能強大的地圖庫,非常適合在 Vue 3 項目中使用。通過合理的架構設計和性能優(yōu)化,可以輕松處理大量標記點的展示需求。

以上就是Vue3集成Leaflet實現(xiàn)一個功能完整的地圖可視化組件的詳細內容,更多關于Vue3 Leaflet地圖可視化組件的資料請關注腳本之家其它相關文章!

相關文章

  • nodejs讀取并去重excel文件

    nodejs讀取并去重excel文件

    給大家?guī)硪黄P于用nodejs實現(xiàn)excel文件的讀取并去重的功能,有興趣的朋友參考學習下。
    2018-04-04
  • Vue中mixins的使用方法詳解

    Vue中mixins的使用方法詳解

    mixins是一種分發(fā) Vue 組件中可復用功能的使用方式,它是一個 js 對象,包含我們組件script中的任意功能選項,下面就跟隨小編一起來看看它的具體使用吧
    2024-03-03
  • 一文帶你上手vue3中的pinia

    一文帶你上手vue3中的pinia

    這篇文章主要以vue3+vite+ts舉例,為大家詳細介紹了vue3中pinia的安裝與使用,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-09-09
  • Vue的data為啥只能是函數(shù)原理詳解

    Vue的data為啥只能是函數(shù)原理詳解

    這篇文章主要為大家介紹了Vue的data為啥只能是函數(shù)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • vue.js vue-router如何實現(xiàn)無效路由(404)的友好提示

    vue.js vue-router如何實現(xiàn)無效路由(404)的友好提示

    眾所周知vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用于構建單頁面應用,下面這篇文章主要給大家介紹了關于vue.js中vue-router如何實現(xiàn)無效路由(404)的友好提示的相關資料,需要的朋友可以參考下。
    2017-12-12
  • graphQL在前端vue中使用實例代碼

    graphQL在前端vue中使用實例代碼

    這篇文章主要介紹了graphQL在前端vue中使用過程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • vue中input框只能輸入漢字校驗的問題

    vue中input框只能輸入漢字校驗的問題

    文章介紹了在Vue中實現(xiàn)input框只能輸入4個漢字的校驗方法,關鍵在于使用`@blur`事件觸發(fā)校驗方法`onIptCN`,并在方法中判斷輸入內容是否符合要求,只有當輸入內容為4個漢字時,新建按鈕才可點擊
    2026-01-01
  • 關于vue中的ajax請求和axios包問題

    關于vue中的ajax請求和axios包問題

    大家在vue中,經(jīng)常會用到數(shù)據(jù)請求問題,常用的有vue-resourse、axios ,今天小編給大家介紹下axios的post請求 ,感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-04-04
  • Vue中fragment.js使用方法小結

    Vue中fragment.js使用方法小結

    這篇文章主要給大家匯總介紹了Vue中fragment.js使用方法的相關資料,需要的朋友可以參考下
    2020-02-02
  • Vue混合文件使用以及ref的引用實例詳解

    Vue混合文件使用以及ref的引用實例詳解

    ref用來輔助開發(fā)者在不依賴于jQuery的情況下,獲取DOM元素或組件的引用,下面這篇文章主要給大家介紹了關于Vue混合文件使用以及ref的引用的相關資料,需要的朋友可以參考下
    2022-12-12

最新評論

新巴尔虎右旗| 浑源县| 和田县| 阆中市| 遂溪县| 石狮市| 琼海市| 连山| 体育| 苗栗县| 青川县| 烟台市| 观塘区| 嵩明县| 清镇市| 绩溪县| 漳平市| 泰和县| 乌兰县| 卓尼县| 慈溪市| 巩留县| 舒兰市| 湛江市| 万荣县| 甘孜县| 双江| 呼伦贝尔市| 左贡县| 清远市| 北辰区| 鄂州市| 汝城县| 鹤山市| 崇仁县| 华安县| 龙游县| 衢州市| 栾城县| 车致| 福鼎市|