1、获取景点详情的请求【my_api.js】
// 引入公共的请求封装
import http from './my_http.js'
// 登录接口(适配服务端返回 Token)
export const login = async (code, avatar) => {
const res = await http('/login/getWXSessionKey', {code,avatar});
};
// 获取bannner列表
export const getBannerList = () => {
return http('/banner/list')
}
// 获取景点类型列表(支持传入typeId参数)
export const getTypeList = () => {
return http('/type/list')
}
// 获取景点列表
export const getAttractionList = (typeId) => {
// 如果有typeId就拼接到URL,没有就不加
const url = typeId ? `/attraction/list?typeId=${typeId}` : '/attraction/list'
return http(url)
}
// 获取景点详情
export const getAttractionInfo = (attractionId) => {
return http(`/attraction/getInfo/${attractionId}`)
}
// 获取收藏列表
export const getFavouriteList = () => {
// 如果有typeId就拼接到URL,没有就不加
return http('/favourite/list')
}
2、页面源码【attraction_details.vue】
<template>
<view class="container"><!-- 导航栏 -->
<up-navbar class="up-navbar-title" bg-color="#00000000" title="" :auto-back="true" left-icon-color="#fff" />
<!-- 景点主图 -->
<view class="attraction-box">
<image class="attraction-image" :src="attraction.cover" mode="aspectFill"></image>
<view class="image-overlay"></view>
<view class="attraction-header">
<view class="attraction-title">{{ attraction.title }}</view>
<view class="attraction-subtitle">{{ attraction.address }}</view>
</view>
</view>
<!-- 景点内容区域 -->
<view class="content-box">
<!-- 景点简介 -->
<view class="section" v-if="attraction.introduction">
<view class="section-title">
<up-icon name="info-circle" color="#3c9cff" size="18"></up-icon>
<text class="title-text">景点简介</text>
</view>
<view class="section-content">{{ attraction.introduction }}</view>
</view>
<!-- 开放时间 -->
<view class="section" v-if="attraction.inbusinessTime1 || attraction.inbusinessTime2">
<view class="section-title">
<up-icon name="clock" color="#3c9cff" size="18"></up-icon>
<text class="title-text">开放时间</text>
</view>
<view class="section-content">
{{ attraction.inbusinessTime1 ? attraction.inbusinessTime1.slice(0,5) : '未设置' }} -
{{ attraction.inbusinessTime2 ? attraction.inbusinessTime2.slice(0,5) : '未设置' }}
</view>
</view>
<!-- 详细描述 -->
<view class="section" v-if="attraction.description">
<view class="section-title">
<up-icon name="map" color="#3c9cff" size="18"></up-icon>
<text class="title-text">景点介绍</text>
</view>
<view class="section-content">{{ attraction.description }}</view>
</view>
<!-- 联系方式 -->
<view class="section" v-if="attraction.tel">
<view class="section-title">
<up-icon name="phone" color="#3c9cff" size="18"></up-icon>
<text class="title-text">联系方式</text>
</view>
<view class="section-content">{{ attraction.tel }}</view>
</view>
</view>
</view>
</template>
<script setup>
import {
onLoad
} from '@dcloudio/uni-app'
import {
ref,
reactive
} from 'vue'
import {
getAttractionInfo
} from '../../api/my_api.js'
// 景点对象
const attraction = ref({})
//接受传递过来的id
onLoad((opt) => {
const attractionId = opt.attractionId
//重新获取景点详情
getInfo(attractionId)
})
// 景点详情
const getInfo = (attractionId) => {
getAttractionInfo(attractionId).then(res => {
attraction.value = res
})
}
</script>
<style lang="scss" scoped>
.container {
position: relative;
min-height: 100vh;
background-color: #f5f5f5;
// 景点盒子
.attraction-box {
position: relative;
height: 500rpx;
overflow: hidden;
.attraction-image {
width: 100%;
height: 100%;
}
.image-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 200rpx;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
}
.attraction-header {
position: absolute;
bottom: 40rpx;
left: 30rpx;
right: 30rpx;
color: #fff;
.attraction-title {
font-size: 42rpx;
font-weight: bold;
margin-bottom: 10rpx;
}
.attraction-subtitle {
font-size: 28rpx;
opacity: 0.9;
}
}
}
// 内容区域
.content-box {
padding: 30rpx;
margin-top: 0rpx;
background-color: #fff;
border-radius: 30rpx 30rpx 0 0;
box-shadow: 0 -5rpx 10rpx rgba(0,0,0,0.05);
.section {
margin-bottom: 40rpx;
.section-title {
display: flex;
align-items: center;
margin-bottom: 20rpx;
font-size: 32rpx;
font-weight: bold;
color: #333;
.title-text {
margin-left: 10rpx;
}
}
.section-content {
font-size: 28rpx;
color: #666;
line-height: 1.6;
text-align: justify;
}
}
}
}
</style>
3、后端返回的数据结构
{
"id": 2,
"title": "石家庄动物园",
"cover": "http://localhost:9001/attraction/8.png",
"introduction": "与萌宠零距离,开启奇妙动物之旅!",
"start": null,
"browse": null,
"img": null,
"description": "石家庄动物园位于河北省石家庄市,是一座大型的综合性动物园,旨在饲养、繁殖、研究和保护各种动物,同时为公众提供观赏和教育的机会。动物园内环境优美,设施齐全,旨在为动物提供一个接近自然的生活环境,同时也为游客创造一个舒适、安全的观赏体验。\n园内分为多个区域,包括猛兽区、食草动物区、鸟语林、爬行馆等,每个区域都根据动物的习性进行了精心设计。在这里,游客可以近距离观察到狮子、老虎、大象、长颈鹿、熊猫等众多珍稀动物。此外,动物园还定期举办各种教育活动和互动体验,如动物喂食、科普讲座等,旨在提高公众的生态保护意识。\n石家庄动物园不仅是家庭休闲的好去处,也是学校组织学生进行生物多样性教育的理想场所。通过实地观察和学习,动物园激发人们对自然的兴趣和对动物的同情心,促进社会公众的生态保护意识。\n总之,石家庄动物园以其丰富的动物种类、优美的环境和丰富的教育活动,为游客提供了一个寓教于乐的场所,是石家庄市重要的旅游景点之一。\n",
"inbusinessTime1": "06:00:00",
"inbusinessTime2": "18:00:00",
"address": "河北省石家庄市鹿泉区观景大街与山前大道交叉口西南处",
"province": null,
"city": null,
"area": null,
"longitude": "114.30 \r\n",
"latitude": "38.06\r\n",
"location": null,
"enableType": "false",
"typeId": "1",
"enableAppointment": "false",
"enablePay": "false",
"tel": null
}
4、效果图
