AI 生成: 一个面向个人/团队/家庭的智能旅游规划工具,支持AI行程生成、地图标注与景点打卡记录。

This commit is contained in:
eeuse
2026-09-29 04:31:48 +08:00
commit 7e7bd600e4
8 changed files with 678 additions and 0 deletions
+156
View File
@@ -0,0 +1,156 @@
// 主入口:串联 UI、认证、地图与 AI
(function () {
const $ = sel => document.querySelector(sel);
// ================== 用户界面 ==================
function renderUserArea() {
const user = window.Auth.currentUser();
const area = $('#userArea');
if (user) {
area.innerHTML = `<span style="margin-right:10px;font-size:13px">👤 ${user}</span>` +
`<button id="logoutBtn" class="btn">退出</button>`;
$('#logoutBtn').addEventListener('click', () => {
window.Auth.logout();
renderUserArea();
loadSpots();
});
} else {
area.innerHTML = `<button id="loginBtn" class="btn">登录 / 注册</button>`;
$('#loginBtn').addEventListener('click', openModal);
}
}
// ================== 弹窗 ==================
function openModal() {
$('#loginModal').classList.remove('hidden');
}
function closeModal() {
$('#loginModal').classList.add('hidden');
$('#usernameInput').value = '';
$('#passwordInput').value = '';
}
function bindModal() {
$('#closeModal').addEventListener('click', closeModal);
$('#doLogin').addEventListener('click', () => {
const u = $('#usernameInput').value.trim();
const p = $('#passwordInput').value;
const res = window.Auth.login(u, p);
if (!res.ok) return alert(res.msg);
closeModal();
renderUserArea();
loadSpots();
});
$('#doRegister').addEventListener('click', () => {
const u = $('#usernameInput').value.trim();
const p = $('#passwordInput').value;
const res = window.Auth.register(u, p);
if (!res.ok) return alert(res.msg);
closeModal();
renderUserArea();
loadSpots();
});
}
// ================== 景点数据存储 ==================
function loadSpots() {
const key = window.Auth.dataKey('spots');
if (!key) {
// 未登录:清空地图
window.MapAPI.setSpots([]);
renderSpotList([]);
return;
}
let spots = [];
try { spots = JSON.parse(localStorage.getItem(key)) || []; }
catch (e) { spots = []; }
window.MapAPI.setSpots(spots);
renderSpotList(spots);
}
function saveSpots(spots) {
const key = window.Auth.dataKey('spots');
if (!key) return;
localStorage.setItem(key, JSON.stringify(spots));
}
// 当 MapAPI 内部数据变化时回调
window.MapAPI.onSpotsChange = function (spots) {
saveSpots(spots);
renderSpotList(spots);
};
// ================== 景点列表渲染 ==================
let currentFilter = 'all';
function renderSpotList(spots) {
const list = $('#spotList');
list.innerHTML = '';
const filtered = spots.filter(s => {
if (currentFilter === 'all') return true;
return s.status === currentFilter;
});
if (filtered.length === 0) {
list.innerHTML = '<li style="color:#94a3b8">暂无景点</li>';
return;
}
filtered.forEach(s => {
const li = document.createElement('li');
li.innerHTML = `<span>${s.name}</span>` +
`<span class="status ${s.status}">${s.status === 'visited' ? '去过' : '想去'}</span>`;
li.style.cursor = 'pointer';
li.addEventListener('click', () => {
window.MapAPI.flyTo(s.lat, s.lng, 14);
});
list.appendChild(li);
});
}
// ================== 过滤器 ==================
function bindFilter() {
document.querySelectorAll('input[name="filter"]').forEach(el => {
el.addEventListener('change', e => {
currentFilter = e.target.value;
renderSpotList(window.MapAPI.getSpots());
});
});
}
// ================== AI 生成 ==================
function bindAI() {
$('#genBtn').addEventListener('click', async () => {
const dest = $('#destInput').value.trim();
const days = parseInt($('#daysInput').value, 10) || 1;
const pref = $('#prefInput').value;
const result = $('#planResult');
result.textContent = '⏳ 正在生成行程...';
try {
const text = await window.AI.generatePlanAsync(dest, days, pref);
result.textContent = text;
// 顺便把目的地飞到地图中心
const cityCoords = {
'杭州': [30.2741, 120.1551],
'北京': [39.9042, 116.4074],
'成都': [30.5728, 104.0668],
'上海': [31.2304, 121.4737]
};
if (cityCoords[dest]) {
window.MapAPI.flyTo(cityCoords[dest][0], cityCoords[dest][1], 11);
}
} catch (err) {
result.textContent = '生成失败:' + err.message;
}
});
}
// ================== 启动 ==================
function init() {
renderUserArea();
bindModal();
bindFilter();
bindAI();
loadSpots();
}
document.addEventListener('DOMContentLoaded', init);
})();