Commit 3d160d03 authored by caoxu's avatar caoxu

Fix: 重新创建CityIntroductionView.vue文件

parent b46f7cdd
<template>
<div class="city-introduction">
<div class="header">
<button class="back-button" @click="goBack"></button>
<h1 class="page-title">墨鱼旅行城市介绍</h1>
</div>
<div class="main-content">
<div class="city-banner">
<img src="https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?w=1200&h=300&fit=crop" alt="城市风景" class="header-image" />
<div class="header-overlay">
<h1 class="city-name">{{ cityName }}</h1>
</div>
</div>
<div class="city-info-section">
<h2 class="section-title">城市介绍</h2>
<div class="city-description">
<p>
欢迎来到这座充满魅力的城市!这里融合了古老的历史文化与现代都市的繁华,
每一个角落都散发着独特的魅力。漫步在古老的街道上,感受历史的沉淀;
探索现代化的建筑群,体验都市的活力。
</p>
</div>
<button class="more-btn" @click="showMoreInfo">更多</button>
</div>
<div class="attractions-section">
<h2 class="section-title">热门景点</h2>
<div class="attractions-grid">
<div v-for="attraction in attractions" :key="attraction.id" class="attraction-card">
<img :src="attraction.image" :alt="attraction.name" class="attraction-image" />
<div class="attraction-info">
<h3 class="attraction-name">{{ attraction.name }}</h3>
<p class="attraction-description">{{ attraction.description }}</p>
<div class="attraction-meta">
<span class="attraction-rating">{{ attraction.rating }}</span>
<span class="attraction-price">¥{{ attraction.price }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="nearby-users-section">
<h2 class="section-title">附近的用户</h2>
<div class="users-grid">
<div v-for="user in nearbyUsers" :key="user.id" class="user-card" @click="viewUserProfile(user)">
<div class="user-avatar-container">
<img :src="user.avatar" :alt="user.name" class="user-avatar" />
<span class="user-status-dot" :class="user.status"></span>
</div>
<div class="user-info">
<div class="user-header">
<h4 class="user-name">{{ user.name }}</h4>
<span class="user-level">{{ user.level }}</span>
</div>
<p class="user-location">{{ user.location }}</p>
<div class="user-stats">
<div class="stat-item">
<span class="stat-icon">👥</span>
<span class="stat-value">{{ user.followers }}</span>
</div>
<div class="stat-item">
<span class="stat-icon">❤️</span>
<span class="stat-value">{{ user.likes }}</span>
</div>
</div>
<div class="user-actions">
<button class="follow-btn" :class="{ following: user.isFollowing }" @click="followUser(user)">
{{ user.isFollowing ? '已关注' : '+ 关注' }}
</button>
<button class="message-btn" @click="sendMessage(user)">
💬
</button>
</div>
</div>
</div>
</div>
</div>
<div class="destination-dynamics-section">
<h2 class="section-title">当前目的地动态</h2>
<div class="dynamics-list">
<div v-for="dynamic in dynamics" :key="dynamic.id" class="dynamic-card">
<div class="dynamic-header">
<img :src="dynamic.userAvatar" :alt="dynamic.userName" class="dynamic-avatar" />
<div class="dynamic-user-info">
<h4 class="dynamic-user-name">{{ dynamic.userName }}</h4>
<span class="dynamic-time">{{ dynamic.time }}</span>
</div>
</div>
<p class="dynamic-content">{{ dynamic.content }}</p>
<div class="dynamic-actions">
<button class="action-btn like-btn">
<span>❤️</span>
<span>{{ dynamic.likes }}</span>
</button>
<button class="action-btn comment-btn">
<span>💬</span>
<span>{{ dynamic.comments }}</span>
</button>
</div>
</div>
</div>
</div>
<div class="food-section">
<h2 class="section-title">特色美食</h2>
<div class="food-grid">
<div v-for="food in foods" :key="food.id" class="food-card">
<img :src="food.image" :alt="food.name" class="food-image" />
<div class="food-info">
<h3 class="food-name">{{ food.name }}</h3>
<p class="food-description">{{ food.description }}</p>
<img :src="food.detailImage" :alt="food.name + '详情'" class="food-detail-image" />
<div class="food-meta">
<span class="food-type">{{ food.type }}</span>
<span class="food-price">¥{{ food.price }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const cityName = ref('洛杉矶')
const attractions = ref([
{
id: 1,
name: '古城博物馆',
description: '千年历史,文化瑰宝,探索古代文明的奥秘。',
image: 'https://images.unsplash.com/photo-1544531585-4e63c6e8a8b?w=400&h=300&fit=crop',
rating: 4.8,
price: 68
},
{
id: 2,
name: '中央公园',
description: '城市绿肺,休闲胜地,享受自然与城市的完美融合。',
image: 'https://images.unsplash.com/photo-1569339967-4e6c6e8a8b?w=400&h=300&fit=crop',
rating: 4.9,
price: 0
},
{
id: 3,
name: '好莱坞星光大道',
description: '明星大道,梦想之地,感受电影文化的魅力。',
image: 'https://images.unsplash.com/photo-1515899020601-4c6c6e8a8b?w=400&h=300&fit=crop',
rating: 4.7,
price: 0
},
{
id: 4,
name: '圣莫尼卡海滩',
description: '阳光沙滩,海浪声声,享受西海岸的浪漫。',
image: 'https://images.unsplash.com/photo-1507525424636-bb4d9b0b7b?w=400&h=300&fit=crop',
rating: 4.6,
price: 0
}
])
const nearbyUsers = ref([
{
id: 1,
name: '张三',
avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop',
location: '距离您 2.3km',
status: 'online',
level: 'Lv.5',
followers: 234,
likes: 567,
isFollowing: false
},
{
id: 2,
name: '李四',
avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&h=100&fit=crop',
location: '距离您 3.8km',
status: 'online',
level: 'Lv.6',
followers: 456,
likes: 892,
isFollowing: true
},
{
id: 3,
name: '王五',
avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop',
location: '距离您 4.2km',
status: 'offline',
level: 'Lv.4',
followers: 123,
likes: 345,
isFollowing: false
},
{
id: 4,
name: '赵六',
avatar: 'https://images.unsplash.com/photo-1438761681033-6361e6a8b?w=100&h=100&fit=crop',
location: '距离您 5.5km',
status: 'traveling',
level: 'Lv.5',
followers: 789,
likes: 723,
isFollowing: true
},
{
id: 5,
name: '孙七',
avatar: 'https://images.unsplash.com/photo-1438761681033-6361e6a8b?w=100&h=100&fit=crop',
location: '距离您 6.1km',
status: 'online',
level: 'Lv.6',
followers: 345,
likes: 678,
isFollowing: false
},
{
id: 6,
name: '孙八',
avatar: 'https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?w=100&h=100&fit=crop',
location: '距离您 5.5km',
status: 'traveling',
level: 'Lv.4',
followers: 98,
likes: 345,
isFollowing: false
}
])
const dynamics = ref([
{
id: 1,
userName: '小明',
userAvatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop',
time: '10分钟前',
content: '今天参观了古城博物馆,真的太震撼了!强烈推荐大家去看看。',
likes: 128,
comments: 32
},
{
id: 2,
userName: '小红',
userAvatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&h=100&fit=crop',
time: '30分钟前',
content: '在中央公园野餐,天气真好,心情超棒!',
likes: 89,
comments: 15
},
{
id: 3,
userName: '大伟',
userAvatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop',
time: '1小时前',
content: '历史街区的夜景太美了,拍了很多照片!',
likes: 256,
comments: 48
}
])
const foods = ref([
{
id: 1,
name: '特色烤鸭',
description: '百年老店,皮脆肉嫩,香气四溢。',
image: 'https://images.unsplash.com/photo-1544025162-d566946569f2?w=400&h=300&fit=crop',
detailImage: 'https://images.unsplash.com/photo-15652995853-8b6c7a1a8d1?w=400&h=200&fit=crop',
type: '传统美食',
price: 88
},
{
id: 2,
name: '手工拉面',
description: '劲道爽滑,汤底浓郁,回味无穷。',
image: 'https://images.unsplash.com/photo-1569718212165-3a8278d5f71f?w=400&h=300&fit=crop',
detailImage: 'https://images.unsplash.com/photo-1563379976878-4d5c7a7f8a3?w=400&h=200&fit=crop',
type: '面食',
price: 35
},
{
id: 3,
name: '传统糕点',
description: '精致可口,甜而不腻,送礼佳品。',
image: 'https://images.unsplash.com/photo-1509368959836-f7801b4d6c1a?w=400&h=300&fit=crop',
detailImage: 'https://images.unsplash.com/photo-1509368959836-f7801b4d6c1a?w=400&h=200&fit=crop',
type: '甜品',
price: 45
},
{
id: 4,
name: '本地海鲜',
description: '新鲜捕捞,烹饪精良,营养丰富。',
image: 'https://images.unsplash.com/photo-1534604973900-85bd99082946?w=400&h=300&fit=crop',
detailImage: 'https://images.unsplash.com/photo-1534604973900-85bd99082946?w=400&h=200&fit=crop',
type: '海鲜',
price: 168
}
])
const goBack = () => {
router.back()
}
const showMoreInfo = () => {
console.log('查看更多城市介绍')
}
const viewUserProfile = (user) => {
console.log('查看用户资料:', user.name)
}
const followUser = (user) => {
user.isFollowing = !user.isFollowing
console.log(user.isFollowing ? '已关注' : '关注', user.name)
}
const sendMessage = (user) => {
console.log('发送消息给:', user.name)
}
</script>
<style scoped>
.city-introduction {
min-height: 100vh;
background-color: #f5f5f5;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
background-color: white;
position: sticky;
top: 0;
z-index: 10;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.back-button {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
padding: 0;
color: #333;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
}
.page-title {
font-size: 18px;
font-weight: 600;
margin: 0;
color: #333;
flex: 1;
text-align: center;
}
.main-content {
padding: 16px;
}
.city-header-section {
width: 100%;
height: 250px;
overflow: hidden;
border-radius: 12px;
margin-bottom: 24px;
position: relative;
}
.city-header-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.header-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.3) 100%);
padding: 24px;
display: flex;
align-items: flex-end;
justify-content: center;
}
.city-name {
font-size: 36px;
font-weight: 800;
color: white;
margin: 0;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
letter-spacing: 2px;
}
.city-info-section,
.attractions-section,
.nearby-users-section,
.destination-dynamics-section,
.food-section {
background-color: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.section-title {
font-size: 20px;
font-weight: 600;
color: #333;
margin: 0 0 16px 0;
padding-bottom: 12px;
border-bottom: 2px solid #42b883;
}
.city-description {
display: flex;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 0;
}
.city-description p {
font-size: 15px;
line-height: 1.8;
color: #666;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
.more-btn {
background: none;
border: none;
color: #42b883;
font-size: 14px;
font-weight: 600;
cursor: pointer;
padding: 8px 0;
transition: all 0.3s ease;
}
.more-btn:hover {
color: #2196f3;
text-decoration: underline;
}
.attractions-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}
.attraction-card {
border: 1px solid #e0e0e0;
border-radius: 12px;
overflow: hidden;
transition: all 0.3s ease;
}
.attraction-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.attraction-image {
width: 100%;
height: 180px;
object-fit: cover;
}
.attraction-info {
padding: 16px;
}
.attraction-name {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0 0 8px 0;
}
.attraction-description {
font-size: 14px;
color: #666;
margin: 0 0 12px 0;
line-height: 1.6;
}
.attraction-meta {
display: flex;
justify-content: space-between;
align-items: center;
}
.attraction-rating {
font-size: 14px;
color: #ff9800;
font-weight: 500;
}
.attraction-price {
font-size: 18px;
font-weight: 700;
color: #42b883;
}
.users-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}
.user-card {
border: 1px solid #e0e0e0;
border-radius: 12px;
padding: 16px;
background-color: #fafafa;
transition: all 0.3s ease;
cursor: pointer;
}
.user-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.user-avatar-container {
position: relative;
width: 60px;
height: 60px;
}
.user-avatar {
width: 100%;
height: 100%;
border-radius: 50%;
object-fit: cover;
border: 3px solid white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.user-status-dot {
position: absolute;
bottom: 2px;
right: 2px;
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid white;
}
.user-status-dot.online {
background-color: #4caf50;
}
.user-status-dot.traveling {
background-color: #2196f3;
}
.user-status-dot.offline {
background-color: #9e9e9e;
}
.user-info {
flex: 1;
}
.user-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.user-name {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 0;
}
.user-level {
font-size: 12px;
color: #42b883;
background-color: #e8f5e9;
padding: 4px 8px;
border-radius: 16px;
font-weight: 500;
}
.user-location {
font-size: 13px;
color: #666;
margin: 0 0 12px 0;
}
.user-stats {
display: flex;
gap: 16px;
margin-bottom: 8px;
}
.stat-item {
display: flex;
align-items: center;
gap: 4px;
}
.stat-icon {
font-size: 14px;
}
.stat-value {
font-weight: 600;
color: #333;
}
.user-actions {
display: flex;
gap: 8px;
}
.follow-btn {
flex: 1;
padding: 6px 12px;
border: 1px solid #42b883;
background-color: white;
color: #42b883;
border-radius: 16px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.follow-btn:hover {
background-color: #42b883;
color: white;
}
.follow-btn.following {
background-color: #e0e0e0;
color: #999;
border-color: #e0e0e0;
}
.message-btn {
width: 36px;
height: 36px;
border: 1px solid #e0e0e0;
background-color: white;
border-radius: 50%;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.message-btn:hover {
background-color: #42b883;
border-color: #42b883;
}
.dynamics-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.dynamic-card {
border: 1px solid #e0e0e0;
border-radius: 12px;
padding: 16px;
background-color: #fafafa;
}
.dynamic-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.dynamic-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.dynamic-user-info {
flex: 1;
}
.dynamic-user-name {
font-size: 14px;
font-weight: 600;
color: #333;
margin: 0;
}
.dynamic-time {
font-size: 12px;
color: #999;
margin-left: auto;
}
.dynamic-content {
font-size: 15px;
line-height: 1.6;
color: #666;
margin: 0 0 12px 0;
}
.dynamic-actions {
display: flex;
gap: 12px;
}
.action-btn {
display: flex;
align-items: center;
gap: 4px;
background: none;
border: none;
font-size: 14px;
cursor: pointer;
color: #666;
padding: 8px 12px;
border-radius: 20px;
transition: all 0.3s ease;
}
.action-btn:hover {
background-color: #f0f0f0;
color: #42b883;
}
.food-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}
.food-card {
border: 1px solid #e0e0e0;
border-radius: 12px;
overflow: hidden;
transition: all 0.3s ease;
}
.food-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.food-image {
width: 100%;
height: 180px;
object-fit: cover;
}
.food-info {
padding: 16px;
}
.food-name {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0 0 8px 0;
}
.food-description {
font-size: 14px;
color: #666;
margin: 0 0 12px 0;
line-height: 1.6;
}
.food-detail-image {
width: 100%;
height: 120px;
object-fit: cover;
border-radius: 8px;
margin-bottom: 12px;
}
.food-meta {
display: flex;
justify-content: space-between;
align-items: center;
}
.food-type {
font-size: 13px;
color: #42b883;
background-color: #e8f5e9;
padding: 4px 8px;
border-radius: 4px;
}
.food-price {
font-size: 18px;
font-weight: 700;
color: #42b883;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment