场地信息地图定点展示
parent
7ef6ad19ff
commit
3f527669ed
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<!-- 地图容器 -->
|
||||
<div id="map-container" ref="mapContainer"></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
||||
|
||||
// 定义 props
|
||||
const props = defineProps({
|
||||
center: {
|
||||
type: Object,
|
||||
default: () => ({ lat: 39.984104, lng: 116.307503 })
|
||||
},
|
||||
zoom: {
|
||||
type: Number,
|
||||
default: 11
|
||||
},
|
||||
markers: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
// 地图实例
|
||||
const map = ref(null)
|
||||
const mapContainer = ref(null)
|
||||
const emit = defineEmits(['map-click'])
|
||||
let markerLayer = null
|
||||
|
||||
const API_KEY = import.meta.env.VITE_APP_TENCENT_MAP_KEY
|
||||
|
||||
onMounted(() => {
|
||||
const script = document.createElement('script')
|
||||
script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${API_KEY}`
|
||||
script.onload = initMap
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
|
||||
function initMap() {
|
||||
if (!window.TMap) {
|
||||
console.error('腾讯地图API加载失败')
|
||||
return
|
||||
}
|
||||
map.value = new TMap.Map(mapContainer.value, {
|
||||
center: new TMap.LatLng(props.center.lat, props.center.lng),
|
||||
zoom: props.zoom,
|
||||
viewMode: '2D'
|
||||
})
|
||||
map.value.on('click', (evt) => {
|
||||
// 触发自定义事件
|
||||
emit('map-click', evt)
|
||||
})
|
||||
if (props.markers && props.markers.length > 0) {
|
||||
addMarkers()
|
||||
}
|
||||
}
|
||||
|
||||
function addMarkers() {
|
||||
if (!window.TMap || !map.value) return
|
||||
removeMarker()
|
||||
markerLayer = new TMap.MultiMarker({
|
||||
map: map.value,
|
||||
styles: {
|
||||
"marker": new TMap.MarkerStyle({
|
||||
width: 25,
|
||||
height: 35,
|
||||
anchor: { x: 12.5, y: 35 }
|
||||
})
|
||||
},
|
||||
geometries: props.markers.map(m => ({
|
||||
position: new TMap.LatLng(m.position.lat, m.position.lng),
|
||||
id: m.id,
|
||||
styleId: 'marker'
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
function removeMarker() {
|
||||
if (markerLayer) {
|
||||
markerLayer.setMap(null)
|
||||
markerLayer = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 监听 props 变化,动态更新地图
|
||||
watch(() => props.center, (val) => {
|
||||
if (map.value && val) {
|
||||
map.value.setCenter(new TMap.LatLng(val.lat, val.lng))
|
||||
}
|
||||
}, { deep: true })
|
||||
|
||||
watch(() => props.zoom, (val) => {
|
||||
if (map.value && val) {
|
||||
map.value.setZoom(val)
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => props.markers, () => {
|
||||
addMarkers()
|
||||
}, { deep: true })
|
||||
|
||||
onUnmounted(() => {
|
||||
if (map.value) {
|
||||
map.value.destroy()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#map-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -81,15 +81,21 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog v-model="mapDialogVisible" title="获取经纬度" width="800px" append-to-body>
|
||||
<iframe
|
||||
v-if="mapDialogVisible"
|
||||
:src="tencentLbsUrl"
|
||||
width="100%"
|
||||
height="600"
|
||||
frameborder="0"
|
||||
></iframe>
|
||||
</el-dialog>
|
||||
<!-- 地图选点弹窗 -->
|
||||
<Dialog v-model="mapDialogVisible" title="地图选点" width="800px" append-to-body >
|
||||
<TencentMap
|
||||
ref="tencentMapRef"
|
||||
:center="{ lat: tempLocation.lat, lng: tempLocation.lng }"
|
||||
:zoom="16"
|
||||
:markers="tempLocation.lat && tempLocation.lng ? [{ id: 'selected', content: formData, position: { lat: tempLocation.lat, lng: tempLocation.lng } }] : []"
|
||||
@map-click="handleMapClick"
|
||||
/>
|
||||
<div style="margin-top: 10px; text-align: right;">
|
||||
<el-button @click="mapDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmMapSelection">确定</el-button>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="业主方" prop="ownerId">
|
||||
|
|
@ -212,6 +218,7 @@ import { defaultProps } from '@/utils/tree'
|
|||
import * as AreaApi from '@/api/system/area'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import * as CustomerApi from '@/api/crm/customer'
|
||||
import TencentMap from '@/components/TencentMap/index.vue'
|
||||
|
||||
/** 场地信息 表单 */
|
||||
defineOptions({ name: 'StationSiteForm' })
|
||||
|
|
@ -223,6 +230,7 @@ const dialogVisible = ref(false) // 弹窗的是否展示
|
|||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const tencentMapRef = ref()
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
|
|
@ -230,6 +238,8 @@ const formData = ref({
|
|||
detailAddress: undefined,
|
||||
locationLng: 0,
|
||||
locationLat: 0,
|
||||
mapCenterLat: 0,
|
||||
mapCenterLng: 0,
|
||||
estimatedPiles: 0,
|
||||
parkingSpace: 0,
|
||||
siteStatus: undefined,
|
||||
|
|
@ -268,7 +278,6 @@ const formRules = reactive({
|
|||
const formRef = ref() // 表单 Ref
|
||||
const mapDialogVisible = ref(false)
|
||||
const tencentLbsUrl = ref('')
|
||||
const TENCENT_MAP_KEY = import.meta.env.VITE_APP_TENCENT_MAP_KEY // 你的腾讯地图key
|
||||
const ownerDialogVisible = ref(false)
|
||||
const managementDialogVisible = ref(false)
|
||||
const selectedOwner = ref()
|
||||
|
|
@ -277,6 +286,7 @@ const ownerFlag = ref(false)
|
|||
const managementFlag = ref(false)
|
||||
const ownerInputDisabled = computed(() => !!formData.value.ownerId)
|
||||
const managementInputDisabled = computed(() => !!formData.value.managementId)
|
||||
const tempLocation = ref({ lat: 39.984104, lng: 116.307503 })
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
|
|
@ -349,6 +359,8 @@ const resetForm = () => {
|
|||
detailAddress: undefined,
|
||||
locationLng: 0,
|
||||
locationLat: 0,
|
||||
mapCenterLat: 0,
|
||||
mapCenterLng: 0,
|
||||
estimatedPiles: 0,
|
||||
parkingSpace: 0,
|
||||
siteStatus: undefined,
|
||||
|
|
@ -390,51 +402,67 @@ const filteredManagementList = computed(() =>
|
|||
: customerList.value
|
||||
);
|
||||
|
||||
/** 初始化 **/
|
||||
const openMapDialog = () => {
|
||||
// 拼接带初始点的 url
|
||||
let url = `https://apis.map.qq.com/tools/locpicker?type=1&key=${TENCENT_MAP_KEY}&referer=myapp`
|
||||
if (formData.value.locationLat && formData.value.locationLng) {
|
||||
url += `&coord=${formData.value.locationLat},${formData.value.locationLng}`
|
||||
}
|
||||
tencentLbsUrl.value = url
|
||||
mapDialogVisible.value = true
|
||||
// // 腾讯地图逆地理编码
|
||||
// async function getLocationNameByLatLng(lat, lng) {
|
||||
// const key = import.meta.env.VITE_APP_TENCENT_MAP_KEY
|
||||
// const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=${key}`
|
||||
// try {
|
||||
// const res = await fetch(url)
|
||||
// const data = await res.json()
|
||||
// if (data.status === 0) {
|
||||
// return data.result.address
|
||||
// }
|
||||
// return `(${lat}, ${lng})`
|
||||
// } catch {
|
||||
// return `(${lat}, ${lng})`
|
||||
// }
|
||||
// }
|
||||
|
||||
// 地图点击事件
|
||||
function handleMapClick(e) {
|
||||
// 腾讯地图API返回的事件对象
|
||||
console.log('地图点击事件:', e)
|
||||
const lat = e.latLng.getLat()
|
||||
const lng = e.latLng.getLng()
|
||||
tempLocation.value = { lat, lng }
|
||||
// getLocationNameByLatLng(lat, lng).then(name => {
|
||||
// formData.value.locationName = name
|
||||
// })
|
||||
}
|
||||
|
||||
function selectAddress(loc: any): void {
|
||||
if (loc.poiname) {
|
||||
formData.value.locationName = loc.poiname
|
||||
} else {
|
||||
formData.value.locationName = ''
|
||||
|
||||
// 确认选点
|
||||
async function confirmMapSelection() {
|
||||
if (!tempLocation.value.lat || !tempLocation.value.lng) {
|
||||
message.error('请在地图上选择位置')
|
||||
return
|
||||
}
|
||||
if (loc.latlng && loc.latlng.lat) {
|
||||
formData.value.locationLat = Number(loc.latlng.lat)
|
||||
formData.value.locationLng = Number(loc.latlng.lng)
|
||||
// 获取地图中心点
|
||||
let center = { lat: 0, lng: 0 }
|
||||
if (tencentMapRef.value && tencentMapRef.value.getCenter) {
|
||||
center = tencentMapRef.value.getCenter()
|
||||
}
|
||||
formData.value.locationLat = tempLocation.value.lat
|
||||
formData.value.locationLng = tempLocation.value.lng
|
||||
formData.value.mapCenterLat = center.lat
|
||||
formData.value.mapCenterLng = center.lng
|
||||
// 可选:逆地理编码获取地名
|
||||
formData.value.locationName = `(${tempLocation.value.lat}, ${tempLocation.value.lng})`
|
||||
mapDialogVisible.value = false
|
||||
}
|
||||
|
||||
const initTencentLbsMap = () => {
|
||||
// @ts-ignore
|
||||
window.selectAddress = selectAddress
|
||||
window.addEventListener(
|
||||
'message',
|
||||
function (event) {
|
||||
let loc = event.data
|
||||
if (loc && loc.module === 'locationPicker') {
|
||||
// @ts-ignore
|
||||
window.selectAddress(loc)
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
const openMapDialog = () => {
|
||||
// 优先用已选点,否则用默认中心
|
||||
const lat = formData.value.locationLat || 39.984104
|
||||
const lng = formData.value.locationLng || 116.307503
|
||||
tempLocation.value = { lat, lng }
|
||||
mapDialogVisible.value = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
AreaApi.getAreaTree().then(res => {
|
||||
areaList.value = res
|
||||
})
|
||||
initTencentLbsMap()
|
||||
})
|
||||
|
||||
watch(mapDialogVisible, (val) => {
|
||||
|
|
|
|||
|
|
@ -152,10 +152,6 @@
|
|||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<!-- 地图弹窗 -->
|
||||
<el-dialog v-model="mapDialogVisible" title="获取经纬度" append-to-body>
|
||||
<IFrame class="h-609px" :src="tencentLbsUrl" />
|
||||
</el-dialog>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue