447 lines
15 KiB
Vue
447 lines
15 KiB
Vue
<template>
|
||
<view class="submit-order">
|
||
<scroll-view scroll-y class="page-scroll">
|
||
<!-- 商品卡片 -->
|
||
<view class="card">
|
||
<view class="product-card">
|
||
<image class="thumb" :src="orderInfo.travelGroupProduct.mainImage" mode="aspectFill" />
|
||
<view class="info">
|
||
<view class="title">{{ orderInfo.travelGroupProduct.name }}</view>
|
||
<view class="price-row">
|
||
<text class="label">实付:</text>
|
||
<text class="price v12-primary-text"><text class="v12-font-20">¥</text>{{ orderInfo.priceGroup.totalPrice }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="notice v12-font-28 v12-primary-text">下单成功后记得联系商家确认入住时间哦~</view>
|
||
</view>
|
||
|
||
|
||
<!-- 填写信息 -->
|
||
<view class="card form-card">
|
||
<view class="section-title">填写您的信息</view>
|
||
<view class="form-item">
|
||
<text class="form-label">姓 名:</text>
|
||
<u-input shape="circle" placeholderStyle="font-size: 24rpx;" v-model="form.name" placeholder="请填写姓名" border="surround" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">联系电话:</text>
|
||
<u-input shape="circle" placeholderStyle="font-size: 24rpx;" v-model="form.phone" placeholder="请填写联系电话" border="surround" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">入住时间:</text>
|
||
<view class="date-row" @click="chooseDate">
|
||
<text class="date-val v12-primary-text">{{ dateRangeText }}</text>
|
||
<!-- <u-icon name="arrow-right" size="18" color="#999"></u-icon> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 支付方式 -->
|
||
<view class="card pay-card">
|
||
<view class="section-title">支付方式</view>
|
||
<view
|
||
class="payItem acea-row row-middle v12-justify-between"
|
||
style="flex-wrap: nowrap; margin-top: 20rpx"
|
||
@click="payItem('weixin')"
|
||
>
|
||
<view class="name acea-row v12-font-24 ">
|
||
<!-- <view class="iconfont icon-weixin2" :class="active === 'weixin' ? 'bounceIn' : ''"></view> -->
|
||
<image style="flex-shrink: 0;width: 32rpx;height: 32rpx;margin-right: 10rpx;" :src="webUrl+'/orderIcon/微信支付.png'" mode=""></image>
|
||
微信支付
|
||
</view>
|
||
<view class="tip"></view>
|
||
<label class="radio">
|
||
<radio style="transform: scale(0.7);" value="" :checked="active === 'weixin'" color="#C52733"/>
|
||
<text></text>
|
||
</label>
|
||
</view>
|
||
<u-divider></u-divider>
|
||
<view
|
||
class="payItem acea-row row-middle v12-justify-between"
|
||
style="flex-wrap: nowrap;"
|
||
@click="payItem('yue')"
|
||
>
|
||
<view class="name acea-row v12-font-24">
|
||
<image style="flex-shrink: 0;width: 32rpx;height: 32rpx;margin-right: 10rpx;" :src="webUrl+'/orderIcon/余额宝.png'" mode=""></image>
|
||
余额支付
|
||
</view>
|
||
<!-- <view class="tip">可用余额:{{ userInfo.nowMoney ? force2Decimal(userInfo.nowMoney) : 0.00 }}</view> -->
|
||
<label class="radio">
|
||
<radio style="transform: scale(0.7);" value="" :checked="active === 'yue'" color="#C52733"/>
|
||
<text></text>
|
||
</label>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 退改规则 -->
|
||
<view class="card text-card">
|
||
<view class="section-title">退改规则</view>
|
||
<view class="plain-text v12-font-26">
|
||
根据商家政策,与商家确认入住时间前可免费取消;如若确认入住后需要更改入住时间,可需联系客服,与商家商议新的入住时间;若与商家确认入住时间后因取消/退订,则根据不同阶段进行退款。
|
||
</view>
|
||
<view class="v12-mt-4">
|
||
<view class="section-title">预定说明</view>
|
||
<view class="plain-text">
|
||
订单生效规则:订单需商家确认后方可生效,确认结果将通过短信通知。您请务必在订单生效后再前往商家办理入住,以免影响您的行程。
|
||
</view>
|
||
<view class="plain-text">
|
||
服务条款说明:预订单由香道滇平台提供,为保障您的权益,请仔细阅读《香道平台旅居预订服务规则》。旅居服务由对应旅居服务提供者(旅居管家/旅居商家)提供。该业务的实际运营及相关责任,由旅居商家基于签约主体公司承担。
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="bottom-space"></view>
|
||
</scroll-view>
|
||
|
||
<!-- 底部栏 -->
|
||
<view class="bottom-bar">
|
||
<view class="total">
|
||
<text>合计:</text>
|
||
<text class="highlight">
|
||
<text class="v12-font-20">¥</text>{{ orderInfo.priceGroup.totalPrice }}
|
||
</text>
|
||
</view>
|
||
<view class="bar-actions">
|
||
<view class="mini-btn" @click="contactMerchant">
|
||
<view>
|
||
<u-icon :name="webUrl + '/home/pho.png'"></u-icon>
|
||
</view>
|
||
<view>联系商家</view>
|
||
</view>
|
||
<view class="buy-btn" @click="subscribePay()">
|
||
<view>
|
||
<u-icon :name="webUrl + '/home/icon-cart.png'" size="24"></u-icon>
|
||
</view>
|
||
<view>立即购买</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日期选择器(简单占位) -->
|
||
<passkeyborad
|
||
v-if="isShowPayPwdPop"
|
||
ref='payPwdPop'
|
||
showMoney
|
||
:money="orderInfo.priceGroup.totalPrice"
|
||
:show="isShowPayPwdPop"
|
||
@close="pwdPopClose"
|
||
@finish="pwdPopFinish"
|
||
></passkeyborad>
|
||
<Calendar ref="calendar"></Calendar>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { createJiaLouOrder, createJiaLouOrderPay } from '@/api/qianxian'
|
||
import buyMixins from '../mixins/buyMixins'
|
||
import blPaymentPasswordInput from '@/components/blPaymentPasswordInput.vue'
|
||
import {mapGetters} from "vuex"
|
||
import passkeyborad from '@/components/yzc-paykeyboard/yzc-paykeyboard'
|
||
export default {
|
||
name: 'SubmitOrder',
|
||
mixins: [buyMixins],
|
||
components: {
|
||
blPaymentPasswordInput,
|
||
passkeyborad
|
||
},
|
||
data() {
|
||
return {
|
||
from: this.$deviceType,
|
||
webUrl: this.$VUE_APP_RESOURCES_URL,
|
||
form: {
|
||
name: '',
|
||
phone: '',
|
||
payWay: 'wechat',
|
||
start: '2025-08-17',
|
||
end: '2025-08-23',
|
||
id: ''
|
||
},
|
||
showCalendar: false,
|
||
minDate: this.formatDate(new Date()),
|
||
orderInfo: {},
|
||
payPassword: null,
|
||
isShowPayPwdPop: false
|
||
}
|
||
},
|
||
onLoad(opts) {
|
||
const { id, orderStartDate, orderEndDate } = opts
|
||
this.form.start = orderStartDate
|
||
this.form.end = orderEndDate
|
||
this.form.id = id
|
||
this.getOrderConfim()
|
||
},
|
||
computed: {
|
||
...mapGetters(["userInfo", "storeItems"]),
|
||
dateRangeText() {
|
||
return this.formatDisplay(this.form.start) + ' ~ ' + this.formatDisplay(this.form.end)
|
||
}
|
||
},
|
||
methods: {
|
||
pwdPopClose() {
|
||
this.isShowPayPwdPop = false
|
||
},
|
||
pwdPopFinish(payPwd) {
|
||
this.payPassword = payPwd
|
||
this.createOrder(true)
|
||
},
|
||
chooseDate() { this.showCalendar = true },
|
||
onDateConfirm(e) {
|
||
const [start, end] = e;
|
||
this.form.start = start
|
||
this.form.end = end
|
||
this.showCalendar = false
|
||
},
|
||
formatDisplay(dateStr) {
|
||
if (!dateStr) return ''
|
||
const [y, m, d] = dateStr.split('-')
|
||
return `${y}年${m}月${d}日`
|
||
},
|
||
formatDate(d) {
|
||
const y = d.getFullYear()
|
||
const m = String(d.getMonth()+1).padStart(2, '0')
|
||
const day = String(d.getDate()).padStart(2, '0')
|
||
return `${y}-${m}-${day}`
|
||
},
|
||
contactMerchant() {
|
||
uni.showToast({ title: '已为您接入管家', icon: 'none' })
|
||
},
|
||
submitOrder() {
|
||
if (!this.form.name || !this.form.phone) {
|
||
uni.showToast({ title: '请完整填写信息', icon: 'none' })
|
||
return
|
||
}
|
||
uni.showToast({ title: '下单成功(示意)', icon: 'success' })
|
||
},
|
||
getOrderConfim() {
|
||
createJiaLouOrder({
|
||
travelGroupProductId: this.form.id,
|
||
orderStartDate: this.form.start,
|
||
orderEndDate: this.form.end
|
||
}).then(res => {
|
||
if (res.status === 200) {
|
||
this.orderInfo = res.data
|
||
// uni.showToast({ title: '下单成功(示意)', icon: 'success' })
|
||
} else {
|
||
// uni.showToast({ title: res.msg || '下单失败', icon: 'none' })
|
||
}
|
||
})
|
||
},
|
||
createOrder(isyue) {
|
||
if (!this.active) {
|
||
uni.showToast({
|
||
title: "请选择支付方式",
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
return
|
||
}
|
||
if (!/^1(3|4|5|7|8|9|6)\d{9}$/.test(this.form.phone)) {
|
||
uni.showToast({
|
||
title: "请填写正确的手机号",
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
return;
|
||
}
|
||
if (!/^[\u4e00-\u9fa5\w]{2,16}$/.test(this.form.name)) {
|
||
uni.showToast({
|
||
title: "请填写您的真实姓名",
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
return
|
||
}
|
||
// 判断如果是余额支付,先要输入支付密码
|
||
if (this.active == 'yue' && !isyue) {
|
||
// 先判断用户是否绑定过手机
|
||
if (this.userInfo.phone) {
|
||
// 再判断用户是否设置过支付密码
|
||
if (this.userInfo.hasPwdPay) {
|
||
// 显示输入支付密码
|
||
this.isShowPayPwdPop = true
|
||
} else {
|
||
// 设置支付密码
|
||
this.$yrouter.push("/pkg_user/views/payPassword?isSetMode=true")
|
||
}
|
||
} else {
|
||
// 跳转到绑定手机
|
||
this.$yrouter.push("/pkg_user/views/bindPhone")
|
||
}
|
||
return
|
||
}
|
||
uni.showLoading({
|
||
title: "生成订单中"
|
||
})
|
||
let from = {}
|
||
if (this.$deviceType == "app") {
|
||
from.from = "app"
|
||
}
|
||
const params = {
|
||
key: this.orderInfo.orderKey,
|
||
realName: this.form.name,
|
||
phone: this.form.phone,
|
||
from: this.from,
|
||
payType: this.active,
|
||
passwordPay: this.payPassword
|
||
// ...from
|
||
}
|
||
//余额支付的支付密码
|
||
if (this.active == 'yue') {
|
||
params.passwordPay = this.payPassword
|
||
}
|
||
var that = this
|
||
createJiaLouOrderPay(params).then(res => {
|
||
uni.hideLoading()
|
||
const data = res.data
|
||
switch (data.status) {
|
||
case "ORDER_EXIST":
|
||
case "EXTEND_ORDER":
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
this.$yrouter.replace({
|
||
path: "/pkg_product/views/sojoumOrderDetails",
|
||
query: {
|
||
id: data.result.orderId
|
||
}
|
||
})
|
||
break;
|
||
case "PAY_DEFICIENCY":
|
||
break;
|
||
case "PAY_ERROR":
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
this.$yrouter.replace({
|
||
path: "/pkg_product/views/sojoumOrderDetails",
|
||
query: {
|
||
id: data.result.orderId
|
||
}
|
||
});
|
||
break;
|
||
case "SUCCESS":
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
this.$yrouter.replace({
|
||
path: "/pkg_product/views/sojoumOrderDetails",
|
||
query: {
|
||
id: data.result.orderId
|
||
}
|
||
})
|
||
break;
|
||
case "WECHAT_H5_PAY":
|
||
// H5支付
|
||
this.$yrouter.replace({
|
||
path: "/pkg_product/views/sojoumOrderDetails",
|
||
query: {
|
||
id: data.result.orderId
|
||
}
|
||
})
|
||
break;
|
||
case "WECHAT_PAY":
|
||
// 小程序支付
|
||
weappPay(data.result.jsConfig).finally(() => {
|
||
this.$yrouter.replace({
|
||
path: "/pkg_product/views/sojoumOrderDetails",
|
||
query: {
|
||
id: data.result.orderId
|
||
}
|
||
})
|
||
})
|
||
break;
|
||
case "WECHAT_APP_PAY":
|
||
// APP支付
|
||
weappPay(data.result.jsConfig).finally(() => {
|
||
this.$yrouter.replace({
|
||
path: "/pkg_product/views/sojoumOrderDetails",
|
||
query: {
|
||
id: data.result.orderId
|
||
}
|
||
});
|
||
})
|
||
break;
|
||
}
|
||
}).catch(err => {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: err.msg ||
|
||
err.response.data.msg ||
|
||
err.response.data.message ||
|
||
"创建订单失败",
|
||
icon: "none",
|
||
duration: 2000
|
||
})
|
||
}).finally(function () {
|
||
that.isShowPayPwdPop = false
|
||
that.$refs.payPwdPop.clear()
|
||
that.$refs.payPwdPop.close()
|
||
})
|
||
},
|
||
subscribePay() {
|
||
uni.requestSubscribeMessage({
|
||
tmplIds: [
|
||
'7O3wKw7_D4t7yfSOlvecKuOQP8QEPY88uBx2FJg43HE',
|
||
'TSmTnGibZ8IxWCiRWOvLxha6-0u7tE-V1-WbDCiPkKU',
|
||
'9Q6xLHe6HyjkU5Zn5k_2zxYPf2y4MxVyUbOSW8pcZRU'
|
||
],
|
||
complete: () => this.createOrder(false)
|
||
})
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.submit-order { min-height: 100vh; }
|
||
.page-scroll { height: calc(100vh - 120rpx); }
|
||
.card { background: #fff; border-radius: 24rpx; margin: 24rpx; padding: 24rpx; }
|
||
.product-card { display: flex; }
|
||
.thumb { width: 160rpx; height: 160rpx; border-radius: 16rpx; }
|
||
.info { flex: 1; margin-left: 20rpx; }
|
||
.title { font-size: 28rpx; color: #333; line-height: 40rpx; font-weight: 600; }
|
||
.price-row { margin-top: 8rpx; display: flex; align-items: baseline; }
|
||
.label { font-size: 24rpx; color: #666; }
|
||
.price { color: #E53935; font-size: 34rpx; font-weight: 700; }
|
||
.notice { margin-top: 12rpx; font-size: 22rpx; color: #999; }
|
||
|
||
.section-title { font-size: 28rpx; color: #111; font-weight: 600; margin-bottom: 12rpx; }
|
||
.form-item { margin-bottom: 20rpx; display: flex; align-items: center; }
|
||
.form-label { width: 120rpx; display: block; font-size: 24rpx; color: #666; margin-bottom: 0; }
|
||
.date-row { display: flex; align-items: center; justify-content: space-between; background: #fff; border-radius: 16rpx; padding: 20rpx; }
|
||
.date-val { font-size: 26rpx; color: #333; }
|
||
|
||
.radio-item { margin-bottom: 16rpx; }
|
||
.text-card .plain-text { font-size: 26rpx; color: #666; line-height: 40rpx; letter-spacing: 2px;}
|
||
|
||
.bottom-space { height: 140rpx; }
|
||
.bottom-bar { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; border-top: 1rpx solid #eee; display: flex; align-items: center; justify-content: space-between; padding: 16rpx 24rpx; }
|
||
.total { font-size: 28rpx; color: #111; font-weight: 700; }
|
||
.total .highlight { color: #C52733; font-weight: 700; }
|
||
.bar-actions { display: flex; gap: 16rpx; }
|
||
.mini-btn {
|
||
padding: 10rpx 22rpx;
|
||
border: 1rpx solid #ccc;
|
||
border-radius: 32rpx;
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.buy-btn {
|
||
padding: 10rpx 28rpx;
|
||
border-radius: 32rpx;
|
||
background: #C52733;
|
||
color: #fff;
|
||
font-size: 26rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.buy-btn.disabled { background: #ccc; pointer-events: none; }
|
||
</style> |