Commit b6accc7b authored by 潘永坪's avatar 潘永坪

图片修改

parent 6b6e686b
<template>
<div>
<u-calendar
:show="show"
@confirm="onConfirm"
@close="show=false"
:maxDate="maxDate"
:defaultDate="defaultDate"
:formatter='formatter'
ref="calendar2"
></u-calendar>
</div>
</template>
<script>
export default {
props: ["dateList"],
watch: {
dateList:{
handler(newValue, oldValue){
if(newValue&&newValue.length>0){
this.maxDate=newValue[newValue.length-1].startTime.substr(0,10)
}
},
deep:true,
immediate:true
}
},
data() {
return {
date: '', //选择的日期
show: false, //控制日历显示隐藏
defaultDate:'', //默认日期
maxDate:'',//最大日期
}
},
created() { //默认为第一天
this.$refs.calendar2.setFormatter(this.formatter)
},
methods: {
//---年月日转化
formatDate(date) {
let year = date.getFullYear()
let month = date.getMonth() + 1;
if (month < 10) {
month = '0' + month
}
let days = date.getDate();
if (days < 10) {
days = '0' + days
}
let dates = year + "-" + month + "-" + days
return dates
},
//---日期确认事件
onConfirm(date) {
this.show = false;
this.$emit("dateConfig", date[0])
},
//---时间格式转换
formatter(day) {
let year = day.date.getFullYear()
let month = day.date.getMonth() + 1;
if (month < 10) {
month = '0' + month
}
let days = day.date.getDate();
if (days < 10) {
days = '0' + days
}
let dates = year + "-" + month + "-" + days
//真机调试手极端报错,暂时注释
// this.dateList.forEach((item, index) => {
// if (item.startTime.substr(0, 10) == dates) {
// day.bottomInfo = "¥" + item.sellingPrice
// day.dot = true
// }
// })
// if (!day.bottomInfo) {
// day.type = "disabled"
// }
return day
},
//---设置默认日期方法
setDefaultDate(val) {
let dates = val.split("-")
let year = parseInt(dates[0])
let month = parseInt(dates[1]) - 1
let day = parseInt(dates[2])
this.defaultDate = new Date(year, month, day)
},
}
}
</script>
<style scoped="scoped">
</style>
<template>
<view class="area-box">
<view class="top" @click="sure()">
<view class="top-left">
选择(索道)出发站点
</view>
<view>
<u-icon name="close"></u-icon>
</view>
</view>
<view v-if="defaultAreaCode" class="defaultArea">
<view>
<text>
当前站点:
</text>
<text>
{{areaObj.areaName}}
</text>
</view>
<view>
<text>
当前排队人数:
</text>
<text>
{{sortIfo.peopleNumber}}
</text>
</view>
<view>
<text>
预计进入排队等候区时间:
</text>
<text>
{{sortIfo.sortTotalTime}}
</text>
</view>
<view>
<text>
退票规则:
</text>
<text>
不可退
</text>
</view>
<view>
<image src="../static/images/scenicSingleOrder/chooseArea.jpg" mode="widthFix"></image>
</view>
<view>
<a class="middle-btn" @click="sure()">确定</a>
</view>
</view>
<template v-else>
<view class="bottom">
<view class="bottom1">
<view>
您所在位置距离“{{areaList[distanceIndex].areaName}}”较近
</view>
<view class="bottom1-choose">
建议选择<text>{{areaList[distanceIndex].areaName}}</text>
</view>
<view class="bottom1-btn">
<text class="btn" @click="getSort(item)" v-for="(item,index) of areaList" :key="index">
{{item.areaName}}
</text>
</view>
</view>
<view class="bottom2">
<image src="../static/images/scenicSingleOrder/chooseArea.jpg" mode="widthFix"></image>
<view style="margin-top: 20rpx;">选错站点可导致排队号码无效。</view>
<view>若无法确定站点,请向索道工作人员咨询。</view>
</view>
</view>
<view class="pop-wrap" v-show="showPop">
<view class="pop-content">
<view>
<text>
您选择的站点是:
</text>
<text>
{{areaObj.areaName}}
</text>
</view>
<template v-if="sortIfo">
<view>
<text>
当前排队人数:
</text>
<text>
{{sortIfo.peopleNumber}}
</text>
</view>
<view>
<text>
预计进入排队等候区时间:
</text>
<text>
{{sortIfo.sortTotalTime}}
</text>
</view>
</template>
<view>
<text>
退票规则:
</text>
<text>
不可退
</text>
</view>
<view>
返程时,根据现场情况需重新取号
</view>
<view v-if="!sortIfo" style="font-size:32rpx;color: #ff0000;">
未找到本站信息,请根据现场大屏幕信息合理购票
</view>
<view style="text-align: center;">
<text class="middle-btn" @click="hidePop()" style="color: #333;margin-right: 48rpx;">
取消
</text>
<text class="middle-btn" @click="sure()">
确定
</text>
</view>
</view>
</view>
</template>
</view>
</template>
<script>
export default {
props: ['areaList', 'sortArr','defaultAreaCode'],
data() {
return {
showPop: false, //控制弹窗显示隐藏
distanceIndex:0, //最小距离下标
distanceList: [], //所有距离列表
sortIfo: '', //排队信息
areaObj: {
areaCode: '', //选中的区域编码
areaName: '', //选中的区域名字
},
longitude:'',//当前位置经度
latitude:'',//当前位置纬度
}
},
created() {
//如果有默认站点
if(this.defaultAreaCode&&this.sortArr.length>0){
this.sortArr.forEach(item=>{
if(item.projectId==this.defaultAreaCode){
this.sortIfo=item
this.sortIfo.peopleNumber = Math.max(item.sortTotalCapacity-item.showEnd,0)
}
})
this.areaList.forEach(item=>{
if(item.areaCode==this.defaultAreaCode){
this.areaObj.areaCode=item.areaCode
this.areaObj.areaName=item.areaName
}
})
return
}
uni.getLocation({
type: 'wgs84',
success:(res)=>{
this.longitude=res.longitude
this.latitude=res.latitude
this.getMinDistance()
}
})
},
methods: {
//---隐藏弹窗
hidePop() {
this.showPop = false
},
//---返回隐藏该组件
returnClose() {
this.$parent.closeArea()
},
//---隐藏该组件
sure() {
this.showPop = false
this.$parent.closeArea()
this.$emit('areaSure', this.areaObj)
},
//---获取排号信息
getSort(item) {
this.showPop = true
let data = {
areaCode: item.areaCode,
merchantCode: this.merchantCode, //商户code
}
this.areaObj.areaCode = item.areaCode //获取选中的站点code,便于找到返回数据的下标
this.areaObj.areaName = item.areaName
this.sortArr.forEach((item)=>{
item.peopleNumber = Math.max(item.sortTotalCapacity-item.showEnd,0)
})
this.sortIfo=this.sortArr.find(item=>item.projectId==this.areaObj.areaCode)||''
},
//---计算距离
getMinDistance() {
if (this.areaList.length > 0) {
this.areaList.forEach((item) => { //计算两个站点的分别距离
let lat1=this.latitude||0
let lng1=this.longitude||0
let lat2=item.latitude||0
let lng2=item.longitude||0
let distance = this.$commonjs.getDistance(lat1,lng1,lat2,lng2)
this.distanceList.push(distance)
})
let minDistance = Math.min.apply(null, this.distanceList)
this.distanceIndex = this.distanceList.indexOf(minDistance)
}
}
}
}
</script>
<style scoped="scoped" lang="scss">
/* 默认站点 */
.defaultArea{
padding:24rpx;
}
.defaultArea view{
margin-top:40rpx;
text-align: center;
}
.defaultArea view text:last-child{
color: #e70313;
font-size:32rpx;
font-weight: bold;
}
.area-box{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index:99;
background: #f5f5f5;
}
.top{
display: flex;
justify-content: space-around;
background: #fff;
height: 80rpx;
align-items: center;
padding: 0 24rpx;
}
.top-left{
flex: 1;
text-align: center;
}
.bottom1{
text-align: center;
view{
margin-top:30rpx;
}
}
.bottom1-choose{
font-size: 32rpx;
color: #ff0000;
text{
font-weight: bold;
font-size: 36rpx;
}
}
.bottom1-btn text:not(:last-child){
margin-right: 48rpx;
}
.bottom2{
margin-top: 60rpx;
font-size: 32rpx;
color: #ff0000;
text-align: center;
}
// 弹窗
.pop-wrap{
background: rgba(0,0,0,0.1);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
}
.pop-content{
background: #FFFFFF;
width: 85%;
border-radius: 10rpx;
padding: 50rpx 20rpx;
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 300rpx auto 0 auto;
view:not(:first-child){
margin-top: 30rpx;
}
}
.pop-content view:not(:last-child) text:last-child{
font-size:36rpx;
font-weight: bolder;
color: #f40000
}
</style>
<template>
<view class="contact-box">
<u-popup :show="contactsShow" @close="contactsShow=false">
<view class="top">
<u-icon name="close" @click="contactsShow=false"></u-icon>
<text>
需填写{{buyNum}}位联系人
<text v-if="buyNum-chooseContact.length>0">
,还需
<text class="top-number">{{buyNum-chooseContact.length}}</text>
位出行人
</text>
</text>
<text @click="config()" class="top-sure">
确定
</text>
</view>
<view class="bottom">
<view @click="showEdit()" class="bottom-add">
<text>
+添加旅客信息
</text>
</view>
<checkbox-group @change="chooseContactChange">
<view class="bottom-list" v-for="(item,index) of contactData" :key="item.id">
<label>
<checkbox :value="JSON.stringify(item)" :checked="item.ifChoose" color="#3688ff" />
<view class="bottom-content">
<view>
{{item.name}}
</view>
<view>
<text>
身份证
</text>
{{item.credentialNumber?item.credentialNumber.substr(0,3)+"****"+item.credentialNumber.substr(14,4):"无"}}
</view>
</view>
</label>
<view @click="goEdit(item)" style="margin-right:20rpx;">
<u-icon name="edit-pen" color="#3688ff" size="28"></u-icon>
</view>
<view @click="clickDele(item.id)">
<u-icon name="trash-fill" color="#3688ff" size="28"></u-icon>
</view>
<u-modal :show="showModal" @confirm="confirmDele" @cancel="showModal=false" showCancelButton title="确认删除该联系人" ></u-modal>
</view>
</checkbox-group>
</view>
</u-popup>
</view>
</template>
<script>
export default {
props: ["contactData", "orderTouristList", "buyNum"],
watch: {
orderTouristList: {
handler(newValue, oldValue) {
if (newValue) {
this.chooseContact = this.orderTouristList
}
},
deep: true,
immediate: true
}
},
data() {
return {
contactsShow: false, //控制联系人弹窗显示隐藏
chooseContact: [], //选中的联系人
showModal: false, //确认弹窗显示隐藏
contactId:'',//删除联系人的Id
}
},
methods: {
//---点击新增,展示编辑联系人弹窗,并传空值给编辑弹窗
showEdit() {
this.contactsShow=false
this.$parent.showEdit()
this.$emit("getEditContact", "")
},
//---展示编辑弹窗,并传值给编辑弹窗
goEdit(obj) {
this.contactsShow=false
this.$parent.showEdit()
this.$emit("getEditContact", obj)
},
//---确定选中的联系人
config() {
this.contactsShow = false
this.$emit("contactListConfig", this.chooseContact)
},
//---联系人姓名变化
chooseContactChange(e){
let value=e.detail.value
let arr=[]
value.forEach(item=>{
arr.push(JSON.parse(item))
})
this.chooseContact=arr
if (arr.length == this.buyNum) { //当选择的人数等于需要填的人数时关闭弹窗
this.config()
}
if (arr.length > this.buyNum) {
arr.shift()
this.config()
}
},
//---点击删除
clickDele(id) {
this.showModal = true
this.contactId=id
},
//---确认删除
confirmDele(){
let data={
id:this.contactId
}
this.$request('wechatUser/contact/deleteContact', data).then((res) => {
if (res.code == '00') {
uni.showToast({
title:'删除成功',
icon:'none'
})
this.showModal = false
this.contactsShow=false
this.$parent.getContactList()
} else {
uni.showToast({
title:res.message,
icon:'none'
})
}
}).catch(() => {
this.showModal = false
})
}
}
}
</script>
<style scoped="scoped" lang="scss">
.top {
height:100rpx;
display: flex;
justify-content: space-between;
background: #f0f0f0;
align-items: center;
padding: 0 24rpx;
}
.top-sure {
color: var(--main-color);
font-size: 28rpx;
}
.top-number{
color: #f9690e;
font-size: 32rpx;
font-weight:bold;
}
.bottom {
padding:0 24rpx 80rpx 24rpx;
}
.bottom-add {
height:130rpx;
display: flex;
align-items: center;
border-bottom: 1px solid #e6e6e6;
width: 100%;
justify-content: center;
}
.bottom-add text{
width:280rpx;
height: 65rpx;
text-align: center;
line-height:65rpx;
border: 1px solid var(--main-color);
color:var(--main-color);
display: inline-block;
border-radius:5rpx;
}
.bottom-list{
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #E6E6E6;
padding:25rpx 0;
}
.bottom-list label {
display: flex;
flex: 1;
align-items: center;
}
.bottom-content {
flex: 1;
margin-left: 40rpx;
}
.bottom-content view {
font-size:28rpx;
color: #666666;
}
.bottom-content view:not(:first-child) {
margin-top: 10rpx;
}
.bottom-content view text {
display: inline-block;
width: 100rpx;
}
</style>
<template>
<view class="editBox" v-show="showEdit">
<view @click="close()" class="return">
<u-icon name="close"></u-icon>
</view>
<view class="editTop">
</view>
<view class="editBottom">
<view class="bottomContent">
<view>
<text>
姓名:
</text>
<input v-model.trim="name" placeholder="请输入中文姓名" />
</view>
<view>
<text>
身份证:
</text>
<input v-model.trim="credentialNumber" maxlength="18" placeholder="请输入身份证号码" />
</view>
<view>
<!--编辑-->
<a class="middle-btn" @click="keepEdit()" v-if="editBtn">完成</a>
<!--新增-->
<a class="middle-btn" @click="keepPlus()" v-else="">完成</a>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: ["editContact"],
data() {
return {
showEdit: false, //控制组件显示隐藏
name: "", //姓名
credentialNumber: "", //身份证号
reviseContactId: "", //被修改人id
editBtn: "", //控制编辑完成按钮显示隐藏
}
},
watch: {
editContact: { //
handler(newValue, oldValue) {
if (newValue) {
this.editBtn = true
} else {
this.editBtn = false
}
this.name = newValue.name||''
this.credentialNumber = newValue.credentialNumber||''
this.reviseContactId = newValue.id||''
},
deep: false,
immediate: false
}
},
methods: {
//---关闭弹窗
close() {
this.showEdit = false
},
//---新增保存
keepPlus() {
if (!this.$commonjs.nameReg().test(this.name)) {
uni.showToast({
title:'请输入正确的中文名字',
icon:'none'
})
return
}
if (!this.$commonjs.idReg().test(this.credentialNumber)) {
uni.showToast({
title:'请输入正确身份证号',
icon:'none'
})
return
}
let data = {
name: this.name, //保存姓名
phone: "", //电话号码
credentialNumber: this.credentialNumber, //身份证号
category: "", //成人或者儿童
openid: uni.getStorageSync("openid"), //用户Id
credentialsType: "", //证件类型
merchantType: 1, //商户类型,1.景区,2.酒店,3.餐饮
}
this.$request("wechatUser/contact/saveContact", data).then((res) => {
if (res.code == "00") {
uni.showToast({
title:'保存成功',
icon:'none'
})
this.$parent.addChoose()
this.showEdit = false
this.name = "" //成功之后清空数据,防止下次新增的时候出现之前的数据
this.credentialNumber = ""
} else {
uni.showToast({
title:res.message,
icon:'none'
})
}
})
},
//---编辑保存
keepEdit() {
if (!this.$commonjs.nameReg().test(this.name)) {
uni.showToast({
title:'请输入正确的中文名字',
icon:'none'
})
return
}
if (!this.$commonjs.idReg().test(this.credentialNumber)) {
uni.showToast({
title:'请输入正确身份证号',
icon:'none'
})
return
}
let data = {
name: this.name, //保存姓名
phone: "", //电话号码
credentialNumber: this.credentialNumber, //身份证号
category: "", //成人或者儿童
openid: uni.getStorageSync("openid"), //用户Id
credentialsType: "", //证件类型
merchantType: 1, //商户类型,1.景区,2.酒店,3.餐饮
id: this.reviseContactId, //被修改人id
}
this.$request("wechatUser/contact/updateContact", data).then((res) => {
if (res.code == "00") {
uni.showToast({
title:'修改成功',
icon:'none'
})
this.$parent.getContactList()
this.showEdit = false
} else {
uni.showToast({
title:res.message,
icon:'none'
})
}
})
}
}
}
</script>
<style scoped="scoped">
.editBox {
height: 100%;
background: #F5F5F5;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10000;
overflow-y: auto;
font-size:28rpx;
}
.return {
height:100rpx;
padding: 0 24rpx;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content:flex-end;
}
.editTop {
height:200rpx;
background: linear-gradient(to bottom, #2984ef, #d8eaf6);
}
.editBottom {
position: relative;
top: -80rpx;
padding: 0 20rpx;
}
.bottomContent {
border-radius: 20rpx;
background: #FFFFFF;
padding: 20rpx 20rpx 60rpx 20rpx;
}
.bottomContent view {
height: 100rpx;
align-items: center;
display: flex;
border-bottom: 1px solid #f0f0f0;
}
.bottomContent view text {
display: inline-block;
width: 120rpx;
text-align-last: justify;
margin-right: 20rpx;
}
.bottomContent view input {
flex: 1;
}
.bottomContent view:last-child {
display: flex;
justify-content: center;
align-items: center;
margin-top: 60rpx;
border: none;
}
</style>
<template>
<u-popup :show="show" :round="10" closeable @close="show=false">
<view class="time">
<view class="time-title">
时间选择
</view>
<view class="time-content" v-if="chooseTimeList&&chooseTimeList.length>0">
<!--库存大于零并且当前时间小于班次的开始时间才显示-->
<view
class='time-list'
v-for="(item,index) of chooseTimeList"
:class="{on:active==index}"
@click="chooseTime(index)"
:key="index" v-if="item.last>0"
>
<view>
{{item.startPlanTime?item.startPlanTime.substr(0,5):""}}
<text v-if="item.endPlanTime">-</text>
{{item.endPlanTime?item.endPlanTime.substr(0,5):""}}
</view>
<view>
剩余:{{item.last}}
</view>
</view>
</view>
<view style="padding: 0.5rem 0rem;color: #FF0000;" v-else>
空空如也...
</view>
<view class="time-sure">
<text class="big-btn" @click="confirm()">确定</text>
</view>
</view>
</u-popup>
</template>
<script>
export default {
props: ["chooseTimeList", "chooseTimeData", "timeActive"],
watch: {
timeActive: { //父组件选中的下标
handler(newValue, oldValue) {
if (newValue >= 0) {
this.active = newValue
}
},
deep: false,
immediate: false
},
},
data() {
return {
show: false, //控制该组件显示隐藏
active: 10000, //默认不选中
times: "", //时间
timeNumber: "", //当前时间转化为数字
}
},
methods: {
//---时间选择
chooseTime(i) {
this.active = i
this.times = this.chooseTimeList[i].startPlanTime
},
//---时间确认事件
confirm(date) {
this.show = false;
this.$emit("timeConfig", this.times)
},
},
mounted() {
let times = new Date().Format("yyyy-MM-dd hh:mm:ss")
this.timeNumber = parseInt(this.$commonjs.changeTime(times))
}
}
</script>
<style scoped="scoped">
.time {
padding:30rpx 20rpx 60rpx 20rpx;
text-align: center;
}
.time-title{
font-size:32rpx;
font-weight: bolder;
}
.time-content {
display: flex;
flex-wrap: wrap;
}
.time-list {
width: 30%;
height: 80rpx;
text-align: center;
line-height: 30rpx;
color: #666666;
background: rgb(242, 242, 242);
border-radius: 16rpx;
margin-right: 5%;
margin-top: 30rpx;
}
.time-list view:first-child {
margin-top: 10rpx;
}
.time-list view {
width: 100%;
text-align: center;
}
.time-content view:nth-child(3n) {
margin-right: 0;
}
.time-list.on {
background: none;
color: #3dbcff;
border: 1px solid #3dbcff;
box-sizing: border-box;
}
.time-sure{
margin-top: 30rpx;
}
</style>
<template>
<view class="orderBox">
<view class="head"> </view>
<view class="middle">
<!-- --------------------------------------------产品信息部分----------------------------------- -->
<view class="middle1">
<view class="middle1Product">
<view class="merchantName">
<text>
{{ productIfo.merchantName || '' }}
</text>
<text>
{{ productIfo.name || '' }}
</text>
</view>
<view @click="showBuyKnow()" class="buyKnow">
<view>
<text v-if="productIfo.backChangeRule == 0">不可退换</text>
<text v-if="productIfo.backChangeRule == 1">可退</text>
<text v-if="productIfo.backChangeRule == 2">随时可退</text>
<text v-if="productIfo.isFetch == 1">无需取号</text>
</view>
<view>
购买须知
<u-icon name="arrow-right"></u-icon>
</view>
</view>
</view>
<!--需要排队并且站点数大于1-->
<view class="middle-place" @click="openArea()" v-if="productIfo.isFetch == 1 && productIfo.productAreaList.length > 1 && showOpenArea">
<view> 出发站点 </view>
<view>
{{ areaObj.areaName || '请选择站点' }}
</view>
<view>
<u-icon name="arrow-right" color="#3688FF"></u-icon>
</view>
</view>
<!--需要排队并且为一个站点-->
<view class="middle-place" v-if="productIfo.isFetch == 1 && productIfo.productAreaList.length == 1 && showOpenArea" @click="getSortInfor()">
<view> 获取排队信息 </view>
<view>
{{ areaObj.areaName }}
</view>
<view>
<u-icon name="arrow-right" color="#3688FF"></u-icon>
</view>
</view>
<view class="middle1Date">
<text>游玩日期</text>
<scroll-view class="date-content" scroll-x="true" :scroll-left="dateScroll" v-if="dateList.length > 0">
<view class="date-list" v-for="(item, index) of dateList" :class="{ on: active == index }" @click="dateChoose(index)" :key="index">
<view class="date-time">
<text v-if="item.week">
<text v-if="item.week != '今天' && item.week != '明天' && item.week != '后天'"></text>
{{ item.week }}
</text>
{{ item.startTime ? item.startTime.substr(5, 5) : '' }}
</view>
<view class="date-price">
<text>¥</text><text>{{ item.sellingPrice }}</text>
</view>
<view v-if="active == index" class="date-icon">
<u-icon name="checkmark" color="#ffffff"></u-icon>
</view>
</view>
</scroll-view>
<text v-else class="no-date"> 不可购买 </text>
<view class="dateMore" @click="showCalendar()">
<view class="date-more-content">
<view>更多</view>
<view>日期</view>
</view>
<u-icon name="arrow-right" color="#3688FF"></u-icon>
</view>
</view>
<view class="middle1Time" v-if="productIfo.productType == 3">
<text> 游玩时间 </text>
<scroll-view class="time-content" scroll-x="true" :scroll-left="timeScroll" v-if="timeList > 0">
<view class="time-list" v-for="(item, index) of timeList" @click="chooseTime(index)" :class="{ on: timeActive == index }" :key="index">
<view>
{{ item.startPlanTime ? item.startPlanTime.substr(0, 5) : '' }}
<text v-if="item.endPlanTime">-</text>
{{ item.endPlanTime ? item.endPlanTime.substr(0, 5) : '' }}
</view>
<view> 剩余:{{ item.last }} </view>
</view>
</scroll-view>
<text class="no-time" v-if="startDate && endDate && timeList.length == 0"> 该日票种已售罄,请选择其他日期 </text>
<text class="no-time" v-if="!startDate || !endDate"> 请先选游玩日期 </text>
<view class="timeMore" @click="showTime()">
<view class="time-more-content">
<view>更多</view>
<view>时间</view>
</view>
<u-icon name="arrow-right" color="#3688FF"></u-icon>
</view>
</view>
<view class="middle1Number">
<view style="font-size: 32rpx; font-weight: bolder"> 购买数量 </view>
<view>
<u-number-box
button-size="36"
inputWidth="40"
:min="1"
:max="maxBookNum"
integer
v-model="buyNum"
@change="buyNumChange"
color="#fff"
bgColor="#3688FF"
iconStyle="color: #fff"
></u-number-box>
</view>
</view>
</view>
<!------------------------------------------------------额外服务部分---------------------------------------------------->
<!-- <view class="extraService" v-if="loadProductResVoList.length>0&&showErmai">
<view v-for="(item,index) of loadProductResVoList" :key="item.id">
<text>
<text style="font-size: 28rpx;font-weight: bold;">
{{item.name}}
</text>
<text style="font-size:20rpx;color: #666666;" v-if="item.deposit">(押金:¥{{item.deposit}})</text>
</text>
<label>
¥{{item.sellingPrice}}
<input type="checkbox" style="margin-left: 20rpx;" :value="item" v-model="choooseService" @change="extraChange(item,index)" />
</label>
</view>
</view> -->
<!-- ----------------------------------------------游客信息----------------------------------------- -->
<view class="middle2" v-if="productIfo.tripTemplateFlag != 2">
<view class="middle2Visitor">
<view class="visitorTitle">
<text> 游客信息 </text>
<text>
需填<text class="title-bold">{{ contactNum }}</text
>位出行人
<text class="title-bold" v-if="contactNum - orderTouristList.length > 0">,还需{{ contactNum - orderTouristList.length }}</text>
</text>
</view>
<view class="visitorPlus">
<view
class="plus-list"
:class="{ on: item.ifChoose == true }"
v-for="(item, index) of contactData.slice(0, 3)"
@click="visitorChoose(index)"
:key="item.id"
>
{{ item.name }}
</view>
<view @click="showContacts()" class="plus-list plus-list-last">
选择/新增
<u-icon name="arrow-right" color="#3688FF"></u-icon>
</view>
</view>
<view class="visitorEdit" v-show="orderTouristList.length > 0">
<view class="edit-list" v-for="(item, index) of orderTouristList" :key="item.id">
<view @click="delChooseContact(item, index)">
<u-icon name="close-circle" color="#3688ff" size="20"></u-icon>
</view>
<view>
{{ item.name }}
</view>
<view>
{{ item.credentialNumber ? item.credentialNumber.substr(0, 3) + '****' + item.credentialNumber.substr(14, 4) : '' }}
</view>
<view @click="showEdit(item)">
<u-icon name="edit-pen-fill" color="#3688ff" size="24"></u-icon>
</view>
</view>
</view>
</view>
<view class="middle2Phone" v-if="productIfo.tripTemplateFlag != 2">
<view class="phoneTitle"> 联系信息 </view>
<view class="phoneNumber">
<text> 联系电话: </text>
<input type="number" maxlength="11" placeholder="请输入联系电话" v-model.trim="ticketPhone" />
<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权获取</button>
</view>
</view>
</view>
<!-- --------------------------------------------------------产品押金部分-------------------------------------------------- -->
<view class="productDeposit" v-if="productIfo.deposit">
<text>
{{ productIfo.name }}
押金
</text>
<text style="color: #ff0000"> {{ productIfo.deposit }}</text>
</view>
<!-- ----------------------------------选中了额外服务之后,不再选额外服务的弹窗 ------------------------------------------------ -->
<!-- <view class="extraPop" v-show="showExtraPop">
<view>
<view>
{{extraChangeData.name}}
</view>
<view>
{{extraChangeData.details}}
</view>
<view>
<text @click="extraNo()">
不想感受
</text>
<text @click="extraYes()">
取消
</text>
</view>
</view>
</view> -->
<!-- -----------------------------------支付之后有额外服务,没有选额外服务的弹窗------------------------------------- -->
<!-- <view class="extraPop" v-show="showPayExtraPop">
<view>
<view>
云智能导览耳机
</view>
<view style="text-align: center;">
深度了解索道典故由来,周边攻略推荐
</view>
<view>
<text @click="payExtraNo()">
不需要
</text>
<text @click="payExtraYes()">
需要
</text>
</view>
</view>
</view> -->
</view>
<view class="bottom">
<view class="bottom-left">
<text> ¥{{ originalTotal || 0 }} </text>
<text> <text>¥</text>{{ sellTotal || 0 }} </text>
</view>
<view class="bottom-right">
<view @click="showDetail()" class="bottom-detail">
明细
<u-icon name="arrow-down"></u-icon>
</view>
<view class="btn" :style="{ background: payBackground }">
<text v-if="productIfo.status == 1">已下架</text>
<text v-if="parseInt(maxBookNum) < 1" style="background: #c0c0c0">暂无库存</text>
<text v-if="productIfo.status != 1 && parseInt(maxBookNum) >= 1" @click="jugeOrder()">去支付</text>
<text class="btn-paying" v-show="showPaying">支付中...</text>
<text class="mask" v-show="showPaying"></text>
</view>
</view>
</view>
<calendar ref="calendar" @dateConfig="dateConfig" :dateList="dateList" v-if="dateList.length > 0"></calendar>
<buyKnow ref="buyKnow" :buyKnowData="buyKnowData"></buyKnow>
<detail
ref="detail"
:merchantName="productIfo.merchantName"
:name="productIfo.name"
:buyNum="buyNum"
:sellingPrice="sellingPrice"
:choooseService="choooseService"
:productDepositTotal="productDepositTotal"
></detail>
<chooseArea
v-if="showArea"
:areaList="productIfo.productAreaList"
@areaSure="areaSure"
:sortArr="sortArr"
:defaultAreaCode="defaultAreaCode"
></chooseArea>
<times ref="times" :chooseTimeList="timeList" @timeConfig="timeConfig" :chooseTimeData="chooseTimeData" :timeActive="timeActive"></times>
<editContacts ref="editContacts" :editContact="editContact"></editContacts>
<contactList
ref="contactList"
@getEditContact="getEditContact"
:contactData="contactData"
@contactListConfig="contactListConfig"
:orderTouristList="orderTouristList"
:buyNum="contactNum"
></contactList>
<!--一个站点时获取排队信息弹窗-->
<u-popup :show="sortInforPop" :round="10" closeable @close="sortInforPop = false">
<view style="padding: 40rpx 60rpx">
<view>
景区名称:
<text class="sortPoptext" style="font-size: 28rpx">{{ productIfo.merchantName }}</text>
</view>
<view style="margin-top: 40rpx">
排队人数:
<text class="sortPoptext">{{ sortIfo.peopleNumber }}</text>
</view>
<view style="margin-top: 40rpx">
当前可排队:
<text class="sortPoptext">{{ sortIfo.showStart }}-</text>
<text class="sortPoptext">{{ sortIfo.showEnd }}</text>
</view>
<view style="margin-top: 40rpx">
当前排号至:
<text class="sortPoptext">{{ sortIfo.sortTotalCapacity }}</text>
</view>
<view style="margin-top: 40rpx; text-align: center" @click="sortInforPop = false">
<text class="middle-btn">确定</text>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import calendar from '../../../components/calendar' //日历组件
import buyKnow from '../../../components/buyKnow' //购票须知
import detail from '../../../components/detail' //明细弹窗
import chooseArea from '../../../components/chooseArea' //选择站点
import contactList from '../../../components/contactList' //联系人弹窗
import editContacts from '../../../components/editContacts' //编辑联系人弹窗
import times from '../../../components/times' //更多时间弹窗
export default {
components: {
calendar,
buyKnow,
detail,
contactList,
editContacts,
times,
chooseArea
},
data() {
return {
defaultAreaCode: '', //默认站点
sortArr: [], //多个站点排号信息列表
sortIfo: '', //单个站点排号信息
sortInforPop: false, //一个站点时获取排队信息弹窗
showErmai: true, //临时的,选择了南站不显示耳麦
showArea: false, //控制选择站点显示隐藏
showOpenArea: false, //是否可以显示选择站点
chooseDate: '', //选择的日期
active: 10000, //日期下标
timeActive: 10000, //时间下标,默认不选中
buyNum: 1, //订单数量
maxBookNum: 999, //最大预订数量
dateList: [], //日期列表
timeList: [], //时间列表
buyKnowData: '', //购买须知数据
editContact: '', //编辑联系人传值对象
productId: '', //产品Id
merchantId: '', //商户Id
ticketPhone: '', //联系电话
productIfo: '', //初始化产品基本信息
originalPrice: 0, //原价
sellingPrice: 0, //卖价
interfaceCode: '', //接口编号
merchantCode: '', //商户code
productCode: '', //产品code
contactData: [], //联系人列表数据
orderTouristList: [], //选中的游客信息列表
contactNum: 1, //需要选择几位联系人数量
cruisePlanId: '', //班次Id
chooseTimeData: '', //选中的时间传给子组件
timeNumber: '', //当前时间转化为数字
startDate: '', //开始日期
endDate: '', //结束日期
startPlayTime: '', //开始时间
endPlayTime: '', //结束时间
areaObj: '', //区域组件的传值
templateList: [], //该产品联系人必须要填写的信息
flag: '', //setTimeout函数
savedMoney: 0, //优惠价格
loadProductResVoList: [], //所有额外服务
choooseService: [], //选中的额外服务
extraPrice: 0, //额外服务总价格
showExtraPop: false, //控制额外服务弹窗显示隐藏
showPayExtraPop: false, //控制支付时有额外服务,没有选中额外服务的弹窗显示隐藏
extraChangeData: '', //额外服务变化时,变化的那个额外服务值
orderProductList: [], //额外服务,儿童票等入参
extraextraDepositTotal: 0, //额外服务总押金
productDepositTotal: 0, //产品总押金
orderSource: '', //订单来源 1公众号平台、2公众号组合页面1、3公众号组合页面2、4胖丁伙伴app、5第三方自助机、6第三方票房窗口
thirdOpenid: '', //第三方openid
beforeBookDays: '', //需提前预定天数
afterBuyUrl: '', //支付成功后页面跳转地址
companyId: '', //公司Id
docQuery: '', //元素变量
payBackground: '', //支付按钮背景颜色
showPaying: false, //是否显示支付中按钮
dateScroll: '', //日期滚动值
timeScroll: '' ,//时间滚动值
}
},
onLoad(option) {
let times = new Date().Format('yyyy-MM-dd hh:mm:ss')
this.timeNumber = parseInt(this.$commonjs.changeTime(times)) //将当前时间转化为数字
this.companyId = option.companyId || ''
this.orderSource = option.orderSource || ''
this.thirdOpenid = option.thirdOpenid || '' //第三方openid
this.productId = option.productId || ''
this.merchantId = option.merchantId || ''
this.initData() //页面初始化数据
this.docQuery = uni.createSelectorQuery().in(this)
},
computed: {
originalTotal() {
//原价总价
if (this.choooseService.length > 0) {
//额外服务价格和押金总价格
let singleProduct = 0 //单个产品押金
this.extraPrice = 0
this.extraDepositTotal = 0 //总押金
for (let i = 0; i < this.choooseService.length; i++) {
this.extraPrice += parseFloat((this.choooseService[i].sellingPrice * this.buyNum).toFixed(2))
if (this.choooseService[i].depositType == 1) {
//等于1,押金金额跟数量没关系
singleProduct = this.choooseService[i].deposit
} else if (this.choooseService[i].depositType == 2) {
//等于2,押金单价乘购买数量
singleProduct = parseFloat((this.choooseService[i].deposit * this.buyNum).toFixed(2))
}
this.extraDepositTotal += singleProduct
}
} else {
this.extraPrice = 0
this.extraDepositTotal = 0
}
if (this.productIfo.deposit) {
//如果有押金
if (this.productIfo.depositType == 1) {
//等于1,押金金额跟数量没关系
this.productDepositTotal = this.productIfo.deposit
} else if (this.productIfo.depositType == 2) {
//等于2,押金单价乘购买数量
this.productDepositTotal = parseFloat((this.productIfo.deposit * this.buyNum).toFixed(2))
}
} else {
this.productDepositTotal = 0
}
return parseFloat((this.originalPrice * this.buyNum + this.productDepositTotal + this.extraPrice + this.extraDepositTotal).toFixed(2)) //产品总价+产品押金+额外产品总价+额外产品押金-优惠价格
},
sellTotal() {
//卖价总价
if (this.choooseService.length == 0) {
this.extraPrice = 0
this.extraDepositTotal = 0
}
return parseFloat(
(this.sellingPrice * this.buyNum + this.productDepositTotal + this.extraPrice + this.extraDepositTotal - this.savedMoney).toFixed(2)
) //产品总价+产品押金+额外产品总价+额外产品押金-优惠价格
}
},
methods: {
//---获取手机号
getPhoneNumber (e) {
// 参数e是绑定的授权方法自动传入过来的, 为了获取到iv和encryptedData值,让后端解析手机号
let data={
sessionKey:uni.getStorageSync('sessionKey')||'',
companyId:uni.getStorageSync('companyId')||'',
appid:uni.getStorageSync('appid')||'',
encryptedData:e.detail.encryptedData,
iv:e.detail.iv,
}
this.$request('/wechat/douyin/getInfo', data).then(res => {
if (res.code == '00') {
let obj=JSON.parse(res.data)
this.ticketPhone=obj.phoneNumber||obj.purePhoneNumber
}else{
uni.showToast({
title: res.message,
icon: 'none'
})
}
})
},
//---获取排号信息
getSortInfor() {
let data = {
areaCode: this.areaObj.areaCode,
merchantCode: this.merchantCode //商户code
}
uni.showLoading({
title: '加载中'
})
this.$request('distribution/distribution/findNewFetchInfoFromSceinc', data).then(res => {
if (res.code == '00') {
this.sortInforPop = true
res.data.forEach(item => {
item.peopleNumber = Math.max(item.sortTotalCapacity - item.showEnd, 0)
})
let index = res.data.findIndex(item => {
return item.projectId == this.areaObj.areaCode
})
this.sortIfo = res.data[index]
}
})
},
//---排号是否上下架
sortUpDown() {
let data = {
merchantCode: this.merchantCode //商户code
}
uni.showLoading({
title: '加载中'
})
this.$request('distribution/distribution/findNewFetchInfoFromSceinc', data).then(res => {
if (res.data.code == '00') {
this.sortArr = res.data.data
let data = res.data
if (this.productIfo.productAreaList.length > 1) {
//有库存并且需要选择两个站点以上的票种,显示区域组件
for (let item in data.main) {
if (data.main[item].sceneSortStatus == '1') {
this.showArea = true
this.showOpenArea = true
}
}
} else if (this.productIfo.productAreaList.length == 1) {
//只有一个站点时,直接选中站点
for (let item in data.main) {
if (data.main[item].sceneSortStatus == '1') {
this.areaObj = this.productIfo.productAreaList[0]
this.showOpenArea = true
}
}
}
}
})
},
//---购买额外服务
extraYes() {
this.showExtraPop = false
this.choooseService.push(this.extraChangeData)
},
//---不购买额外服务
extraNo() {
this.showExtraPop = false
},
//---额外服务多选框变化
extraChange(item, i) {
if (!document.querySelectorAll('.extraService input')[i].checked) {
this.showExtraPop = true
this.extraChangeData = item
}
},
//---获取子组件的传值
areaSure(data) {
this.areaObj = data
if (this.areaObj.areaCode == 'cjsd_project_0001') {
//选择了南站不显示耳麦
this.showErmai = false
this.choooseService = []
} else {
this.showErmai = true
}
},
//---展示选择站点
openArea() {
this.areaObj = ''
this.showArea = true
},
//---关闭选择站点
closeArea() {
this.showArea = false
},
//---展示详情弹窗
showDetail() {
this.$refs.detail.show = true
},
//---展示日历
showCalendar() {
this.$refs.calendar.show = true
},
//---日期选择
dateChoose(index) {
this.active = index //修改选中样式
this.maxBookNum = Math.min(this.dateList[index].surplus, this.productIfo.maxBookNum) //剩余量变化
this.originalPrice = this.dateList[index].originalPrice //原价变化
this.sellingPrice = this.dateList[index].sellingPrice //卖家变化
this.chooseDate = this.dateList[index].startTime.substr(0, 10) //日历组件选中日期
this.endDate = this.dateList[index].endTime //开始日期
this.startDate = this.dateList[index].startTime //结束日期
this.$refs.calendar.defaultDate = this.chooseDate
if (this.productIfo.productType == 3) {
//如果为班次票,点击时,请求班次票接口
this.cruisePlanId = '' //清空班次id
this.timeActive = 10000
this.getTimeStock()
}
},
//---日历确认事件
dateConfig(data) {
let index = this.dateList.findIndex(item => {
return item.startTime.substr(0, 10) == data
})
this.dateChoose(index) //选中确认的日期
this.docQuery
.selectAll('.date-list')
.boundingClientRect(data => {
this.dateScroll = (data[index].width + 4) * index
})
.exec()
},
//---展示更多时间
showTime() {
this.$refs.times.show = true
},
//---时间选择
chooseTime(i) {
this.timeActive = i
this.cruisePlanId = this.timeList[i].cruisePlanId //获取班次Id
this.chooseTimeData = this.timeList[i].startPlanTime
this.maxBookNum = Math.min(this.timeList[i].last, this.productIfo.maxBookNum) //获取剩余库存
//如果为班次票,开始时间为班次时间的开始时间,结束时间为班次时间的结束时间,班次时间的结束时间为空时,结束时间为班次时间的开始时间
this.startPlayTime = this.timeList[i].startPlanTime
this.endPlayTime = this.timeList[i].endPlanTime || this.timeList[i].startPlanTime
},
//---时间确认事件
timeConfig(data) {
let index = this.timeList.findIndex(item => {
return item.startPlanTime == data
})
if (index > -1) {
//子组件点击确认之后有选择的时间
this.chooseTime(index) //选中确认的日期
this.docQuery
.selectAll('.time-list')
.boundingClientRect(data => {
this.timeScroll = (data[index].width + 4) * index
})
.exec()
}
},
//---获取点击的编辑联系人信息,传给编辑联系人组件
getEditContact(data) {
this.editContact = data
},
//---删除选中的联系人
delChooseContact(item, index) {
//所有联系人中找到删除联系人下标,改成未选中状态
let sub = this.contactData.findIndex(item2 => item2.id == item.id)
this.contactData[sub].ifChoose = false
this.orderTouristList.splice(index, 1) //删除数组
},
//---展示编辑联系人
showEdit(obj) {
this.$refs.editContacts.showEdit = true
this.editContact = obj
},
//---联系人列表选中确定之后传值事件
contactListConfig(data) {
//把选中的联系人放在前面
this.contactData.forEach((item, index) => {
data.forEach(item2 => {
if (item.id == item2.id) {
delete this.contactData[index]
}
})
})
this.contactData = this.contactData.filter(function (val) {
return val
})
this.contactData = data.concat(this.contactData)
//获取选中的联系人
this.orderTouristList = data
//清空之前的选中状态
this.contactData.forEach(item => {
item.ifChoose = false
})
//选中的联系人,设为选中状态
this.contactData.forEach(item => {
this.orderTouristList.forEach(item2 => {
if (item.id == item2.id) {
item.ifChoose = true
}
})
})
},
//---展示新增联系人,并获取联系人列表
showContacts() {
this.$refs.contactList.contactsShow = true
},
//---游客选择
visitorChoose(i) {
let chooseList = this.orderTouristList
let data = this.contactData
data[i].ifChoose = !data[i].ifChoose
if (data[i].ifChoose) {
if (chooseList.length == this.contactNum) {
//需要人数满足时,点击增加联系人时,删除最后一个,增加点击的那个人
chooseList[chooseList.length - 1].ifChoose = false
chooseList.splice(chooseList.length - 1, 1)
}
chooseList.push(data[i]) //加入数组
} else {
let index = chooseList.findIndex(items => {
return items.id == data[i].id
})
chooseList.splice(index, 1) //删除数组
}
this.$forceUpdate()
},
//---订单数量变化
buyNumChange(e) {
if (e.value >= this.maxBookNum) {
uni.showToast({
title: '最大可预订数量为' + this.maxBookNum,
icon: 'none'
})
}
if (this.productIfo.tripTemplateFlag == 1) {
//实名制
this.contactNum = e.value //需要填写的联系人数量等于购买数量
if (this.contactNum < this.orderTouristList.length) {
//当选中联系人数量大于购买数量时
this.orderTouristList.splice(this.orderTouristList.length - 1, 1) //删除多余的联系人
}
} else if (this.productIfo.tripTemplateFlag == 0) {
//非实名制
this.contactNum = 1
}
},
//---展示购票须知
showBuyKnow() {
this.$refs.buyKnow.buyKnowShow = true
},
//---页面初始化数据,获取产品基本信息
initData() {
let data = {
id: this.productId //产品id
}
uni.showLoading({
title: '加载中'
})
this.$request('scenic/groupGood/loadProduct', data).then(res => {
if (res.code == '00') {
this.productIfo = res.data
this.defaultAreaCode = this.productIfo.defaultAreaCode || ''
//找到站点默认站点数据
if (this.defaultAreaCode) {
this.productIfo.productAreaList.forEach(item => {
if (item.areaCode == this.defaultAreaCode) {
this.areaObj = {}
this.areaObj.areaCode = item.areaCode
this.areaObj.areaName = item.areaName
}
})
}
;(this.merchantCode = this.productIfo.merchantVo.code), //商户code
(this.productId = res.data.id) //产品id变化,重新赋值产品id
this.merchantId = res.data.merchantId //重新赋值商户id
this.beforeBookDays = res.data.beforeBookDays || 0 //提前预定天数
this.buyKnowData = res.data //购买须知,传给子组件
this.loadProductResVoList = res.data.loadProductResVoList //额外服务
this.afterBuyUrl = res.data.afterBuyUrl || '' //支付成功后页面跳转
//this.choooseService=res.data.data.loadProductResVoList//默认全部选中
if (this.productIfo.status == 1) {
//下架状态
this.payBackground = '#C0C0C0'
}
if (this.productIfo.productType != 3) {
//不为班次票时,开始时间为当前时间,结束时间为23:59:59
this.startPlayTime = new Date().Format('hh:mm:ss')
this.endPlayTime = '23:59:59'
}
if (this.productIfo.tripTemplateResList.length > 0) {
//用于判断选中的联系人信息是否填写完善
this.productIfo.tripTemplateResList.forEach(item => {
this.templateList.push(item.enumKey)
})
}
this.getPriceList()
this.getDiscountPrice() //获取优惠价格
if (this.productIfo.tripTemplateFlag != 2) {
//等于2时不需要填写联系人信息和手机号码
this.getContactList()
}
} else {
uni.showToast({
title: res.message,
icon: 'none'
})
}
})
},
//---获取产品价格库存列表
getPriceList() {
let data = {
productId: this.productId //产品id
}
this.$request('scenic/user/product/priceStockList', data).then(res => {
if (res.code == '00') {
this.dateList = res.data //日期列表
if (this.dateList.length > 0) {
let time1 = this.dateList[0].startTime.substr(0, 10) + this.productIfo.bookTime //获取价格列表的第一个日期+预订最晚时间
let timeNum1 = parseInt(this.$commonjs.changeTime(time1))
let time2 = new Date().Format('yyyy-MM-dd hh:mm:ss')
let timeNum2 = parseInt(this.$commonjs.changeTime(time2)) //将当前时间转化为数字
if (timeNum2 > timeNum1) {
//如果当前时间大于价格列表第一个日期+预订最晚时间,第一个价格不显示
this.dateList.splice(0, 1)
}
this.dateList.forEach((item, index) => {
//价格上面时间小于当前时间加上需预定天数之后的需删除
let date = new Date()
date.setDate(date.getDate() + this.beforeBookDays)
let newDate = date.Format('yyyy-MM-dd')
let priceTime = this.$commonjs.changeTime(item.endTime.substr(0, 10))
let newTime = this.$commonjs.changeTime(newDate)
if (priceTime < newTime) {
delete this.dateList[index]
}
})
this.dateList = this.dateList.filter(val => {
return val
})
if (this.dateList.length == 0) {
uni.showToast({
title: '没有库存',
icon: 'none'
})
this.showArea = false
this.payBackground = '#C0C0C0'
return
}
if (this.productIfo.isFetch == 1) {
this.sortUpDown()
}
if (this.dateList.length == 1 && this.beforeBookDays == 0) {
//长度为1而且只能预订当天,默认选中第一个日期
//真机模拟的时候手机端不显示今天,明天后天,延迟执行
setTimeout(item => {
this.$refs.calendar.defaultDate = this.dateList[0].startTime.substr(0, 10)
}, 1000)
this.maxBookNum = Math.min(this.dateList[0].surplus, this.productIfo.maxBookNum) //剩余量
this.startDate = this.dateList[0].startTime //开始日期
this.endDate = this.dateList[0].endTime //结束日期
this.originalPrice = this.dateList[0].originalPrice //原价
this.sellingPrice = this.dateList[0].sellingPrice //卖价
this.active = 0
if (this.productIfo.productType == 3) {
//如果为班次票,请求班次票接口
this.getTimeStock()
}
}
} else {
uni.showToast({
title: '没有库存',
icon: 'none'
})
this.showArea = false
this.payBackground = '#C0C0C0'
}
let today = this.$commonjs.today() //今天
let tomorrow = this.$commonjs.tomorrow() //明天
let afterTomorrow = this.$commonjs.afterTomorrow() //后天
this.dateList.forEach((item, index) => {
item.week = '日一二三四五六'.charAt(new Date(item.startTime.substr(0, 10)).getDay())
if (item.startTime.substr(0, 10) == today) {
item.week = '今天'
}
if (item.startTime.substr(0, 10) == tomorrow) {
item.week = '明天'
}
if (item.startTime.substr(0, 10) == afterTomorrow) {
item.week = '后天'
}
})
} else {
uni.showToast({
title: res.message,
icon: 'none'
})
}
})
},
//---获取班次票
getTimeStock() {
let data = {
endDate: this.endDate, //结束日期
startDate: this.startDate, //开始日期
interfaceCode: this.productIfo.merchantVo.interfaceCompanyId, //接口编号
merchantCode: this.merchantCode, //商户code
productCode: this.productIfo.code //产品code
}
uni.showLoading({
title: '加载中'
})
this.$request('distribution/distribution/getTimeStock', data).then(res => {
if (res.code == '00') {
this.timeList = res.data
this.timeList.forEach((item, index) => {
//增加一个时间Number字段,用于判断当前时间大于班次结束时间时,不显示该班次
item.timeNumber = parseInt(this.$commonjs.changeTime(item.planDate.substr(0, 10) + item.endPlanTime))
if (this.timeNumber > item.timeNumber || item.last == 0) {
this.timeList.splice(index, 1)
}
})
} else {
uni.showToast({
title: res.message,
icon: 'none'
})
}
})
},
//---初始化联系人列表
getContactList() {
let data = {
openid: uni.getStorageSync('openid') || ''
}
this.$request('wechatUser/contact/findContactList', data).then(res => {
if (res.code == '00') {
this.contactData = res.data
this.contactData.forEach(item => {
//用于判断是否被选中
item.ifChoose = false
})
//编辑成功重新调该方法时,把之前选中的游客,设为选中状态
this.contactData.forEach(item => {
this.orderTouristList.forEach(item2 => {
if (item.id == item2.id) {
item.ifChoose = true
}
})
})
//删除联系人成功重新调该方法时,之前选中的联系人,数据库可能被删除,删除该联系人
this.orderTouristList.forEach((item, index) => {
if (!this.contactData.find(item2 => item.id == item2.id)) {
this.orderTouristList.splice(index, 1)
}
})
} else {
uni.showToast({
title: res.message,
icon: 'none'
})
}
})
},
//---添加并选中联系人--用于添加联系人之后直接从联系人列表选出需要填写的几位联系人
addChoose() {
let data = {
openid: uni.getStorageSync('openid') || ''
}
this.$request('wechatUser/contact/findContactList', data).then(res => {
if (res.code == '00') {
this.contactData = res.data
for (let i = 0; i < this.contactNum; i++) {
let item = this.contactData[i] || null
if (item) {
item.ifChoose = true
}
}
this.orderTouristList = this.contactData.slice(0, this.contactNum)
} else {
uni.showToast({
title: res.message,
icon: 'none'
})
}
})
},
//---获取优惠价格
getDiscountPrice() {
let data = {
productId: this.productId, //产品ID
merchantId: this.merchantId, //商家ID
companyId: this.companyId, //公司ID
openid: uni.getStorageSync('openid') || '' //openid
}
this.$request('scenic/user/productRule/getProductRule', data).then(res => {})
},
//---不需要享受耳麦服务
payExtraNo() {
this.showPayExtraPop = false
this.placeOrder()
},
//---需要享受耳麦服务
payExtraYes() {
this.showPayExtraPop = false
this.choooseService = this.loadProductResVoList
this.placeOrder()
},
//---点击去支付判断是否直接下单
jugeOrder() {
if (this.loadProductResVoList.length == 0) {
//没有额外服务,直接支付
this.placeOrder()
}
if (this.loadProductResVoList.length > 0) {
//有额外服务,并且选择了额外服务的,直接支付
if (this.choooseService.length > 0) {
this.placeOrder()
}
}
if (this.loadProductResVoList.length > 0) {
//有额外服务,没有选中额外服务的,弹出提示框
if (this.productIfo.tripTemplateFlag != 2) {
if (!this.$commonjs.phoneReg().test(this.ticketPhone)) {
//未填写正确手机号码
uni.showToast({
title: '请填写正确的手机号码',
icon: 'none'
})
return
}
}
if (this.productIfo.tripTemplateFlag == 1) {
//实名制
if (this.orderTouristList.length != this.buyNum) {
uni.showToast({
title: '需要添加' + this.buyNum + '位出行人',
icon: 'none'
})
return
}
} else if (this.productIfo.tripTemplateFlag == 0) {
//非实名制
if (this.orderTouristList.length < 1) {
uni.showToast({
title: '需要添加一位出行人',
icon: 'none'
})
return
}
}
if (this.productIfo.productType == 3) {
//如果为班次票,需要选择班次
if (this.cruisePlanId == '') {
uni.showToast({
title: '该票为班次票,请选择游玩时间',
icon: 'none'
})
return
}
}
if (this.productIfo.isFetch == 1 && this.showOpenArea) {
//需要选择站点的票种,必须选择站点
if (!this.areaObj.areaCode) {
uni.showToast({
title: '请选择站点',
icon: 'none'
})
return
}
}
if (this.choooseService.length == 0 && this.showErmai) {
//没有购买额外服务,并且选择的北站,跳出弹窗
this.showPayExtraPop = true
}
if (this.choooseService.length == 0 && !this.showErmai) {
//没有购买额外服务,并且选择的南站,直接购买
this.placeOrder()
}
}
},
//---下单
placeOrder() {
if (this.dateList.length == 0) {
//价格库存为空时,点击无效
return
}
if (this.productIfo.status == 1) {
//下架状态,点击无效
return
}
if (this.productIfo.tripTemplateFlag != 2) {
//需要填写电话号码
if (!this.$commonjs.phoneReg().test(this.ticketPhone) && this.productIfo.tripTemplateFlag != 2) {
//未填写正确手机号码
uni.showToast({
title: '请填写正确的手机号码',
icon: 'none'
})
return
}
}
if (!this.startDate || !this.endDate) {
uni.showToast({
title: '请选择游玩日期',
icon: 'none'
})
return
}
if (this.productIfo.tripTemplateFlag == 1) {
//实名制
if (this.orderTouristList.length != this.buyNum) {
uni.showToast({
title: '需要添加' + this.buyNum + '位出行人',
icon: 'none'
})
return
}
} else if (this.productIfo.tripTemplateFlag == 0) {
//非实名制
if (this.orderTouristList.length < 1) {
uni.showToast({
title: '需要添加一位出行人',
icon: 'none'
})
return
}
}
if (this.productIfo.productType == 3) {
//如果为班次票,需要选择班次
if (this.cruisePlanId == '') {
uni.showToast({
title: '该票为班次票,请选择游玩时间',
icon: 'none'
})
return
}
}
if (this.productIfo.isFetch == 1 && this.showOpenArea) {
//需要选择站点的票种,必须选择站点
if (!this.areaObj.areaCode) {
uni.showToast({
title: '请选择站点',
icon: 'none'
})
return
}
}
this.showPaying = true
setTimeout(() => {
this.showPaying = false
}, 6000)
this.preOrder()
},
//---预下单
preOrder() {
//时间戳转化
let bookStartTime=''
if(this.$commonjs.today()==this.startDate.substr(0,10)){
//如果是当天就取当前时间+10秒
bookStartTime = new Date().getTime()+10*1000
}else{
//不是当天就取开始时间
//手机兼容
let startDate=this.startDate.replace(/-/g, '/')
bookStartTime = new Date(startDate).getTime()
}
//手机兼容
let endDate=this.endDate.replace(/-/g, '/')
let bookEndTime = new Date(endDate).getTime()
//参数游客信息组装
let reservationInfoList = []
this.orderTouristList.forEach((item, index) => {
reservationInfoList.push({
category: 0,
name: item.name,
identificationNumber: item.credentialNumber
})
})
//商品库 spu & 非商品库 sku
tt.createOrder({
skuList: [
{
skuId: this.productIfo.distributionProductId, // sku 商品Id 必传
skuType: 1, // sku 商品类型 必传 1-商品库商品 2-非商品库商品
quantity: this.buyNum, // 数量 必传
price: parseFloat((this.sellingPrice * 100).toFixed(2)), // 价格 非商品库 sku 商品必传
goodsInfo: {
goodsName: this.productIfo.name, // 商品名称
goodsPhoto: 'http://picture.pangdly.com/company/2022-02/2022-02-10/zip/z001644484223062b28c62cc60b0c65e.jpg', // 商品图片链接
goodsId: this.productIfo.distributionProductId, // 商品ID
goodsType: 1, //1-商品库商品2-非商品库商品
GoodsBookInfo: {
bookType: 1 //预约类型:1. 不需要预约 2. 在线预约
}
}
// extraInfo: {
// ticketName: '成人票', // 票种,非商品库门票类 sku 必传
// date: '2023-05-16', // 日期,非商品库门票类 sku 必传
// },
}
],
bookInfo: {
itemBookInfoList: [
{
poiId: this.productIfo.poiId, // 预约门店的 poiId,必填
shopName: this.productIfo.merchantName, // 预约店铺名称,必填
outShopId: this.productIfo.merchantId, // 预约门店的外部店铺id,必填
goodsId: this.productIfo.distributionProductId, // 商品id,必填
bookStartTime, // 预定开始时间(ms),13位毫秒时间戳,必填
bookEndTime, //预定结束时间(ms),13位毫秒时间戳,必填
reservationInfoList // 留资信息 非必填
}
]
},
payment: {
totalAmount: parseFloat((this.buyNum * this.sellingPrice * 100).toFixed(2)) // 订单总价 必填
},
contactInfo: {
//联系人
phoneNumber: this.ticketPhone // 手机号 非必传
},
callbackData: {
productAreaCode: this.areaObj.areaCode || this.defaultAreaCode //站点信息
},
success: res => {
const { orderId, outOrderNo } = res
uni.navigateTo({
url: '/pages/salePay/paySuccess/paySuccess?orderId=' + outOrderNo
})
},
fail: res => {
const { orderId, outOrderNo, errNo, errMsg, errLogId } = res
if (errLogId) {
console.log('预下单失败', errNo, errMsg, errLogId)
}
if( errMsg || errNo){
console.log('支付失败',errNo, errMsg , orderId, outOrderNo)
}
uni.showToast({
title: errMsg,
icon: 'none',
duration: 3000
})
}
})
}
}
}
</script>
<style lang="scss" scoped="scoped">
.head {
height: 160rpx;
background: linear-gradient(to bottom, #2984ef, #d8eaf6);
}
.orderBox {
min-height: 100%;
background: #f5f5f5;
}
.middle {
position: relative;
top: -100rpx;
padding: 0 20rpx;
padding-bottom: 20rpx;
}
/*中间第一部分*/
.middle1 {
padding: 32rpx 20rpx 0 20rpx;
background: #ffffff;
border-radius: 10rpx;
}
.middle1 > view:not(:last-child) {
border-bottom: 1px solid #e5e5e5;
}
.middle1Product {
padding-bottom: 20rpx;
}
.merchantName {
display: flex;
align-items: center;
}
.merchantName text:first-child {
font-size: 36rpx;
font-weight: bolder;
}
.merchantName text:nth-child(2) {
color: #666666;
margin-left: 20rpx;
}
.buyKnow {
margin-top: 20rpx;
background: #fef0e6;
height: 56rpx;
font-size: 24rpx;
display: flex;
justify-content: space-between;
padding-left: 10rpx;
align-items: center;
border-radius: 5rpx;
}
.buyKnow view:first-child {
color: #f9690e;
}
.buyKnow view:nth-child(2) {
color: #6d4d00;
display: flex;
}
.middle-place {
height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.middle-place view:nth-child(2) {
flex: 1;
margin-left: 20rpx;
color: #f9690e;
font-size: 28rpx;
font-weight: bolder;
}
.middle1Date {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
}
.middle1Date > text:first-child {
flex-shrink: 0;
}
.date-content {
flex: 1;
margin-left: 20rpx;
overflow-x: scroll;
white-space: nowrap;
height: 90rpx;
}
.date-content::-webkit-scrollbar {
display: none;
}
.date-list {
width: 130rpx;
height: 90rpx;
text-align: center;
border: 1px solid #cccccc;
margin-right: 8rpx;
border-radius: 10rpx;
position: relative;
display: inline-block;
}
.date-list.on {
border: 1px solid var(--main-color);
}
.no-date {
color: #ff0000;
flex: 1;
margin-left: 30rpx;
font-weight: bolder;
}
.date-time {
font-size: 24rpx;
margin-top: 8rpx;
}
.date-price {
margin-top: 8rpx;
color: #f9690e;
}
.date-price text {
font-weight: bolder;
font-size: 30rpx;
}
.date-price text:first-child {
font-weight: 400;
font-size: 24rpx;
}
.date-icon {
position: absolute;
right: -1px;
bottom: -1px;
display: inline-block;
width: 30rpx;
height: 28rpx;
background: var(--main-color);
border-radius: 10rpx 0;
}
.dateMore {
flex-shrink: 0;
width: 100rpx;
height: 90rpx;
border: 1px solid var(--main-color);
border-radius: 10rpx;
display: flex;
justify-content: center;
align-items: center;
}
.date-more-content {
margin: 0 4rpx;
color: var(--main-color);
}
.middle1Time {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
}
.middle1Time > text:first-child {
flex-shrink: 0;
}
.time-content {
flex: 1;
margin-left: 20rpx;
overflow-x: scroll;
white-space: nowrap;
height: 90rpx;
}
.time-content::-webkit-scrollbar {
display: none;
}
.time-list {
width: 180rpx;
height: 90rpx;
line-height: 30rpx;
text-align: center;
margin-right: 8rpx;
border-radius: 15rpx;
display: inline-block;
background: rgb(242, 242, 242);
}
.time-list view {
margin-top: 10rpx;
}
.time-list.on {
background: none;
color: var(--main-color);
border: 1px solid var(--main-color);
box-sizing: border-box;
}
.timeMore {
flex-shrink: 0;
width: 100rpx;
height: 90rpx;
border: 1px solid var(--main-color);
border-radius: 10rpx;
display: flex;
justify-content: center;
align-items: center;
}
.time-more-content {
margin: 0 4rpx;
color: var(--main-color);
}
.no-time {
color: #ff0000;
flex: 1;
margin-left: 30rpx;
font-weight: bolder;
}
.middle1Number {
display: flex;
justify-content: space-between;
padding: 36rpx 0;
align-items: center;
}
/*中间第二部分*/
.middle2 {
padding: 40rpx 20rpx;
background: #ffffff;
border-radius: 10rpx;
margin-top: 20rpx;
}
.middle2Visitor {
padding-bottom: 40rpx;
border-bottom: 1px solid #e5e5e5;
}
.visitorTitle {
position: relative;
}
.visitorTitle > text:first-child {
font-size: 32rpx;
font-weight: bolder;
}
.visitorTitle > text:nth-child(2) {
font-size: 24rpx;
color: #666666;
margin-left: 10rpx;
}
.title-bold {
color: #f9690e;
font-weight: bolder;
font-size: 28rpx;
}
.visitorPlus {
margin-top: 30rpx;
display: flex;
flex-wrap: wrap;
}
.plus-list {
height: 70rpx;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
padding: 5rpx 0;
width: 145rpx;
text-align: center;
color: #999999;
border: 1px solid #999999;
margin-right: 15rpx;
border-radius: 5rpx;
position: relative;
box-sizing: border-box;
margin-top: 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.plus-list-last {
color: var(--main-color);
background: #efefef;
width: 160rpx;
border: none;
}
.plus-list.on {
border: 1px solid var(--main-color);
color: var(--main-color);
}
.visitorEdit {
margin-top: 40rpx;
}
.visitorEdit > view:not(first-child) {
margin-top: 25rpx;
}
.edit-list {
display: flex;
justify-content: space-between;
align-items: center;
}
.edit-list view:nth-child(2) {
display: inline-block;
width: 120rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-left: 30rpx;
}
.edit-list view:nth-child(3) {
flex: 1;
}
.phoneTitle {
font-size: 28rpx;
font-weight: bolder;
margin-top: 30rpx;
}
.phoneNumber {
margin-top: 30rpx;
border-bottom: 1px solid #e6e6e6;
display: flex;
align-items: center;
padding-bottom: 10rpx;
}
.phoneNumber input {
flex: 1;
}
/*押金部分*/
.productDeposit {
padding: 40rpx 15rpx;
background: #ffffff;
border-radius: 10rpx;
margin-top: 20rpx;
display: flex;
justify-content: space-between;
}
/*额外服务部分*/
.extraService {
padding: 30rpx 20rpx;
background: #ffffff;
border-radius: 10rpx;
margin-top: 20rpx;
}
.extraService view {
display: flex;
justify-content: space-between;
align-items: center;
line-height: 30rpx;
}
.extraService view:not(:first-child) {
margin-top: 30rpx;
}
.extraService view label {
font-weight: bolder;
color: #f45803;
flex-shrink: 0;
}
.extraPop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
z-index: 99;
}
.extraPop view {
width: 85%;
background: #ffffff;
border-radius: 10rpx;
padding: 40rpx 30rpx;
}
.extraPop view view:first-child {
text-align: center;
font-size: 28rpx;
font-weight: bolder;
}
.extraPop view view:nth-child(2) {
margin-top: 20rpx;
color: #666666;
line-height: 30rpx;
}
.extraPop view view:nth-child(3) {
margin-top: 40rpx;
text-align: center;
}
.extraPop view view:nth-child(3) text {
display: inline-block;
width: 145rpx;
height: 60rpx;
text-align: center;
line-height: 60rpx;
border-radius: 10rpx;
}
.extraPop view view:nth-child(3) text:nth-child(1) {
border: 1px solid #e8e8e8;
color: #666666;
margin-right: 40rpx;
}
.extraPop view view:nth-child(3) text:nth-child(2) {
background: linear-gradient(#ff5454, #ff8538);
color: #ffffff;
}
/*底部部分*/
.bottom {
height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
background: #ffffff;
position: fixed;
bottom: 0;
width: 100%;
max-width: 750rpx;
z-index: 10;
padding: 0 24rpx 0 40rpx;
box-sizing: border-box;
box-shadow: 0 0 3rpx #666666;
}
.bottom-left > text:first-child {
font-size: 28rpx;
text-decoration: line-through;
margin-right: 16rpx;
}
.bottom-left text:nth-child(2) {
font-size: 40rpx;
font-weight: bolder;
color: #f45803;
}
.bottom-left text:nth-child(2) text {
font-size: 32rpx;
}
.bottom-right {
display: flex;
align-items: center;
}
.bottom-detail {
display: flex;
}
.btn {
position: relative;
width: 200rpx;
height: 80rpx;
margin-left: 20rpx;
line-height: 80rpx;
font-size: 32rpx;
font-weight: bolder;
border-radius: 16rpx;
}
.btn text {
position: absolute;
width: 100%;
height: 100%;
display: inline-block;
left: 0;
color: #ffffff;
top: 0;
}
.btn-paying {
z-index: 1;
background: #c0c0c0;
border-radius: 16rpx;
}
.btn .mask{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.1);
}
.sortPoptext {
font-size: 30rpx;
font-weight: bolder;
color: #f32048;
}
</style>
static/img/index/home.png

1.79 KB | W: | H:

static/img/index/home.png

1.31 KB | W: | H:

static/img/index/home.png
static/img/index/home.png
static/img/index/home.png
static/img/index/home.png
  • 2-up
  • Swipe
  • Onion skin
static/img/index/homeChoose.png

1.45 KB | W: | H:

static/img/index/homeChoose.png

1.28 KB | W: | H:

static/img/index/homeChoose.png
static/img/index/homeChoose.png
static/img/index/homeChoose.png
static/img/index/homeChoose.png
  • 2-up
  • Swipe
  • Onion skin
static/img/index/my.png

2.22 KB | W: | H:

static/img/index/my.png

1.97 KB | W: | H:

static/img/index/my.png
static/img/index/my.png
static/img/index/my.png
static/img/index/my.png
  • 2-up
  • Swipe
  • Onion skin
static/img/index/myChoose.png

1.76 KB | W: | H:

static/img/index/myChoose.png

1.99 KB | W: | H:

static/img/index/myChoose.png
static/img/index/myChoose.png
static/img/index/myChoose.png
static/img/index/myChoose.png
  • 2-up
  • Swipe
  • Onion skin
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment