123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>智途 - 行程管家</title>
- <script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
- <script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
- <link href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" rel="stylesheet">
- <style>
- :root {
- --ion-color-primary: #4CAF50;
- --ion-color-primary-rgb: 76,175,80;
- --ion-color-primary-contrast: #ffffff;
- --ion-color-primary-contrast-rgb: 255,255,255;
- --ion-color-primary-shade: #439a46;
- --ion-color-primary-tint: #5eb762;
- --ion-color-secondary: #FF9800;
- --ion-color-tertiary: #2196F3;
- }
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- font-family: "PingFang SC", "Helvetica Neue", Arial, sans-serif;
- }
- body {
- background-color: #f5f5f5;
- color: #333;
- max-width: 100vw;
- overflow-x: hidden;
- padding-bottom: 60px;
- }
- /* 顶部标题栏 */
- .header {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- height: 50px;
- background-color: var(--ion-color-primary);
- color: white;
- display: flex;
- justify-content: center;
- align-items: center;
- z-index: 100;
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
- }
- .header-title {
- font-size: 18px;
- font-weight: bold;
- }
- .header-back {
- position: absolute;
- left: 15px;
- font-size: 20px;
- cursor: pointer;
- }
- /* 内容区域 */
- .content {
- margin-top: 50px;
- padding: 15px;
- padding-bottom: 70px;
- }
- /* 模式切换 */
- .mode-switcher {
- display: flex;
- background: white;
- border-radius: 12px;
- overflow: hidden;
- margin-bottom: 20px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
- }
- .mode-tab {
- flex: 1;
- text-align: center;
- padding: 12px;
- font-size: 14px;
- color: #666;
- transition: all 0.3s;
- }
- .mode-tab.active {
- background-color: var(--ion-color-primary);
- color: white;
- font-weight: bold;
- }
- /* AI助手按钮 */
- .ai-button-container {
- margin-bottom: 20px;
- }
- .ai-toggle-button {
- width: 100%;
- background: white;
- border: none;
- border-radius: 12px;
- padding: 15px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
- cursor: pointer;
- }
- .ai-button-left {
- display: flex;
- align-items: center;
- }
- .ai-avatar {
- width: 40px;
- height: 40px;
- background: linear-gradient(135deg, #2196F3, #64B5F6);
- border-radius: 50%;
- display: flex;
- justify-content: center;
- align-items: center;
- color: white;
- margin-right: 10px;
- }
- .ai-button-text {
- text-align: left;
- }
- .ai-button-title {
- font-weight: bold;
- font-size: 16px;
- margin-bottom: 2px;
- }
- .ai-button-subtitle {
- font-size: 12px;
- color: #666;
- }
- /* AI对话区 (默认隐藏) */
- .ai-assistant {
- background: white;
- border-radius: 12px;
- padding: 15px;
- margin-bottom: 20px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
- display: none;
- }
- .ai-assistant.active {
- display: block;
- }
- .ai-header {
- display: flex;
- align-items: center;
- margin-bottom: 15px;
- }
- .ai-name {
- font-weight: bold;
- font-size: 16px;
- }
- .ai-status {
- font-size: 12px;
- color: #4CAF50;
- margin-left: auto;
- }
- .chat-container {
- height: 250px;
- overflow-y: auto;
- margin-bottom: 15px;
- padding-right: 5px;
- }
- .message {
- margin-bottom: 10px;
- display: flex;
- flex-direction: column;
- }
- .message-ai {
- align-items: flex-start;
- }
- .message-user {
- align-items: flex-end;
- }
- .message-bubble {
- max-width: 80%;
- padding: 10px 15px;
- border-radius: 18px;
- font-size: 14px;
- line-height: 1.4;
- }
- .ai-bubble {
- background: #f1f1f1;
- border-top-left-radius: 4px;
- }
- .user-bubble {
- background: var(--ion-color-primary);
- color: white;
- border-top-right-radius: 4px;
- }
- .message-time {
- font-size: 10px;
- color: #999;
- margin-top: 4px;
- }
- .input-area {
- display: flex;
- gap: 10px;
- }
- .message-input {
- flex: 1;
- border: 1px solid #eee;
- border-radius: 20px;
- padding: 10px 15px;
- font-size: 14px;
- outline: none;
- }
- .send-button {
- width: 40px;
- height: 40px;
- border-radius: 50%;
- background: var(--ion-color-primary);
- color: white;
- border: none;
- display: flex;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- }
- /* 快速建议按钮 */
- .quick-suggestions {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- margin-bottom: 15px;
- }
- .quick-suggestion {
- background: #f1f1f1;
- border-radius: 15px;
- padding: 8px 12px;
- font-size: 12px;
- cursor: pointer;
- transition: all 0.2s;
- }
- .quick-suggestion:hover {
- background: #e0e0e0;
- }
- /* 推荐行程 */
- .recommended-trips {
- margin-top: 20px;
- }
- .section-title {
- font-size: 16px;
- font-weight: bold;
- margin-bottom: 15px;
- display: flex;
- align-items: center;
- }
- .section-title ion-icon {
- margin-right: 8px;
- color: var(--ion-color-primary);
- }
- .trip-card {
- background: white;
- border-radius: 12px;
- overflow: hidden;
- margin-bottom: 15px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
- }
- .trip-image {
- width: 100%;
- height: 120px;
- object-fit: cover;
- }
- .trip-info {
- padding: 12px;
- }
- .trip-title {
- font-size: 16px;
- font-weight: bold;
- margin-bottom: 5px;
- }
- .trip-duration {
- font-size: 12px;
- color: #666;
- margin-bottom: 8px;
- display: flex;
- align-items: center;
- }
- .trip-duration ion-icon {
- margin-right: 5px;
- font-size: 14px;
- }
- .trip-tags {
- display: flex;
- flex-wrap: wrap;
- gap: 5px;
- margin-top: 10px;
- }
- .trip-tag {
- font-size: 10px;
- padding: 2px 6px;
- background-color: #e8f5e9;
- color: #2e7d32;
- border-radius: 10px;
- }
- /* 底部Tab栏 */
- .tab-bar {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- height: 60px;
- background-color: white;
- display: flex;
- justify-content: space-around;
- align-items: center;
- box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.05);
- z-index: 100;
- }
- .tab-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- color: #666;
- font-size: 12px;
- flex: 1;
- height: 100%;
- }
- .tab-item.active {
- color: var(--ion-color-primary);
- }
- .tab-item ion-icon {
- font-size: 20px;
- margin-bottom: 3px;
- }
- /* 加载动画 */
- .typing-indicator {
- display: flex;
- padding: 10px 15px;
- }
- .typing-dot {
- width: 8px;
- height: 8px;
- background: #ccc;
- border-radius: 50%;
- margin: 0 2px;
- animation: typing 1.4s infinite ease-in-out;
- }
- .typing-dot:nth-child(1) {
- animation-delay: 0s;
- }
- .typing-dot:nth-child(2) {
- animation-delay: 0.2s;
- }
- .typing-dot:nth-child(3) {
- animation-delay: 0.4s;
- }
- @keyframes typing {
- 0%, 60%, 100% {
- transform: translateY(0);
- }
- 30% {
- transform: translateY(-5px);
- }
- }
- /* 旋转箭头动画 */
- .toggle-arrow {
- transition: transform 0.3s ease;
- }
- .toggle-arrow.active {
- transform: rotate(180deg);
- }
- </style>
- </head>
- <body>
- <ion-app>
- <!-- 顶部标题栏 -->
- <div class="header">
- <ion-icon name="arrow-back" class="header-back"></ion-icon>
- <div class="header-title">行程管家</div>
- </div>
-
- <!-- 内容区域 -->
- <div class="content">
- <!-- 模式切换 -->
- <div class="mode-switcher">
- <div class="mode-tab active">智能规划</div>
- <div class="mode-tab">我的行程</div>
- <div class="mode-tab">收藏</div>
- </div>
- <!-- AI助手按钮 -->
- <div class="ai-button-container">
- <button class="ai-toggle-button" id="aiToggleButton">
- <div class="ai-button-left">
- <div class="ai-avatar">
- <ion-icon name="sparkles"></ion-icon>
- </div>
- <div class="ai-button-text">
- <div class="ai-button-title">咨询AI助手</div>
- <div class="ai-button-subtitle">获取个性化行程建议</div>
- </div>
- </div>
- <ion-icon name="chevron-down" class="toggle-arrow"></ion-icon>
- </button>
- </div>
- <!-- AI助手对话区 (默认隐藏) -->
- <div class="ai-assistant" id="aiAssistant">
- <div class="ai-header">
- <div class="ai-avatar">
- <ion-icon name="sparkles"></ion-icon>
- </div>
- <div class="ai-name">智途AI助手</div>
- <div class="ai-status">在线</div>
- </div>
- <!-- 快速建议 -->
- <div class="quick-suggestions">
- <div class="quick-suggestion">三日游推荐</div>
- <div class="quick-suggestion">当地美食</div>
- <div class="quick-suggestion">交通方式</div>
- <div class="quick-suggestion">景点门票</div>
- </div>
- <div class="chat-container" id="chatContainer">
- <div class="message message-ai">
- <div class="message-bubble ai-bubble">
- 您好!我是您的行程管家助手,可以为您推荐旅游路线、预订门票、解答旅行问题等。您今天想去哪里玩呢?
- </div>
- <div class="message-time">10:30</div>
- </div>
- </div>
- <div class="input-area">
- <input type="text" class="message-input" placeholder="输入您的问题..." id="messageInput">
- <button class="send-button" id="sendButton">
- <ion-icon name="send"></ion-icon>
- </button>
- </div>
- </div>
- <!-- 推荐行程 -->
- <div class="recommended-trips">
- <div class="section-title">
- <ion-icon name="map-outline"></ion-icon>
- 热门行程推荐
- </div>
- <div class="trip-card">
- <img src="https://picsum.photos/400/300?random=hangzhou" class="trip-image" alt="杭州行程">
- <div class="trip-info">
- <div class="trip-title">杭州经典三日游</div>
- <div class="trip-duration">
- <ion-icon name="time-outline"></ion-icon>
- 3天2晚 · 精华路线
- </div>
- <div class="trip-tags">
- <span class="trip-tag">西湖</span>
- <span class="trip-tag">灵隐寺</span>
- <span class="trip-tag">宋城</span>
- <span class="trip-tag">美食</span>
- </div>
- </div>
- </div>
- <div class="trip-card">
- <img src="https://picsum.photos/400/300?random=shanghai" class="trip-image" alt="上海行程">
- <div class="trip-info">
- <div class="trip-title">上海都市两日游</div>
- <div class="trip-duration">
- <ion-icon name="time-outline"></ion-icon>
- 2天1晚 · 城市探索
- </div>
- <div class="trip-tags">
- <span class="trip-tag">外滩</span>
- <span class="trip-tag">迪士尼</span>
- <span class="trip-tag">豫园</span>
- <span class="trip-tag">购物</span>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- 底部Tab栏 -->
- <div class="tab-bar">
- <div class="tab-item">
- <ion-icon name="home-outline"></ion-icon>
- <span>首页</span>
- </div>
- <div class="tab-item active">
- <ion-icon name="calendar-outline"></ion-icon>
- <span>行程</span>
- </div>
- <div class="tab-item">
- <ion-icon name="compass-outline"></ion-icon>
- <span>发现</span>
- </div>
- <div class="tab-item">
- <ion-icon name="person-outline"></ion-icon>
- <span>我的</span>
- </div>
- </div>
- </ion-app>
- <script>
- // 获取DOM元素
- const aiToggleButton = document.getElementById('aiToggleButton');
- const aiAssistant = document.getElementById('aiAssistant');
- const toggleArrow = document.querySelector('.toggle-arrow');
- const sendButton = document.getElementById('sendButton');
- const messageInput = document.getElementById('messageInput');
- const chatContainer = document.getElementById('chatContainer');
-
- // 切换AI助手显示/隐藏
- aiToggleButton.addEventListener('click', () => {
- aiAssistant.classList.toggle('active');
- toggleArrow.classList.toggle('active');
- });
-
- // 获取当前时间
- function getCurrentTime() {
- const now = new Date();
- return `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`;
- }
-
- // 模拟AI回复
- function simulateAIResponse(message) {
- // 显示AI正在输入
- const typingIndicator = document.createElement('div');
- typingIndicator.className = 'message message-ai';
- typingIndicator.innerHTML = `
- <div class="typing-indicator">
- <div class="typing-dot"></div>
- <div class="typing-dot"></div>
- <div class="typing-dot"></div>
- </div>
- `;
-
- chatContainer.appendChild(typingIndicator);
- chatContainer.scrollTop = chatContainer.scrollHeight;
-
- // 模拟AI思考时间
- setTimeout(() => {
- typingIndicator.remove();
-
- let aiResponseText = "";
-
- // 根据用户消息生成不同回复
- if (message.includes("杭州") || message.includes("hangzhou")) {
- aiResponseText = `
- <strong>杭州三日游推荐行程:</strong><br><br>
- <strong>第一天:西湖景区</strong><br>
- - 断桥残雪<br>
- - 雷峰塔<br>
- - 三潭印月<br><br>
- <strong>第二天:文化体验</strong><br>
- - 灵隐寺<br>
- - 西溪湿地<br><br>
- <strong>第三天:娱乐休闲</strong><br>
- - 宋城主题公园<br>
- - 河坊街美食<br><br>
- 需要我帮您预订门票或酒店吗?
- `;
- } else if (message.includes("上海") || message.includes("shanghai")) {
- aiResponseText = `
- <strong>上海两日游推荐行程:</strong><br><br>
- <strong>第一天:城市地标</strong><br>
- - 外滩<br>
- - 东方明珠<br>
- - 南京路步行街<br><br>
- <strong>第二天:娱乐体验</strong><br>
- - 上海迪士尼乐园<br>
- - 豫园<br><br>
- 需要我帮您规划详细路线吗?
- `;
- } else {
- aiResponseText = `
- 我已收到您的请求:"${message}"<br><br>
- 我可以为您提供以下帮助:<br>
- 1. 旅游路线规划<br>
- 2. 景点门票预订<br>
- 3. 酒店推荐<br>
- 4. 当地美食推荐<br><br>
- 您需要哪方面的帮助呢?
- `;
- }
-
- const aiResponse = document.createElement('div');
- aiResponse.className = 'message message-ai';
- aiResponse.innerHTML = `
- <div class="message-bubble ai-bubble">${aiResponseText}</div>
- <div class="message-time">${getCurrentTime()}</div>
- `;
-
- chatContainer.appendChild(aiResponse);
- chatContainer.scrollTop = chatContainer.scrollHeight;
- }, 1500);
- }
-
- // 发送消息功能
- sendButton.addEventListener('click', sendMessage);
- messageInput.addEventListener('keypress', (e) => {
- if (e.key === 'Enter') sendMessage();
- });
-
- function sendMessage() {
- const message = messageInput.value.trim();
- if (!message) return;
-
- // 添加用户消息
- const userMessage = document.createElement('div');
- userMessage.className = 'message message-user';
- userMessage.innerHTML = `
- <div class="message-bubble user-bubble">${message}</div>
- <div class="message-time">${getCurrentTime()}</div>
- `;
-
- chatContainer.appendChild(userMessage);
- messageInput.value = '';
- chatContainer.scrollTop = chatContainer.scrollHeight;
-
- // 模拟AI回复
- simulateAIResponse(message);
- }
-
- // 快速建议点击事件
- const quickSuggestions = document.querySelectorAll('.quick-suggestion');
- quickSuggestions.forEach(suggestion => {
- suggestion.addEventListener('click', () => {
- const text = suggestion.textContent;
- messageInput.value = text;
- messageInput.focus();
- });
- });
- </script>
- </body>
- </html>
|