AI 生成: 基于AI的酒店推荐系统,集成地图路线与距离显示,使用Flask后端与Leaflet前端。

This commit is contained in:
admin
2026-10-01 15:18:18 +08:00
commit e3579ee139
6 changed files with 254 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
// 初始化地图
const map = L.map('map').setView([31.2304, 121.4737], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
let markers = [];
let routeLine = null;
let userMarker = null;
// 获取用户位置(模拟为上海中心)
const userLat = 31.2304, userLng = 121.4737;
userMarker = L.marker([userLat, userLng], { icon: L.divIcon({ className: 'user-marker', html: '📍', iconSize: [24, 24] }) }).addTo(map).bindPopup('您的位置');
// 搜索按钮
document.getElementById('searchBtn').addEventListener('click', async () => {
const destination = document.getElementById('destination').value;
const budget = document.getElementById('budget').value;
const preferences = Array.from(document.querySelectorAll('.checkboxes input:checked')).map(cb => cb.value);
const res = await fetch('/api/recommend', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ destination, budget, preferences, lat: userLat, lng: userLng })
});
const data = await res.json();
renderHotels(data.hotels);
renderMarkers(data.hotels);
});
function renderHotels(hotels) {
const list = document.getElementById('hotelList');
list.innerHTML = '';
hotels.forEach((h, i) => {
const card = document.createElement('div');
card.className = 'hotel-card';
card.innerHTML = `
<h3>${h.name}</h3>
<div class="meta"><span>⭐ ${h.rating}</span><span>¥${h.price}/晚</span></div>
<div class="meta"><span>📏 ${h.distance} km</span><span>🎯 ${h.score}分</span></div>
<div class="tags">${h.tags.map(t => `<span>${t}</span>`).join('')}</div>
`;
card.addEventListener('click', () => {
document.querySelectorAll('.hotel-card').forEach(c => c.classList.remove('active'));
card.classList.add('active');
showRoute(h);
});
list.appendChild(card);
});
}
function renderMarkers(hotels) {
markers.forEach(m => map.removeLayer(m));
markers = [];
if (routeLine) { map.removeLayer(routeLine); routeLine = null; }
const bounds = [[userLat, userLng]];
hotels.forEach(h => {
const marker = L.marker([h.lat, h.lng]).addTo(map)
.bindPopup(`<b>${h.name}</b><br>¥${h.price}/晚 · ⭐${h.rating}<br>距离: ${h.distance} km`);
markers.push(marker);
bounds.push([h.lat, h.lng]);
});
map.fitBounds(bounds, { padding: [50, 50] });
}
function showRoute(hotel) {
if (routeLine) map.removeLayer(routeLine);
// 直线路线(实际可接入路由API)
const points = [[userLat, userLng], [hotel.lat, hotel.lng]];
routeLine = L.polyline(points, { color: '#667eea', weight: 4, dashArray: '8,8' }).addTo(map);
map.fitBounds(routeLine.getBounds(), { padding: [50, 50] });
L.popup()
.setLatLng([(userLat + hotel.lat) / 2, (userLng + hotel.lng) / 2])
.setContent(`距离: ${hotel.distance} km`)
.openOn(map);
}