Files
2025-12-04 18:22:22 +08:00

853 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view style="padding-bottom: 40rpx;">
<Popup :show="timePopup" :width="750" :padding="0" type="bottom" radius="32rpx 32rpx 0 0">
<reserve-time
@confirm="confirmSelectTime"
@close="timePopup = false"
/>
</Popup>
<!-- 费用明细弹窗 -->
<Popup :show="billPopup" :width='750' :padding="0" type="bottom" backgroundColor="#FBFBFB" radius="32rpx 32rpx 0 0">
<view class="ww100 box-s-b pop-improt typeof pr time-popup">
<image style="width: 64rpx;height: 64rpx;position: absolute; top: 26rpx;right: 30rpx;" src="@/static/icon/close2.png" mode="" @click="closeBillPopup"></image>
<view class="d-c-c pt42" style="margin-top: 38rpx;">
<text class="f34 fb">费用明细</text>
</view>
<view class="bg-white bill-info">
<!-- 网球场 -->
<view v-if="venue.type_id == 1">
<view class="title1 d-b-c">
<view>场地费</view>
<view>
<price-format color="#303133" :subscript-size="30" :first-size="30" :second-size="30" :price="bill.cdf.total"></price-format>
</view>
</view>
<view class="title2 d-b-c">
<view>场地费(¥{{ bill.cdf.price }}元/小时)</view>
<view>x{{ bill.cdf.nums }}</view>
</view>
</view>
<!-- 篮球场 -->
<view v-if="venue.type_id == 2">
<view class="title1 d-b-c">
<view>使用费</view>
<view>
<price-format color="#303133" :subscript-size="30" :first-size="30" :second-size="30" :price="bill.cdf.total"></price-format>
</view>
</view>
<view class="title2 d-b-c">
<view>¥{{ bill.cdf.price }}元/人</view>
<view>x1</view>
</view>
</view>
<view style="margin-top: 52rpx;" v-if="venue.type_id == 1">
<view class="title1 d-b-c">
<view>灯光费</view>
<view>
<price-format color="#303133" :subscript-size="30" :first-size="30" :second-size="30" :price="bill.dgf.total"></price-format>
</view>
</view>
<view class="title2 d-b-c">
<view>灯光费(¥{{ bill.dgf.price }}元/小时)</view>
<view>x{{ bill.dgf.nums }}</view>
</view>
</view>
<view class="line"></view>
<view class="title3 d-b-c">
<view>实付金额</view>
<view>
<price-format color="#303133" :subscript-size="30" :first-size="30" :second-size="30" :price="bill.total"></price-format>
</view>
</view>
</view>
<view class="price2 bg-white" style="margin: 0; padding: 56rpx 22rpx 42rpx;">
<view class="d-b-c price-block" style="margin: 0;">
<view class="d-f d-c j-c-b">
<view class="">
合计: <price-format color="#FF5951" :subscript-size="26" :first-size="40" :second-size="40" :price="bill.total"></price-format>
</view>
<view class="d-f j-c-c a-i-c" style="margin-top: 10rpx;" @click="closeBillPopup">
<view class="price-detail">费用明细</view>
<image style="width: 14rpx;height: 8rpx;margin-left: 10rpx;" src="@/static/icon/up.png" mode=""></image>
</view>
</view>
<view class="price-btn" @tap="toReserve">立即预约</view>
</view>
</view>
</view>
</Popup>
<navbar title="预约网球场馆"></navbar>
<!-- <view class="banner">
<banner :itemData="bannerData"></banner>
</view> -->
<!-- 信息介绍 -->
<view class="info-block">
<view class="info-title mx-30rpx">{{ venue.name }}</view>
<view class="d-f mx-30rpx">
<uni-rate v-model="venue.star" active-color="#FF5951" :size="18" />
<text class="rate">{{ venue.star }}推荐</text>
</view>
<view class="time mx-30rpx">营业时间:{{ venue.day_time }} {{ venue.start_time }}-{{ venue.end_time }}</view>
<view class="line"></view>
<view class="d-b-c mx-30rpx">
<view class="d-f">
<image style="width: 36rpx;height: 36rpx;margin-top: 4rpx;" src="@/static/icon/location2.png"
mode=""></image>
<view class="">
<view class="address-time">{{ venue.address }}</view>
<view class="address-time">距您{{ venue.distance }}km</view>
</view>
</view>
<view class="d-f">
<view class="d-f d-c a-i-c" style="margin-right: 20rpx;" @tap="handleLocation">
<image style="width: 64rpx;height: 64rpx;margin-top: 2rpx" src="@/static/icon/share.png"
mode=""></image>
<view class="mark-text">导航</view>
</view>
<view class="d-f d-c a-i-c" @tap="handleCall">
<image style="width: 64rpx;height: 64rpx;margin-top: 2rpx" src="@/static/icon/mobile.png"
mode=""></image>
<view class="mark-text">电话</view>
</view>
</view>
</view>
</view>
<!-- 分隔线 -->
<view class="split-line"></view>
<!-- 网球场——场馆信息 -->
<view class="info-block mx-30rpx" v-if="typeId == 1">
<view class="tag-block">
<view class="tag-title">立即预定</view>
<view class="tag">
<view class="tag1">可预约</view>
<view class="tag2">已选中</view>
<view class="tag3">不可约</view>
</view>
</view>
<view class="date-block">
<view class="">
<view class="date1-block">
<view class="date1-block-item bg-f7f7f7">
<view class="">周三</view>
<view class="">12/03</view>
</view>
<view class="date1-block-item bg-365A9A text-fff">
<view class="">周三</view>
<view class="">12/03</view>
</view>
<view class="date1-block-item bg-f7f7f7">
<view class="">周三</view>
<view class="">12/03</view>
</view>
<view class="date1-block-item bg-f7f7f7">
<view class="">周三</view>
<view class="">12/03</view>
</view>
</view>
</view>
</view>
<!-- <view class="d-f">
<view class="tab" v-for="(item, index) in tab" :key="index"
:style="currentTab === item.type ? 'background-color: #F0F5FF; color: #365A9A;' : ''"
@tap="handleChangeTab(item)" >
{{ item.name }}
</view>
</view>
<view class="">
<view class="" v-for="(item, index) in venueRoomLists" :key="index">
<view class="d-b-c">
<view class="">
<image style="width: 200rpx;height: 200rpx;border-radius: 10rpx; margin-right: 32rpx;" :src="item.img" mode=""></image>
</view>
<view class="flex-1">
<view class="cg-name">{{ item.title }}</view>
<view class="d-b-c">
<view class="">
<price-format color="#FF5951" :subscript-size="26" :first-size="38" :second-size="26" :price="item.price"></price-format>
</view>
<view class="reserve-btn" @tap="heandleToReserve(item.id)">
预定
</view>
</view>
</view>
</view>
<view class="d-f a-i-c" style="margin-top: 16rpx;">
<view class="time-block" v-for="(item, index) in 17" :key="index">
<view class="time-block-text font-400 text-20rpx leading-28rpx" :style="index === 1 ? 'color:#C9C9C9;' : ''">{{ item + 5 }}</view>
<view class="time-block-box h-12rpx rounded-6rpx mt-4rpx" :style="index === 1 ? 'color:#C9C9C9;' : ''"></view>
</view>
</view>
<view class="line"></view>
</view>
</view> -->
</view>
<!-- 篮球场场馆信息 -->
<view class="info-block" v-if="typeId == 2">
<view class="tab-bar-scroll mx-30rpx">
<view class="tab-bar">
<view v-for="(item, idx) in venueRoomLists" :key="item.display" class="tab-bar-item"
:class="{ active: idx === selectedRoomIndex}" @click="handleTabClick(idx)">
{{ item.title }}
</view>
</view>
</view>
<view class="line"></view>
<view class="mx-30rpx">
<view class="reserve-time">预定时间</view>
<view class="reserve-desc" @click="timePopup = true">
<view class="reserve-desc-title">默认4小时注意闭馆时间</view>
<view class="reserve-desc-info">
<view class="">{{ date || '请选择' }}</view>
<view class="">
<image class="" src="@/static/icon/right.png" style="width: 32rpx; height: 32rpx;"></image>
</view>
</view>
</view>
</view>
</view>
<view class="price" v-if="showPrice && typeId == 2">
<view class="line"></view>
<view class="d-b-c price-block">
<view class="d-f d-c j-c-b">
<view class="">
合计 <price-format color="#FF5951" :subscript-size="26" :first-size="40" :second-size="40" :price="bill.total"></price-format>
</view>
<view class="d-f j-c-c a-i-c" style="margin-top: 10rpx;" @tap="handleShowBill">
<view class="price-detail">费用明细</view>
<image style="width: 14rpx;height: 8rpx;margin-left: 10rpx;" src="@/static/icon/down.png" mode=""></image>
</view>
</view>
<view class="price-btn" @tap="toReserve">立即预约</view>
</view>
</view>
</view>
</template>
<script>
import navbar from '@/components/navbar.vue';
import banner from '@/components/diy/banner/banner.vue';
import priceFormat from '@/components/price-format/price-format.vue';
import ReserveTime from '@/components/reserve-time'
import Popup from '@/components/uni-popup.vue';
export default {
components: {
navbar,
banner,
priceFormat,
Popup,
ReserveTime
},
data() {
return {
id: 0,
typeId: 1,
bannerData: {
data: [],
style: { btnColor: "#ffffff", background: "#ffffff", btnShape: "round", imgShape: "round", height: "330" }
},
selectedRoomIndex: 0, // 篮球场--场馆信息-选中tab索引
value: 4,
currentTab: 1,
tab: [
{ type: 1, name: '今天' },
{ type: 2, name: '明天' },
{ type: 3, name: '后天' },
],
venue: {},
venueRoomLists: [],
loadding: true,
timePopup: false,
date: '',
showPrice: true,
bill: {
cdf: {
nums: 0, // 场地费小时数
price: 0, // 场地费单价
total: 0 // 场地费总价
},
dgf: {
nums: 0, // 灯光数量
price: 0, // 灯光单价
total: 0 // 灯光总价
},
total: 0 // 总价
},
billPopup: false,
};
},
onLoad(args) {
this.id = args.id || 0
this.typeId = args.typeId || 1
this.getData()
this.handleGetVenueRoom()
},
methods: {
getData() {
let self = this;
uni.showLoading({
title: '加载中'
});
// 获取场馆详情
self._post(
'ground.ground/groundDetails',
{
app_id: self.getAppId(),
id: self.id,
latitude: uni.getStorageSync('latitude') || '',
longitude: uni.getStorageSync('longitude') || '',
},
function (res) {
if (res.code) {
self.loadding = false;
self.venue = res.data.lists
res.data.lists.image_arr.map(items => {
self.bannerData.data.push({ imgUrl: items, height: '400px' })
})
}
}
)
},
// 获取场馆包间列表
handleGetVenueRoom() {
let self = this;
uni.showLoading({
title: '加载中'
});
self._post(
'ground.ground/groundRoomLists',
{
app_id: self.getAppId(),
ground_id: self.id,
},
function (res) {
if (res.code) {
self.venueRoomLists = res.data.lists
console.log("🚀 ~ self.venueRoomLists:", self.venueRoomLists)
self.loadding = false;
}
}
)
},
// 篮球场场馆-切换tab
handleTabClick(idx) {
this.selectedRoomIndex = idx
},
// 切换tab
handleChangeTab(e) {
this.currentTab = e.type;
this.handleGetVenueRoom()
},
// 跳转预定页面
heandleToReserve(id) {
uni.navigateTo({
url: `/bundle/reserve/reserve?venueId=${this.venue.id}&roomId=${id}`
});
},
// 处理导航
handleLocation() {
uni.openLocation({
latitude: this.venue.latitude,
longitude: this.venue.longitude,
name: this.venue.name,
address: this.venue.address,
scale: 18
});
},
// 处理拨打电话
handleCall() {
uni.makePhoneCall({
phoneNumber: this.venue.contact_phone
});
},
// 确认选择时间
confirmSelectTime(e) {
this.date = e.value
let self = this
// 计算费用明细
uni.showLoading({
title: '加载中'
});
// 计算费用明细
self._post(
'ground.ground/countPrice',
{
app_id: self.getAppId(),
room_id: self.id,
nums: 4,
type_id: self.venue.type_id,
},
function(res) {
const result = res.data.lists
self.bill = {
total: result.order_amount,
cdf: {
nums: result.nums,
price: result.room_price,
total: result.room_all_price
},
dgf: {
nums: result.nums,
price: result.light_price,
total: result.light_all_price
}
}
self.loadding = false;
}
)
},
// 显示费用明细
handleShowBill() {
this.showPrice = false;
this.billPopup = true;
},
closeBillPopup() {
this.billPopup = false;
this.showPrice = true;
},
// 篮球场-立即预约
toReserve() {
if (!this.date) {
uni.showToast({
title: '请选择预约时间',
icon: 'none'
});
return;
}
uni.navigateTo({
url: `/bundle/reserve/confirm?venueId=${this.venue.id}&roomId=${this.venueRoomLists[this.selectedRoomIndex].id}&date=${this.date}&typeId=${this.venue.type_id}`
});
},
}
};
</script>
<style lang="scss">
page {
background-color: #fff;
}
.banner {
.diy-banner-box {
margin-bottom: 0 !important;
}
}
.info-block {
.info-title {
font-weight: bold;
font-size: 34rpx;
color: #303133;
line-height: 48rpx;
margin-bottom: 10rpx;
}
.rate {
margin-left: 8rpx;
font-weight: 400;
font-size: 26rpx;
color: #606266;
line-height: 36rpx;
}
.time {
font-size: 26rpx;
color: #606266;
line-height: 48rpx;
}
.line {
height: 2rpx;
background-color: #F6F7F9;
margin: 24rpx 0;
}
.address-time {
font-weight: 400;
font-size: 26rpx;
color: #606266;
line-height: 36rpx;
}
.tab {
width: 108rpx;
height: 52rpx;
text-align: center;
line-height: 52rpx;
background-color: #F7F7F7;
font-size: 26rpx;
color: #606266;
border-radius: 8rpx;
margin-top: 16rpx;
margin-right: 10rpx;
margin-bottom: 32rpx;
}
.cg-name {
font-size: 28rpx;
color: #303133;
line-height: 40rpx;
margin-bottom: 74rpx;
}
.reserve-btn {
width: 104rpx;
height: 52rpx;
border-radius: 10rpx;
border: 2rpx solid #365A9A;
font-weight: 400;
font-size: 26rpx;
color: #365A9A;
line-height: 52rpx;
text-align: center;
}
.time-block {
text-align: center;
margin-right: 8rpx;
.time-block-text {
font-weight: 400;
font-size: 20rpx;
color: #365A9A;
line-height: 28rpx;
text-align: center;
}
.time-block-box {
width: 30rpx;
height: 12rpx;
background: #365A9A;
border-radius: 6rpx;
}
}
.tag-block {
display: flex;
justify-content: space-between;
}
.tag-title {
font-weight: 500;
font-size: 32rpx;
color: #303133;
line-height: 44rpx;
padding-top: 10rpx;
}
.tag {
display: flex;
}
.tag1, .tag2, .tag3 {
font-size: 24rpx;
line-height: 34rpx;
color: #909399;
display: flex;
align-items: center;
margin-right: 20rpx;
}
.tag1::before {
content: " ";
display: block;
width: 20rpx;
height: 20rpx;
border-radius: 100%;
background: #F7F7F7;
border: 2rpx solid #E9ECF4;
margin-right: 10rpx;
}
.tag2::before {
content: " ";
display: block;
width: 20rpx;
height: 20rpx;
border-radius: 100%;
background: #365A9A;
border: 2rpx solid #365A9A;
margin-right: 10rpx;
}
.tag3::before {
content: " ";
display: block;
width: 20rpx;
height: 20rpx;
border-radius: 100%;
background: #D4DAE6;
border: 2rpx solid #D4DAE6;
margin-right: 10rpx;
}
.text-303133 {
color: #303133;
}
.text-fff {
color: #fff
}
.bg-f7f7f7 {
background-color: #F7F7F7;
}
.bg-365A9A {
background-color: #365A9A;
}
.bg-D4DAE6 {
background-color: #D4DAE6;
}
.date1-block {
display: flex;
align-items: center;
margin-top: 20rpx;
.date1-block-item {
width: 128rpx;
height: 100rpx;
border-radius: 16rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-right: 20rpx;
}
}
}
.tab-bar-scroll {
overflow-x: auto;
background: #fff;
}
.tab-bar {
display: flex;
flex-direction: row;
background: #fff;
}
.tab-bar-item:first-child{
padding: 0 !important;
}
.tab-bar-item {
flex-shrink: 0;
padding: 0 32rpx;
height: 62rpx;
line-height: 62rpx;
font-size: 32rpx;
color: #303133;
margin: 10rpx 16rpx 10rpx 0;
border-bottom: 4rpx solid transparent;
cursor: pointer;
}
.tab-bar-item.active {
color: #365A9A;
font-weight: bold;
position: relative;
}
.tab-bar-item.active::after {
content: '';
display: block;
width: 60rpx;
height: 10rpx;
background: #365A9A;
border-radius: 6rpx;
position: absolute;
left: 50%;
bottom: -10rpx;
transform: translateX(-50%);
}
.mx-30rpx {
margin-left: 30rpx;
margin-right: 30rpx;
}
.reserve-time {
font-weight: 500;
font-size: 32rpx;
color: #303133;
line-height: 44rpx;
}
.reserve-desc {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 22rpx;
color: #606266;
}
.reserve-desc-info {
display: flex;
align-items: center;
}
.box {
border-radius: 16rpx;
padding: 32rpx 30rpx;
margin: 0 30rpx;
}
.title {
font-size: 32rpx;
color: #303133;
line-height: 44rpx;
margin-bottom: 28rpx;
}
.desc {
font-weight: 500;
font-size: 26rpx;
color: #303133;
line-height: 48rpx;
margin-bottom: 16rpx;
}
.desc:last-child {
margin-bottom: 0;
}
.current {
position: absolute;
left: 0;
top: 38rpx;
width: 8rpx;
height: 32rpx;
background-color: #365A9A;
border-radius: 4rpx;
}
.dot {
width: 8rpx;
height: 8rpx;
background: #6A6363;
margin-right: 12rpx;
}
.mt20 {
margin-top: 20rpx;
}
.desc2 {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.desc2:last-child {
margin-bottom: 0;
}
.price {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
.line {
height: 2rpx;
background: #E5E5E5;
width: 100%;
}
.price-block {
margin: 42rpx 22rpx;
}
.price-detail {
color: #365A9A;
font-size: 24rpx;
line-height: 34rpx;
}
}
.price-btn {
width: 368rpx;
height: 90rpx;
line-height: 90rpx;
text-align: center;
background: #365A9A;
border-radius: 8rpx;
font-size: 32rpx;
color: #FFF;
}
.bill-info {
border-radius: 16rpx;
margin: 32rpx 30rpx 22rpx;
padding: 48rpx 30rpx 30rpx;
.title1 {
font-size: 30rpx;
color: #303133;
line-height: 42rpx;
}
.title2 {
margin-top: 12rpx;
font-weight: 400;
font-size: 24rpx;
color: #909399;
line-height: 34rpx;
}
.line {
border: 2rpx solid #F6F7F9;
margin: 34rpx 0 30rpx;
}
.title3 {
font-size: 30rpx;
color: #303133;
line-height: 42rpx;
}
}
</style>