Pārlūkot izejas kodu

1.完善精选航线的静态内容

chenhg 1 mēnesi atpakaļ
vecāks
revīzija
d72c4c567b
11 mainītis faili ar 608 papildinājumiem un 500 dzēšanām
  1. 0 410
      constants.ts
  2. 1 1
      index.tsx
  3. 8 6
      App.tsx
  4. 53 9
      src/components/Navbar.tsx
  5. 2 2
      src/config/index.ts
  6. 38 9
      src/constants.ts
  7. 18 1
      src/contexts/ThemeContext.tsx
  8. 7 6
      src/pages/Home.tsx
  9. 472 0
      src/pages/Itineraries.tsx
  10. 9 0
      src/types.ts
  11. 0 56
      types.ts

+ 0 - 410
constants.ts

@@ -1,410 +0,0 @@
-
-
-import { MenuItem, CruiseShip, Itinerary, Feature, Language } from './types';
-
-export const PHONE_NUMBER = "400-696-0666";
-
-// Placeholder images for the carousel (Simulating the user provided images)
-// 1. Interior Dining/Lounge
-// 2. Deck with Umbrellas
-// 3. Ship/Lock/Gorge view
-export const HERO_IMAGES = [
-  "https://images.unsplash.com/photo-1578474843222-9593bc88d8b0?q=80&w=1920&auto=format&fit=crop", // Dining/Lounge feel
-  "https://images.unsplash.com/photo-1599640845513-2627a35c602a?q=80&w=1920&auto=format&fit=crop", // Deck/Ocean feel
-  "https://images.unsplash.com/photo-1534055691060-0382f646016c?q=80&w=1920&auto=format&fit=crop"  // Gorge/River feel
-];
-
-export const CONTENT = {
-  zh: {
-    nav: {
-      book: "立即预订",
-      contact: "联系客服",
-      menu: [
-        { title: "首页", link: "#/" },
-        { 
-          title: "长江行游轮", 
-          link: "#/ships",
-          submenu: [
-            { title: "长江行系列", link: "#/ships?section=series" },
-            { title: "长江行·揽月", link: "#/ships?section=lanyue" },
-            { title: "长江行·极光", link: "#/ships?section=aurora" },
-          ]
-        },
-        { 
-          title: "精选航线", 
-          link: "#/itineraries",
-          submenu: [
-            { title: "航线行程", link: "#itinerary-routes" },
-            { title: "产品亮点", link: "#itinerary-highlights" },
-            { title: "游轮航期", link: "#itinerary-schedules" },
-          ]
-        },
-        { 
-          title: "游轮体验", 
-          link: "#experience",
-          submenu: [
-            { title: "品质服务", link: "#exp-service" },
-            { title: "星级餐饮", link: "#exp-dining" },
-            { title: "丰富活动", link: "#exp-activities" },
-          ]
-        },
-        { 
-          title: "游轮空间", 
-          link: "#spaces",
-          submenu: [
-            { title: "设施设备", link: "#space-facilities" },
-            { title: "房型介绍", link: "#space-rooms" },
-            { title: "尊享礼遇", link: "#space-vip" },
-          ]
-        },
-        { 
-          title: "出行攻略", 
-          link: "#guide",
-          submenu: [
-            { title: "出行指南", link: "#guide-tips" },
-            { title: "常见问题", link: "#guide-faq" },
-          ]
-        },
-        { 
-          title: "关于我们", 
-          link: "#about",
-          submenu: [
-            { title: "企业简介", link: "#about-intro" },
-            { title: "官方媒体", link: "#about-media" },
-          ]
-        },
-      ]
-    },
-    hero: {
-      welcome: "欢迎来到长江行游轮",
-      title_italic: "驻足",
-      title_normal: "即是旅途",
-      subtitle: "体验长江之上的奢华与服务,超乎您的想象。水上圣殿,静候君临。",
-      btn_find: "探索航线",
-      btn_ships: "游轮舰队"
-    },
-    home: {
-      featured_sub: "精选航程",
-      featured_title: "甄选航线",
-      view_all: "查看所有航线",
-      days: "天",
-      details: "查看详情",
-      dining_title: "卓越美食",
-      dining_desc: "品味米其林灵感菜单,由世界级名厨精选当地最新鲜食材烹饪。每一餐都是一次味蕾的旅行。",
-      dining_btn: "探索餐饮",
-      fleet_sub: "游轮舰队",
-      fleet_title: "移动的水上圣殿",
-      discover_ship: "探索游轮",
-      exp_sub: "游轮体验",
-      exp_title: "沉浸于",
-      exp_title_italic: "非凡时刻",
-      exp_desc: "从您登船的那一刻起,每一个细节都旨在提供舒适、优雅与冒险的完美融合。",
-    },
-    footer: {
-      desc: "重塑长江之旅。奢华与传承的完美交融。",
-      hotline: "24/7 预订热线",
-      privacy: "隐私政策",
-      terms: "条款与条件",
-      cookies: "Cookie 政策",
-      rights: "版权所有。"
-    },
-    shipsPage: {
-      hero_sub: "游轮舰队",
-      hero_desc: "重新定义长江之上的奢华之旅。",
-      now_sailing: "现已启航",
-      coming_soon: "2026 即将启幕",
-      flagship_label: "旗舰荣耀",
-      stats_tons: "17,000 吨",
-      stats_stars: "五星级奢华",
-      stats_ratio: "船员配比",
-      view_itineraries: "查看航线",
-      future_label: "游轮未来式",
-      waitlist_btn: "加入候补名单",
-      intro: {
-        title: "何谓“长江行”?",
-        desc: "长江,这条奔腾不息的巨龙,早已超越地理范畴,深深融入中华民族的文化基因与精神血脉。她是“唯见长江天际流”的壮阔无垠,是“不尽长江滚滚来”的时空浩荡,更是“大江东去,浪淘尽,千古风流人物”的历史回响。“长江行”不止是一次航行,更是一场三重境界的深度体验。",
-        points: [
-          {
-            title: "行·贯古今",
-            desc: "循黄金水道,溯千年文脉。让孤帆远影的诗意、金戈铁马的雄浑、桨声灯影的风华,在船舷两侧流淌成活的史诗。"
-          },
-          {
-            title: "行·见天地",
-            desc: "跨省际壮游,揽山河入怀。夔门之险、荆江九曲、沃野平畴、都市风华...万里气象与地域精粹皆成窗外交响。"
-          },
-          {
-            title: "行·致未来",
-            desc: "以匠心远见,雕时代典范。这是面向未来的智慧航行,一次对至臻体验与永续之美的承诺。"
-          }
-        ]
-      },
-      lanyue: {
-        title: "长江行·揽月",
-        desc: "“长江行·揽月”作为长江行系列游轮首艘旗舰,是目前国内尺寸最大的绿色低碳环保型度假游轮之一,也是三峡旅游集团继“长江三峡1”“西陵峡·和悦”“西陵峡·和谐”“宜昌远影”之后推出的新一代新能源游轮旗舰。"
-      },
-      aurora: {
-        title: "长江行·极光",
-        desc: "2026首航,敬请期待。"
-      }
-    },
-    ships: [
-      {
-        id: "lanyue",
-        name: "长江行·揽月",
-        description: "体验长江之上的奢华巅峰。优雅的避世圣所。",
-        image: "https://picsum.photos/800/600?random=1"
-      },
-      {
-        id: "jiguang",
-        name: "长江行·极光",
-        description: "现代设计与传统待客之道的融合。无与伦比的观景体验。",
-        image: "https://picsum.photos/800/600?random=2"
-      },
-      {
-        id: "star",
-        name: "长江行·星河",
-        description: "树立内河游轮新标杆。私密、尊贵、难忘。",
-        image: "https://picsum.photos/800/600?random=3"
-      }
-    ],
-    itineraries: [
-      {
-        id: "1",
-        title: "三峡探索之旅",
-        days: 4,
-        price: "¥3,999 起",
-        image: "https://picsum.photos/600/400?random=10",
-        route: "重庆 - 宜昌"
-      },
-      {
-        id: "2",
-        title: "长江人文之旅",
-        days: 5,
-        price: "¥4,599 起",
-        image: "https://picsum.photos/600/400?random=11",
-        route: "宜昌 - 重庆"
-      },
-      {
-        id: "3",
-        title: "大江东去长航线",
-        days: 8,
-        price: "¥8,888 起",
-        image: "https://picsum.photos/600/400?random=12",
-        route: "重庆 - 上海"
-      }
-    ],
-    features: [
-      {
-        title: "管家服务",
-        description: "每间套房均配备24小时私人管家服务。",
-        icon: "user"
-      },
-      {
-        title: "米其林餐饮",
-        description: "由世界知名主厨精心策划的菜单。",
-        icon: "utensils"
-      },
-      {
-        title: "文化沉浸",
-        description: "专属岸上观光与船上讲座。",
-        icon: "map"
-      }
-    ]
-  },
-  en: {
-    nav: {
-      book: "BOOK NOW",
-      contact: "Contact",
-      menu: [
-        { title: "HOME", link: "#/" },
-        { 
-          title: "VISTA CRUISES", 
-          link: "#/ships",
-          submenu: [
-            { title: "The Vista Series", link: "#/ships?section=series" },
-            { title: "Vista Lanyue", link: "#/ships?section=lanyue" },
-            { title: "Vista Aurora", link: "#/ships?section=aurora" },
-          ]
-        },
-        { 
-          title: "VOYAGES", 
-          link: "#/itineraries",
-          submenu: [
-            { title: "Itineraries", link: "#itinerary-routes" },
-            { title: "Highlights", link: "#itinerary-highlights" },
-            { title: "Schedules", link: "#itinerary-schedules" },
-          ]
-        },
-        { 
-          title: "EXPERIENCE", 
-          link: "#experience",
-          submenu: [
-            { title: "Service", link: "#exp-service" },
-            { title: "Dining", link: "#exp-dining" },
-            { title: "Activities", link: "#exp-activities" },
-          ]
-        },
-        { 
-          title: "SPACES", 
-          link: "#spaces",
-          submenu: [
-            { title: "Facilities", link: "#space-facilities" },
-            { title: "Suites", link: "#space-rooms" },
-            { title: "Privileges", link: "#space-vip" },
-          ]
-        },
-        { 
-          title: "GUIDE", 
-          link: "#guide",
-          submenu: [
-            { title: "Travel Tips", link: "#guide-tips" },
-            { title: "FAQ", link: "#guide-faq" },
-          ]
-        },
-        { 
-          title: "ABOUT US", 
-          link: "#about",
-          submenu: [
-            { title: "Introduction", link: "#about-intro" },
-            { title: "Media", link: "#about-media" },
-          ]
-        },
-      ]
-    },
-    hero: {
-      welcome: "Welcome to Vista Cruises",
-      title_italic: "Stay &",
-      title_normal: "Journey",
-      subtitle: "Experience the majestic Yangtze River with a level of luxury and service never before imagined. Your sanctuary on the water awaits.",
-      btn_find: "Find a Cruise",
-      btn_ships: "Our Ships"
-    },
-    home: {
-      featured_sub: "Featured Voyages",
-      featured_title: "Curated Itineraries",
-      view_all: "View All Voyages",
-      days: "Days",
-      details: "Details",
-      dining_title: "Culinary Excellence",
-      dining_desc: "Savor the flavors of the region with our Michelin-inspired menus, crafted by world-class chefs using the freshest local ingredients. Every meal is a journey in itself.",
-      dining_btn: "Explore Dining",
-      fleet_sub: "The Fleet",
-      fleet_title: "Our Floating Sanctuaries",
-      discover_ship: "Discover Ship",
-      exp_sub: "The Experience",
-      exp_title: "Immerse Yourself in",
-      exp_title_italic: "The Extraordinary",
-      exp_desc: "From the moment you step onboard, every detail is curated to provide a seamless blend of comfort, elegance, and adventure. Watch our journey unfold.",
-    },
-    footer: {
-      desc: "Reimagining the Yangtze experience. Where luxury meets heritage in perfect harmony.",
-      hotline: "24/7 Reservation Hotline",
-      privacy: "Privacy Policy",
-      terms: "Terms & Conditions",
-      cookies: "Cookie Policy",
-      rights: "Vista Cruises. All Rights Reserved."
-    },
-    shipsPage: {
-      hero_sub: "The Fleet",
-      hero_desc: "Redefining luxury on the Yangtze River.",
-      now_sailing: "Now Sailing",
-      coming_soon: "Coming 2026",
-      flagship_label: "The Flagship",
-      stats_tons: "17,000 Tons",
-      stats_stars: "5-Star Luxury",
-      stats_ratio: "Crew Ratio",
-      view_itineraries: "View Itineraries",
-      future_label: "Future of Cruising",
-      waitlist_btn: "Join Waitlist",
-      intro: {
-        title: "The Vista Philosophy",
-        desc: "The Yangtze, a dragon that never sleeps, transcends geography to become the spiritual bloodline of a nation. Vista Cruises offers not just a journey, but a three-fold experience of depth and discovery.",
-        points: [
-          {
-            title: "History",
-            desc: "Tracing thousands of years of culture along the golden waterway."
-          },
-          {
-            title: "Nature",
-            desc: "Embracing the majestic mountains and rivers, from the dangerous Kuimen to the fertile plains."
-          },
-          {
-            title: "Future",
-            desc: "A commitment to ultimate experience and sustainable beauty with craftsmanship and foresight."
-          }
-        ]
-      },
-      lanyue: {
-        title: "Vista Lanyue",
-        desc: "As the first flagship of the Vista series, Lanyue is one of the largest green, low-carbon vacation cruises in China. It represents the new generation of new energy flagships."
-      },
-      aurora: {
-        title: "Vista Aurora",
-        desc: "Maiden Voyage 2026. Stay tuned."
-      }
-    },
-    ships: [
-      {
-        id: "lanyue",
-        name: "Vista Lanyue",
-        description: "Experience the epitome of luxury on the Yangtze with the Lanyue. A sanctuary of elegance.",
-        image: "https://picsum.photos/800/600?random=1"
-      },
-      {
-        id: "jiguang",
-        name: "Vista Aurora",
-        description: "Modern design meets traditional hospitality. The Jiguang offers an unparalleled viewing experience.",
-        image: "https://picsum.photos/800/600?random=2"
-      },
-      {
-        id: "star",
-        name: "Vista Star",
-        description: "A new standard for river cruising. Intimate, exclusive, and unforgettable.",
-        image: "https://picsum.photos/800/600?random=3"
-      }
-    ],
-    itineraries: [
-      {
-        id: "1",
-        title: "Three Gorges Discovery",
-        days: 4,
-        price: "Fr. ¥3,999",
-        image: "https://picsum.photos/600/400?random=10",
-        route: "Chongqing - Yichang"
-      },
-      {
-        id: "2",
-        title: "Yangtze Heritage",
-        days: 5,
-        price: "Fr. ¥4,599",
-        image: "https://picsum.photos/600/400?random=11",
-        route: "Yichang - Chongqing"
-      },
-      {
-        id: "3",
-        title: "Grand River Voyage",
-        days: 8,
-        price: "Fr. ¥8,888",
-        image: "https://picsum.photos/600/400?random=12",
-        route: "Chongqing - Shanghai"
-      }
-    ],
-    features: [
-      {
-        title: "Butler Service",
-        description: "24-hour personal butler service for every suite.",
-        icon: "user"
-      },
-      {
-        title: "Michelin Dining",
-        description: "Curated menus by world-renowned chefs.",
-        icon: "utensils"
-      },
-      {
-        title: "Cultural Immersion",
-        description: "Exclusive shore excursions and onboard lectures.",
-        icon: "map"
-      }
-    ]
-  }
-};

