/**
* 会面点 - Meeting Point
* 前端应用主逻辑
*/
// ========================================
// 全局状态
// ========================================
const state = {
map: null,
amapKey: '', // Web服务API Key
amapJsKey: '', // JS API Key
amapJsSecret: '', // JS API 安全密钥
locations: [], // 参与者位置列表
markers: [], // 位置标记
centerMarker: null, // 中心点标记
poiMarkers: [], // POI标记
center: null, // 计算出的中心点
searchCircle: null, // 搜索范围圆
infoWindow: null, // 信息窗口
currentPOIs: [], // 当前搜索结果
colors: [
'#3b82f6', '#ef4444', '#10b981', '#8b5cf6',
'#f59e0b', '#ec4899', '#06b6d4', '#84cc16'
]
};
// ========================================
// 初始化
// ========================================
document.addEventListener('DOMContentLoaded', async () => {
await loadConfig();
initMap();
bindEvents();
initMobileUI();
});
// ========================================
// 移动端UI初始化
// ========================================
function initMobileUI() {
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay');
const menuBtn = document.getElementById('menuBtn');
const mobileSearchBtn = document.getElementById('mobileSearchBtn');
const mobileActionBar = document.getElementById('mobileActionBar');
const mobileSearchInput = document.getElementById('mobileSearchInput');
const mobileSearchClear = document.getElementById('mobileSearchClear');
const mobileSearchTips = document.getElementById('mobileSearchTips');
const floatingResultBtn = document.getElementById('floatingResultBtn');
const floatingResultBadge = document.getElementById('floatingResultBadge');
if (!sidebar || !overlay) return;
// 切换侧边栏
function toggleSidebar() {
sidebar.classList.toggle('active');
overlay.classList.toggle('active');
// 打开侧边栏时隐藏浮动按钮
if (sidebar.classList.contains('active') && floatingResultBtn) {
floatingResultBtn.style.display = 'none';
}
}
// 关闭侧边栏
function closeSidebar() {
sidebar.classList.remove('active');
overlay.classList.remove('active');
// 关闭侧边栏时,如果有搜索结果且结果面板隐藏,显示浮动按钮
const panel = document.getElementById('floatingResults');
if (floatingResultBtn && state.currentPOIs && state.currentPOIs.length > 0 &&
(!panel || panel.style.display === 'none')) {
window.showFloatingResultBtn(state.currentPOIs.length);
}
}
// 菜单按钮点击
if (menuBtn) {
menuBtn.addEventListener('click', toggleSidebar);
}
// 遮罩点击关闭
overlay.addEventListener('click', closeSidebar);
// 移动端搜索按钮
if (mobileSearchBtn) {
mobileSearchBtn.addEventListener('click', handleSearch);
}
// 移动端地址搜索
if (mobileSearchInput) {
let searchTimeout;
mobileSearchInput.addEventListener('input', (e) => {
const value = e.target.value.trim();
mobileSearchClear.style.display = value ? 'block' : 'none';
clearTimeout(searchTimeout);
if (value.length >= 2) {
searchTimeout = setTimeout(() => fetchMobileSearchTips(value), 300);
} else {
mobileSearchTips.classList.remove('active');
}
});
mobileSearchInput.addEventListener('focus', () => {
if (mobileSearchInput.value.trim().length >= 2) {
mobileSearchTips.classList.add('active');
}
});
mobileSearchClear.addEventListener('click', () => {
mobileSearchInput.value = '';
mobileSearchClear.style.display = 'none';
mobileSearchTips.classList.remove('active');
});
// 点击外部关闭搜索提示
document.addEventListener('click', (e) => {
if (!e.target.closest('.mobile-search-bar')) {
mobileSearchTips.classList.remove('active');
}
});
}
// 浮动结果按钮点击 - 重新打开结果面板
if (floatingResultBtn) {
floatingResultBtn.addEventListener('click', () => {
const panel = document.getElementById('floatingResults');
if (panel && state.currentPOIs.length > 0) {
panel.style.display = 'flex';
floatingResultBtn.style.display = 'none';
if (mobileActionBar) {
mobileActionBar.style.display = 'none';
}
}
});
}
// 点击搜索结果后自动关闭侧边栏(移动端)
window.closeSidebarOnMobile = function() {
if (window.innerWidth <= 768) {
closeSidebar();
}
};
// 隐藏/显示移动端操作栏
window.toggleMobileActionBar = function(show) {
if (mobileActionBar && window.innerWidth <= 768) {
mobileActionBar.style.display = show ? 'flex' : 'none';
}
};
// 显示浮动结果按钮
window.showFloatingResultBtn = function(count) {
if (floatingResultBtn) {
// 清除所有内联样式,让CSS控制
floatingResultBtn.style.cssText = 'display: flex;';
if (floatingResultBadge) {
floatingResultBadge.textContent = count;
}
console.log('显示浮动结果按钮,数量:', count);
}
};
// 隐藏浮动结果按钮
window.hideFloatingResultBtn = function() {
if (floatingResultBtn) {
floatingResultBtn.style.display = 'none';
}
};
// 监听窗口大小变化
window.addEventListener('resize', () => {
if (window.innerWidth > 768) {
closeSidebar();
if (mobileActionBar) {
mobileActionBar.style.display = 'none';
}
if (floatingResultBtn) {
floatingResultBtn.style.display = 'none';
}
} else {
const floatingResults = document.getElementById('floatingResults');
const resultsHidden = !floatingResults || floatingResults.style.display === 'none';
if (mobileActionBar && resultsHidden) {
mobileActionBar.style.display = 'flex';
}
// 如果有搜索结果且结果面板隐藏,显示浮动按钮
if (resultsHidden && state.currentPOIs && state.currentPOIs.length > 0) {
window.showFloatingResultBtn(state.currentPOIs.length);
}
}
});
}
// 移动端地址搜索提示
async function fetchMobileSearchTips(keywords) {
const mobileSearchTips = document.getElementById('mobileSearchTips');
try {
const response = await fetch(`/api/tips?keywords=${encodeURIComponent(keywords)}&city=`);
const data = await response.json();
if (data.tips && data.tips.length > 0) {
renderMobileSearchTips(data.tips);
} else {
mobileSearchTips.classList.remove('active');
}
} catch (error) {
console.error('获取搜索提示失败:', error);
}
}
function renderMobileSearchTips(tips) {
const mobileSearchTips = document.getElementById('mobileSearchTips');
const mobileSearchInput = document.getElementById('mobileSearchInput');
const mobileSearchClear = document.getElementById('mobileSearchClear');
mobileSearchTips.innerHTML = tips.map(tip => `
${tip.name}
${tip.district}${tip.address}
`).join('');
// 绑定点击事件
mobileSearchTips.querySelectorAll('.mobile-search-tip-item').forEach(item => {
item.addEventListener('click', () => {
const location = {
name: item.dataset.name,
address: item.dataset.address,
coordinate: {
lng: parseFloat(item.dataset.lng),
lat: parseFloat(item.dataset.lat)
}
};
addLocation(location);
// 清理搜索框
mobileSearchInput.value = '';
mobileSearchClear.style.display = 'none';
mobileSearchTips.classList.remove('active');
});
});
mobileSearchTips.classList.add('active');
}
async function loadConfig() {
try {
const response = await fetch('/api/config');
const data = await response.json();
state.amapKey = data.amap_key;
state.amapJsKey = data.amap_js_key || data.amap_key;
state.amapJsSecret = data.amap_js_secret;
// 配置安全密钥(必须在加载JS API之前设置)
if (state.amapJsSecret) {
window._AMapSecurityConfig = {
securityJsCode: state.amapJsSecret
};
}
// 动态加载高德地图JS API
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = `https://webapi.amap.com/maps?v=2.0&key=${state.amapJsKey}&plugin=AMap.PlaceSearch,AMap.Geocoder,AMap.AutoComplete`;
script.onload = resolve;
script.onerror = () => reject(new Error('加载高德地图JS API失败'));
document.head.appendChild(script);
});
} catch (error) {
console.error('加载配置失败:', error);
alert('加载配置失败,请检查后端服务是否启动');
}
}
function initMap() {
// 初始化地图
state.map = new AMap.Map('mapContainer', {
zoom: 12,
center: [116.397428, 39.90923], // 默认北京
mapStyle: 'amap://styles/dark', // 深色主题
viewMode: '2D'
});
// 初始化信息窗口
state.infoWindow = new AMap.InfoWindow({
isCustom: true,
autoMove: true,
offset: new AMap.Pixel(0, -40)
});
// 地图点击事件
state.map.on('click', handleMapClick);
// 先IP定位快速显示,再尝试精确定位
AMap.plugin(['AMap.CitySearch', 'AMap.Geolocation'], () => {
// 1. 先IP定位(快速)
const citySearch = new AMap.CitySearch();
citySearch.getLocalCity((status, result) => {
if (status === 'complete' && result.info === 'OK') {
const bounds = result.bounds;
if (bounds) {
state.map.setBounds(bounds);
}
console.log('IP定位成功,城市:', result.city);
}
});
// 2. 然后尝试精确定位(较慢但更准确)
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 10000,
buttonPosition: 'RB',
buttonOffset: new AMap.Pixel(10, 20),
zoomToAccuracy: true
});
// 添加定位控件到地图
state.map.addControl(geolocation);
geolocation.getCurrentPosition((status, result) => {
if (status === 'complete' && result.position) {
state.map.setCenter(result.position);
state.map.setZoom(15);
console.log('精确定位成功:', result.formattedAddress);
} else {
console.log('精确定位失败,使用IP定位结果');
}
});
});
}
// ========================================
// 事件绑定
// ========================================
function bindEvents() {
// 搜索输入
const searchInput = document.getElementById('searchInput');
const clearSearch = document.getElementById('clearSearch');
const searchTips = document.getElementById('searchTips');
let searchTimeout;
searchInput.addEventListener('input', (e) => {
const value = e.target.value.trim();
clearSearch.style.display = value ? 'block' : 'none';
clearTimeout(searchTimeout);
if (value.length >= 2) {
searchTimeout = setTimeout(() => fetchSearchTips(value), 300);
} else {
searchTips.classList.remove('active');
}
});
clearSearch.addEventListener('click', () => {
searchInput.value = '';
clearSearch.style.display = 'none';
searchTips.classList.remove('active');
});
// 点击外部关闭搜索提示
document.addEventListener('click', (e) => {
if (!e.target.closest('.search-box')) {
searchTips.classList.remove('active');
}
});
// 快捷标签
document.querySelectorAll('.tag').forEach(tag => {
tag.addEventListener('click', () => {
document.querySelectorAll('.tag').forEach(t => t.classList.remove('active'));
tag.classList.add('active');
document.getElementById('poiKeywords').value = tag.dataset.keyword;
});
});
// 搜索半径滑块
const radiusSlider = document.getElementById('searchRadius');
const radiusValue = document.getElementById('radiusValue');
radiusSlider.addEventListener('input', () => {
const value = parseInt(radiusSlider.value);
radiusValue.textContent = value >= 1000 ? `${value / 1000} 公里` : `${value} 米`;
});
// 搜索按钮
document.getElementById('searchBtn').addEventListener('click', handleSearch);
// POI关键词输入
document.getElementById('poiKeywords').addEventListener('input', () => {
document.querySelectorAll('.tag').forEach(t => t.classList.remove('active'));
});
}
// ========================================
// 搜索提示
// ========================================
async function fetchSearchTips(keywords) {
const searchTips = document.getElementById('searchTips');
try {
const response = await fetch(`/api/tips?keywords=${encodeURIComponent(keywords)}&city=`);
const data = await response.json();
if (data.tips && data.tips.length > 0) {
renderSearchTips(data.tips);
} else {
searchTips.classList.remove('active');
}
} catch (error) {
console.error('获取搜索提示失败:', error);
}
}
function renderSearchTips(tips) {
const searchTips = document.getElementById('searchTips');
searchTips.innerHTML = tips.map(tip => `
${tip.name}
${tip.district}${tip.address}
`).join('');
// 绑定点击事件
searchTips.querySelectorAll('.search-tip-item').forEach(item => {
item.addEventListener('click', () => {
const location = {
name: item.dataset.name,
address: item.dataset.address,
coordinate: {
lng: parseFloat(item.dataset.lng),
lat: parseFloat(item.dataset.lat)
}
};
addLocation(location);
// 清理搜索框
document.getElementById('searchInput').value = '';
document.getElementById('clearSearch').style.display = 'none';
searchTips.classList.remove('active');
});
});
searchTips.classList.add('active');
}
// ========================================
// 地图点击添加位置
// ========================================
// 待确认的位置
let pendingLocation = null;
function handleMapClick(e) {
const lnglat = e.lnglat;
// 逆地理编码获取地址,然后直接添加
AMap.plugin('AMap.Geocoder', () => {
const geocoder = new AMap.Geocoder();
geocoder.getAddress([lnglat.lng, lnglat.lat], (status, result) => {
if (status === 'complete' && result.info === 'OK') {
const address = result.regeocode.formattedAddress;
const location = {
name: `位置 ${state.locations.length + 1}`,
address: address,
coordinate: {
lng: lnglat.lng,
lat: lnglat.lat
}
};
// 直接添加位置
addLocation(location);
}
});
});
}
// 显示地图点击确认弹框
function showMapClickConfirm(address) {
const confirmDialog = document.getElementById('mapClickConfirm');
const confirmAddress = document.getElementById('confirmAddress');
const confirmOk = document.getElementById('confirmOk');
const confirmCancel = document.getElementById('confirmCancel');
if (!confirmDialog) return;
confirmAddress.textContent = address;
confirmDialog.style.display = 'flex';
// 确认添加
confirmOk.onclick = () => {
if (pendingLocation) {
addLocation(pendingLocation);
pendingLocation = null;
}
confirmDialog.style.display = 'none';
};
// 取消
confirmCancel.onclick = () => {
pendingLocation = null;
confirmDialog.style.display = 'none';
};
// 点击背景关闭
confirmDialog.onclick = (e) => {
if (e.target === confirmDialog) {
pendingLocation = null;
confirmDialog.style.display = 'none';
}
};
}
// ========================================
// 位置管理
// ========================================
function addLocation(location) {
state.locations.push(location);
// 添加地图标记
const index = state.locations.length - 1;
const color = state.colors[index % state.colors.length];
const marker = new AMap.Marker({
position: [location.coordinate.lng, location.coordinate.lat],
content: `${index + 1}
`,
offset: new AMap.Pixel(-18, -18)
});
marker.on('click', () => {
showInfoWindow(marker, location);
});
state.markers.push(marker);
state.map.add(marker);
// 调整视野
if (state.locations.length > 1) {
state.map.setFitView(state.markers);
} else {
state.map.setCenter([location.coordinate.lng, location.coordinate.lat]);
state.map.setZoom(14);
}
// 更新UI
updateLocationList();
updateSearchButton();
// 清除之前的搜索结果
clearSearchResults();
}
function removeLocation(index) {
// 移除标记
state.map.remove(state.markers[index]);
state.markers.splice(index, 1);
state.locations.splice(index, 1);
// 更新剩余标记的编号和颜色
state.markers.forEach((marker, i) => {
const color = state.colors[i % state.colors.length];
marker.setContent(`${i + 1}
`);
});
// 更新UI
updateLocationList();
updateSearchButton();
// 调整视野
if (state.markers.length > 0) {
state.map.setFitView(state.markers);
}
// 清除之前的搜索结果
clearSearchResults();
}
function updateLocationList() {
const listEl = document.getElementById('locationList');
const countEl = document.getElementById('locationCount');
countEl.textContent = state.locations.length;
if (state.locations.length === 0) {
listEl.innerHTML = `
🗺️
还没有添加位置
搜索地址或点击地图开始
`;
return;
}
listEl.innerHTML = state.locations.map((loc, index) => {
const color = state.colors[index % state.colors.length];
return `
${index + 1}
${loc.name}
${loc.address || '暂无地址'}
`;
}).join('');
}
function updateSearchButton() {
const btn = document.getElementById('searchBtn');
const mobileBtn = document.getElementById('mobileSearchBtn');
const mobileCount = document.getElementById('mobileLocationCount');
const count = state.locations.length;
const disabled = count < 2;
btn.disabled = disabled;
if (mobileBtn) {
mobileBtn.disabled = disabled;
// 更新按钮文字显示当前状态
if (count === 0) {
mobileBtn.textContent = '🔍 搜索会面点';
} else if (count === 1) {
mobileBtn.textContent = '🔍 再添加1个位置';
} else {
mobileBtn.textContent = '🔍 搜索会面点';
}
}
if (mobileCount) {
mobileCount.textContent = count;
}
}
// ========================================
// 搜索功能
// ========================================
async function handleSearch() {
const keywords = document.getElementById('poiKeywords').value.trim();
const radius = parseInt(document.getElementById('searchRadius').value);
if (!keywords) {
// 自动打开侧边栏设置面板
const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay');
if (sidebar && window.innerWidth <= 768) {
sidebar.classList.add('active');
if (overlay) overlay.classList.add('active');
}
// 聚焦到关键词输入框
const poiInput = document.getElementById('poiKeywords');
if (poiInput) {
poiInput.focus();
poiInput.setAttribute('placeholder', '⚠️ 请选择或输入搜索类型...');
// 3秒后恢复原来的placeholder
setTimeout(() => {
poiInput.setAttribute('placeholder', '例如:咖啡馆、餐厅、KTV...');
}, 3000);
}
return;
}
if (state.locations.length < 2) {
alert('请至少添加2个位置');
return;
}
showLoading(true);
try {
// 1. 计算中心点
const centerResponse = await fetch('/api/center', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ locations: state.locations })
});
const centerData = await centerResponse.json();
state.center = centerData.center;
// 显示中心点标记
showCenterMarker();
// 2. 搜索周边POI
const searchResponse = await fetch('/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
center: state.center,
keywords: keywords,
radius: radius
})
});
const searchData = await searchResponse.json();
// 显示搜索结果
showSearchResults(searchData.pois, radius);
// 移动端自动关闭侧边栏
if (window.closeSidebarOnMobile) {
window.closeSidebarOnMobile();
}
} catch (error) {
console.error('搜索失败:', error);
alert('搜索失败,请稍后重试');
} finally {
showLoading(false);
}
}
function showCenterMarker() {
// 移除旧的中心点标记
if (state.centerMarker) {
state.map.remove(state.centerMarker);
}
// 创建新的中心点标记
state.centerMarker = new AMap.Marker({
position: [state.center.lng, state.center.lat],
content: '⭐
',
offset: new AMap.Pixel(-24, -24),
zIndex: 200
});
state.map.add(state.centerMarker);
// 不显示中心点浮动提示
// document.getElementById('centerInfo').style.display = 'block';
}
function showSearchResults(pois, radius) {
// 清除旧的POI标记
clearPOIMarkers();
// 显示搜索范围圆
if (state.searchCircle) {
state.map.remove(state.searchCircle);
}
state.searchCircle = new AMap.Circle({
center: [state.center.lng, state.center.lat],
radius: radius,
fillColor: '#f59e0b',
fillOpacity: 0.1,
strokeColor: '#f59e0b',
strokeWeight: 2,
strokeOpacity: 0.6
});
state.map.add(state.searchCircle);
// 添加POI标记
pois.forEach((poi, index) => {
const marker = new AMap.Marker({
position: [poi.location.lng, poi.location.lat],
content: `${index + 1}
`,
offset: new AMap.Pixel(-16, -16),
zIndex: 100
});
marker.on('click', () => {
showPOIInfoWindow(marker, poi);
highlightResult(index);
});
state.poiMarkers.push(marker);
state.map.add(marker);
});
// 渲染结果列表
renderResultList(pois);
// 调整视野(右侧留出空间给浮动面板)
const allMarkers = [...state.markers, state.centerMarker, ...state.poiMarkers];
state.map.setFitView(allMarkers, false, [80, 420, 80, 80]);
}
function renderResultList(pois) {
const panel = document.getElementById('floatingResults');
const list = document.getElementById('floatingResultList');
const count = document.getElementById('floatingResultCount');
const filterInput = document.getElementById('resultFilter');
// 保存POI数据供筛选使用
state.currentPOIs = pois;
count.textContent = pois.length;
if (pois.length === 0) {
list.innerHTML = `
😕
未找到相关地点
尝试增大搜索半径或更换关键词
`;
} else {
list.innerHTML = pois.map((poi, index) => {
const dist = parseDistance(poi.distance);
const rankColors = [
'background:linear-gradient(135deg,#ffd700,#ffb800);color:#0f0f1a',
'background:linear-gradient(135deg,#c0c0c0,#a0a0a0);color:#0f0f1a',
'background:linear-gradient(135deg,#cd7f32,#b87333);color:#0f0f1a'
];
const rankBg = rankColors[index] || 'background:#16213e;color:#64748b';
return `
${index + 1}
${poi.name}
${poi.address || poi.type}
${poi.tel ? `📞 ${poi.tel}` : ''}
${dist.value}
${dist.unit}
`;
}).join('');
// 点击事件已通过 onclick 内联绑定
}
panel.style.display = 'flex';
filterInput.value = '';
// 隐藏浮动结果按钮(因为结果面板已显示)
if (window.hideFloatingResultBtn) {
window.hideFloatingResultBtn();
}
// 移动端隐藏操作栏
if (window.toggleMobileActionBar) {
window.toggleMobileActionBar(false);
}
// 绑定关闭按钮事件
document.getElementById('closeFloatingResults').onclick = () => {
panel.style.display = 'none';
// 移动端显示操作栏和浮动结果按钮
if (window.toggleMobileActionBar) {
window.toggleMobileActionBar(true);
}
if (window.showFloatingResultBtn && state.currentPOIs.length > 0) {
window.showFloatingResultBtn(state.currentPOIs.length);
}
};
// 绑定筛选事件
filterInput.oninput = (e) => {
const keyword = e.target.value.trim().toLowerCase();
filterResults(keyword);
};
}
// 解析距离为数值和单位
function parseDistance(distance) {
const d = parseInt(distance);
if (d >= 1000) {
return { value: (d / 1000).toFixed(1), unit: '公里' };
}
return { value: d, unit: '米' };
}
// 筛选结果
function filterResults(keyword) {
const items = document.querySelectorAll('.floating-result-item');
let visibleCount = 0;
items.forEach(item => {
const name = item.dataset.name?.toLowerCase() || '';
const address = item.querySelector('.address')?.textContent.toLowerCase() || '';
if (!keyword || name.includes(keyword) || address.includes(keyword)) {
item.classList.remove('hidden');
visibleCount++;
} else {
item.classList.add('hidden');
}
});
// 更新显示数量
document.getElementById('floatingResultCount').textContent = visibleCount;
}
function formatDistance(distance) {
const d = parseInt(distance);
if (d >= 1000) {
return (d / 1000).toFixed(1) + ' 公里';
}
return d + ' 米';
}
function focusPOI(index) {
const marker = state.poiMarkers[index];
const poi = state.currentPOIs[index];
if (marker && poi) {
// 先高亮结果
highlightResult(index);
// 关闭当前信息窗口
state.infoWindow.close();
// 使用 panTo 平滑移动到目标位置
const position = marker.getPosition();
state.map.panTo(position);
// 延迟设置缩放和打开信息窗口,确保地图移动完成
setTimeout(() => {
state.map.setZoom(16);
showPOIInfoWindow(marker, poi);
}, 300);
// 移动端:关闭结果面板,显示浮动按钮
if (window.innerWidth <= 768) {
const panel = document.getElementById('floatingResults');
if (panel) {
panel.style.display = 'none';
}
if (window.showFloatingResultBtn) {
window.showFloatingResultBtn(state.currentPOIs.length);
}
if (window.toggleMobileActionBar) {
window.toggleMobileActionBar(true);
}
}
}
}
function highlightResult(index) {
document.querySelectorAll('.floating-result-item').forEach((item, i) => {
item.classList.toggle('active', i === index);
});
// 滚动到对应项
const activeItem = document.querySelector(`.floating-result-item[data-index="${index}"]`);
if (activeItem) {
activeItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
// ========================================
// 信息窗口
// ========================================
function showInfoWindow(marker, location) {
const content = `
${location.name}
${location.address || '暂无地址'}
`;
state.infoWindow.setContent(content);
state.infoWindow.open(state.map, marker.getPosition());
}
function showPOIInfoWindow(marker, poi) {
const distText = formatDistance(poi.distance);
const navUrl = `https://uri.amap.com/navigation?to=${poi.location.lng},${poi.location.lat},${encodeURIComponent(poi.name)}&mode=car&coordinate=gaode`;
const content = `
${poi.name}
🎯 距中心点: ${distText}
${poi.address ? `
📍 ${poi.address}
` : ''}
${poi.tel ? `
📞 ${poi.tel}
` : ''}
导航前往
`;
state.infoWindow.setContent(content);
state.infoWindow.open(state.map, marker.getPosition());
}
// ========================================
// 工具函数
// ========================================
function clearSearchResults() {
// 隐藏结果区域
document.getElementById('floatingResults').style.display = 'none';
document.getElementById('centerInfo').style.display = 'none';
document.getElementById('resultFilter').value = '';
// 移动端显示操作栏,隐藏浮动按钮
if (window.toggleMobileActionBar) {
window.toggleMobileActionBar(true);
}
if (window.hideFloatingResultBtn) {
window.hideFloatingResultBtn();
}
// 清除标记
clearPOIMarkers();
if (state.centerMarker) {
state.map.remove(state.centerMarker);
state.centerMarker = null;
}
if (state.searchCircle) {
state.map.remove(state.searchCircle);
state.searchCircle = null;
}
state.center = null;
state.currentPOIs = [];
}
function clearPOIMarkers() {
state.poiMarkers.forEach(marker => {
state.map.remove(marker);
});
state.poiMarkers = [];
}
function showLoading(show) {
document.getElementById('loadingOverlay').style.display = show ? 'flex' : 'none';
}
// ========================================
// 暴露全局函数
// ========================================
window.removeLocation = removeLocation;
window.focusPOI = focusPOI;