386 行
14 KiB
JavaScript
可执行文件
386 行
14 KiB
JavaScript
可执行文件
// 全局JSONP回调函数
|
|
window.geocodeCallback = function(result) {
|
|
if (window.vueMapComponent) {
|
|
window.vueMapComponent.handleGeocodeResult(result);
|
|
}
|
|
};
|
|
|
|
window.reverseGeocodeCallback = function(result) {
|
|
if (window.vueMapComponent) {
|
|
window.vueMapComponent.handleReverseGeocodeResult(result);
|
|
}
|
|
};
|
|
|
|
Vue.component('get-position-map-tencent', {
|
|
template: `<div>
|
|
<el-input type="text" id="suggestId" v-model="keyword"
|
|
placeholder="搜索地址"
|
|
@keydown.enter.exact.native.prevent="addressSearch">
|
|
<template slot="append">
|
|
<el-button @click="addressSearch">搜索</el-button>
|
|
</template>
|
|
</el-input>
|
|
<div ref="mapContent" style="height: 380px;width: 610px;border: 1px solid #DCDFE6"></div>
|
|
</div>`,
|
|
props: {
|
|
'longitude': {
|
|
type: Number,
|
|
default: '',
|
|
},//经度
|
|
'latitude': {
|
|
type: Number,
|
|
default: '',
|
|
},//纬度
|
|
'address': {
|
|
type: String,
|
|
default: '',
|
|
},//地图中心的地址
|
|
'getCountType': {
|
|
type: Number,
|
|
default: 1,// 1单个地址 2多个地址
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
mapLoading: false,
|
|
mapApp: null,
|
|
marker: null,
|
|
mapContent: "", // 地图挂载dom
|
|
center: {
|
|
lng: 116.397475,
|
|
lat: 39.908817,
|
|
},
|
|
keyword: "",
|
|
key: '', // API key将从后端获取
|
|
currentSearchAddress: '',
|
|
currentReverseLat: 0,
|
|
currentReverseLng: 0,
|
|
};
|
|
},
|
|
methods: {
|
|
//获取腾讯地图API Key
|
|
async getTencentMapKey() {
|
|
try {
|
|
const response = await fetch('/index.php/Retail/Store/getTencentMapKey', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
});
|
|
const result = await response.json();
|
|
|
|
if (result.status === 1 && result.key) {
|
|
this.key = result.key;
|
|
return true;
|
|
} else {
|
|
console.error('获取腾讯地图API Key失败:', result.msg || '未知错误');
|
|
this.$message.error('获取地图配置失败,请联系管理员');
|
|
return false;
|
|
}
|
|
} catch (error) {
|
|
console.error('获取腾讯地图API Key异常:', error);
|
|
this.$message.error('获取地图配置异常,请检查网络连接');
|
|
return false;
|
|
}
|
|
},
|
|
|
|
//初始化地图
|
|
async mapInit() {
|
|
if (this.mapApp && this.mapApp.destroy) {
|
|
this.mapApp.destroy();
|
|
} else {
|
|
this.mapContent.innerHTML = "";
|
|
}
|
|
|
|
// 如果没有API key,先获取
|
|
if (!this.key) {
|
|
const success = await this.getTencentMapKey();
|
|
if (!success) {
|
|
return; // 获取API key失败,停止初始化
|
|
}
|
|
}
|
|
|
|
this.checkScript();
|
|
},
|
|
|
|
//检查腾讯地图API是否已加载
|
|
checkScript() {
|
|
if (typeof TMap !== 'undefined' && TMap.Map) {
|
|
this.tencentMapInit();
|
|
} else {
|
|
// 动态加载腾讯地图API GL
|
|
const script = document.createElement('script');
|
|
script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${this.key}`;
|
|
script.onload = () => {
|
|
this.waitForTMapLoad().then(() => {
|
|
this.tencentMapInit();
|
|
}).catch(error => {
|
|
console.error('腾讯地图API加载失败:', error);
|
|
this.$message.error('地图加载失败,请刷新页面重试');
|
|
});
|
|
};
|
|
script.onerror = () => {
|
|
console.error('腾讯地图API脚本加载失败');
|
|
this.$message.error('地图脚本加载失败,请检查网络连接');
|
|
};
|
|
document.head.appendChild(script);
|
|
}
|
|
},
|
|
|
|
// 等待腾讯地图API加载完成
|
|
waitForTMapLoad() {
|
|
return new Promise((resolve, reject) => {
|
|
if (typeof TMap !== 'undefined' && TMap.Map) {
|
|
resolve();
|
|
} else {
|
|
let attempts = 0;
|
|
const maxAttempts = 50;
|
|
const checkInterval = setInterval(() => {
|
|
attempts++;
|
|
if (typeof TMap !== 'undefined' && TMap.Map) {
|
|
clearInterval(checkInterval);
|
|
resolve();
|
|
} else if (attempts >= maxAttempts) {
|
|
clearInterval(checkInterval);
|
|
reject(new Error('腾讯地图API加载超时'));
|
|
}
|
|
}, 100);
|
|
}
|
|
});
|
|
},
|
|
|
|
//初始化腾讯地图
|
|
tencentMapInit() {
|
|
try {
|
|
// 设置全局引用
|
|
window.vueMapComponent = this;
|
|
|
|
// 创建地图实例
|
|
this.mapApp = new TMap.Map(this.mapContent, {
|
|
center: new TMap.LatLng(this.center.lat, this.center.lng),
|
|
zoom: 15,
|
|
viewMode: '2D',
|
|
mapStyleId: 'style1'
|
|
});
|
|
|
|
// 地图点击事件
|
|
this.mapApp.on('click', (evt) => {
|
|
const latLng = evt.latLng;
|
|
this.updateMapMaker(latLng.lat, latLng.lng);
|
|
this.reverseGeocode(latLng.lat, latLng.lng);
|
|
});
|
|
|
|
// 初始化标记点
|
|
this.updateMapMaker(this.center.lat, this.center.lng);
|
|
|
|
this.mapLoading = true;
|
|
console.log('腾讯地图初始化成功');
|
|
|
|
} catch (error) {
|
|
console.error('地图初始化失败:', error);
|
|
this.$message.error('地图初始化失败: ' + error.message);
|
|
}
|
|
},
|
|
|
|
//更新地图标记点
|
|
updateMapMaker(lat, lng, address = '', callback = null) {
|
|
if (!this.mapApp) return;
|
|
|
|
// 清除之前的标记点
|
|
if (this.marker) {
|
|
this.marker.setMap(null);
|
|
}
|
|
|
|
// 创建新的标记点
|
|
this.marker = new TMap.MultiMarker({
|
|
map: this.mapApp,
|
|
styles: {
|
|
'marker-style': new TMap.MarkerStyle({
|
|
width: 25,
|
|
height: 35,
|
|
anchor: { x: 12, y: 35 },
|
|
src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/marker.png'
|
|
})
|
|
},
|
|
geometries: [{
|
|
id: 'location-marker',
|
|
styleId: 'marker-style',
|
|
position: new TMap.LatLng(lat, lng),
|
|
properties: {
|
|
title: address || '当前位置'
|
|
}
|
|
}]
|
|
});
|
|
|
|
// 更新地图中心
|
|
this.mapApp.setCenter(new TMap.LatLng(lat, lng));
|
|
|
|
// 更新数据
|
|
this.updateData(lat, lng, address);
|
|
|
|
if (callback) callback();
|
|
},
|
|
|
|
// 处理地理编码JSONP回调
|
|
handleGeocodeResult(result) {
|
|
if (result.status === 0 && result.result && result.result.location) {
|
|
const location = result.result.location;
|
|
const lat = location.lat;
|
|
const lng = location.lng;
|
|
const address = this.currentSearchAddress;
|
|
|
|
this.updateMapMaker(lat, lng, address);
|
|
this.$message.success(`搜索成功!找到地址: ${address}`);
|
|
console.log('地址搜索成功:', result);
|
|
|
|
} else {
|
|
this.$message.error('未找到该地址,请检查地址是否正确');
|
|
console.error('地址搜索失败:', result);
|
|
}
|
|
},
|
|
|
|
// 处理反向地理编码JSONP回调
|
|
handleReverseGeocodeResult(result) {
|
|
const lat = this.currentReverseLat;
|
|
const lng = this.currentReverseLng;
|
|
|
|
if (result.status === 0 && result.result && result.result.address) {
|
|
const address = result.result.address;
|
|
this.updateData(lat, lng, address);
|
|
console.log('反向地理编码成功:', result);
|
|
} else {
|
|
this.updateData(lat, lng, '无法获取地址信息');
|
|
console.error('反向地理编码失败:', result);
|
|
}
|
|
},
|
|
|
|
// 反向地理编码(根据坐标获取地址)
|
|
async reverseGeocode(lat, lng) {
|
|
if (!this.mapApp) {
|
|
console.log('地图未初始化');
|
|
return;
|
|
}
|
|
|
|
// 确保有API key
|
|
if (!this.key) {
|
|
const success = await this.getTencentMapKey();
|
|
if (!success) {
|
|
this.updateData(lat, lng, '获取地址配置失败');
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 保存当前坐标
|
|
this.currentReverseLat = lat;
|
|
this.currentReverseLng = lng;
|
|
|
|
// 使用JSONP方式调用腾讯地图WebService API
|
|
const reverseGeocodeUrl = `https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=${this.key}&output=jsonp&callback=reverseGeocodeCallback`;
|
|
|
|
// 创建script标签进行JSONP请求
|
|
const script = document.createElement('script');
|
|
script.src = reverseGeocodeUrl;
|
|
script.onerror = () => {
|
|
this.updateData(lat, lng, '地址获取失败');
|
|
console.error('反向地理编码JSONP请求失败');
|
|
};
|
|
|
|
document.head.appendChild(script);
|
|
|
|
// 清理script标签
|
|
setTimeout(() => {
|
|
if (script.parentNode) {
|
|
document.head.removeChild(script);
|
|
}
|
|
}, 5000);
|
|
},
|
|
|
|
//关键词查询
|
|
async addressSearch() {
|
|
const address = this.keyword.trim();
|
|
|
|
if (!address) {
|
|
this.$message.error('请输入要搜索的地址');
|
|
return;
|
|
}
|
|
|
|
if (!this.mapApp) {
|
|
this.$message.error('地图未初始化,请稍后再试');
|
|
return;
|
|
}
|
|
|
|
// 确保有API key
|
|
if (!this.key) {
|
|
const success = await this.getTencentMapKey();
|
|
if (!success) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.$message.info('正在搜索地址...');
|
|
|
|
// 保存当前搜索的地址
|
|
this.currentSearchAddress = address;
|
|
|
|
// 使用JSONP方式调用腾讯地图WebService API
|
|
const geocodeUrl = `https://apis.map.qq.com/ws/geocoder/v1/?address=${encodeURIComponent(address)}&key=${this.key}&output=jsonp&callback=geocodeCallback`;
|
|
|
|
// 创建script标签进行JSONP请求
|
|
const script = document.createElement('script');
|
|
script.src = geocodeUrl;
|
|
script.onerror = () => {
|
|
this.$message.error('地址搜索失败,请检查网络连接');
|
|
console.error('JSONP请求失败');
|
|
};
|
|
|
|
document.head.appendChild(script);
|
|
|
|
// 清理script标签
|
|
setTimeout(() => {
|
|
if (script.parentNode) {
|
|
document.head.removeChild(script);
|
|
}
|
|
}, 5000);
|
|
},
|
|
|
|
//更新数据
|
|
updateData(lat, lng, address = '') {
|
|
this.center.lat = lat;
|
|
this.center.lng = lng;
|
|
|
|
// 更新父组件的数据
|
|
this.$emit('update:longitude', lng);
|
|
this.$emit('update:latitude', lat);
|
|
if (address) {
|
|
this.$emit('update:address', address);
|
|
}
|
|
},
|
|
|
|
//获取初始数据
|
|
getInitData(callback) {
|
|
if (this.longitude && this.latitude) {
|
|
this.center.lng = this.longitude;
|
|
this.center.lat = this.latitude;
|
|
}
|
|
if (this.address) {
|
|
this.keyword = this.address;
|
|
}
|
|
if (callback) callback();
|
|
},
|
|
},
|
|
mounted() {
|
|
this.mapContent = this.$refs.mapContent;
|
|
this.getInitData(() => {
|
|
this.mapInit();
|
|
});
|
|
},
|
|
created() {
|
|
this.getInitData();
|
|
},
|
|
beforeDestroy() {
|
|
// 清理全局引用
|
|
if (window.vueMapComponent === this) {
|
|
window.vueMapComponent = null;
|
|
}
|
|
}
|
|
}); |