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