<template>
|
<view class="spot-detail-page">
|
<!-- 顶部信息 -->
|
<view class="header">
|
<view class="header-info">
|
<view class="geo-row">
|
<view class="geo-path">{{ geoPath }}</view>
|
<image src="/static/common/earth.png" class="earth-icon" />
|
</view>
|
<view class="title-row">
|
<view class="title">{{ location?.locationName || '景点详情' }}</view>
|
<up-icon name="heart" size="40rpx" :color="collected ? '#FF4D4F' : '#ccc'" @click="toggleCollect" />
|
</view>
|
</view>
|
</view>
|
|
<!-- 主图 -->
|
<view class="main-image">
|
<image :src="mainImage" mode="aspectFill" class="main-img" />
|
</view>
|
|
<!-- 地址、类型、电话、身份准入等 -->
|
<view class="info-list">
|
<view class="info-item">{{ location?.address }}</view>
|
<view class="info-item"><up-icon name="/static/common/marker.png" size="32rpx" /> {{ location?.sceneType || '类型未知' }}</view>
|
<view class="info-item"><up-icon name="/static/common/parking.png" size="32rpx" /> {{ location?.parkingInfo || '无电话' }}</view>
|
<view class="info-item"><up-icon name="/static/common/visit.png" size="32rpx" /> {{ location?.isOpenVisitStr === '是' ? '允许参观' : '不允许参观' }}</view>
|
</view>
|
|
<!-- 介绍描述 -->
|
<view class="divider-line"></view>
|
<view class="desc-block">
|
<text>{{ location?.landmarkDesc || location?.visitInfo || '暂无介绍' }}</text>
|
</view>
|
|
<!-- 地图 -->
|
<view class="map-block" v-if="showMap">
|
<!-- 腾讯地图小程序组件(uni-app中需配置腾讯地图key) -->
|
<map
|
:latitude="location?.gpsLat"
|
:longitude="location?.gpsLng"
|
:markers="mapMarkers"
|
style="width: 100%; height: 300rpx;"
|
v-if="location?.gpsLat && location?.gpsLng"
|
/>
|
<image v-else src="/static/common/geo-earth.png" class="map-placeholder" />
|
</view>
|
|
<!-- 实景图 -->
|
<view class="scene-block" v-if="sceneImages.length">
|
<view class="scene-title">实景图 <text class="scene-count">{{ sceneImages.length }}</text></view>
|
<view class="scene-list">
|
<image
|
v-for="(img, idx) in sceneImages"
|
:key="idx"
|
:src="img"
|
mode="aspectFill"
|
class="scene-image"
|
@tap="previewScene(idx)"
|
/>
|
</view>
|
</view>
|
|
<!-- 关联影视作品 -->
|
<view class="film-block" v-if="relatedFilms.length">
|
<view class="film-title">关联影视作品</view>
|
<view class="film-list">
|
<view class="film-item" v-for="film in relatedFilms" :key="film.id">
|
<image :src="film.coverUrl" class="film-cover" />
|
<view class="film-info">
|
<view class="film-name">{{ film.nameCn }}</view>
|
<view class="film-en">{{ film.nameEn }}</view>
|
<view class="film-meta">
|
<text>{{ film.typeStr }}</text>
|
<text v-if="film.country"> / {{ film.country }}</text>
|
<text v-if="film.releaseYear"> / {{ film.releaseYear }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</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 { FilmLocationVO, FilmWorks } from '@/types/index'
|
|
const location = ref<FilmLocationVO>()
|
const collected = ref(false)
|
const geoPath = ref('亚洲-中国-海南省-海口市')
|
const mainImage = ref('')
|
const sceneImages = ref<string[]>([])
|
const relatedFilms = ref<FilmWorks[]>([])
|
const showMap = ref(true)
|
|
|
onLoad(async (options: any) => {
|
const id = options.id
|
if (id) {
|
await getLocationDetail(id)
|
await getRelatedFilms(id)
|
}
|
})
|
|
const getLocationDetail = async (id: string) => {
|
const { code, data } = await $http.request('get', '/api/filmLocation/list/view', {
|
params: { id }
|
})
|
if (code === 0) {
|
location.value = data
|
// 主图优先locationUrl,其次visitorPhotos
|
if (data.locationUrl) {
|
mainImage.value = data.locationUrl
|
console.log(data.locationUrl)
|
console.log( mainImage.value)
|
} else if (data.visitorPhotos) {
|
try {
|
const arr = JSON.parse(data.visitorPhotos)
|
mainImage.value = arr[0]?.url || ''
|
} catch {
|
mainImage.value = ''
|
}
|
}
|
// 实景图
|
if (data.visitorPhotos) {
|
try {
|
const arr = JSON.parse(data.visitorPhotos)
|
sceneImages.value = arr.map((item: any) => item.url)
|
} catch {
|
sceneImages.value = []
|
}
|
} else {
|
sceneImages.value = []
|
}
|
// 拼接地理层级
|
geoPath.value = [
|
'亚洲',
|
'中国',
|
data.province,
|
data.city
|
].filter(Boolean).join('-')
|
} else {
|
$message.showToast('获取景点信息失败')
|
}
|
}
|
|
// 地图标记
|
const mapMarkers = ref([
|
{
|
id: 1,
|
latitude: location.value?.gpsLat,
|
longitude: location.value?.gpsLng,
|
iconPath: '/static/common/marker.png',
|
width: 40,
|
height: 40
|
}
|
])
|
|
const previewScene = (idx: number) => {
|
uni.previewImage({
|
current: sceneImages.value[idx],
|
urls: sceneImages.value
|
})
|
}
|
|
// 影视作品接口示例
|
const getRelatedFilms = async (locationId: string) => {
|
// 假设接口 /api/filmWorks/related?locationId=xxx
|
const { code, data } = await $http.request('get', '/api/filmLocation/related', {
|
params: { locationId }
|
})
|
if (code === 0 && Array.isArray(data)) {
|
relatedFilms.value = data
|
} else {
|
relatedFilms.value = []
|
}
|
}
|
|
const toggleCollect = () => {
|
collected.value = !collected.value
|
$message.showToast(collected.value ? '已收藏' : '已取消收藏')
|
}
|
</script>
|
|
<style scoped>
|
.spot-detail-page {
|
background: #fff;
|
min-height: 100vh;
|
}
|
.header {
|
display: flex;
|
align-items: flex-start;
|
padding: 30rpx 20rpx 10rpx 20rpx;
|
}
|
.header-info {
|
flex: 1;
|
margin-left: 20rpx;
|
}
|
.geo-path {
|
color: #6c8fc5;
|
font-size: 22rpx;
|
margin-bottom: 10rpx;
|
}
|
.title-row {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-top: 30rpx; /* 增加名称与上方的间距 */
|
}
|
.title {
|
font-size: 36rpx;
|
font-weight: bold;
|
margin-right: 16rpx;
|
}
|
.earth-icon {
|
width: 144rpx; /* 放大三倍 */
|
height: 144rpx;
|
}
|
.main-image {
|
width: 100%;
|
height: 320rpx;
|
margin-top: 40rpx; /* 增加名称和图片之间的间隔 */
|
margin-bottom: 40rpx;
|
}
|
.main-img {
|
width: 100%;
|
height: 100%;
|
object-fit: cover;
|
border-radius: 10rpx;
|
}
|
/*.info-list {*/
|
/* padding: 0 20rpx;*/
|
/* margin-bottom: 20rpx;*/
|
/*}*/
|
/*.info-item {*/
|
/* font-size: 28rpx;*/
|
/* color: #333;*/
|
/* margin-bottom: 16rpx;*/
|
/* display: flex;*/
|
/* align-items: center;*/
|
/*}*/
|
/*.desc-block {*/
|
/* padding: 0 20rpx 30rpx 20rpx;*/
|
/* color: #666;*/
|
/* font-size: 26rpx;*/
|
/*}*/
|
.info-list {
|
padding: 20rpx; /* 增加内边距 */
|
margin: 20rpx 0; /* 调整上下外边距 */
|
background-color: #f9f9f9;
|
border-radius: 12rpx;
|
}
|
|
.info-item {
|
font-size: 28rpx;
|
color: #333;
|
margin-bottom: 20rpx; /* 调整间距 */
|
display: flex;
|
align-items: center;
|
line-height: 1.6;
|
}
|
|
.info-item:last-child {
|
margin-bottom: 0;
|
}
|
|
/* 添加分割线样式 */
|
.divider-line {
|
height: 1px;
|
background-color: #eee;
|
margin: 30rpx 20rpx 20rpx 20rpx;
|
}
|
|
/* 调整描述区块的间距 */
|
.desc-block {
|
padding: 0 20rpx 30rpx 20rpx;
|
color: #666;
|
font-size: 26rpx;
|
line-height: 1.8;
|
margin-top: 20rpx;
|
}
|
.map-block {
|
margin: 20rpx 0;
|
}
|
.map-placeholder {
|
width: 100%;
|
height: 300rpx;
|
object-fit: cover;
|
border-radius: 10rpx;
|
}
|
.scene-block {
|
padding: 0 20rpx 30rpx 20rpx;
|
}
|
.scene-title {
|
font-size: 28rpx;
|
font-weight: bold;
|
margin-bottom: 10rpx;
|
}
|
.scene-count {
|
color: #888;
|
font-size: 22rpx;
|
margin-left: 10rpx;
|
}
|
.scene-list {
|
display: flex;
|
gap: 20rpx;
|
flex-wrap: wrap;
|
}
|
.scene-image {
|
width: 45vw;
|
height: 140rpx;
|
object-fit: cover;
|
border-radius: 8rpx;
|
margin-bottom: 10rpx;
|
}
|
.film-block {
|
padding: 0 20rpx 30rpx 20rpx;
|
}
|
.film-title {
|
font-size: 28rpx;
|
font-weight: bold;
|
margin-bottom: 10rpx;
|
}
|
.film-list {
|
display: flex;
|
flex-direction: column;
|
gap: 20rpx;
|
}
|
.film-item {
|
display: flex;
|
align-items: flex-start;
|
gap: 20rpx;
|
}
|
.film-cover {
|
width: 120rpx;
|
height: 160rpx;
|
object-fit: cover;
|
border-radius: 8rpx;
|
}
|
.film-info {
|
flex: 1;
|
}
|
.film-name {
|
font-size: 28rpx;
|
font-weight: bold;
|
}
|
.film-en {
|
font-size: 22rpx;
|
color: #888;
|
margin-bottom: 6rpx;
|
}
|
.film-meta {
|
font-size: 22rpx;
|
color: #888;
|
}
|
.geo-row {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
margin-bottom: 15rpx;
|
}
|
</style>
|