From 500078714411487af00161e01bd7e0b5efdc3414 Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期四, 07 八月 2025 13:32:32 +0800
Subject: [PATCH] add:热门景点

---
 sub-pages/hot-city/hot-city-detail.vue |  375 +++++++++++++++++++++++
 pages/home/home.vue                    |  156 +++++++++
 static/common/item-films.png           |    0 
 static/common/item-route.png           |    0 
 pages.json                             |   19 +
 sub-pages/hot-city/index.vue           |  381 +++++++++++++++++++++++
 static/common/item-map.png             |    0 
 7 files changed, 928 insertions(+), 3 deletions(-)

diff --git a/pages.json b/pages.json
index cd1324f..04c7637 100644
--- a/pages.json
+++ b/pages.json
@@ -86,6 +86,25 @@
 					}
 				}
 			]
+		},
+		{
+			"root": "sub-pages/hot-city",
+			"pages": [
+				{
+					"path": "index",
+					"style": {
+						"navigationBarTitleText": "城市",
+						"enablePullDownRefresh": true
+					}
+				}
+				,{
+					"path": "hot-city-detail",
+					"style": {
+						"navigationBarTitleText": "城市详情",
+						"enablePullDownRefresh": true
+					}
+				}
+			]
 		}
 		,{
 			"root": "sub-pages/mine",
diff --git a/pages/home/home.vue b/pages/home/home.vue
index 80ed122..353f27b 100644
--- a/pages/home/home.vue
+++ b/pages/home/home.vue
@@ -23,7 +23,7 @@
       </view>
 
       <view class="trip-card-swiper">
-        <swiper :current="currentPage" @change="onSwiperChange" circular style="min-height: 1850rpx;">
+        <swiper :current="currentPage" @change="onSwiperChange" circular style="min-height: 1650rpx;">
           <swiper-item v-for="(group, pageIndex) in pagedTripCards" :key="pageIndex">
             <TripCard v-for="(item, index) in group" :key="index" :tag="item.tag" :title="item.coverTitle"
               :subtitle="item.coverAlt" :score="item.collectCount" :imageUrl="item.coverUrl"
@@ -32,8 +32,34 @@
         </swiper>
       </view>
 
-<!--      <SectionTitle title="全球影视地标" optitle="查看全部" goUrl="/pages/home/home-more" />-->
+      <SectionTitle title="全球影视地标" optitle="查看全部" goUrl="/pages/home/home-more" />
 <!--      <GlobalGeo />-->
+      <view class="continent-section">
+        <view class="continent-item all" @click="navigateToAll">全部</view>
+        <view class="continents-container">
+          <view class="continent-row" v-for="(row, index) in continentRows" :key="index">
+            <view
+                class="continent-item continent"
+                v-for="(continent, colIndex) in row"
+                :key="colIndex"
+                @click="navigateToDetail(continent)"
+            >
+              {{ continent.name }}
+            </view>
+            <!-- 添加占位元素保持布局 -->
+            <view
+                v-for="n in (3 - row.length)"
+                :key="'placeholder'+n"
+                class="continent-placeholder"
+            ></view>
+          </view>
+        </view>
+        <view class="continent-item separator"></view>
+        <view class="continent-item nearby" @click="navigateToNearby">
+          <view>附</view>
+          <view>近</view>
+        </view>
+      </view>
 
       <SectionTitle title="场景博物馆" optitle="查看全部" goUrl="/sub-pages/hot-spot/index" />
       <SceneMuseumCard v-for="(item, index) in cardList" :key="index" :image="item.image" :title="item.title"
@@ -57,7 +83,6 @@
 
 import HomeMain from './home-main.vue'
 import TripCard from './trip-card.vue'
-import GlobalGeo from './global-geo.vue'
 import SceneMuseumCard from './scene-museum-card.vue'
 import Community from './community.vue'
 import { SwiperChangeEvent } from '@dcloudio/uni-app'
@@ -70,6 +95,54 @@
 
 // 主题
 const theme = ref('light')
+
+const continents = ref([])
+
+const getContinents = async () => {
+  try {
+    const {code, data} = await $http.request('get', '/api/code/value?type=CONTINENT_TYPE')
+    if (code == 0 && data) {
+      continents.value = data.map(item => (
+          {
+            id: item.id,
+            name: item.label
+          })
+      )
+    }
+
+  } catch (error) {
+    console.log('获取洲数据失败', error)
+    $message.showToast('获取洲数据失败')
+  }
+
+}
+
+const continentRows = computed(() => {
+  const rows = [];
+  const continentsList = [...continents.value];
+
+  // 将洲分成三行
+  for (let i = 0; i < 3; i++) {
+    const start = i * 3;
+    const end = start + 3;
+    rows.push(continentsList.slice(start, end));
+  }
+
+  return rows;
+});
+
+const navigateToDetail = (continent) => {
+  //跳转到具体页面
+  uni.navigateTo({
+    url: `/sub-pages/hot-city/index?continentId=${continent.id}`
+  })
+}
+const navigateToNearby = () => {
+  //附近功能跳转
+  uni.navigateTo({
+    url: '/pages/nearby/nearby'
+  })
+}
 
 
 // 当前页数
@@ -115,6 +188,7 @@
 onMounted(() => {
   const localTheme = uni.getStorageSync('theme') || 'light'
   theme.value = localTheme
+  getContinents()
 })
 
 onShow(() => {
@@ -255,6 +329,82 @@
   margin-top: 20rpx;
   margin-bottom: 20rpx;
 }
+
+.continent-section {
+  display: flex;
+  align-items: stretch;
+  border-top: 1px dashed #ccc;
+  border-bottom: 1px dashed #ccc;
+  padding: 10rpx 0;
+  height: 220rpx; /* 固定高度容纳三行 */
+}
+
+.all, .nearby {
+  flex-shrink: 0;
+  width: 15%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  font-size: 30rpx;
+  font-weight: bold;
+}
+
+.continents-container {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+
+.continent-row {
+  display: flex;
+  justify-content: flex-start; /* 改为左对齐 */
+  height: 33.33%; /* 每行高度占三分之一 */
+  padding: 5rpx 0;
+}
+
+.continent {
+  flex: 0 0 30%; /* 固定宽度30% */
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  text-align: center;
+  font-size: 28rpx;
+  padding: 5rpx 0;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-right: 5%; /* 元素间间距 */
+}
+
+/* 最后一个元素不需要右边距 */
+.continent:last-child {
+  margin-right: 0;
+}
+
+.continent-placeholder {
+  flex: 0 0 30%; /* 占位元素宽度 */
+  margin-right: 5%; /* 保持与正常元素相同的间距 */
+}
+
+/* 最后一个占位元素不需要右边距 */
+.continent-placeholder:last-child {
+  margin-right: 0;
+}
+
+.separator {
+  width: 1px;
+  background-color: #ccc;
+  margin: 0 10rpx;
+  align-self: center;
+  height: 80%; /* 分隔线高度为父容器的80% */
+}
+
+.nearby {
+  flex-direction: column;
+  font-size: 30rpx;
+}
 </style>
 
 <style scoped lang="scss">
diff --git a/static/common/item-films.png b/static/common/item-films.png
new file mode 100644
index 0000000..53a3b37
--- /dev/null
+++ b/static/common/item-films.png
Binary files differ
diff --git a/static/common/item-map.png b/static/common/item-map.png
new file mode 100644
index 0000000..57e7456
--- /dev/null
+++ b/static/common/item-map.png
Binary files differ
diff --git a/static/common/item-route.png b/static/common/item-route.png
new file mode 100644
index 0000000..f4cf09f
--- /dev/null
+++ b/static/common/item-route.png
Binary files differ
diff --git a/sub-pages/hot-city/hot-city-detail.vue b/sub-pages/hot-city/hot-city-detail.vue
new file mode 100644
index 0000000..9cc73e4
--- /dev/null
+++ b/sub-pages/hot-city/hot-city-detail.vue
@@ -0,0 +1,375 @@
+<template>
+  <view class="container">
+    <view class="header-info">
+      <image src="/static/common/earth.png" class="earth-icon"></image>
+      <view class="city-info">
+        <text class="city-name">{{cityInfo.cityName}}</text>
+        <text class="city-pinyin">{{cityInfo.cityPinyin}}</text>
+        <text class="city-continent">{{cityInfo.cityCountry}} {{cityInfo.cityContinent}}</text>
+      </view>
+    </view>
+
+    <view class="main-image">
+      <image :src="cityInfo.mainImage" mode="aspectFit" class="main-img" />
+    </view>
+
+    <view class="main-text">
+      <text class="info-title1">{{cityInfo.infoTitle1}}</text>
+      <text class="info-title2">
+        {{cityInfo.infoTitle2}}
+      </text>
+    </view>
+
+    <!-- 添加三个可点击块 -->
+    <view class="tab-container">
+      <view class="tab-item" @click="activeTab = 'films'">
+        <image src="/static/common/item-films.png" class="tab-icon"></image>
+        <text class="tab-text">影片</text>
+      </view>
+      <view class="tab-item" @click="activeTab = 'map'">
+        <image src="/static/common/item-map.png" class="tab-icon"></image>
+        <text class="tab-text">地图</text>
+      </view>
+      <view class="tab-item" @click="activeTab = 'route'">
+        <image src="/static/common/item-route.png" class="tab-icon"></image>
+        <text class="tab-text">路线</text>
+      </view>
+    </view>
+
+    <!-- 根据 activeTab 展示不同内容 -->
+    <view v-if="activeTab === 'films'" class="content-container">
+      <text class="content-title">影片列表</text>
+      <!-- 影片列表内容 -->
+      <view v-for="(film, index) in films" :key="index" class="film-item"  @click="goToFilmDetail(film.id)">
+        <image :src="film.coverUrl" class="film-poster"></image>
+        <text class="film-name">{{ film.nameCn }}</text>
+      </view>
+    </view>
+
+    <view v-if="activeTab === 'map'" class="content-container">
+      <text class="content-title">景点列表和地图</text>
+      <!-- 地图内容 -->
+      <map
+          class="map-content"
+          :latitude="mapCenter.latitude"
+          :longitude="mapCenter.longitude"
+          :scale="mapCenter.scale"
+          :markers="mapMarkers"
+      ></map>
+      <view v-for="(spot, index) in spots" :key="index" class="spot-item"  @click="goToSpotDetail(spot.id)">
+        <text class="spot-name">{{ spot.locationName }}</text>
+        <text class="spot-desc">{{ spot.landmarkDesc }}</text>
+      </view>
+    </view>
+
+    <view v-if="activeTab === 'route'" class="content-container">
+      <text class="content-title">路线</text>
+      <!-- 路线内容(暂时为空) -->
+      <text>暂无内容</text>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue';
+import { onLoad } from '@dcloudio/uni-app'
+import { useGlobal } from '@/composables/useGlobal'
+const { $http, $message } = useGlobal()
+import {FilmWorks,FilmLocationVO} from "@/types/index";
+
+// 定义 activeTab 并设置默认值为 'films'
+const activeTab = ref('films');
+
+const films = ref<FilmWorks[]>();
+const cityInfo = ref({
+  cityName: '北京',
+  cityPinyin: 'Beijing',
+  cityCountry: '中国',
+  cityContinent: 'Asia',
+  mainImage: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg',
+  infoTitle1: '',
+  infoTitle2: '',
+})
+
+
+onLoad(async (options: any) => {
+  const name = options.name
+  const pinyin = options.pinyin
+  const country = options.country
+  const continent = options.continent
+
+  // 修复后的代码 - 确保所有必需的属性都被设置
+  cityInfo.value = {
+    cityName: name || '北京',  // 提供默认值
+    cityPinyin: pinyin || '',
+    cityCountry: country || '中国',
+    cityContinent: continent || 'Asia',
+    mainImage: 'https://ai-public.mastergo.com/ai/img_res/6a226f9e9652c51cd535c3490535dfeb.jpg',
+    infoTitle1: '',
+    infoTitle2: ''
+  }
+
+  if (name) {
+    await getRelatedFilms(name)
+    await getLocations(name)
+  }
+})
+
+const getRelatedFilms = async (name: string) => {
+  const { code, data } = await $http.request('get', '/api/filmLocation/city', {
+    params: { name }
+  })
+  if (code === 0 && Array.isArray(data)) {
+    films.value = data
+  } else {
+    films.value = []
+  }
+}
+
+const getLocations = async (name: string) => {
+  const { code, data } = await $http.request('get', '/api/filmLocation/location', {
+    params: { name }
+  })
+  if (code === 0 && Array.isArray(data)) {
+    spots.value = data
+
+    if (data.length > 0) {
+
+      // 使用第一个景点的数据更新cityInfo
+      const firstSpot = data[0];
+
+      // 更新主图,如果没有locationUrl则使用默认图
+      cityInfo.value.mainImage = firstSpot.locationUrl || cityInfo.value.mainImage;
+
+      // 更新infoTitle1,使用locationName
+      if (firstSpot.locationName) {
+        cityInfo.value.infoTitle1 = firstSpot.locationName;
+      }
+
+      // 更新infoTitle2,组合address、sceneType、classicScene和landmarkDesc
+      let infoTitle2Content = '';
+      if (firstSpot.address) {
+        infoTitle2Content += firstSpot.address;
+      }
+      if (firstSpot.sceneType) {
+        infoTitle2Content += (infoTitle2Content ? ' ' : '') + firstSpot.sceneType;
+      }
+      if (firstSpot.classicScene) {
+        infoTitle2Content += (infoTitle2Content ? ' ' : '') + firstSpot.classicScene;
+      }
+      if (firstSpot.landmarkDesc) {
+        infoTitle2Content += (infoTitle2Content ? ' ' : '') + firstSpot.landmarkDesc;
+      }
+
+      if (infoTitle2Content) {
+        cityInfo.value.infoTitle2 = infoTitle2Content;
+      }
+      // 设置中心点为第一个景点的位置
+      mapCenter.value.latitude = data[0].gpsLat || 39.9042
+      mapCenter.value.longitude = data[0].gpsLng || 116.4074
+      mapCenter.value.scale = 12
+
+      // 创建标记点数组
+      mapMarkers.value = data.map((spot, index) => ({
+        id: index,
+        latitude: spot.gpsLat,
+        longitude: spot.gpsLng,
+        title: spot.locationName,
+        iconPath: '/static/common/marker.png', // 可以替换为实际的标记图标路径
+        width: 30,
+        height: 30
+      })).filter(marker => marker.latitude && marker.longitude) // 过滤掉没有坐标的标记
+    }
+  } else {
+    spots.value = []
+  }
+}
+
+const spots = ref<FilmLocationVO[]>();
+
+// 添加地图中心点和标记数据
+const mapCenter = ref({
+  latitude: 39.9042,
+  longitude: 116.4074,
+  scale: 10
+});
+
+const mapMarkers = ref([]);
+
+
+// 跳转到影片详情页
+const goToFilmDetail = (id: number) => {
+  uni.navigateTo({
+    url: `/sub-pages/film-list/film-detail?id=${id}`
+  });
+};
+
+// 跳转到景点详情页
+const goToSpotDetail = (id: number) => {
+  uni.navigateTo({
+    url: `/sub-pages/hot-spot/spot-detail?id=${id}`
+  });
+};
+</script>
+
+<style scoped>
+.container {
+  padding: 20rpx;
+}
+
+.header-info {
+  display: flex;
+  align-items: center;
+  margin-bottom: 30rpx;
+  padding: 20rpx;
+  background-color: #f8f8f8;
+  border-radius: 16rpx;
+}
+
+.earth-icon{
+  width: 180rpx;
+  height: 180rpx;
+  margin-right: 30rpx;
+}
+
+.city-info {
+  display: flex;
+  flex-direction: column;
+}
+
+.city-name {
+  font-size: 40rpx;
+  font-weight: bold;
+  margin-bottom: 10rpx;
+}
+
+.city-pinyin {
+  font-size: 32rpx;
+  color: #666;
+  margin-bottom: 10rpx;
+}
+
+.city-continent {
+  font-size: 28rpx;
+  color: #999;
+}
+
+.main-image {
+  width: 100%;
+  height: 400rpx;
+  margin-bottom: 30rpx;
+  border-radius: 16rpx;
+  overflow: hidden;
+}
+
+.main-img {
+  width: 100%;
+  height: 100%;
+}
+
+.main-text {
+  padding: 20rpx;
+  margin-bottom: 30rpx;
+  background-color: #f8f8f8;
+  border-radius: 16rpx;
+}
+
+.info-title1 {
+  font-size: 32rpx;
+  font-weight: bold;
+  margin-bottom: 15rpx;
+  display: block;
+}
+
+.info-title2 {
+  font-size: 28rpx;
+  line-height: 1.6;
+  color: #333;
+}
+
+.tab-container {
+  display: flex;
+  justify-content: space-around;
+  padding: 20rpx 0;
+  margin-bottom: 30rpx;
+  border-top: 1rpx solid #eee;
+  border-bottom: 1rpx solid #eee;
+}
+
+.tab-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 20rpx;
+}
+
+.tab-icon {
+  width: 60rpx;
+  height: 60rpx;
+  margin-bottom: 10rpx;
+}
+
+.tab-text {
+  font-size: 28rpx;
+}
+
+.content-container {
+  padding: 20rpx;
+  background-color: #f8f8f8;
+  border-radius: 16rpx;
+  margin-bottom: 20rpx;
+}
+
+.content-title {
+  font-size: 36rpx;
+  font-weight: bold;
+  margin-bottom: 30rpx;
+  display: block;
+}
+
+.film-item {
+  display: flex;
+  align-items: center;
+  margin-bottom: 30rpx;
+  padding: 20rpx;
+  background-color: #fff;
+  border-radius: 12rpx;
+}
+
+.film-poster {
+  width: 120rpx;
+  height: 160rpx;
+  margin-right: 20rpx;
+  border-radius: 8rpx;
+}
+
+.film-name {
+  font-size: 32rpx;
+}
+
+.map-content {
+  width: 100%;
+  height: 400rpx;
+  margin-bottom: 30rpx;
+  border-radius: 16rpx;
+}
+
+.spot-item {
+  margin-bottom: 30rpx;
+  padding: 20rpx;
+  background-color: #fff;
+  border-radius: 12rpx;
+}
+
+.spot-name {
+  font-size: 32rpx;
+  font-weight: bold;
+  margin-bottom: 10rpx;
+  display: block;
+}
+
+.spot-desc {
+  font-size: 28rpx;
+  color: #666;
+}
+</style>
diff --git a/sub-pages/hot-city/index.vue b/sub-pages/hot-city/index.vue
new file mode 100644
index 0000000..3de6160
--- /dev/null
+++ b/sub-pages/hot-city/index.vue
@@ -0,0 +1,381 @@
+<template>
+  <view :class="['app', theme]">
+    <!-- 搜索框部分 -->
+    <view style="padding-top: 10rpx;">
+      <up-search
+          height="70rpx"
+          placeholder="搜索城市"
+          search-icon-size="40rpx"
+          margin="0rpx 30rpx"
+          v-model="search"
+          :show-action="true"
+          @search="onSearch"
+          @custom="onSearch"
+          @click-icon="onSearch"
+      />
+    </view>
+
+    <!-- 标签切换部分 -->
+    <up-tabs :list="tabList" @click="click">
+      <template #right>
+        <view style="padding-left: 4px;" @tap="() => showToast('插槽被点击')">
+          <up-icon name="list" size="40rpx" bold></up-icon>
+        </view>
+      </template>
+    </up-tabs>
+
+    <!-- 城市列表 -->
+    <view class="city-items">
+      <!-- 搜索状态下的列表 -->
+      <template v-if="search">
+        <view
+            class="city-item"
+            v-for="city in displayedCities"
+            :key="city.id"
+            @click="handleCityClick(city)"
+        >
+          {{ city.name }}
+        </view>
+      </template>
+
+      <!-- 非搜索状态下的列表 -->
+      <template v-else>
+        <!-- 热门城市部分 -->
+        <view class="section" v-if="filteredHotCities.length">
+          <view class="section-title">热门城市</view>
+          <view class="hot-city-list">
+            <view
+                class="hot-city-item"
+                v-for="city in filteredHotCities"
+                :key="'hot-'+city.id"
+                @click="handleCityClick(city)"
+            >
+              {{ city.name }}
+            </view>
+          </view>
+        </view>
+
+        <!-- A-Z城市列表 -->
+        <view class="section" v-for="group in groupedCities" :key="group.letter">
+          <view class="section-title">{{ group.letter }}</view>
+          <view
+              class="city-detail-item"
+              v-for="city in group.cities"
+              :key="'az-'+city.id"
+              @click="handleCityClick(city)"
+          >
+            <view class="city-name">{{ city.name }}</view>
+            <view class="city-sub-info">
+              <text class="city-pinyin">{{ city.pinyin }}</text>
+              <text class="city-country"> · {{ city.country }}</text>
+            </view>
+          </view>
+        </view>
+      </template>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed, onMounted, watch } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import { useGlobal } from '@/composables/useGlobal'
+const { $http, $message, $store } = useGlobal()
+
+const theme = ref('light')
+const search = ref('')
+
+// 响应式数据
+const tabList = ref([])
+
+const currentTab = ref('Asia')
+
+// 更新热门城市数据结构,添加国家字段
+// const hotCities = ref([
+//   { id: 1, name: '北京市', pinyin: 'Beijing', country: '中国', continent: 'asia' },
+//   { id: 2, name: '上海市', pinyin: 'Shanghai', country: '中国', continent: 'asia' },
+//   { id: 3, name: '纽约', pinyin: 'New York', country: '美国', continent: 'northAmerica' },
+//   { id: 4, name: '伦敦', pinyin: 'London', country: '英国', continent: 'europe' },
+// ])
+const hotCities = ref([])
+
+// 更新所有城市数据结构,添加国家字段
+const allCities = ref([])
+
+// 当前洲的热门城市
+const filteredHotCities = computed(() => {
+  if (currentTab.value === 'all') {
+    return hotCities.value;
+  }
+  return hotCities.value.filter(city => city.continent === currentTab.value);
+});
+
+// 当前洲的所有城市(按拼音分组)
+const groupedCities = computed(() => {
+  // 获取当前洲的城市列表
+  let cities = [];
+  if (currentTab.value === 'all') {
+    cities = [...allCities.value];
+  } else {
+    cities = allCities.value.filter(city => city.continent === currentTab.value);
+  }
+
+  // 按拼音首字母分组
+  const groups: Record<string, any[]> = {};
+  cities.forEach(city => {
+    const firstLetter = city.pinyin.charAt(0).toUpperCase();
+    if (!groups[firstLetter]) {
+      groups[firstLetter] = [];
+    }
+    groups[firstLetter].push(city);
+  });
+
+  // 转换为数组并按字母排序
+  return Object.keys(groups)
+      .sort()
+      .map(letter => ({
+        letter,
+        cities: groups[letter].sort((a, b) =>
+            a.pinyin.localeCompare(b.pinyin))
+      }));
+});
+
+// 根据当前标签显示对应的城市(用于搜索状态)
+const displayedCities = computed(() => {
+  let cities = [];
+  if (currentTab.value === 'all') {
+    cities = [...hotCities.value, ...allCities.value];
+  } else {
+    cities = allCities.value.filter(city => city.continent === currentTab.value);
+  }
+
+  // 添加搜索过滤功能
+  if (search.value) {
+    return cities.filter(city =>
+        city.name?.includes(search.value) ||
+        city.pinyin?.toLowerCase().includes(search.value.toLowerCase())
+    )
+  }
+  return cities
+})
+
+// 标签点击事件
+// const click = (item: { name: string; value: string }) => {
+//   currentTab.value = item.value
+//   console.log('currentTab:', currentTab.value)
+// }
+const click = async (item: { name: string; value: string }) => {
+  currentTab.value = item.value;
+  console.log('currentTab:', currentTab.value);
+
+  // 显示加载状态
+  uni.showLoading({ title: '加载中...' });
+
+  try {
+    await getHotCities();
+    await getAllCities();
+  } finally {
+    uni.hideLoading();
+  }
+};
+
+// 搜索事件
+const onSearch = (value: string) => {
+  const searchValue = typeof value === 'string' ? value : search.value
+  search.value = searchValue
+}
+
+const handleCityClick = (city: any) => {
+  console.log('City clicked:', city)
+  // 实际应用中这里可以添加选择城市后的逻辑
+  uni.navigateTo({
+    url: `/sub-pages/hot-city/hot-city-detail?name=${city.name}`
+  })
+}
+
+const showToast = (msg: string) => {
+  uni.showToast({ title: msg, icon: 'none' })
+}
+
+onLoad(async(options) => {
+  const storedTheme = uni.getStorageSync('theme') || 'light'
+  theme.value = storedTheme
+
+  console.log("options", options)
+
+  if (options && options.continentId) {
+    // 等待获取 tab 列表完成
+    await getTabList()
+
+    const continentId = options.continentId.toString()
+    console.log('continentId:', continentId);
+    console.log("tabList.value", tabList.value)
+
+    const tab = tabList.value.find(t => {
+      console.log(`Comparing "${t.id}" with "${continentId}"`);
+      return t.id.toString() === continentId.toString();
+    });
+    console.log("tab", tab)
+    if (tab) {
+      console.log('  currentTab.value ',   currentTab.value )
+      currentTab.value = tab.value
+      console.log('  currentTab.value ',   currentTab.value )
+      console.log('Tab found and set:', tab)
+      // 关键:在设置完 currentTab 后,立即获取对应的数据
+      await getHotCities();
+      await getAllCities();
+    } else {
+      console.log('Tab not found for continentId:', options.continentId)
+      console.log('Available tabs:', tabList.value)
+    }
+  } else {
+    // 如果没有传参,正常获取 tab 列表和数据
+    await getTabList()
+    await getHotCities();
+    await getAllCities();
+  }
+})
+
+
+// onMounted(() => {
+//   // 初始化数据
+//   // getTabList();
+//   getHotCities();
+//   getAllCities();
+// })
+
+// 监听currentTab变化,重新获取数据
+// 确保 watch 能够深度监听并正确处理异步操作
+watch(currentTab, async (newVal, oldVal) => {
+  console.log('Tab changed from', oldVal, 'to', newVal);
+  await getHotCities();
+  await getAllCities();
+}, { flush: 'post' });
+
+const getAllCities = async () => {
+  // 获取所有城市
+  try{
+    const { code, data } = await $http.request('get', '/api/filmLocation/info',{
+      params: {
+        continent: currentTab.value,
+      }
+    })
+    if (code === 0 && data) {
+      allCities.value = data.map(item => ({
+        id: item.id,
+        name: item.city,
+        pinyin: item.pinyin,
+        country: item.country,
+        continent: item.continent
+      }))
+    }
+  }catch (e) {
+    console.log("获取热门城市失败", e)
+    $message.showToast("获取热门城市失败")
+  }
+}
+
+ const getHotCities = async () => {
+  //获取热门城市
+   try{
+     const { code, data } = await $http.request('get', '/api/filmHotCity/list',{
+       params: {
+         size: 10,
+         continent: currentTab.value=='all'?'':currentTab.value,
+         current: 1
+       }
+     })
+     if (code === 0 && data) {
+       hotCities.value = data.records.map(item => ({
+         id: item.id,
+         name: item.name,
+         country: item.country,
+         continent: item.continent
+       }))
+     }
+   }catch (e) {
+     console.log("获取热门城市失败", e)
+     $message.showToast("获取热门城市失败")
+   }
+}
+
+const getTabList = async () => {
+  // 获取洲列表
+  try {
+    const {code, data} = await $http.request('get', '/api/code/value?type=CONTINENT_TYPE')
+    if (code == 0 && data) {
+      tabList.value = data.map((item: any) => ({
+        id: item.id,
+        name: item.label,
+        value: item.value // 确保这里返回洲的标识符
+      }))
+    }
+  } catch (e) {
+    console.log("获取洲数据失败", e)
+    $message.showToast("获取洲数据失败")
+  }
+}
+</script>
+
+<style scoped>
+.city-items {
+  padding: 0 30rpx;
+}
+
+.section {
+  margin-bottom: 30rpx;
+}
+
+.section-title {
+  font-size: 28rpx;
+  color: #666;
+  padding: 20rpx 0;
+  border-bottom: 1rpx solid #eee;
+  margin-bottom: 15rpx;
+}
+
+.hot-city-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20rpx;
+}
+
+.hot-city-item {
+  background-color: #f5f5f5;
+  padding: 15rpx 25rpx;
+  border-radius: 10rpx;
+  font-size: 28rpx;
+}
+
+.city-detail-item {
+  padding: 25rpx 0;
+  border-bottom: 1rpx solid #f5f5f5;
+}
+
+.city-name {
+  font-size: 32rpx;
+  font-weight: 500;
+  margin-bottom: 8rpx;
+}
+
+.city-sub-info {
+  display: flex;
+  font-size: 26rpx;
+  color: #888;
+}
+
+.city-pinyin {
+  font-style: italic;
+}
+
+.city-country {
+  margin-left: 5rpx;
+}
+
+/* 搜索状态下的简单列表样式 */
+.city-item {
+  padding: 25rpx 0;
+  border-bottom: 1rpx solid #f5f5f5;
+  font-size: 32rpx;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3