+ 1 - 1
index.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import ReactDOM from 'react-dom/client';
-import App from './App';
+import App from './src/App.tsx';
 
 const rootElement = document.getElementById('root');
 if (!rootElement) {

+ 8 - 6
App.tsx

@@ -1,12 +1,13 @@
 
 import React from 'react';
 import { HashRouter as Router, Routes, Route } from 'react-router-dom';
-import Home from '@/src/pages/Home';
-import Ships from '@/src/pages/Ships';
-import AboutUs from '@/src/pages/AhoutUs';
-import Guide from '@/src/pages/Guide';
-import { LanguageProvider } from '@/src/contexts/LanguageContext';
-import { ThemeProvider } from '@/src/contexts/ThemeContext';
+import Home from '@/src/pages/Home.tsx';
+import Ships from '@/src/pages/Ships.tsx';
+import Itineraries from '@/src/pages/Itineraries.tsx';
+import AboutUs from '@/src/pages/AhoutUs.tsx';
+import Guide from '@/src/pages/Guide.tsx';
+import { LanguageProvider } from '@/src/contexts/LanguageContext.tsx';
+import { ThemeProvider } from '@/src/contexts/ThemeContext.tsx';
 
 const App: React.FC = () => {
   return (
@@ -17,6 +18,7 @@ const App: React.FC = () => {
             <Route path="/" element={<Home />} />
             <Route path="/ships" element={<Ships />} />
             <Route path="/about" element={<AboutUs />} />
+            <Route path="/itineraries" element={<Itineraries />} />
             <Route path="/guide" element={<Guide />} />
             <Route path="*" element={<Home />} />
           </Routes>

+ 53 - 9
src/components/Navbar.tsx

@@ -57,29 +57,73 @@ const Navbar: React.FC = () => {
 
   // Handle Navigation Click (Smart Routing)
   const handleNavClick = (e: React.MouseEvent, link: string) => {
+    // 处理纯锚点链接(如 #itinerary-highlights)
     if (link.startsWith('#') && !link.startsWith('#/')) {
         e.preventDefault();
         const anchorId = link.substring(1);
 
-        if (location.pathname !== '/') {
+        // First try to find the anchor on current page
+        const el = document.getElementById(anchorId);
+        if (el) {
+            // Scroll to anchor on current page
+            el.scrollIntoView({ behavior: 'smooth' });
+        } else if (location.pathname !== '/') {
+            // Only redirect to home if anchor not found on current page
             navigate('/');
             setTimeout(() => {
-                const el = document.getElementById(anchorId);
-                if (el) el.scrollIntoView({ behavior: 'smooth' });
+                const homeEl = document.getElementById(anchorId);
+                if (homeEl) homeEl.scrollIntoView({ behavior: 'smooth' });
             }, 100);
-        } else {
+        }
+        setActiveMenuIndex(null);
+    }
+    // 处理包含锚点的路由链接(如 #/itineraries#itinerary-highlights)
+    else if (link.startsWith('#/') && link.includes('#')) {
+        e.preventDefault();
+        const [routePart, anchorPart] = link.substring(1).split('#');
+        const anchorId = anchorPart;
+
+        // 先导航到路由,然后滚动到锚点
+        navigate(routePart);
+        setTimeout(() => {
             const el = document.getElementById(anchorId);
             if (el) el.scrollIntoView({ behavior: 'smooth' });
-        }
+        }, 100);
         setActiveMenuIndex(null);
-    } 
+    }
+    // 处理包含查询参数的路由链接(如 #/itineraries?section=routes)
+    else if (link.startsWith('#/') && link.includes('?')) {
+        e.preventDefault();
+        const routePart = link.substring(1);
+        // 直接导航到包含查询参数的路由
+        navigate(routePart);
+        setActiveMenuIndex(null);
+    }
     else if (link.startsWith('#/')) {
        setActiveMenuIndex(null);
     }
   };
 
   const getLinkTo = (link: string) => {
-      if (link.startsWith('#/')) return link.substring(1);
+      if (link.startsWith('#/')) {
+          // 处理包含锚点或查询参数的路由链接
+          // 如 #/itineraries#itinerary-highlights 或 #/itineraries?section=routes
+          const routeAndParams = link.substring(1); // 去掉开头的 #
+          
+          // 处理 hash 锚点
+          if (routeAndParams.includes('#')) {
+              const [route] = routeAndParams.split('#');
+              return route;
+          }
+          
+          // 处理查询参数
+          if (routeAndParams.includes('?')) {
+              return routeAndParams;
+          }
+          
+          // 普通路由
+          return routeAndParams;
+      }
       if (link.startsWith('#')) return '/';
       return link;
   };
@@ -200,8 +244,8 @@ const Navbar: React.FC = () => {
                </button>
 
                <a 
-                  href="#book"
-                  onClick={(e) => handleNavClick(e, '#book')}
+                  href="https://www.dreamcruises.cn/ticket/index?b=d7945ce3d91637802d7ac1c7b9e34988"
+                  onClick={(e) => handleNavClick(e, '/')}
                   className={`px-6 py-2 border transition-all duration-300 text-xs font-bold tracking-widest uppercase ${
                    scrolled 
                    ? 'border-vista-darkblue text-vista-darkblue hover:bg-vista-darkblue hover:text-white' 

+ 2 - 2
src/config/index.ts

@@ -37,12 +37,12 @@ const requestInstance = {
   },
   download: async <T = any>(option: any) => {
     const res = await request({ method: 'GET', responseType: 'blob', ...option });
-    return res as Promise<T>;
+    return res as T;
   },
   upload: async <T = any>(option: any) => {
     option.headersType = 'multipart/form-data';
     const res = await request({ method: 'POST', ...option });
-    return res as Promise<T>;
+    return res as T;
   }
 };
 

+ 38 - 9
src/constants.ts

@@ -37,9 +37,9 @@ export const CONTENT = {
           title: "精选航线", 
           link: "#/itineraries",
           submenu: [
-            { title: "航线行程", link: "#itinerary-routes" },
-            { title: "产品亮点", link: "#itinerary-highlights" },
-            { title: "游轮航期", link: "#itinerary-schedules" },
+            { title: "航线行程", link: "#/itineraries?section=routes" },
+            { title: "产品亮点", link: "#/itineraries?section=highlights" },
+            { title: "游轮航期", link: "#/itineraries?section=schedules" },
           ]
         },
         { 
@@ -321,7 +321,15 @@ export const CONTENT = {
         days: 4,
         price: "¥3,999 起",
         image: "https://picsum.photos/600/400?random=10",
-        route: "重庆 - 宜昌"
+        route: "重庆 - 宜昌",
+        description: "探索长江三峡的壮丽风光,体验从重庆到宜昌的经典航程。沿途欣赏夔门、神女溪、三峡大坝等世界级景点。",
+        highlights: ["三峡大坝工程参观", "神女溪深度游览", "夔门风光摄影", "船上文化讲座"],
+        itinerary: [
+          { day: 1, title: "重庆登船", description: "下午登船,欢迎晚宴,游轮启航" },
+          { day: 2, title: "三峡风光", description: "游览白帝城,瞿塘峡,巫峡" },
+          { day: 3, title: "西陵峡", description: "神女溪,三峡大坝,升船机体验" },
+          { day: 4, title: "宜昌离船", description: "早餐后离船,行程结束" }
+        ]
       },
       {
         id: "2",
@@ -329,7 +337,16 @@ export const CONTENT = {
         days: 5,
         price: "¥4,599 起",
         image: "https://picsum.photos/600/400?random=11",
-        route: "宜昌 - 重庆"
+        route: "宜昌 - 重庆",
+        description: "从宜昌逆流而上,深入探索长江三峡的自然风光和人文历史。享受船上奢华设施和贴心服务。",
+        highlights: ["三峡大坝全景", "巫峡十二峰", "神女溪游船", "三峡文化表演"],
+        itinerary: [
+          { day: 1, title: "宜昌登船", description: "下午登船,欢迎仪式,游轮启航" },
+          { day: 2, title: "西陵峡", description: "三峡大坝,升船机,西陵峡风光" },
+          { day: 3, title: "巫峡", description: "神女溪,巫峡十二峰,瞿塘峡" },
+          { day: 4, title: "白帝城", description: "白帝城参观,重庆离船" },
+          { day: 5, title: "重庆离船", description: "早餐后离船,行程结束" }
+        ]
       },
       {
         id: "3",
@@ -337,7 +354,19 @@ export const CONTENT = {
         days: 8,
         price: "¥8,888 起",
         image: "https://picsum.photos/600/400?random=12",
-        route: "重庆 - 上海"
+        route: "重庆 - 上海",
+        description: "全程8天,从重庆到上海,纵览长江全貌。感受中国最长河流的多样性和魅力。",
+        highlights: ["三峡全景", "武汉黄鹤楼", "南京中山陵", "上海外滩"],
+        itinerary: [
+          { day: 1, title: "重庆登船", description: "下午登船,欢迎晚宴" },
+          { day: 2, title: "三峡起点", description: "游览丰都鬼城,进入三峡" },
+          { day: 3, title: "瞿塘峡", description: "夔门,白帝城,瞿塘峡" },
+          { day: 4, title: "巫峡", description: "巫峡十二峰,神女溪" },
+          { day: 5, title: "西陵峡", description: "三峡大坝,升船机" },
+          { day: 6, title: "武汉", description: "黄鹤楼,长江大桥" },
+          { day: 7, title: "南京", description: "中山陵,夫子庙" },
+          { day: 8, title: "上海离船", description: "外滩,豫园,离船" }
+        ]
       }
     ],
     features: [
@@ -377,9 +406,9 @@ export const CONTENT = {
           title: "VOYAGES", 
           link: "#/itineraries",
           submenu: [
-            { title: "Itineraries", link: "#itinerary-routes" },
-            { title: "Highlights", link: "#itinerary-highlights" },
-            { title: "Schedules", link: "#itinerary-schedules" },
+            { title: "Itineraries", link: "#/itineraries?section=routes" },
+            { title: "Highlights", link: "#/itineraries?section=highlights" },
+            { title: "Schedules", link: "#/itineraries?section=schedules" },
           ]
         },
         { 

+ 18 - 1
src/contexts/ThemeContext.tsx

@@ -89,12 +89,27 @@ export const ThemeProvider: React.FC<{ children: ReactNode }> = ({ children }) =
 
   // Fetch hero images from API when component mounts
   useEffect(() => {
+    // Check if we already have hero images in localStorage to avoid unnecessary API calls
+    const savedImages = localStorage.getItem('vista_hero_images');
+    if (savedImages) {
+      return; // Skip API call if we already have images saved
+    }
+
     const loadHeroImagesFromApi = async () => {
+      // Add a flag to prevent duplicate API calls in React Strict Mode
+      const apiCallFlag = 'vista_hero_images_api_called';
+      if (sessionStorage.getItem(apiCallFlag)) {
+        return; // Skip if we already made the call in this session
+      }
+
       try {
         // Import the functions dynamically to avoid circular dependencies
-        const { fetchHotArticles, extractHeroImagesFromArticles } =
+        const { fetchHotArticles, extractHeroImagesFromArticles } = 
             await import('../services/articleService.ts');
         
+        // Mark that we're making the API call
+        sessionStorage.setItem(apiCallFlag, 'true');
+
         // Fetch hot articles from the API
         const articlesData = await fetchHotArticles(1, 6);
         
@@ -111,6 +126,8 @@ export const ThemeProvider: React.FC<{ children: ReactNode }> = ({ children }) =
       } catch (error) {
         console.error('Failed to fetch hero images from API:', error);
         // Fallback to existing images if API fails
+        // Clear the flag if the API call failed so we can try again
+        sessionStorage.removeItem('vista_hero_images_api_called');
       }
     };
 

+ 7 - 6
src/pages/Home.tsx

@@ -1,4 +1,5 @@
 import React, { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
 import Navbar from '@/src/components/Navbar.tsx';
 import Sidebar from '@/src/components/Sidebar.tsx';
 import Footer from '@/src/components/Footer.tsx';
@@ -79,12 +80,12 @@ const Home: React.FC = () => {
                 {t.hero.subtitle}
             </p>
             <div className="flex space-x-6">
-                <button className="px-8 py-4 bg-vista-gold text-white font-bold tracking-widest uppercase text-sm hover:bg-white hover:text-vista-darkblue transition-all duration-300 shadow-lg">
+                <Link to="/itineraries?section=routes" className="px-8 py-4 bg-vista-gold text-white font-bold tracking-widest uppercase text-sm hover:bg-white hover:text-vista-darkblue transition-all duration-300 shadow-lg">
                     {t.hero.btn_find}
-                </button>
-                <button className="px-8 py-4 border border-white text-white font-bold tracking-widest uppercase text-sm hover:bg-white hover:text-vista-darkblue transition-all duration-300 shadow-lg">
+                </Link>
+                <Link to="/ships" className="px-8 py-4 border border-white text-white font-bold tracking-widest uppercase text-sm hover:bg-white hover:text-vista-darkblue transition-all duration-300 shadow-lg">
                     {t.hero.btn_ships}
-                </button>
+                </Link>
             </div>
         </div>
 
@@ -102,9 +103,9 @@ const Home: React.FC = () => {
                     <span className="text-vista-gold uppercase tracking-widest text-sm font-bold">{t.home.featured_sub}</span>
                     <h2 className="text-4xl font-serif text-vista-darkblue mt-3">{t.home.featured_title}</h2>
                 </div>
-                <a href="#all-trips" className="hidden md:flex items-center text-vista-darkblue font-bold text-sm tracking-widest uppercase hover:text-vista-gold transition-colors mt-4 md:mt-0">
+                <Link to="/itineraries?section=routes" className="hidden md:flex items-center text-vista-darkblue font-bold text-sm tracking-widest uppercase hover:text-vista-gold transition-colors mt-4 md:mt-0">
                     {t.home.view_all} <ChevronRight size={16} className="ml-2" />
-                </a>
+                </Link>
             </div>
 
             <div className="grid grid-cols-1 md:grid-cols-3 gap-8">

+ 472 - 0
src/pages/Itineraries.tsx

@@ -0,0 +1,472 @@
+import React, { useState, useEffect } from 'react';
+import Navbar from '@/src/components/Navbar.tsx';
+import Sidebar from '@/src/components/Sidebar.tsx';
+import Footer from '@/src/components/Footer.tsx';
+import { CONTENT } from '../constants.ts';
+import { ChevronRight, MapPin, Calendar, DollarSign, X, ChevronDown, Info } from 'lucide-react';
+import { useLanguage } from '@/src/contexts/LanguageContext.tsx';
+import { useTheme } from '@/src/contexts/ThemeContext.tsx';
+import { Itinerary } from '../types.ts';
+import { useLocation } from 'react-router-dom';
+
+const Itineraries: React.FC = () => {
+  const { language } = useLanguage();
+  const { itineraries } = useTheme();
+  const [selectedItinerary, setSelectedItinerary] = useState<Itinerary | null>(null);
+  const [selectedDays, setSelectedDays] = useState<number[]>([]);
+  const [sortBy, setSortBy] = useState<string>('default');
+  const location = useLocation();
+  
+  const t = CONTENT[language];
+  
+  // Get section from query parameters
+  const section = new URLSearchParams(location.search).get('section');
+  
+  // Scroll to section when section parameter changes
+  useEffect(() => {
+    if (section) {
+      const element = document.getElementById(`itinerary-${section}`);
+      if (element) {
+        element.scrollIntoView({ behavior: 'smooth', block: 'start' });
+      }
+    }
+  }, [section]);
+  
+  // Filter itineraries by selected days
+  const filteredItineraries = itineraries.filter((itinerary) => {
+    if (selectedDays.length === 0) return true;
+    return selectedDays.includes(itinerary.days);
+  });
+  
+  // Sort itineraries
+  const sortedItineraries = [...filteredItineraries].sort((a, b) => {
+    switch (sortBy) {
+      case 'price-low':
+        return parseInt(a.price.replace(/[^0-9]/g, '')) - parseInt(b.price.replace(/[^0-9]/g, ''));
+      case 'price-high':
+        return parseInt(b.price.replace(/[^0-9]/g, '')) - parseInt(a.price.replace(/[^0-9]/g, ''));
+      case 'days-low':
+        return a.days - b.days;
+      case 'days-high':
+        return b.days - a.days;
+      default:
+        return 0;
+    }
+  });
+  
+  // Toggle day filter
+  const toggleDayFilter = (days: number) => {
+    setSelectedDays(prev => {
+      if (prev.includes(days)) {
+        return prev.filter(d => d !== days);
+      } else {
+        return [...prev, days];
+      }
+    });
+  };
+  
+  // Clear all filters
+  const clearFilters = () => {
+    setSelectedDays([]);
+    setSortBy('default');
+  };
+
+  // Itinerary details are now directly available in the itineraries data
+
+  return (
+    <div className="min-h-screen bg-white font-sans text-vista-darkblue overflow-x-hidden">
+      <Navbar />
+      <Sidebar />
+
+      {/* Hero Section */}
+      <section className="relative h-[60vh] md:h-[70vh] w-full overflow-hidden bg-vista-darkblue">
+        <div className="absolute inset-0 bg-gradient-to-br from-vista-darkblue/95 to-vista-darkblue/60 z-10"></div>
+        <div className="absolute inset-0 bg-cover bg-center opacity-40" style={{ backgroundImage: `url(https://picsum.photos/1920/1080?random=20)` }}></div>
+        <div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXR0ZXJuIGlkPSJwYXR0ZXJuIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBwYXR0ZXJuVW5pdHM9InVzZXJTcGFjZU9uVXNlIj48cGF0aCBkPSJNMTAgMTBoMjB2MjBIMTB6TTMwIDEwaDIwdjIwSDMweiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAuNSIvPjwvcGF0dGVybj48L3N2Zz4=')] opacity-10 z-20"></div>
+        <div className="relative z-30 h-full flex flex-col justify-center items-center text-center px-4 py-12">
+          <span className="text-vista-gold uppercase tracking-widest text-xs sm:text-sm font-bold mb-4">{t.nav.menu[2].title}</span>
+          <h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-7xl font-serif text-white mb-4 sm:mb-6 leading-tight">探索长江精选航线</h1>
+          <p className="text-white/90 max-w-2xl sm:max-w-3xl text-base sm:text-lg md:text-xl mb-6 sm:mb-8 leading-relaxed">体验无与伦比的奢华旅程,欣赏长江三峡的壮丽风光和人文历史</p>
+          <a href="#itinerary-routes" className="px-8 sm:px-10 py-3 sm:py-4 bg-vista-gold text-white font-bold tracking-widest uppercase text-xs sm:text-sm hover:bg-opacity-90 transition-all duration-300 shadow-lg hover:shadow-xl">
+            {t.nav.book}
+          </a>
+        </div>
+      </section>
+
+      {/* Main Content */}
+      <section className="py-24 bg-white" id="itinerary-routes">
+        <div className="max-w-7xl mx-auto px-6">
+          {/* Section Title */}
+          <div className="text-center mb-12">
+            <div className="inline-block relative mb-4">
+              <span className="text-vista-gold uppercase tracking-widest text-sm font-bold">{t.nav.menu[2].submenu?.[0].title}</span>
+              <div className="absolute -bottom-2 left-1/2 transform -translate-x-1/2 w-16 h-1 bg-vista-gold/30"></div>
+            </div>
+            <h2 className="text-4xl md:text-5xl font-serif text-vista-darkblue mt-3 mb-6">精选航线</h2>
+            <p className="text-vista-darkblue/70 max-w-3xl mx-auto text-lg">
+              选择您理想的长江游轮之旅,每一条航线都经过精心设计,带您探索长江的自然美景和人文历史
+            </p>
+          </div>
+
+          {/* Filters and Sorting */}
+          <div className="mb-12 bg-gray-50 rounded-lg p-6 shadow-sm">
+            <div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
+              {/* Day Filter */}
+              <div>
+                <div className="flex items-center gap-4 mb-3">
+                  <span className="text-sm font-bold uppercase tracking-wider text-vista-darkblue">天数</span>
+                  {selectedDays.length > 0 && (
+                    <button 
+                      className="text-xs text-vista-gold hover:text-vista-darkblue transition-colors"
+                      onClick={clearFilters}
+                    >
+                      清除筛选
+                    </button>
+                  )}
+                </div>
+                <div className="flex flex-wrap gap-3">
+                  {[4, 5, 8].map((days) => (
+                    <button
+                      key={days}
+                      className={`px-4 py-2 rounded-full text-sm font-medium transition-all duration-300 ${selectedDays.includes(days) ? 'bg-vista-gold text-white shadow-md' : 'bg-white border border-gray-200 text-vista-darkblue hover:border-vista-gold hover:text-vista-gold'}`}
+                      onClick={() => toggleDayFilter(days)}
+                    >
+                      {days} {t.home.days}
+                    </button>
+                  ))}
+                </div>
+              </div>
+              
+              {/* Sort By */}
+              <div>
+                <div className="flex items-center gap-2 mb-3">
+                  <span className="text-sm font-bold uppercase tracking-wider text-vista-darkblue">排序</span>
+                </div>
+                <select
+                  className="bg-white border border-gray-200 rounded-lg px-4 py-2 pr-10 text-sm text-vista-darkblue focus:outline-none focus:border-vista-gold focus:ring-2 focus:ring-vista-gold/20"
+                  value={sortBy}
+                  onChange={(e) => setSortBy(e.target.value)}
+                >
+                  <option value="default">默认排序</option>
+                  <option value="price-low">价格从低到高</option>
+                  <option value="price-high">价格从高到低</option>
+                  <option value="days-low">天数从少到多</option>
+                  <option value="days-high">天数从多到少</option>
+                </select>
+              </div>
+            </div>
+            
+            {/* Results Count */}
+            <div className="mt-6 pt-4 border-t border-gray-200 text-sm text-vista-darkblue/60">
+              找到 {sortedItineraries.length} 条航线
+            </div>
+          </div>
+
+          {/* Itinerary Grid */}
+          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-12">
+            {sortedItineraries.map((item) => (
+              <div 
+                key={item.id} 
+                className="group bg-white border border-gray-100 shadow-sm hover:shadow-xl transition-all duration-300 cursor-pointer rounded-lg overflow-hidden transform hover:-translate-y-2"
+                onClick={() => setSelectedItinerary(item)}
+              >
+                <div className="relative overflow-hidden h-72">
+                  {item.video ? (
+                    <video 
+                      src={item.video} 
+                      poster={item.image}
+                      className="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-700"
+                      autoPlay
+                      muted
+                      loop
+                      playsInline
+                    />
+                  ) : (
+                    <img 
+                      src={item.image} 
+                      alt={item.title} 
+                      className="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-700" 
+                    />
+                  )}
+                  <div className="absolute top-4 left-4 bg-white/95 backdrop-blur-sm px-4 py-2 rounded-full text-xs font-bold tracking-widest uppercase z-10 text-vista-darkblue shadow-sm">
+                    {item.days} {t.home.days}
+                  </div>
+                </div>
+                
+                <div className="p-8">
+                  <div className="flex items-center text-xs text-vista-darkblue/50 uppercase tracking-widest mb-3">
+                    <MapPin size={14} className="mr-1" />
+                    {item.route}
+                  </div>
+                  <h3 className="text-2xl font-serif text-vista-darkblue mb-5 group-hover:text-vista-gold transition-colors leading-tight">{item.title}</h3>
+                  
+                  <div className="space-y-4 mb-7">
+                    <div className="flex items-center text-sm text-vista-darkblue/80">
+                      <Calendar size={16} className="mr-2 text-vista-gold" />
+                      <span>{item.days}天{item.days - 1}晚</span>
+                    </div>
+                    <div className="flex items-center text-sm text-vista-darkblue/80">
+                      <DollarSign size={16} className="mr-2 text-vista-gold" />
+                      <span className="text-vista-gold font-bold">{item.price}</span>
+                    </div>
+                  </div>
+                  
+                  <button className="w-full flex items-center justify-center gap-2 px-6 py-3 bg-vista-darkblue text-white font-bold tracking-widest uppercase text-xs hover:bg-vista-gold transition-all duration-300 shadow-md hover:shadow-lg">
+                    {t.home.details} <Info size={14} />
+                  </button>
+                </div>
+              </div>
+            ))}
+          </div>
+        </div>
+      </section>
+      
+      {/* 产品亮点 Section */}
+      <section className="py-24 bg-gray-50" id="itinerary-highlights">
+        <div className="max-w-7xl mx-auto px-6">
+          {/* Section Title */}
+          <div className="text-center mb-16">
+            <div className="inline-block relative mb-4">
+              <span className="text-vista-gold uppercase tracking-widest text-sm font-bold">{t.nav.menu[2].submenu?.[1].title}</span>
+              <div className="absolute -bottom-2 left-1/2 transform -translate-x-1/2 w-16 h-1 bg-vista-gold/30"></div>
+            </div>
+            <h2 className="text-4xl md:text-5xl font-serif text-vista-darkblue mt-3 mb-6">产品亮点</h2>
+            <p className="text-vista-darkblue/70 max-w-3xl mx-auto text-lg">
+              我们的游轮航线为您提供无与伦比的旅行体验,每一个细节都经过精心设计
+            </p>
+          </div>
+          
+          {/* Highlights Grid */}
+          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-10">
+            <div className="bg-white rounded-lg p-8 shadow-md hover:shadow-xl transition-all duration-300">
+              <div className="w-16 h-16 bg-vista-gold rounded-full flex items-center justify-center mb-6">
+                <MapPin size={32} className="text-white" />
+              </div>
+              <h3 className="text-2xl font-serif text-vista-darkblue mb-4">精选航线</h3>
+              <p className="text-vista-darkblue/70 leading-relaxed">
+                精心设计的航线,带您探索长江的自然美景和人文历史,每一处都值得细细品味
+              </p>
+            </div>
+            
+            <div className="bg-white rounded-lg p-8 shadow-md hover:shadow-xl transition-all duration-300">
+              <div className="w-16 h-16 bg-vista-gold rounded-full flex items-center justify-center mb-6">
+                <Calendar size={32} className="text-white" />
+              </div>
+              <h3 className="text-2xl font-serif text-vista-darkblue mb-4">灵活选择</h3>
+              <p className="text-vista-darkblue/70 leading-relaxed">
+                提供4天、5天、8天等多种行程选择,满足不同旅行者的需求和时间安排
+              </p>
+            </div>
+            
+            <div className="bg-white rounded-lg p-8 shadow-md hover:shadow-xl transition-all duration-300">
+              <div className="w-16 h-16 bg-vista-gold rounded-full flex items-center justify-center mb-6">
+                <DollarSign size={32} className="text-white" />
+              </div>
+              <h3 className="text-2xl font-serif text-vista-darkblue mb-4">性价比高</h3>
+              <p className="text-vista-darkblue/70 leading-relaxed">
+                价格包含住宿、餐饮、景点门票和导游服务,让您的旅行更加省心省力
+              </p>
+            </div>
+            
+            <div className="bg-white rounded-lg p-8 shadow-md hover:shadow-xl transition-all duration-300">
+              <div className="w-16 h-16 bg-vista-gold rounded-full flex items-center justify-center mb-6">
+                <ChevronRight size={32} className="text-white" />
+              </div>
+              <h3 className="text-2xl font-serif text-vista-darkblue mb-4">专业服务</h3>
+              <p className="text-vista-darkblue/70 leading-relaxed">
+                经验丰富的导游和船员团队,为您提供贴心周到的服务,确保旅途愉快
+              </p>
+            </div>
+            
+            <div className="bg-white rounded-lg p-8 shadow-md hover:shadow-xl transition-all duration-300">
+              <div className="w-16 h-16 bg-vista-gold rounded-full flex items-center justify-center mb-6">
+                <Info size={32} className="text-white" />
+              </div>
+              <h3 className="text-2xl font-serif text-vista-darkblue mb-4">深度体验</h3>
+              <p className="text-vista-darkblue/70 leading-relaxed">
+                不仅仅是观光,更是一次深度体验长江文化和当地风土人情的机会
+              </p>
+            </div>
+            
+            <div className="bg-white rounded-lg p-8 shadow-md hover:shadow-xl transition-all duration-300">
+              <div className="w-16 h-16 bg-vista-gold rounded-full flex items-center justify-center mb-6">
+                <ChevronDown size={32} className="text-white" />
+              </div>
+              <h3 className="text-2xl font-serif text-vista-darkblue mb-4">舒适体验</h3>
+              <p className="text-vista-darkblue/70 leading-relaxed">
+                豪华游轮设施齐全,为您提供舒适的住宿和餐饮体验,让您的旅途更加惬意
+              </p>
+            </div>
+          </div>
+        </div>
+      </section>
+      
+      {/* 游轮航期 Section */}
+      <section className="py-24 bg-white" id="itinerary-schedules">
+        <div className="max-w-7xl mx-auto px-6">
+          {/* Section Title */}
+          <div className="text-center mb-16">
+            <div className="inline-block relative mb-4">
+              <span className="text-vista-gold uppercase tracking-widest text-sm font-bold">{t.nav.menu[2].submenu?.[2].title}</span>
+              <div className="absolute -bottom-2 left-1/2 transform -translate-x-1/2 w-16 h-1 bg-vista-gold/30"></div>
+            </div>
+            <h2 className="text-4xl md:text-5xl font-serif text-vista-darkblue mt-3 mb-6">游轮航期</h2>
+            <p className="text-vista-darkblue/70 max-w-3xl mx-auto text-lg">
+              查看我们的游轮航期,选择最适合您的出行时间
+            </p>
+          </div>
+          
+          {/* Schedules Table */}
+          <div className="overflow-x-auto">
+            <table className="w-full border-collapse">
+              <thead>
+                <tr className="bg-vista-darkblue text-white">
+                  <th className="px-8 py-6 text-left text-sm font-bold uppercase tracking-wider">航线名称</th>
+                  <th className="px-8 py-6 text-left text-sm font-bold uppercase tracking-wider">天数</th>
+                  <th className="px-8 py-6 text-left text-sm font-bold uppercase tracking-wider">出发日期</th>
+                  <th className="px-8 py-6 text-left text-sm font-bold uppercase tracking-wider">价格</th>
+                  <th className="px-8 py-6 text-left text-sm font-bold uppercase tracking-wider">操作</th>
+                </tr>
+              </thead>
+              <tbody>
+                {itineraries.map((item, index) => (
+                  <tr key={item.id} className={`${index % 2 === 0 ? 'bg-gray-50' : 'bg-white'} border-b border-gray-100 hover:bg-vista-gold/5 transition-colors`}>
+                    <td className="px-8 py-6">
+                      <div className="font-serif text-vista-darkblue font-medium">{item.title}</div>
+                      <div className="text-xs text-vista-darkblue/50 mt-1">{item.route}</div>
+                    </td>
+                    <td className="px-8 py-6 text-vista-darkblue">{item.days} {t.home.days}</td>
+                    <td className="px-8 py-6 text-vista-darkblue">
+                      <div className="space-y-1">
+                        {['2025-12-25', '2025-12-30', '2026-01-05'].map((date, idx) => (
+                          <div key={idx} className="text-sm">{date}</div>
+                        ))}
+                      </div>
+                    </td>
+                    <td className="px-8 py-6">
+                      <span className="text-vista-gold font-bold">{item.price}</span>
+                    </td>
+                    <td className="px-8 py-6">
+                      <button 
+                        className="px-4 py-2 bg-vista-gold text-white font-bold tracking-widest uppercase text-xs rounded-full hover:bg-vista-darkblue transition-all duration-300"
+                        onClick={() => setSelectedItinerary(item)}
+                      >
+                        {t.home.details}
+                      </button>
+                    </td>
+                  </tr>
+                ))}
+              </tbody>
+            </table>
+          </div>
+        </div>
+      </section>
+
+      {/* Itinerary Details Modal */}
+      {selectedItinerary && (
+        <div className="fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4 overflow-y-auto">
+          <div className="bg-white rounded-lg max-w-4xl w-full max-h-[90vh] overflow-y-auto transform transition-all duration-500 ease-out scale-100 opacity-100">
+            <div className="relative h-80 overflow-hidden">
+              <img 
+                src={selectedItinerary.image} 
+                alt={selectedItinerary.title} 
+                className="w-full h-full object-cover transition-transform duration-500 hover:scale-105"
+              />
+              <button 
+                className="absolute top-4 right-4 bg-white/90 backdrop-blur-sm rounded-full p-3 hover:bg-white transition-all duration-300 shadow-lg hover:shadow-xl"
+                onClick={() => setSelectedItinerary(null)}
+              >
+                <X size={24} className="text-vista-darkblue" />
+              </button>
+              <div className="absolute top-4 left-4 bg-white/95 backdrop-blur-sm px-4 py-2 rounded-full text-xs font-bold tracking-widest uppercase z-10 text-vista-darkblue shadow-sm">
+                {selectedItinerary.days} {t.home.days}
+              </div>
+            </div>
+            
+            <div className="p-8">
+              <div className="flex flex-col md:flex-row md:items-center justify-between mb-8">
+                <div>
+                  <h2 className="text-3xl md:text-4xl font-serif text-vista-darkblue mb-2 leading-tight">{selectedItinerary.title}</h2>
+                  <div className="flex items-center text-xs text-vista-darkblue/50 uppercase tracking-widest">
+                    <MapPin size={14} className="mr-1" />
+                    {selectedItinerary.route}
+                  </div>
+                </div>
+                <div className="mt-4 md:mt-0 flex items-center gap-8">
+                  <div className="flex items-center gap-2">
+                    <Calendar size={20} className="text-vista-gold" />
+                    <span className="text-vista-darkblue font-bold">{selectedItinerary.days}天{selectedItinerary.days - 1}晚</span>
+                  </div>
+                  <div className="flex items-center gap-2">
+                    <DollarSign size={20} className="text-vista-gold" />
+                    <span className="text-vista-gold font-serif italic text-2xl">{selectedItinerary.price}</span>
+                  </div>
+                </div>
+              </div>
+              
+              <div className="space-y-10">
+                <div>
+                  <h3 className="text-xl font-serif text-vista-darkblue mb-5 uppercase tracking-wider">{t.features[2].title}</h3>
+                  <p className="text-vista-darkblue/80 leading-relaxed text-lg">
+                    {selectedItinerary.description}
+                  </p>
+                </div>
+                
+                <div>
+                  <h3 className="text-xl font-serif text-vista-darkblue mb-5 uppercase tracking-wider">行程亮点</h3>
+                  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+                    {selectedItinerary.highlights.map((highlight: string, index: number) => (
+                      <div key={index} className="flex items-start gap-3 p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors">
+                        <div className="w-3 h-3 bg-vista-gold rounded-full mt-2 flex-shrink-0"></div>
+                        <span className="text-vista-darkblue/80 leading-relaxed">{highlight}</span>
+                      </div>
+                    ))}
+                  </div>
+                </div>
+                
+                <div>
+                  <h3 className="text-xl font-serif text-vista-darkblue mb-5 uppercase tracking-wider">每日行程</h3>
+                  <div className="relative space-y-12">
+                    {/* Timeline line */}
+                    <div className="absolute left-1/2 transform -translate-x-1/2 w-1 bg-vista-gold/20 h-full"></div>
+                    
+                    {selectedItinerary.itinerary.map((day: any, index: number) => (
+                      <div key={index} className={`relative flex ${index % 2 === 0 ? 'md:flex-row' : 'md:flex-row-reverse'} items-center gap-8`}>
+                        {/* Timeline dot */}
+                        <div className="absolute left-1/2 transform -translate-x-1/2 w-6 h-6 rounded-full bg-vista-gold border-4 border-white shadow-lg z-10 flex items-center justify-center">
+                          <span className="text-white text-xs font-bold">{day.day}</span>
+                        </div>
+                        
+                        {/* Content card */}
+                        <div className="w-full md:w-5/12 bg-white border border-gray-100 rounded-lg p-6 shadow-md hover:shadow-xl transition-all duration-300">
+                          <div className="flex items-center justify-between mb-3">
+                            <h4 className="text-lg font-bold text-vista-darkblue">{day.title}</h4>
+                            <span className="text-xs font-bold text-vista-gold uppercase tracking-wider">第 {day.day} 天</span>
+                          </div>
+                          <p className="text-vista-darkblue/80 leading-relaxed">{day.description}</p>
+                        </div>
+                        
+                        {/* Empty space for alternating layout */}
+                        <div className="hidden md:block w-5/12"></div>
+                      </div>
+                    ))}
+                  </div>
+                </div>
+              </div>
+              
+              <div className="mt-12 flex justify-center">
+                <button className="px-12 py-5 bg-vista-gold text-white font-bold tracking-widest uppercase text-sm hover:bg-vista-darkblue transition-all duration-300 shadow-lg hover:shadow-xl transform hover:-translate-y-1">
+                  {t.nav.book}
+                </button>
+              </div>
+            </div>
+          </div>
+        </div>
+      )}
+
+      <Footer />
+    </div>
+  );
+};
+
+export default Itineraries;

+ 9 - 0
src/types.ts

@@ -17,6 +17,12 @@ export interface CruiseShip {
   image: string;
 }
 
+export interface DailyItinerary {
+  day: number;
+  title: string;
+  description: string;
+}
+
 export interface Itinerary {
   id: string;
   title: string;
@@ -25,6 +31,9 @@ export interface Itinerary {
   image: string;
   video?: string; // Added video support
   route: string;
+  description: string;
+  highlights: string[];
+  itinerary: DailyItinerary[];
 }
 
 export interface Feature {

+ 0 - 56
types.ts

@@ -1,56 +0,0 @@
-
-export interface SubMenuItem {
-  title: string;
-  link: string;
-}
-
-export interface MenuItem {
-  title: string;
-  link: string;
-  submenu?: SubMenuItem[];
-}
-
-export interface CruiseShip {
-  id: string;
-  name: string;
-  description: string;
-  image: string;
-}
-
-export interface Itinerary {
-  id: string;
-  title: string;
-  days: number;
-  price: string;
-  image: string;
-  video?: string; // Added video support
-  route: string;
-}
-
-export interface Feature {
-  title: string;
-  description: string;
-  icon: string;
-}
-
-export interface DiningSection {
-  title: string;
-  description: string;
-  buttonText: string;
-  image: string;
-}
-
-export interface VideoSectionContent {
-  title: string;
-  titleItalic: string;
-  description: string;
-  thumbnail: string;
-}
-
-// New Interface for Ships Page Images
-export interface ShipsPageImages {
-  lanyue: string[]; // Expecting 4 images
-  aurora: string;
-}
-
-export type Language = 'zh' | 'en';