2025 后端自学UNIAPP【项目实战:旅游项目】7、景点详情页面【完结】

1、获取景点详情的请求【my_api.js】

javascript 复制代码
// 引入公共的请求封装
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】

html 复制代码
 <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、后端返回的数据结构

javascript 复制代码
{
	"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、效果图

相关推荐
酒旅Agent开发实战18 分钟前
AI 旅行规划助手如何接入真实酒旅数据:从自然语言到酒店预订的全流程 MCP 实战
人工智能·ai·旅游·skill·酒店api·机票api
大圣编程1 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang1 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆2 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜2 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞4 小时前
异步HttpModule的实现方式
java·服务器·前端
丹宇码农6 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_943782356 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
GV191rLvq7 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net