|
|
@ -4,9 +4,18 @@ |
|
|
:title="t('mapPickerTitle')" |
|
|
:title="t('mapPickerTitle')" |
|
|
width="800px" |
|
|
width="800px" |
|
|
:before-close="handleClose" |
|
|
:before-close="handleClose" |
|
|
|
|
|
:close-on-click-modal="false" |
|
|
|
|
|
:close-on-press-escape="false" |
|
|
|
|
|
:show-close="false" |
|
|
> |
|
|
> |
|
|
|
|
|
<div class="map-container" id="container"> |
|
|
<div class="map-container" id="container"></div> |
|
|
<div |
|
|
|
|
|
v-if="!props.modelValue.lat || !props.modelValue.lng" |
|
|
|
|
|
class="map-placeholder" |
|
|
|
|
|
> |
|
|
|
|
|
{{ props.placeholder }} |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
<div class="address-search"> |
|
|
<div class="address-search"> |
|
|
<el-select |
|
|
<el-select |
|
|
v-model="province" |
|
|
v-model="province" |
|
|
@ -50,7 +59,12 @@ |
|
|
v-model="detailAddress" |
|
|
v-model="detailAddress" |
|
|
:placeholder="t('detailAddressPlaceholder')" |
|
|
:placeholder="t('detailAddressPlaceholder')" |
|
|
/> |
|
|
/> |
|
|
<el-button type="primary" @click="handleAddressSearch">{{ t('search') }}</el-button> |
|
|
<el-button |
|
|
|
|
|
type="primary" |
|
|
|
|
|
@click="handleAddressSearch" |
|
|
|
|
|
:disabled="!province || !city || !district" |
|
|
|
|
|
>{{ t('search') }}</el-button |
|
|
|
|
|
> |
|
|
</div> |
|
|
</div> |
|
|
<template #footer> |
|
|
<template #footer> |
|
|
<span class="dialog-footer"> |
|
|
<span class="dialog-footer"> |
|
|
@ -64,7 +78,7 @@ |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script lang="ts" setup> |
|
|
<script lang="ts" setup> |
|
|
import { ref, onMounted, watch } from 'vue' |
|
|
import { ref, onMounted, watch, computed } from 'vue' |
|
|
import { getAreaListByPid, getAreaByCode } from '@/app/api/sys' |
|
|
import { getAreaListByPid, getAreaByCode } from '@/app/api/sys' |
|
|
import { createMarker, latLngToAddress, addressToLatLng } from '@/utils/qqmap' |
|
|
import { createMarker, latLngToAddress, addressToLatLng } from '@/utils/qqmap' |
|
|
import { t } from '@/lang' |
|
|
import { t } from '@/lang' |
|
|
@ -78,21 +92,44 @@ const props = defineProps({ |
|
|
address: '', |
|
|
address: '', |
|
|
}), |
|
|
}), |
|
|
}, |
|
|
}, |
|
|
|
|
|
placeholder: { |
|
|
|
|
|
type: String, |
|
|
|
|
|
default: t('mapPickerPlaceholder'), |
|
|
|
|
|
}, |
|
|
|
|
|
visible: { |
|
|
|
|
|
type: Boolean, |
|
|
|
|
|
default: false, |
|
|
|
|
|
}, |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
const emit = defineEmits(['update:modelValue', 'confirm']) |
|
|
const emit = defineEmits(['update:visible', 'update:modelValue', 'confirm']) |
|
|
|
|
|
|
|
|
const dialogVisible = ref(false) |
|
|
const dialogVisible = computed({ |
|
|
|
|
|
get() { |
|
|
|
|
|
return props.visible |
|
|
|
|
|
}, |
|
|
|
|
|
set(value) { |
|
|
|
|
|
emit('update:visible', value) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
watch(dialogVisible, (newVal) => { |
|
|
|
|
|
emit('update:modelValue', newVal) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
const handleClose = (done: () => void) => { |
|
|
const handleClose = (done: () => void) => { |
|
|
done() |
|
|
done() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const handleConfirm = () => { |
|
|
const handleConfirm = () => { |
|
|
|
|
|
if (!props.modelValue.lat || !props.modelValue.lng) { |
|
|
|
|
|
ElMessage.warning(t('mapPickerWarning')) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
emit('confirm', { |
|
|
emit('confirm', { |
|
|
lat: props.modelValue.lat, |
|
|
lat: props.modelValue.lat, |
|
|
lng: props.modelValue.lng, |
|
|
lng: props.modelValue.lng, |
|
|
address: detailAddress.value |
|
|
address: detailAddress.value, |
|
|
}) |
|
|
}) |
|
|
dialogVisible.value = false |
|
|
dialogVisible.value = false |
|
|
} |
|
|
} |
|
|
@ -112,8 +149,11 @@ const cityList = ref<any[]>([]) |
|
|
const districtList = ref<any[]>([]) |
|
|
const districtList = ref<any[]>([]) |
|
|
|
|
|
|
|
|
// 初始化地图 |
|
|
// 初始化地图 |
|
|
onMounted(() => { |
|
|
const initMapScript = () => { |
|
|
const mapScript = document.createElement('script') |
|
|
const container = document.getElementById('container') |
|
|
|
|
|
if (!container) return |
|
|
|
|
|
|
|
|
|
|
|
mapScript = document.createElement('script') |
|
|
mapKey.value = 'IZQBZ-3UHEU-WTCVD-2464U-I5N4V-ZFFU3' |
|
|
mapKey.value = 'IZQBZ-3UHEU-WTCVD-2464U-I5N4V-ZFFU3' |
|
|
mapScript.type = 'text/javascript' |
|
|
mapScript.type = 'text/javascript' |
|
|
mapScript.src = |
|
|
mapScript.src = |
|
|
@ -125,13 +165,35 @@ onMounted(() => { |
|
|
}, 500) |
|
|
}, 500) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 初始化省份列表 |
|
|
mapScript.onerror = (error) => { |
|
|
getAreaListByPid(0).then((res) => { |
|
|
console.error('地图脚本加载失败:', error) |
|
|
provinceList.value = res.data |
|
|
} |
|
|
}) |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
let mapScript: HTMLScriptElement | null = null |
|
|
|
|
|
|
|
|
|
|
|
watch(dialogVisible, (newVal) => { |
|
|
|
|
|
if (newVal) { |
|
|
|
|
|
if (mapScript) { |
|
|
|
|
|
document.body.removeChild(mapScript) |
|
|
|
|
|
mapScript = null |
|
|
|
|
|
} |
|
|
|
|
|
initMapScript() |
|
|
|
|
|
getAreaListByPid(0).then((res) => { |
|
|
|
|
|
provinceList.value = res.data |
|
|
|
|
|
}) |
|
|
|
|
|
} else { |
|
|
|
|
|
if (mapScript) { |
|
|
|
|
|
document.body.removeChild(mapScript) |
|
|
|
|
|
mapScript = null |
|
|
|
|
|
} |
|
|
|
|
|
map = null |
|
|
|
|
|
marker = null |
|
|
|
|
|
} |
|
|
|
|
|
}, { immediate: true }) |
|
|
|
|
|
|
|
|
const initMap = () => { |
|
|
const initMap = () => { |
|
|
|
|
|
console.log('initMap') |
|
|
const TMap = (window as any).TMap |
|
|
const TMap = (window as any).TMap |
|
|
const center = new TMap.LatLng(39.90403, 116.407526) |
|
|
const center = new TMap.LatLng(39.90403, 116.407526) |
|
|
map = new TMap.Map('container', { |
|
|
map = new TMap.Map('container', { |
|
|
@ -239,6 +301,16 @@ watch( |
|
|
height: 400px; |
|
|
height: 400px; |
|
|
border: 1px solid #dcdfe6; |
|
|
border: 1px solid #dcdfe6; |
|
|
border-radius: 4px; |
|
|
border-radius: 4px; |
|
|
|
|
|
position: relative; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.map-placeholder { |
|
|
|
|
|
position: absolute; |
|
|
|
|
|
top: 50%; |
|
|
|
|
|
left: 50%; |
|
|
|
|
|
transform: translate(-50%, -50%); |
|
|
|
|
|
color: #909399; |
|
|
|
|
|
font-size: 14px; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.address-search { |
|
|
.address-search { |
|
|
|