roamfuding-xcx/page_fenbao/gonglue/gongluexq.vue

388 lines
17 KiB
Vue
Raw Permalink Normal View History

2025-11-08 11:21:57 +08:00
<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>