388 lines
17 KiB
Vue
388 lines
17 KiB
Vue
<template>
|
||
<view class="page">
|
||
<u-navbar title="攻略详情" :border-bottom="false" :background="bgc" back-icon-color="#262B37" title-color='#262B37'
|
||
title-size='36' height='40' id="navbar">
|
||
</u-navbar>
|
||
<!-- 顶部大图 -->
|
||
<view class="hero">
|
||
<image class="hero-img" :src="globj.photo" mode="aspectFill" style="width: 100%; height: 420rpx;"></image>
|
||
</view>
|
||
|
||
<!-- 基本信息 -->
|
||
<view class="base-info">
|
||
<view class="title-row">
|
||
<view class="left">
|
||
<view class="name">{{globj.areaName}}</view>
|
||
<view class="meta">{{globj.areaAddress == null ? '--' : globj.areaAddress}}</view>
|
||
</view>
|
||
<view class="actions">
|
||
<image @click="btntel" src="https://api.ccttiot.com/smartmeter/img/static/uFSDCjc5wPk8Wq9XSyr4" style="width: 40rpx;height: 40rpx;" mode=""></image>
|
||
<image @click="btndh" src="https://api.ccttiot.com/smartmeter/img/static/uFDC6JRPVkfL2PYrRlz0" style="width: 54rpx;height: 52rpx;" mode=""></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 小节:景区简介 -->
|
||
<view class="section-block" @click="btnjieshao">
|
||
<view class="section-hd"><text class="dot"></text><text class="txt">景区简介</text><text class="more">更多介绍</text> <image style="width: 32rpx;height: 32rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uiUIIoq5dM91HwG6ifIS" mode=""></image> </view>
|
||
<view class="para">
|
||
{{globj.description}}
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 小节:核心景点 -->
|
||
<view class="section-block" style="padding-bottom: 0;" v-if="globj.coreSpots.length > 0">
|
||
<view class="section-hd"><text class="dot"></text><text class="txt">核心景点</text></view>
|
||
<view class="thumbs">
|
||
<view class="thumb-item" v-for="(item,index) in globj.coreSpots">
|
||
<image :src="item.picture" mode="aspectFill" class="thumb-img" style="width: 204rpx; height: 204rpx;"></image>
|
||
<view class="thumb-name">{{item.name}}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 小节:行程概览 -->
|
||
<view class="section-block">
|
||
<view class="section-hd"><text class="dot"></text><text class="txt">行程概览</text></view>
|
||
<view class="facts list">
|
||
<view class="fact"> <image src="https://api.ccttiot.com/smartmeter/img/static/unOeWhbxfVsgh2jXJ0si" mode=""></image> <text class="f-t">行程天数:{{globj.days}}天</text></view>
|
||
<view class="fact"> <image src="https://api.ccttiot.com/smartmeter/img/static/uEz1yLuz7ID5iHVqGnfe" mode=""></image> <text class="f-t">游玩景点:{{globj.spotNum == null ? 0 : globj.spotNum}}个| <text style="margin-right: 6rpx;" v-for="(item,index) in globj.spotNames" :key="index">{{item}}</text> </text></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- Day tabs(绿色下划线) -->
|
||
<!-- <view class="day-tabs underline g">
|
||
<view class="tab active">第1天</view>
|
||
<view class="tab">第2天</view>
|
||
</view> -->
|
||
|
||
<!-- 行程推荐(黑灰系时间轴) -->
|
||
<view class="section-block">
|
||
<view class="timeline4">
|
||
<view class="row" v-for="(day, dIndex) in itinerary" :key="dIndex">
|
||
<view class="left">
|
||
<view class="n">{{ (dIndex+1).toString().padStart(2,'0') }}</view>
|
||
<view class="d">Day</view>
|
||
<view class="vl"></view>
|
||
</view>
|
||
<view class="right">
|
||
<view class="poi-card4" v-for="(poi, pIndex) in day.items" :key="pIndex">
|
||
<view class="poi-hd"><text class="sq"></text><text class="t">{{ poi.title }}</text></view>
|
||
<view class="poi-desc">{{ poi.desc }}</view>
|
||
<view class="grid-3">
|
||
<image v-for="(img, iidx) in poi.photos" :key="iidx" :src="img" mode="aspectFill" class="gimg" style="width: 200rpx; height: 200rpx;" @click="previewImage(img, poi.photos)" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
bgc: {
|
||
backgroundColor: "#fff",
|
||
},
|
||
itinerary: [
|
||
{
|
||
items: []
|
||
},{
|
||
items: []
|
||
},
|
||
],
|
||
id:'',
|
||
globj:{},
|
||
strategyDetails:[],
|
||
// 按天数分组的数据对象
|
||
groupedStrategyDetails: {}
|
||
}
|
||
},
|
||
onLoad(option) {
|
||
this.id = option.id
|
||
this.getxq()
|
||
},
|
||
methods: {
|
||
// 点击更多介绍进行跳转
|
||
btnjieshao(){
|
||
uni.navigateTo({
|
||
url:'/page_fenbao/remenxq?id=' + this.globj.areaId
|
||
})
|
||
},
|
||
// 点击拨打电话
|
||
btntel(){
|
||
uni.makePhoneCall({
|
||
phoneNumber: this.globj.areaPhone,
|
||
success: function(res) {
|
||
console.log('拨打电话成功', res)
|
||
},
|
||
fail: function(err) {
|
||
console.error('拨打电话失败', err)
|
||
}
|
||
})
|
||
},
|
||
// 点击进行导航
|
||
btndh(){
|
||
// 检查坐标数据是否存在
|
||
if (!this.globj.areaLat || !this.globj.areaLon) {
|
||
uni.showToast({
|
||
title: '坐标数据不完整',
|
||
icon: 'none',
|
||
duration:3000
|
||
})
|
||
return
|
||
}
|
||
// 先申请位置权限
|
||
uni.getSetting({
|
||
success: (res) => {
|
||
if (res.authSetting['scope.userLocation'] === false) {
|
||
// 用户拒绝了位置权限,引导用户开启
|
||
uni.showModal({
|
||
title: '位置权限',
|
||
content: '需要获取您的位置信息才能进行导航,请在设置中开启位置权限',
|
||
confirmText: '去设置',
|
||
success: (modalRes) => {
|
||
if (modalRes.confirm) {
|
||
uni.openSetting()
|
||
}
|
||
}
|
||
})
|
||
return
|
||
}
|
||
// 权限正常,打开地图
|
||
this.openMap()
|
||
}
|
||
})
|
||
},
|
||
// 打开地图
|
||
openMap() {
|
||
uni.openLocation({
|
||
latitude: parseFloat(this.globj.areaLat), // 确保是数字类型
|
||
longitude: parseFloat(this.globj.areaLon), // 确保是数字类型
|
||
name: this.globj.areaName || '目的地', // 地点名称
|
||
success: function(res) {
|
||
console.log('打开地图成功', res);
|
||
},
|
||
fail: function(err) {
|
||
console.error('打开地图失败', err);
|
||
uni.showToast({
|
||
title: '打开地图失败: ' + (err.errMsg || '未知错误'),
|
||
icon: 'none',
|
||
duration: 3000
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 请求攻略详情
|
||
getxq(){
|
||
this.$u.get(`/app/strategy/detail/${this.id}?assembleDetail=true`).then((res) => {
|
||
if(res.code == 200){
|
||
this.globj = res.data
|
||
// 按dayNumber分组strategyDetails
|
||
this.groupedStrategyDetails = this.groupStrategyDetailsByDay(res.data.strategyDetails)
|
||
// 更新itinerary数据,使用分组后的数据
|
||
this.updateItinerary(this.groupedStrategyDetails)
|
||
}
|
||
})
|
||
},
|
||
// 按天数分组策略详情数据
|
||
groupStrategyDetailsByDay(strategyDetails) {
|
||
const grouped = {}
|
||
strategyDetails.forEach(item => {
|
||
const dayNumber = item.dayNumber
|
||
if (!grouped[dayNumber]) {
|
||
grouped[dayNumber] = []
|
||
}
|
||
grouped[dayNumber].push(item)
|
||
})
|
||
// 按天数排序
|
||
const sortedGrouped = {}
|
||
Object.keys(grouped).sort((a, b) => parseInt(a) - parseInt(b)).forEach(dayNumber => {
|
||
sortedGrouped[dayNumber] = grouped[dayNumber]
|
||
})
|
||
return sortedGrouped
|
||
},
|
||
// 获取指定天数的数据
|
||
getDayData(dayNumber) {
|
||
return this.groupedStrategyDetails[dayNumber] || []
|
||
},
|
||
// 获取所有天数
|
||
getAllDays() {
|
||
return Object.keys(this.groupedStrategyDetails).map(day => parseInt(day)).sort((a, b) => a - b)
|
||
},
|
||
// 更新itinerary数据
|
||
updateItinerary(groupedDetails) {
|
||
this.itinerary = Object.keys(groupedDetails).map(dayNumber => {
|
||
return {
|
||
dayNumber: parseInt(dayNumber),
|
||
items: groupedDetails[dayNumber].map(item => ({
|
||
title: item.name || '景点',
|
||
desc: item.description || '暂无描述',
|
||
photos: item.photo ? item.photo.split(',').map(url => url.trim()) : []
|
||
}))
|
||
}
|
||
}).sort((a, b) => a.dayNumber - b.dayNumber)
|
||
},
|
||
// 预览图片
|
||
previewImage(current, urls) {
|
||
uni.previewImage({
|
||
current: current, // 当前显示图片的http链接
|
||
urls: urls, // 需要预览的图片http链接列表
|
||
success: function (res) {
|
||
console.log('预览图片成功')
|
||
},
|
||
fail: function (err) {
|
||
console.log('预览图片失败', err)
|
||
}
|
||
})
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
page { background: #fff; }
|
||
.page { background: #fff; min-height: 100vh; }
|
||
/* 顶部大图 */
|
||
.hero { width: 100%; height: 420rpx; overflow: hidden; }
|
||
.hero-img { width: 100%; height: 100%; }
|
||
/* 基本信息 */
|
||
.base-info {
|
||
padding: 30rpx;
|
||
.title-row {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
.left {
|
||
.name { font-size: 52rpx; font-weight: 700; color: #262B37; }
|
||
.meta { margin-top: 8rpx; font-size: 28rpx; color: #3D3D3D; }
|
||
}
|
||
.actions { display: flex; gap: 30rpx;align-items: center; }
|
||
.act { padding: 8rpx 16rpx; border: 1rpx solid #e6e6e6; border-radius: 28rpx; font-size: 28rpx; color: #333; }
|
||
}
|
||
.tags {
|
||
margin-top: 20rpx; display: flex; gap: 16rpx; flex-wrap: wrap;
|
||
.tag { padding: 8rpx 18rpx; background: #f6f7f9; color: #555; font-size: 26rpx; border-radius: 28rpx; }
|
||
}
|
||
.gallery { margin-top: 20rpx; white-space: nowrap; height: 140rpx;
|
||
.g-img { width: 200rpx; height: 140rpx; border-radius: 12rpx; margin-right: 16rpx; }
|
||
}
|
||
}
|
||
/* 区块标题 */
|
||
.section { padding: 10rpx 30rpx 40rpx; }
|
||
.sec-title { font-size: 32rpx; font-weight: 700; color: #262B37; padding: 20rpx 0; }
|
||
/* 简介 */
|
||
.intro .intro-text { font-size: 26rpx; color: #555; line-height: 1.8; background: #f8f9fb; padding: 28rpx; border-radius: 16rpx; }
|
||
/* 精选景点 */
|
||
.picks .picks-scroll { white-space: nowrap; }
|
||
.pick-item { display: inline-flex; flex-direction: column; margin-right: 20rpx; }
|
||
.pick-img { border-radius: 12rpx; }
|
||
.pick-name { margin-top: 10rpx; font-size: 26rpx; color: #666; text-align: center; }
|
||
/* 行程概览 */
|
||
.overview .overview-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16rpx; }
|
||
.ov-item { background: #f6f7f9; border-radius: 12rpx; padding: 18rpx; }
|
||
.ov-k { font-size: 26rpx; color: #7a7f8a; }
|
||
.ov-v { margin-top: 6rpx; font-size: 28rpx; color: #262B37; font-weight: 600; }
|
||
/* Day tabs */
|
||
.day-tabs { display: flex; gap: 20rpx; padding-top: 0; }
|
||
.day-tabs .tab { padding: 10rpx 26rpx; border-radius: 999rpx; background: #f2fbf6; color: #20b26b; font-size: 28rpx; }
|
||
.day-tabs .tab.active { background: #20b26b; color: #fff; }
|
||
/* 时间轴 */
|
||
.timeline { position: relative; }
|
||
.day-block { position: relative; padding-left: 90rpx; }
|
||
.day-block:before { content: ''; position: absolute; left: 40rpx; top: 0; bottom: 0; width: 2rpx; background: #e0f3e9; }
|
||
.day-head { display: flex; align-items: center; margin: 10rpx 0 20rpx; }
|
||
.day-num { width: 64rpx; height: 64rpx; border-radius: 8rpx; background: #20b26b; color: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; position: absolute; left: 8rpx; box-shadow: 0 4rpx 12rpx rgba(32,178,107,0.3); }
|
||
.day-num .big { font-size: 26rpx; line-height: 26rpx; }
|
||
.day-num .small { font-size: 18rpx; opacity: 0.9; }
|
||
.day-text { margin-left: 10rpx; }
|
||
.d-title { font-size: 30rpx; font-weight: 600; color: #262B37; }
|
||
.d-sub { font-size: 28rpx; color: #7a7f8a; margin-top: 6rpx; }
|
||
.day-list { display: flex; flex-direction: column; gap: 26rpx; margin-bottom: 36rpx; }
|
||
.poi { display: flex; gap: 16rpx; position: relative; }
|
||
.poi-icon { position: absolute; left: 18rpx; top: 18rpx; font-size: 26rpx; color: #20b26b; }
|
||
.poi-card { flex: 1; background: #fff; border-radius: 16rpx; padding: 20rpx; box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.06); }
|
||
.poi-title { font-size: 28rpx; font-weight: 600; color: #262B37; }
|
||
.poi-desc { margin-top: 8rpx; font-size: 28rpx; color: #666; line-height: 1.6; }
|
||
.poi-photos { margin-top: 12rpx; display: grid; grid-template-columns: repeat(3, 1fr); gap: 12rpx; }
|
||
.pimg { width: 100%; height: 160rpx; border-radius: 10rpx; }
|
||
/* 信息卡 */
|
||
.info-card { padding: 18rpx 26rpx; background: #fff; border-radius: 16rpx; margin: -40rpx 20rpx 6rpx; box-shadow: 0 6rpx 18rpx rgba(0,0,0,0.06); border: 2rpx solid #eef0f3; }
|
||
.info-card.float { position: relative; z-index: 2; }
|
||
.title-wrap { display: flex; justify-content: space-between; align-items: center; }
|
||
.title-left .cn { font-size: 32rpx; font-weight: 800; color: #1f2a37; }
|
||
.title-left .en { margin-top: 6rpx; font-size: 20rpx; color: #9aa4b2; letter-spacing: 2rpx; }
|
||
.title-left .sub { margin-top: 8rpx; font-size: 26rpx; color: #8a949e; }
|
||
.title-right { display: flex; gap: 12rpx; }
|
||
.ic { width: 48rpx; height: 48rpx; border-radius: 10rpx; background: #f3f4f6; border: 2rpx solid #eef0f3; display: flex; align-items: center; justify-content: center; color: #374151; }
|
||
/* 小节标题 */
|
||
.section-block { padding: 10rpx 20rpx 20rpx; }
|
||
.section-hd { display: flex; align-items: center; gap: 12rpx; margin: 18rpx 2rpx; }
|
||
.section-hd .dot { width: 8rpx; height: 28rpx; background: #111827; border-radius: 4rpx; }
|
||
.section-hd .txt { font-size: 36rpx; font-weight: 800; color: #111827; }
|
||
.section-hd .more { margin-left: auto; font-size: 26rpx; color: #3D3D3D; }
|
||
.para { font-size: 28rpx; color: #4b5563; line-height: 1.8; }
|
||
/* 精选景点 */
|
||
.thumbs { display: flex; gap: 16rpx; overflow: scroll;padding-bottom: 20rpx;}
|
||
.thumb-item { width: 210rpx; }
|
||
.thumb-img { border-radius: 12rpx; border: 2rpx solid #eef0f3; }
|
||
.thumb-name { margin-top: 8rpx; text-align: center; color: #6b7280; font-size: 26rpx; }
|
||
/* 行程概览 */
|
||
.kv-row { display: flex; align-items: center; background: #f1f6ff; border-radius: 12rpx; padding: 16rpx; margin-bottom: 10rpx; border: 2rpx solid #cfe0ff; }
|
||
.kv { flex: 1; display: flex; justify-content: space-between; align-items: baseline; }
|
||
.k { font-size: 26rpx; color: #6f7c96; }
|
||
.v { font-size: 26rpx; color: #24324a; font-weight: 700; }
|
||
.divider { width: 1rpx; height: 28rpx; background: #ccd9f5; margin: 0 16rpx; }
|
||
.facts { margin-top: 10rpx; display: grid; grid-template-columns: 1fr; gap: 10rpx; }
|
||
.fact { display: flex; align-items: center; gap: 10rpx; color: #405072; font-size: 28rpx; }
|
||
.fact image{ width: 28rpx; height: 28rpx; }
|
||
.f-ic { color: #3a6fd9; }
|
||
/* Day tabs 下划线风格 */
|
||
.day-tabs.underline { display: flex; gap: 40rpx; padding: 4rpx 26rpx 8rpx; }
|
||
.day-tabs.underline .tab { font-size: 26rpx; color: #6f7c96; padding-bottom: 10rpx; }
|
||
.day-tabs.underline .tab.active { color: #24324a; font-weight: 700; border-bottom: 4rpx solid #3a6fd9; }
|
||
/* 新版时间轴(蓝色) */
|
||
.timeline3 { padding-top: 8rpx; }
|
||
.timeline3 .row { display: flex; }
|
||
.timeline3 .left { width: 120rpx; align-items: center; display: flex; flex-direction: column; }
|
||
.timeline3 .n { font-size: 40rpx; font-weight: 800; color: #3a6fd9; }
|
||
.timeline3 .d { font-size: 20rpx; color: #3a6fd9; margin-top: -6rpx; }
|
||
.timeline3 .vl { width: 2rpx; flex: 1; background: #d7e6ff; margin-top: 12rpx; }
|
||
.timeline3 .right { flex: 1; padding-bottom: 26rpx; }
|
||
.rt-title { font-size: 28rpx; font-weight: 800; color: #24324a; }
|
||
.rt-sub { font-size: 28rpx; color: #6f7c96; margin-top: 6rpx; }
|
||
.poi-card3 { margin-top: 18rpx; background: #fff; border-radius: 12rpx; padding: 18rpx; box-shadow: 0 4rpx 14rpx rgba(0,0,0,0.06); border: 2rpx solid #e6efff; }
|
||
.poi-hd { display: flex; align-items: center; gap: 10rpx; }
|
||
.poi-hd .sq { width: 16rpx; height: 16rpx; background: #3a6fd9; border-radius: 4rpx; }
|
||
.poi-hd .t { font-size: 32rpx; font-weight: 700; color: #24324a; }
|
||
.poi-desc { margin-top: 6rpx; font-size: 28rpx; color: #56617a; line-height: 1.8; }
|
||
.grid-3 { margin-top: 12rpx; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10rpx; }
|
||
.gimg { border-radius: 10rpx; border: 2rpx solid #e6efff; }
|
||
/* 行程概览:四行列表 */
|
||
.list { display: flex; flex-direction: column; gap: 14rpx; }
|
||
.fact { display: flex; align-items: center; gap: 12rpx; font-size: 28rpx; color: #4b5563; }
|
||
.f-ic { color: #10b981; }
|
||
.f-btn { margin-left: auto; font-size: 26rpx; color: #10b981; }
|
||
/* Day tabs 绿色下划线 */
|
||
.day-tabs.underline.g { display: flex; gap: 40rpx; padding: 6rpx 20rpx 8rpx; }
|
||
.day-tabs.underline.g .tab { font-size: 26rpx; color: #6b7280; padding-bottom: 10rpx; }
|
||
.day-tabs.underline.g .tab.active { color: #111827; font-weight: 700; border-bottom: 4rpx solid #10b981; }
|
||
/* 时间轴(黑灰) */
|
||
.timeline4 { padding-top: 6rpx; }
|
||
.timeline4 .row { display: flex; }
|
||
.timeline4 .left { width: 66rpx; align-items: center; display: flex; flex-direction: column; }
|
||
.timeline4 .n { font-size: 40rpx; font-weight: 800; color: #111827; }
|
||
.timeline4 .d { font-size: 20rpx; color: #6b7280; margin-top: -6rpx; }
|
||
.timeline4 .vl { width: 2rpx; flex: 1; background: #e5e7eb; margin-top: 12rpx; }
|
||
.timeline4 .right { flex: 1; padding-bottom: 26rpx; padding-left: 6rpx; }
|
||
.rt-title { font-size: 28rpx; font-weight: 800; color: #111827; }
|
||
.rt-sub { font-size: 28rpx; color: #6b7280; margin-top: 6rpx; }
|
||
.poi-card4 { margin-top: 18rpx; background: #fff; border-radius: 12rpx; padding: 18rpx; box-shadow: 0 4rpx 14rpx rgba(0,0,0,0.06); border: 2rpx solid #f3f4f6; }
|
||
.poi-hd { display: flex; align-items: center; gap: 10rpx; }
|
||
.poi-hd .sq { width: 16rpx; height: 16rpx; background: #10b981; border-radius: 4rpx; }
|
||
.poi-hd .t { font-size: 32rpx; font-weight: 700; color: #111827; }
|
||
.poi-desc { margin-top: 6rpx; font-size: 28rpx; color: #4b5563; line-height: 1.8; }
|
||
.grid-3 { margin-top: 12rpx; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10rpx; }
|
||
.gimg { border-radius: 10rpx; border: 2rpx solid #f3f4f6; }
|
||
</style> |