|
|
- <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 {
- return (await this.$fetch('queryTouristList', { isDefault: '1' })).records
- } 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>
|