鸿宇研学生前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

433 lines
10 KiB

<template>
<view class="page__view">
<view class="main">
<navbar title="活动详情" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="transparent" />
<view class="swiper">
<uv-swiper
:list="bannerList"
keyName="image"
indicator
indicatorMode="dot"
indicatorInactiveColor="rgba(255, 255, 255, 0.7)"
height="680rpx"
></uv-swiper>
</view>
<view class="summary">
<view class="card info">
<view class="card-header">{{ detail.title }}</view>
<view class="card-content">
<view class="desc">{{ detail.brief }}</view>
<view class="flex tags" v-if="tagList.length">
<view class="tag" v-for="(tag, tIdx) in tagList" :key="tIdx">
{{ tag }}
</view>
</view>
<view class="flex data">
<view class="flex price">
<view class="price-val">
<text>¥</text>
<text class="highlight">{{ priceInt }}</text>
<text>{{ `${priceFrac}起` }}</text>
</view>
<view class="price-bef" v-if="detail.priceOrigin">¥<text>{{ detail.priceOrigin }}</text></view>
</view>
<view class="registered" v-if="detail.applyNum">
{{ `${detail.applyNum}人已报名` }}
</view>
</view>
</view>
</view>
<view class="card">
<view class="card-header">选择团期</view>
<view class="card-content">
<timeOptionsSelect v-model="selectTime" :options="detail.dateList"></timeOptionsSelect>
</view>
</view>
<view class="card comment">
<view class="flex card-header">
<view>评论</view>
<button class="flex btn" @click="jumpToCommentRecords">
<view>查看全部</view>
<image class="img" src="@/static/image/icon-arrow-right.png" mode="widthFix"></image>
</button>
</view>
<view class="card-content">
<commentList :list="commentList"></commentList>
</view>
</view>
</view>
<!-- <uv-sticky bgColor="#F3F3F3"> -->
<view class="tabs">
<uv-tabs
:list="tabs"
:scrollable="false"
lineColor="#00A9FF"
lineWidth="48rpx"
lineHeight="4rpx"
:activeStyle="{
'font-family': 'PingFang SC',
'font-weight': 500,
'font-size': '32rpx',
'line-height': 1.4,
'color': '#00A9FF',
}"
:inactiveStyle="{
'font-family': 'PingFang SC',
'font-weight': 400,
'font-size': '32rpx',
'line-height': 1.4,
'color': '#191919',
}"
@click="clickTabs"
></uv-tabs>
</view>
<!-- </uv-sticky> -->
<view class="detail" v-if="displayContent">
<uv-parse :content="displayContent"></uv-parse>
</view>
</view>
<view class="flex bottom">
<button plain class="flex flex-column btn btn-simple" open-type="contact">
<image class="icon" src="@/pages_order/static/product/icon-service.png" mode="widthFix"></image>
<view>客服</view>
</button>
<view class="flex operate">
<button class="flex btn btn-palin" @click="onCollect">{{ isCollected ? '移除收藏' : '收藏' }}</button>
<button class="flex btn btn-primary" @click="onBuy">立即购买</button>
</view>
</view>
<orderInfoPopup ref="orderInfoPopup" :data="detail" @timeChange="selectTime = $event"></orderInfoPopup>
</view>
</template>
<script>
import timeOptionsSelect from '@/pages_order/order/orderConfirm/timeOptionsSelect.vue'
import commentList from './commentList.vue'
import orderInfoPopup from '@/pages_order/order/orderConfirm/infoPopup.vue'
export default {
components: {
timeOptionsSelect,
commentList,
orderInfoPopup,
},
data() {
return {
id: null,
detail: {},
next: 'createOrder', // createOrder | addCart
commentList: [],
tabs: [
{ name: '行程亮点' },
{ name: '课程目标' },
{ name: '详细行程' },
],
current: 0,
selectTime: null,
}
},
computed: {
bannerList() {
const { image } = this.detail
if (!image) {
return []
}
return Array.isArray(image) ? image : image.split(',')
},
tagList() {
const { tagDetails } = this.detail || {}
return tagDetails?.length ? tagDetails.split('、') : []
},
priceInt() {
return Math.floor(this.detail.priceDiscount)
},
priceFrac() {
let frac = this.detail.priceDiscount % this.priceInt
return frac > 0 ? frac.toFixed(2).slice(1) : ''
},
displayContent() {
const {
special,
target,
process,
} = this.detail
if (this.current == 0) {
return special
} else if (this.current == 1) {
return target
} else if (this.current == 2) {
return process
}
return ''
},
isCollected() {
return this.detail.isCollection == '1'
},
},
onLoad(arg) {
const { id } = arg
this.id = id
this.fetchDetail(id)
this.fetchComment(id)
},
methods: {
async fetchDetail(activityId) {
try {
const result = await this.$fetch('queryActivityById', { activityId })
this.detail = result
} catch (err) {
}
},
async fetchComment(activityId) {
try {
const queryParams = {
pageNo: 1,
pageSize: 2,
activityId,
}
this.commentList = (await this.$fetch('queryCommentList', queryParams, true, null, true))?.records
} catch (err) {
console.log('fetchComment', err)
}
},
async onCollect() {
let succ = await this.$store.dispatch('collect', this.id)
succ && this.fetchDetail(this.id)
},
onBuy() {
this.$refs.orderInfoPopup.open({ selectTime: this.selectTime })
},
jumpToCommentRecords() {
this.$utils.navigateTo(`/pages_order/comment/commentRecordsOfProduct?id=${this.id}`)
},
//点击tab栏
clickTabs({ index }) {
this.current = index
},
},
}
</script>
<style scoped lang="scss">
.page__view {
width: 100vw;
min-height: 100vh;
background: linear-gradient(#DAF3FF, #F3F3F3 500rpx, #F3F3F3);
position: relative;
}
.main {
width: 100vw;
// padding: calc(var(--status-bar-height) + 120rpx) 0 198rpx 0;
padding-bottom: 198rpx;
box-sizing: border-box;
}
.swiper {
/deep/ .uv-swiper-indicator__wrapper__dot,
/deep/ .uv-swiper-indicator__wrapper__dot--active {
width: 30rpx;
}
/deep/ .uv-swiper-indicator__wrapper__dot--active {
background: linear-gradient(to right, #21FEEC, #019AF9);
}
}
.summary {
width: 100%;
padding: 40rpx 32rpx;
box-sizing: border-box;
}
.card {
width: 100%;
padding: 32rpx;
box-sizing: border-box;
background: #FFFFFF;
border-radius: 24rpx;
& + & {
margin-top: 40rpx;
}
&-header {
font-family: PingFang SC;
font-weight: 500;
font-size: 32rpx;
line-height: 1.4;
color: #181818;
}
&-content {
margin-top: 16rpx;
}
&.info {
.desc {
font-size: 26rpx;
white-space: pre-wrap;
color: #8B8B8B;
}
.tags {
margin-top: 16rpx;
justify-content: flex-start;
flex-wrap: wrap;
gap: 16rpx;
.tag {
padding: 2rpx 14rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
line-height: 1.4;
color: #00A9FF;
background: #E9F8FF;
border: 2rpx solid #00A9FF;
border-radius: 8rpx;
}
}
.data {
margin-top: 16rpx;
justify-content: space-between;
}
.price {
justify-content: flex-start;
align-items: baseline;
column-gap: 6rpx;
&-val {
font-size: 24rpx;
font-weight: 500;
color: #FF4800;
.highlight {
font-size: 48rpx;
}
}
&-bef {
text-decoration: line-through;
font-size: 24rpx;
color: #8B8B8B;
}
}
.registered {
padding: 2rpx 10rpx;
font-weight: 500;
font-size: 30rpx;
color: #FF4800;
border: 2rpx solid #FF4800;
border-radius: 4rpx;
}
}
&.comment {
.card-header {
justify-content: space-between;
}
.btn {
column-gap: 4rpx;
font-size: 24rpx;
color: #8B8B8B;
.img {
width: 32rpx;
height: auto;
}
}
}
}
.detail {
// font-size: 0;
}
.bottom {
position: fixed;
left: 0;
bottom: 0;
z-index: 999;
justify-content: space-between;
column-gap: 16rpx;
width: 100vw;
// height: 198rpx;
padding: 24rpx 40rpx 0 40rpx;
padding-bottom: calc(env(safe-area-inset-bottom) + 24rpx);
background: #FFFFFF;
box-sizing: border-box;
.btn-simple {
border: none;
font-family: PingFang SC;
font-weight: 400;
font-size: 22rpx;
line-height: 1.1;
color: #999999;
.icon {
width: 52rpx;
height: auto;
margin-bottom: 4rpx;
}
}
.operate {
justify-content: flex-end;
column-gap: 16rpx;
.btn {
font-size: 36rpx;
font-weight: 500;
border-radius: 41rpx;
line-height: 1.4;
&-palin {
padding: 14rpx 46rpx;
color: #252545;
border: 2rpx solid #252545;
}
&-primary {
padding: 14rpx 62rpx;
color: #FFFFFF;
background: linear-gradient(to right, #21FEEC, #019AF9);
border: 2rpx solid #00A9FF;
}
}
}
}
</style>