From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/components/Map/index.vue | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 268 insertions(+), 0 deletions(-)
diff --git a/src/components/Map/index.vue b/src/components/Map/index.vue
new file mode 100644
index 0000000..7b9ae1c
--- /dev/null
+++ b/src/components/Map/index.vue
@@ -0,0 +1,268 @@
+<!-- 鍦板浘缁勪欢锛氬熀浜庣櫨搴﹀湴鍥綠L瀹炵幇 -->
+<!-- TODO @super锛氳繕瀛樺湪涓や釜娌¤В鍐崇殑灏廱ug,涓�涓槸淇敼鎵嬪姩瀹氫綅鏃朵竴娆″姞杞� 涓嶇煡閬撲负浣曞畾浣嶇偣鍦ㄥ湴鍥惧乏涓婅 璋冧簡鍗婂ぉ娌¤В鍐� 绗簩涓槸妫�绱㈠湴鍧�纭畾瀹氫綅鐨勫姛鑳藉弬鐓х櫨搴︾殑鏂囨。娌′篃鎼炲ソ 鍥炲ご鍐嶈В鍐充竴涓� -->
+<template>
+ <div v-if="props.isWrite">
+ <el-form ref="form" label-width="120px">
+ <el-form-item label="瀹氫綅浣嶇疆:">
+ <el-select
+ class="w-full"
+ v-model="state.address"
+ clearable
+ filterable
+ remote
+ reserve-keyword
+ placeholder="鍙緭鍏ュ湴鍧�鏌ヨ缁忕含搴�"
+ :remote-method="autoSearch"
+ @change="handleAddressSelect"
+ :loading="state.loading"
+ >
+ <el-option
+ v-for="item in state.mapAddrOptions"
+ :key="item.value"
+ :label="item.name"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="璁惧鍦板浘:">
+ <!-- TODO @super锛氳繖閲岀湅鐪� unocss 鍝� -->
+ <div id="bdMap" class="mapContainer"></div>
+ </el-form-item>
+ </el-form>
+ </div>
+ <div v-else>
+ <el-descriptions :column="2" border :labelStyle="{ 'font-weight': 'bold' }">
+ <el-descriptions-item label="璁惧浣嶇疆:">{{ state.address }}</el-descriptions-item>
+ </el-descriptions>
+ <div id="bdMap" class="mapContainer"></div>
+ </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, onMounted } from 'vue'
+import { propTypes } from '@/utils/propTypes'
+
+// 鎵╁睍 Window 鎺ュ彛浠ュ寘鍚櫨搴﹀湴鍥� GL API
+declare global {
+ interface Window {
+ BMapGL: any
+ initBaiduMap: () => void
+ }
+}
+
+const emits = defineEmits(['locateChange', 'update:center'])
+const state = reactive({
+ lonLat: '', // 缁忓害,绾害
+ address: '',
+ loading: false,
+ latitude: '', // 绾害
+ longitude: '', // 缁忓害
+ map: null as any, // 鍦板浘瀵硅薄
+ mapAddrOptions: [] as any[],
+ mapMarker: null as any, // 鏍囪瀵硅薄
+ geocoder: null as any,
+ autoComplete: null as any,
+ tips: [] // 鎼滅储鎻愮ず
+})
+
+const props = defineProps({
+ clickMap: propTypes.bool.def(false),
+ isWrite: propTypes.bool.def(false),
+ center: propTypes.string.def('')
+})
+
+/** 鍔犺浇鐧惧害鍦板浘 */
+const loadMap = () => {
+ state.address = ''
+ state.latitude = ''
+ state.longitude = ''
+
+ // 鍒涘缓鐧惧害鍦板浘 API 鑴氭湰锛屽姩鎬佸姞杞�
+ const script = document.createElement('script')
+ script.src = `https://api.map.baidu.com/api?v=1.0&type=webgl&ak=${
+ import.meta.env.VITE_BAIDU_MAP_KEY
+ }&callback=initBaiduMap`
+ document.body.appendChild(script)
+
+ // 瀹氫箟鍏ㄥ眬鍥炶皟鍑芥暟
+ window.initBaiduMap = () => {
+ initMap()
+ initGeocoder()
+ initAutoComplete()
+
+ // TODO @super锛氳繖閲屽姞涓�琛屾敞閲�
+ if (props.clickMap) {
+ state.map.addEventListener('click', (e: any) => {
+ console.log(e)
+ const point = e.latlng
+ console.log(point)
+ state.lonLat = point.lng + ',' + point.lat
+ console.log(state.lonLat)
+ regeoCode(state.lonLat)
+ })
+ }
+
+ // TODO @super锛氳繖閲屽姞涓�琛屾敞閲�
+ if (props.center) {
+ regeoCode(props.center)
+ }
+ }
+}
+
+/** 鍒濆鍖栧湴鍥� */
+const initMap = () => {
+ const mapId = 'bdMap'
+ state.map = new window.BMapGL.Map(mapId)
+ // TODO @super锛氳繖涓槸榛樿鐨勫搰锛�
+ state.map.centerAndZoom(new window.BMapGL.Point(116.404, 39.915), 11)
+ state.map.enableScrollWheelZoom()
+ state.map.disableDoubleClickZoom()
+
+ // 娣诲姞鍦板浘鎺т欢
+ state.map.addControl(new window.BMapGL.NavigationControl())
+ state.map.addControl(new window.BMapGL.ScaleControl())
+ state.map.addControl(new window.BMapGL.ZoomControl())
+}
+
+/** 鍒濆鍖栧湴鐞嗙紪鐮佸櫒 */
+const initGeocoder = () => {
+ state.geocoder = new window.BMapGL.Geocoder()
+}
+
+/** 鍒濆鍖栬嚜鍔ㄥ畬鎴� */
+const initAutoComplete = () => {
+ state.autoComplete = new window.BMapGL.Autocomplete({
+ input: 'searchInput',
+ location: state.map
+ })
+}
+
+/**
+ * 鎼滅储鍦板潃
+ * @param queryValue 鎼滅储鍏抽敭璇�
+ */
+const autoSearch = (queryValue: string) => {
+ if (!queryValue) {
+ state.mapAddrOptions = []
+ return
+ }
+
+ state.loading = true
+
+ // 浣跨敤鐧惧害鍦板浘鍦扮偣妫�绱㈡湇鍔�
+ const localSearch = new window.BMapGL.LocalSearch(state.map, {
+ onSearchComplete: (results: any) => {
+ state.loading = false
+ const temp: any[] = []
+
+ if (results && results.getPoi) {
+ const pois = results.getPoi()
+ pois.forEach((p: any) => {
+ const point = p.point
+ if (point && point.lng && point.lat) {
+ temp.push({
+ name: p.title,
+ value: point.lng + ',' + point.lat
+ })
+ }
+ })
+ }
+
+ state.mapAddrOptions = temp
+ }
+ })
+
+ localSearch.search(queryValue)
+}
+
+/**
+ * 澶勭悊鍦板潃閫夋嫨
+ * @param value 閫変腑鐨勫湴鍧�鍊�
+ */
+const handleAddressSelect = (value: string) => {
+ if (value) {
+ regeoCode(value)
+ }
+}
+
+/**
+ * 娣诲姞鏍囪鐐�
+ * @param lnglat 缁忕含搴︽暟缁�
+ */
+// TODO @super锛氭嫾鍐欙紱灏介噺涓嶈鏈� idea 缁胯壊鎻愰啋鍝�
+const setMarker = (lnglat: any) => {
+ if (!lnglat) return
+
+ // 濡傛灉鐐规爣璁板凡瀛樺湪鍒欏厛绉婚櫎鍘熺偣
+ if (state.mapMarker !== null) {
+ state.map.removeOverlay(state.mapMarker)
+ state.lonLat = ''
+ }
+
+ // 鍒涘缓鏂扮殑鏍囪鐐�
+ const point = new window.BMapGL.Point(lnglat[0], lnglat[1])
+ state.mapMarker = new window.BMapGL.Marker(point)
+
+ // 娣诲姞鐐规爣璁板埌鍦板浘
+ state.map.addOverlay(state.mapMarker)
+ state.map.centerAndZoom(point, 16)
+}
+
+/**
+ * 缁忕含搴﹁浆鍖栦负鍦板潃銆佹坊鍔犳爣璁扮偣
+ * @param lonLat 缁忓害,绾害瀛楃涓�
+ */
+// TODO @super锛氭嫾鍐欙紱灏介噺涓嶈鏈� idea 缁胯壊鎻愰啋鍝�
+const regeoCode = (lonLat: string) => {
+ if (!lonLat) return
+
+ // TODO @super锛氭嫾鍐欙紱灏介噺涓嶈鏈� idea 缁胯壊鎻愰啋鍝�
+ const lnglat = lonLat.split(',')
+ if (lnglat.length !== 2) return
+
+ state.longitude = lnglat[0]
+ state.latitude = lnglat[1]
+
+ // 閫氱煡鐖剁粍浠朵綅缃彉鏇�
+ emits('locateChange', lnglat)
+ emits('update:center', lonLat)
+
+ // 鍏堝皢鍦板浘涓績鐐硅缃埌鐩爣浣嶇疆
+ const point = new window.BMapGL.Point(lnglat[0], lnglat[1])
+ state.map.centerAndZoom(point, 16)
+
+ // 鍐嶈缃爣璁板苟鑾峰彇鍦板潃
+ setMarker(lnglat)
+ getAddress(lnglat)
+}
+
+// TODO @super锛歭nglat 鎷煎啓
+/**
+ * 鏍规嵁缁忕含搴﹁幏鍙栧湴鍧�淇℃伅
+ *
+ * @param lnglat 缁忕含搴︽暟缁�
+ */
+const getAddress = (lnglat: any) => {
+ const point = new window.BMapGL.Point(lnglat[0], lnglat[1])
+
+ state.geocoder.getLocation(point, (result: any) => {
+ if (result && result.address) {
+ state.address = result.address
+ }
+ })
+}
+
+/** 鏄惧紡鏆撮湶鏂规硶锛屼娇鍏跺彲浠ヨ鐖剁粍浠惰闂� */
+defineExpose({ regeoCode })
+
+onMounted(() => {
+ loadMap()
+})
+</script>
+
+<style scoped>
+.mapContainer {
+ width: 100%;
+ height: 400px;
+}
+</style>
--
Gitblit v1.8.0