鸿宇研学生前端代码
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.
 
 
 

422 lines
12 KiB

<template>
<view class="page__view">
<navbar title="填写订单" leftClick @leftClick="$utils.navigateBack" />
<view class="main">
<productCard :data="orderInfo"></productCard>
<uv-form
ref="form"
:model="form"
errorType="toast"
>
<view class="card">
<view class="card-header">联系人信息</view>
<view class="form-item">
<uv-form-item prop="name" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/static/image/icon-require.png" mode="widthFix"></image>
真实姓名
</view>
<view class="form-item-content">
<formInput v-model="form.name"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="phone" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/static/image/icon-require.png" mode="widthFix"></image>
手机号码
</view>
<view class="form-item-content">
<formInput v-model="form.phone"></formInput>
</view>
</uv-form-item>
</view>
</view>
<view class="card">
<view class="card-header">订单详情</view>
<view style="margin-top: 16rpx;">
<uv-form-item prop="members" :customStyle="formItemStyle">
<!-- style="width: calc(100vw - 40rpx*2);" -->
<view>
<peopleNumberInput
:adults.sync="form.adults"
:teenager.sync="form.teenager"
:child.sync="form.child"
:adultsPrice="productPackage.adultsPrice"
:teenagerPrice="productPackage.teenagerPrice"
:childPrice="productPackage.childPrice"
></peopleNumberInput>
<memberChooseView
:members.sync="form.members"
></memberChooseView>
</view>
</uv-form-item>
</view>
</view>
<view class="card">
<view class="card-header">其他</view>
<view class="form-item">
<uv-form-item prop="coupon" :customStyle="formItemStyle">
<view class="form-item-label">选择优惠券</view>
<view class="form-item-content">
<view class="flex row" @click="jumpToSelectCoupon">
<view v-if="form.coupon" class="text">{{ couponInfo.label }}</view>
<view v-else class="text placeholder">请选择</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="invoice" :customStyle="formItemStyle">
<view class="form-item-label">选择发票类型</view>
<view class="form-item-content">
<view class="flex row" @click="jumpToSelectInvoice">
<view v-if="form.invoice" class="text">{{ getInvoiceDesc(form.invoice) }}</view>
<view v-else class="text placeholder">请选择</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
</view>
</uv-form-item>
</view>
</view>
</uv-form>
<view class="notice">
<!-- <view class="notice-header">下单须知</view> -->
<view class="notice-content">
<!-- todo: check key -->
<!-- <uv-parse :content="configList['order_instructions']"></uv-parse> -->
如有特殊病史或有不宜参加的旅程(项目)、男女报名如无法同住、分开报名需安排同住同车等,请备注
</view>
</view>
</view>
<view class="bottom">
<view class="agreement">
<uv-checkbox-group
v-model="checkboxValue"
shape="circle"
>
<uv-checkbox
size="40rpx"
icon-size="40rpx"
activeColor="#00A9FF"
:name="1"
></uv-checkbox>
</uv-checkbox-group>
<view class="desc">
我已阅读并同意
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_agreement', '退订政策')">《退订政策》</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '合同范本')">《合同范本》</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '预订须知')">《预订须知》</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '安全提示')">《安全提示》</text>
</view>
</view>
<view class="flex bar">
<view class="col price">
<view class="flex price-label">
已选<view class="highlight">{{ `${totolPeople}人` }}</view>总额
</view>
<view class="flex price-value">
¥<view class="highlight">{{ totalPrice }}</view>
</view>
</view>
<button class="col btn btn-primary btn-pay" @click="onPay">立即支付</button>
</view>
</view>
<agreementModal ref="modal" @confirm="onConfirmAgreement"></agreementModal>
</view>
</template>
<script>
import { mapState } from 'vuex'
import productCard from '@/pages_order/order/components/productCard.vue'
import peopleNumberInput from './peopleNumberInput.vue'
import memberChooseView from './memberChooseView.vue'
import formInput from '@/pages_order/components/formInput.vue'
import agreementModal from '@/pages_order/components/agreementModal.vue'
export default {
components: {
productCard,
peopleNumberInput,
memberChooseView,
formInput,
agreementModal,
},
data() {
return {
form: {
name: null,
phone: null,
adults: 0,
teenager: 0,
child: 0,
members: [],
coupon: null,
invoice: null,
},
checkboxValue: [],
formItemStyle: { padding: 0 },
}
},
computed: {
...mapState(['configList', 'userInfo', 'orderInfo', 'couponInfo']),
productPackage() {
const { time, product } = this.orderInfo
const { timeOptions } = product || {}
return timeOptions?.find?.(item => item.id === time) || {}
},
totolPeople() {
const { adults, teenager, child } = this.form
return (adults || 0) + (teenager || 0) + (child || 0)
},
totalPrice() {
const { adults, teenager, child, coupon } = this.form
const { adultsPrice, teenagerPrice, childPrice } = this.productPackage
let total = 0
adults && (total += adults * (adultsPrice || 0))
teenager && (total += teenager * (teenagerPrice || 0))
child && (total += child * (childPrice || 0))
coupon && (total -= (this.couponInfo?.price || 0))
return total
},
},
watch: {
form: {
handler(val) {
this.$refs.form.setRules(this.getRules())
},
deep: true
}
},
onShow() {
if (this.couponInfo) {
this.form.coupon = this.couponInfo.id
}
},
onLoad(arg) {
console.log('onLoad')
console.log('orderInfo', this.orderInfo)
this.initData()
},
onReady() {
this.$refs.form.setRules(this.getRules())
},
onUnload() {
this.$store.commit('setCouponInfo', null)
},
methods: {
getRules() {
const { adults, teenager, child } = this.form
return {
'name': {
type: 'string',
required: true,
message: '请输入真实姓名',
},
'phone': {
type: 'string',
required: true,
message: '请输入手机号码',
},
'adults': {
type: 'number',
required: true,
message: '请选择人数',
validator: (rule, value, callback) => {
if (adults || teenager || child) {
return true
}
return false
},
},
'members': {
type: 'array',
required: true,
message: '请选择出行人',
},
}
},
initData() {
const {
time,
adults,
teenager,
child,
members,
} = this.orderInfo
this.form = {
name: null,
phone: null,
adults,
teenager,
child,
members: members.map(item => ({ ...item, isSelected: true })),
coupon: null,
invoice: null,
}
},
jumpToSelectCoupon() {
uni.navigateTo({
url: `/pages_order/coupon/couponSelect/index`
})
},
getCouponDesc() {
// todo
},
jumpToSelectInvoice() {
// todo
},
getInvoiceDesc() {
// todo
},
onConfirmAgreement(confirm) {
if (confirm) {
this.checkboxValue = [1]
} else {
this.checkboxValue = []
}
},
async onPay() {
if(!this.checkboxValue.length){
return uni.showToast({
title: '请先同意《用户协议》《隐私协议》《消费者告知》',
icon:'none'
})
}
try {
await this.$refs.form.validate()
// todo: fetch create order and save wx pay data
const {
product,
time,
} = this.orderInfo
const {
name,
phone,
adults,
teenager,
child,
members,
coupon,
invoice,
} = this.form
const orderInfo = {
product,
couponInfo: this.couponInfo,
time,
adults,
teenager,
child,
members,
coupon,
invoice,
name,
phone,
}
this.$store.commit('setOrderInfo', orderInfo)
// todo: get id?
uni.navigateTo({
url: `/pages_order/order/orderPay/index`
})
} catch (err) {
}
},
onPaySuccess() {
setTimeout(() => {
// todo: check → jump to order list page ?
uni.reLaunch({
url: `/pages_order/order/orderList/index`
});
}, 700)
},
onPayCancel() {
// todo: check → jump to order list page?
uni.redirectTo({
url: `/pages_order/order/orderList/index?index=1`
});
},
},
}
</script>
<style scoped lang="scss">
@import '../styles/style.scss';
.price {
justify-content: flex-start;
&-label {
justify-content: flex-start;
column-gap: 12rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 24rpx;
line-height: 1.4;
color: #626262;
.highlight {
font-size: 24rpx;
font-weight: 500;
color: $uni-color;
}
}
&-value {
justify-content: flex-start;
column-gap: 8rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
line-height: 1.4;
color: $uni-color;
.highlight {
font-size: 40rpx;
}
}
}
.btn-pay {
flex: none;
width: auto;
padding: 14rpx 74rpx;
}
</style>