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

372 lines
9.3 KiB

<template>
<view>
<uv-popup ref="popup" mode="bottom" bgColor="none" @change="onPopupChange">
<view class="popup__view">
<view class="flex header">
选择日期/套餐/人数
</view>
<uv-form
ref="form"
:model="form"
errorType="toast"
>
<view class="section">
<uv-form-item prop="time" :customStyle="formItemStyle">
<view class="flex section-header">
<view>选择团期</view>
<button class="flex btn" @click="openTimePicker">
<view class="highlight">日历选择</view>
<image class="img" src="@/static/image/icon-arrow-right.png" mode="widthFix"></image>
</button>
</view>
<timeCalendarSelect ref="timeCalendarSelect" v-model="form.time" :options="data.timeOptions"></timeCalendarSelect>
<view class="flex section-content">
<timeOptionsSelect style="width: calc(100vw - 40rpx*2);"
v-model="form.time"
:options="data.timeOptions"
></timeOptionsSelect>
</view>
</uv-form-item>
</view>
<view class="section">
<uv-form-item prop="adults" :customStyle="formItemStyle">
<view class="flex section-header">
<view>选择人数</view>
</view>
<view class="flex section-content">
<peopleNumberInput style="width: calc(100vw - 40rpx*2);"
:adults.sync="form.adults"
:teenager.sync="form.teenager"
:child.sync="form.child"
:adultsPrice="selectTimeObj.adultsPrice"
:teenagerPrice="selectTimeObj.teenagerPrice"
:childPrice="selectTimeObj.childPrice"
></peopleNumberInput>
</view>
</uv-form-item>
</view>
<view class="section">
<uv-form-item prop="members" :customStyle="formItemStyle">
<view class="flex section-header">
<view>选择人员</view>
<button class="flex btn" @click="jumpToSelectMember">
<view>请选择出行人</view>
<image class="img" src="@/static/image/icon-arrow-right.png" mode="widthFix"></image>
</button>
</view>
<view class="flex section-content member">
<view class="member-item" v-for="item in form.members" :key="item.id">
{{ item.name }}
</view>
</view>
</uv-form-item>
</view>
</uv-form>
<view class="footer">
<button class="flex btn" @click="onConfirm">填写订单</button>
</view>
</view>
</uv-popup>
</view>
</template>
<script>
import { mapState } from 'vuex'
import timeOptionsSelect from '@/pages_order/order/orderConfirm/timeOptionsSelect.vue'
import timeCalendarSelect from '@/pages_order/order/orderConfirm/timeCalendarSelect.vue'
import peopleNumberInput from '@/pages_order/order/orderConfirm/peopleNumberInput.vue'
export default {
components: {
timeOptionsSelect,
timeCalendarSelect,
peopleNumberInput,
},
props: {
data: {
type: Object,
default() {
return {}
}
},
},
data() {
return {
options: [],
form: {
time: null,
adults: 0,
teenager: 0,
child: 0,
members: [],
},
formItemStyle: { padding: 0 },
}
},
computed : {
...mapState(['configList', 'travelerList']),
selectTimeObj() {
const { time: id } = this.form
const { timeOptions } = this.data
if (id) {
return timeOptions?.find?.(option => option.id === id) || {}
}
return timeOptions?.[0] || {}
},
},
watch: {
travelerList(val) {
if (val?.length) {
this.form.members = val
this.$store.commit('setTravelerList', [])
}
},
form: {
handler(val) {
this.$refs.form.setRules(this.getRules())
},
deep: true
}
},
onReady() {
this.$refs.form.setRules(this.getRules())
},
methods: {
getRules() {
const { adults, teenager, child } = this.form
return {
'time': {
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: '请选择出行人',
},
}
},
openTimePicker() {
this.$refs.timeCalendarSelect.open()
},
async getDefaultMembers() {
try {
// todo: fetch defalt members
return [
{
id: '001',
name: '李梓发',
idNo: '430223********9999',
type: 0,
},
{
id: '002',
name: '吴彦谦',
idNo: '430223********9999',
type: 0,
},
{
id: '003',
name: '冯云',
idNo: '430223********9999',
type: 1,
},
{
id: '004',
name: '冯思钗',
idNo: '430223********9999',
type: 2,
},
{
id: '005',
name: '李书萍',
idNo: '430223********9999',
type: 0,
},
{
id: '006',
name: '冯艺莲',
idNo: '430223********9999',
type: 1,
},
]
} catch (err) {
return []
}
},
jumpToSelectMember() {
const { members } = this.form
const selectIds = members.map(item => item.id).join(',')
console.log('jumpToSelectMember', selectIds)
this.$utils.navigateTo(`/pages_order/traveler/travelerList?selectIds=${selectIds}`)
},
async open(data) {
const { selectTime } = data || {}
const defaultMembers = await this.getDefaultMembers()
this.form.time = selectTime || null
this.form.members = defaultMembers
this.$refs.popup.open()
},
close() {
this.$refs.popup.close()
},
async onConfirm() {
try {
await this.$refs.form.validate()
const {
time,
adults,
teenager,
child,
members,
} = this.form
const orderInfo = {
product: this.data,
time,
adults,
teenager,
child,
members,
}
this.$store.commit('setOrderInfo', orderInfo)
uni.navigateTo({
url: '/pages_order/order/orderConfirm/index'
})
} catch (err) {
}
},
onPopupChange(e) {
if (e.show) {
return
}
this.$emit('timeChange', this.form.time)
},
},
}
</script>
<style lang="scss" scoped>
.popup__view {
width: 100vw;
display: flex;
flex-direction: column;
box-sizing: border-box;
font-family: PingFang SC;
font-weight: 400;
line-height: 1.4;
background: #FFFFFF;
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
}
.header {
position: relative;
width: 100%;
padding: 24rpx 0;
box-sizing: border-box;
font-family: PingFang SC;
font-weight: 500;
font-size: 34rpx;
line-height: 1.4;
color: #181818;
border-bottom: 2rpx solid #EEEEEE;
}
.section {
padding: 24rpx 40rpx;
font-family: PingFang SC;
font-weight: 400;
&-header {
justify-content: space-between;
font-size: 32rpx;
font-weight: 500;
color: #181818;
.btn {
column-gap: 4rpx;
font-size: 32rpx;
font-weight: 400;
color: #8B8B8B;
.highlight {
color: #181818;
}
.img {
width: 32rpx;
height: auto;
}
}
}
&-content {
margin-top: 20rpx;
}
}
.member {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12rpx;
&-item {
padding: 16rpx;
text-align: center;
font-size: 28rpx;
color: #181818;
background: #F9F9F9;
border-radius: 16rpx;
}
}
.footer {
width: 100%;
// height: 214rpx;
padding: 32rpx 40rpx;
box-sizing: border-box;
.btn {
width: 100%;
padding: 14rpx 0;
font-family: PingFang SC;
font-weight: 500;
font-size: 36rpx;
line-height: 1.4;
color: #FFFFFF;
background-image: linear-gradient(to right, #21FEEC, #019AF9);
border: 2rpx solid #00A9FF;
border-radius: 41rpx;
}
}
</style>