<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>
|