普兆健康管家前端代码仓库
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.
 
 
 

574 lines
19 KiB

<template>
<view class="page__view">
<navbar title="检测预约" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#F3F2F7" />
<view class="main">
<view class="card">
<view class="card-header">{{ typeDesc }}</view>
<view class="flex row">
<view class="row-label">联系电话</view>
<view class="row-content">{{ configList.customer_service_phone || '-' }}</view>
</view>
</view>
<view class="card">
<view class="card-header">预约信息</view>
<view class="form">
<uv-form
ref="form"
:model="form"
errorType="toast"
>
<!-- 自采 -->
<template v-if="type == 0">
<view class="form-item">
<uv-form-item prop="addressData" :customStyle="formItemStyle">
<view class="form-item-label">寄送地址</view>
<view class="form-item-content">
<view class="flex row" @click="jumpToSelectAddress">
<view v-if="form.addressData" class="text">{{ getAddressDesc(form.addressData) }}</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>
</template>
<!-- 上门 -->
<template v-else-if="type == 1">
<view class="form-item">
<uv-form-item prop="addressData" :customStyle="formItemStyle">
<view class="form-item-label">体检地址</view>
<view class="form-item-content">
<view class="flex row" @click="jumpToSelectAddress">
<view v-if="form.addressData" class="text">{{ getAddressDesc(form.addressData) }}</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="date" :customStyle="formItemStyle">
<view class="form-item-label">预约日期</view>
<view class="form-item-content">
<view class="flex row" @click="openDatePicker">
<view v-if="form.date" class="text">{{ $dayjs(form.date).format('YYYY-MM-DD') }}</view>
<view v-else class="text placeholder">请选择内容</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
<uv-datetime-picker
ref="datetimePicker"
v-model="form.date"
mode="date"
title="预约日期"
confirmColor="#7451DE"
cancelColor="#8B8B8B"
round="32rpx"
:minDate="minTime"
@confirm="onDateChange"
></uv-datetime-picker>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="timeRange" :customStyle="formItemStyle">
<view class="form-item-label">预约时段</view>
<view class="form-item-content">
<view class="flex row" @click="openTimePicker">
<view v-if="form.timeRange" class="text">{{ form.timeRange.join('~') }}</view>
<view v-else class="text placeholder">请选择内容</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
<uv-picker
ref="timeRangePicker"
:columns="timeColumns"
:defaultIndex="[0, 0]"
title="预约时段"
confirmColor="#7451DE"
cancelColor="#8B8B8B"
round="32rpx"
@change="onTimeRangeColChange"
@confirm="onTimeRangeChange"
></uv-picker>
</view>
</uv-form-item>
</view>
</template>
<!-- 到店 -->
<template v-else-if="type == 2">
<view class="form-item">
<uv-form-item prop="date" :customStyle="formItemStyle">
<view class="form-item-label">预约日期</view>
<view class="form-item-content">
<view class="flex row" @click="openDatePicker">
<view v-if="form.date" class="text">{{ $dayjs(form.date).format('YYYY-MM-DD') }}</view>
<view v-else class="text placeholder">请选择内容</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
<uv-datetime-picker
ref="datetimePicker"
v-model="form.date"
mode="date"
title="预约日期"
confirmColor="#7451DE"
cancelColor="#8B8B8B"
round="32rpx"
:minDate="minTime"
@confirm="onDateChange"
></uv-datetime-picker>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="timeRange" :customStyle="formItemStyle">
<view class="form-item-label">预约时段</view>
<view class="form-item-content">
<view class="flex row" @click="openTimePicker">
<view v-if="form.timeRange" class="text">{{ form.timeRange.join('~') }}</view>
<view v-else class="text placeholder">请选择内容</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
<uv-picker
ref="timeRangePicker"
:columns="timeColumns"
:defaultIndex="[0, 0]"
title="预约时段"
confirmColor="#7451DE"
cancelColor="#8B8B8B"
round="32rpx"
@change="onTimeRangeColChange"
@confirm="onTimeRangeChange"
></uv-picker>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="hospitalId" :customStyle="formItemStyle">
<view class="form-item-label">预约医院</view>
<view class="form-item-content">
<view class="flex row" @click="openHospitalPicker">
<view v-if="form.hospitalId" class="text">{{ getHospitalDesc(form.hospitalId) }}</view>
<view v-else class="text placeholder">请选择内容</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
<uv-picker
ref="hospitalPicker"
:columns="[hospitalOptions]"
keyName="label"
title="预约医院"
confirmColor="#7451DE"
cancelColor="#8B8B8B"
round="32rpx"
@confirm="onHospitalChange"
></uv-picker>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="name" :customStyle="formItemStyle">
<view class="form-item-label">姓名</view>
<view class="form-item-content input">
<formInput v-model="form.name" placeholder="请输入内容"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="phone" :customStyle="formItemStyle">
<view class="form-item-label">联系方式</view>
<view class="form-item-content input">
<formInput v-model="form.phone" placeholder="请输入内容"></formInput>
</view>
</uv-form-item>
</view>
</template>
</uv-form>
</view>
</view>
</view>
<view class="bottom">
<button class="btn" @click="onSubmit">提交预约</button>
</view>
</view>
</template>
<script>
import { mapState } from 'vuex'
import formInput from '@/pages_order/components/formInput.vue'
// 可选预约类型 0自采,1上门,2到店,3已取消
const SUBSCRIBE_TYPE_AND_DESC_MAPPING = {
0: '自采',
1: '上门',
2: '到店',
3: '已取消',
}
export default {
components: {
formInput,
},
data() {
return {
id: null,
productId: null,
type: null,
info: {},
form: {
addressData: null,
date: null,
timeRange: null,
hospitalId: null,
name: null,
phone: null,
},
formItemStyle: { padding: 0 },
minTime: new Date().getTime(),
hours: [],
timeColumns: [],
hospitalOptions: []
}
},
computed: {
...mapState(['configList', 'userInfo', 'payOrderProduct', 'addressInfo']),
typeDesc() {
const desc = SUBSCRIBE_TYPE_AND_DESC_MAPPING[this.type] || ''
return `${desc}检测`
},
},
onShow() {
if (this.addressInfo) {
const {
id,
name,
phone,
province,
city,
district,
detail,
} = this.addressInfo
this.form.addressData = {
id,
name,
phone,
area: [province, city, district].filter(val => val),
address: detail,
}
this.$store.commit('setAddressInfo', null)
}
},
async onLoad(arg) {
const { id, type } = arg
this.id = id
this.type = parseInt(type)
await this.getData(id)
if (this.type == 2) { // 到店
this.fetchHospitalOptions()
}
},
onReady() {
this.setRules()
},
onUnload() {
this.$store.commit('setAddressInfo', null)
},
methods: {
async getData(id) {
try {
const result = await this.$fetch('getSubscribeDetail', { id })
const {
productId,
name,
phone,
sendAddressId,
sendAddress,
sendAddressDetail,
subscribeDate,
subscribeTime,
hospitalId,
} = result
this.form = {
addressData: {
id: sendAddressId,
name,
phone,
area: [sendAddress],
address: sendAddressDetail,
},
date: new Date(subscribeDate).getTime(),
timeRange: subscribeTime ? JSON.parse(subscribeTime) : null,
hospitalId,
name,
phone,
}
this.productId = productId
} catch (err) {
}
},
async fetchHospitalOptions() {
try {
const result = await this.$fetch('getSubscribeHospital', { productId: this.productId })
this.hospitalOptions = result.map(item => {
const { id, name } = item
return { id, label: name }
})
} catch (err) {
}
},
setRules() {
let rules = {}
switch(this.type) {
case 0: // 自采
rules = {
'addressData': {
type: 'object',
required: true,
message: '请选择寄送地址',
},
}
break
case 1: // 上门
rules = {
'addressData': {
type: 'object',
required: true,
message: '请选择体检地址',
},
'date': {
type: 'number',
required: true,
message: '请选择预约日期',
},
'timeRange': {
type: 'array',
required: true,
message: '请选择预约时段',
},
}
this.setTimeColumns()
break
case 2: // 到店
rules = {
'date': {
type: 'number',
required: true,
message: '请选择预约日期',
},
'timeRange': {
type: 'array',
required: true,
message: '请选择预约时段',
},
'hospitalId': {
type: 'string',
required: true,
message: '请选择预约医院',
},
'name': {
type: 'string',
required: true,
message: '请输入姓名',
},
'phone': {
type: 'string',
required: true,
message: '请输入联系方式',
},
}
this.setTimeColumns()
break
default:
break
}
this.$refs.form.setRules(rules);
},
getAddressDesc(data) {
if (!data) {
return ''
}
const { area, address } = data
return `${area?.join?.('') || ''}${address}`
},
getHospitalDesc() {
},
fixedZero(num) {
return `${num < 10 ? '0' + num : num}`
},
setTimeColumns(date) {
let currentTime = this.$dayjs()
let startHour = 8
let endHour = 22
if (date && this.$dayjs(date).isSame(currentTime, 'day')) {
let currentHour = currentTime.hour()
if (currentHour > endHour) {
this.timeColumns = []
return
}
if (currentHour > startHour) {
startHour = currentHour
}
if (startHour == endHour) {
this.timeColumns = []
return
}
}
this.hours = new Array(endHour - startHour + 1).fill(startHour).map((val, idx) => val + idx)
let startCols = this.hours.slice(0, this.hours.length - 1).map(hour => `${this.fixedZero(hour)}:00`)
let endCols = this.hours.slice(1).map(hour => `${this.fixedZero(hour)}:00`)
this.timeColumns = [startCols, endCols]
this.$refs.timeRangePicker.setColumnValues(0, startCols)
this.$refs.timeRangePicker.setColumnValues(1, endCols)
},
openTimePicker() {
this.$refs.timeRangePicker.open();
},
onTimeRangeColChange(e) {
if (e.columnIndex == 0) {
let startIdx = e.indexs[0]
let endCols = startIdx == this.hours.length - 1 ? [] : this.hours.slice(startIdx + 1).map(hour => `${this.fixedZero(hour)}:00`)
this.timeColumns[1] = endCols
this.$refs.timeRangePicker.setColumnValues(1, endCols)
}
},
onTimeRangeChange(e) {
this.form.timeRange = e.value
const [startTime, endTime] = this.form.timeRange
let startIdx = startTime ? this.timeColumns[0].findIndex(item => item === startTime) : 0
let endIdx = endTime ? this.timeColumns[1].findIndex(item => item === endTime) : 0
this.$refs.timeRangePicker.setIndexs([startIdx, endIdx], true);
},
openDatePicker() {
this.$refs.datetimePicker.open();
},
onDateChange(e) {
const date = e.value
this.setTimeColumns(date)
const [startTime] = this.form.timeRange || []
let dateStr = this.$dayjs(date).format('YYYY-MM-DD')
if (startTime && this.$dayjs(`${dateStr} ${startTime}`).isBefore(this.$dayjs())) {
this.form.timeRange = null
this.$refs.datetimePicker.setIndexs([0, 0]);
}
},
openHospitalPicker() {
this.$refs.hospitalPicker.open();
},
onHospitalChange(e) {
this.form.hospitalId = e.value[0].id
},
getHospitalDesc(id) {
return this.hospitalOptions.find(item => item.id === id)?.label
},
jumpToSelectAddress() {
this.$utils.navigateTo('/pages_order/address/addressList')
},
async onSubmit() {
try {
await this.$refs.form.validate()
const params = {
id: this.id,
}
if (this.type == 0) { // 自采
const { addressData } = this.form
const {
id: sendAddressId,
name,
phone,
area,
address,
} = addressData
params.sendAddressId = sendAddressId || ''
params.sendAddress = area.join('')
params.sendAddressDetail = address
params.name = name
params.phone = phone
} else if (this.type == 1) { // 上门
const { addressData, date, timeRange } = this.form
const {
id: sendAddressId,
name,
phone,
area,
address,
} = addressData
params.sendAddressId = sendAddressId || ''
params.sendAddress = area.join('')
params.sendAddressDetail = address
params.name = name
params.phone = phone
params.subscribeDate = this.$dayjs(date).format('YYYY-MM-DD')
params.subscribeTime = JSON.stringify(timeRange)
} else if (this.type == 2) { // 到店
const { date, timeRange, hospitalId, name, phone } = this.form
params.subscribeDate = this.$dayjs(date).format('YYYY-MM-DD')
params.subscribeTime = JSON.stringify(timeRange)
params.hospitalId = hospitalId
params.name = name
params.phone = phone
}
await this.$fetch('submitOrUpdateSubscribe', params)
uni.showToast({
icon: 'success',
title: '提交成功',
});
setTimeout(() => {
this.$utils.redirectTo(`/pages_order/checkup/checkupBook/detail?id=${this.id}`)
}, 800)
} catch (err) {
console.log('onSubmit err', err)
}
},
},
}
</script>
<style scoped lang="scss">
@import './style.scss';
</style>