<template>
<div class="distance-calculator">
<h1>城市距离计算器</h1>
<!-- 城市输入框 -->
<div class="input-group">
<input
v-model="city1"
placeholder="请输入第一个城市"
@keyup.enter="calculateDistance"
/>
<input
v-model="city2"
placeholder="请输入第二个城市"
@keyup.enter="calculateDistance"
/>
</div>
<!-- 计算按钮 -->
<button @click="calculateDistance" :disabled="loading">
{{ loading ? '计算中...' : '计算距离' }}
</button>
<!-- 结果显示 -->
<div v-if="result" class="result">
{{ result }}
</div>
<!-- 错误提示 -->
<div v-if="error" class="error">
{{ error }}
</div>
</div>
</template>
<script>
// 1. 需要安装的依赖:
// - Vue 3 (已包含在项目中)
// - 高德地图JS API (通过CDN引入,无需npm安装)
// - 可选: 如果需要HTTP请求,可以安装axios (npm install axios)
import { ref, onMounted } from 'vue';
export default {
name: 'DistanceCalculator',
setup() {
// 2. 响应式数据
const city1 = ref('北京'); // 默认值可修改或留空
const city2 = ref('上海'); // 默认值可修改或留空
const result = ref('');
const error = ref('');
const loading = ref(false);
// 3. 高德地图实例
let geocoder = null;
let AMap = null;
// 4. 初始化高德地图
const initAMap = () => {
return new Promise((resolve, reject) => {
// 首先设置安全配置
window._AMapSecurityConfig = {
securityJsCode: 'efe5df61770675b2985df3e32565fb80' // 安全密钥
};
// 检查是否已加载
if (window.AMap) {
AMap = window.AMap;
// 确保插件加载完成后再初始化
AMap.plugin(['AMap.Geocoder', 'AMap.GeometryUtil'], () => {
geocoder = new AMap.Geocoder({
city: "全国" // 指定查询范围为全国
});
resolve();
});
return;
}
// 动态加载高德地图JS
const script = document.createElement('script');
script.src = `https://webapi.amap.com/maps?v=1.4.15&key=05d4c031a356cdffb8055c0d1532ced8`; // API key
script.onload = () => {
if (window.AMap) {
AMap = window.AMap;
// 加载完成后加载插件
AMap.plugin(['AMap.Geocoder', 'AMap.GeometryUtil'], () => {
try {
geocoder = new AMap.Geocoder({
city: "全国" // 指定查询范围为全国
});
resolve();
} catch (err) {
reject(new Error('Geocoder 插件初始化失败'));
}
});
} else {
reject(new Error('AMap 加载失败'));
}
};
script.onerror = () => {
reject(new Error('高德地图脚本加载失败'));
};
document.head.appendChild(script);
});
};
// 5. 计算距离的主要函数
const calculateDistance = async () => {
if (loading.value) return;
try {
loading.value = true;
error.value = '';
result.value = '';
// 确保高德地图已初始化
if (!geocoder) {
await initAMap();
}
// 验证输入
if (!city1.value.trim() || !city2.value.trim()) {
throw new Error('请输入两个城市名称');
}
// 获取城市坐标
const [location1, location2] = await Promise.all([
new Promise((resolve, reject) => {
geocoder.getLocation(city1.value, (status, result) => {
if (status === 'complete' && result.geocodes.length) {
resolve(result.geocodes[0].location);
} else {
reject(new Error(`无法获取 ${city1.value} 的坐标`));
}
});
}),
new Promise((resolve, reject) => {
geocoder.getLocation(city2.value, (status, result) => {
if (status === 'complete' && result.geocodes.length) {
resolve(result.geocodes[0].location);
} else {
reject(new Error(`无法获取 ${city2.value} 的坐标`));
}
});
})
]);
if (!AMap.GeometryUtil) {
throw new Error('GeometryUtil 插件未加载成功');
}
const distance = AMap.GeometryUtil.distance(
[location1.lng, location1.lat],
[location2.lng, location2.lat]
);
const distanceInKm = Math.round(distance / 1000);
result.value = `${city1.value} 到 ${city2.value} 的直线距离约为: ${distanceInKm}公里`;
} catch (err) {
console.error('计算距离出错:', err);
error.value = err.message || '计算距离时出错';
} finally {
loading.value = false;
}
};
// 6. 组件挂载时初始化
onMounted(() => {
// 预加载高德地图
initAMap().catch(err => {
console.error('初始化地图失败:', err);
error.value = '初始化地图失败,请刷新重试';
});
});
return {
city1,
city2,
result,
error,
loading,
calculateDistance
};
}
};
</script>
<style scoped>
.distance-calculator {
max-width: 500px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.input-group {
margin: 20px 0;
display: flex;
gap: 10px;
}
input {
flex: 1;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.result {
margin-top: 20px;
padding: 10px;
background-color: #f8f9fa;
border-radius: 4px;
}
.error {
margin-top: 20px;
padding: 10px;
color: #dc3545;
background-color: #f8d7da;
border-radius: 4px;
}
</style>