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.

317 lines
8.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="container">
<HeaderCustom title='预约服务'></HeaderCustom>
<div class="titleBox">
<div class="title">预约服务</div>
<div class="line"></div>
<div class="desc">
请填写以下相关信息我们的销售工程师会尽快与您联系并提供报价单
</div>
</div>
<div class="formBox">
<uv-form labelPosition="left" :model="formField" labelWidth="100" :rules="rules" ref="form">
<uv-form-item required label="姓名" prop="name">
<uv-input v-model="formField.name" border="none" placeholder="请输入姓名">
</uv-input>
</uv-form-item>
<uv-form-item required label="手机号码" prop="phone">
<uv-input v-model="formField.phone" border="none" placeholder="请输入手机号码">
</uv-input>
</uv-form-item>
<uv-form-item required label="邮箱" prop="email">
<uv-input v-model="formField.email" border="none" placeholder="请输入邮箱">
</uv-input>
</uv-form-item>
<uv-form-item required label="地址" prop="adress" @click="openAddressPicker">
<uv-input v-model="formField.adress" readonly border="none" placeholder="请选择地址">
</uv-input>
<uv-picker ref="addressPicker" :columns="addressList" keyName="name" @change="addressChange"
@confirm="confirm">
</uv-picker>
</uv-form-item>
<uv-form-item labelPosition='top' required label="咨询业务类型" prop="appointment_type">
<!-- <uv-input v-model="formField.type" readonly border="none" placeholder="请选择咨询业务类型">
</uv-input> -->
<div class="type_select_box">
<div class="item" :class="{selected:formField.appointment_type.includes('别墅梯采购')}"
@click="pickType('别墅梯采购')">
<img class="img" src="/static/imgs/bstcg.png" alt="">
别墅梯采购
</div>
<div class="item" :class="{selected:formField.appointment_type.includes('旧梯换新')}"
@click="pickType('旧梯换新')">
<img class="img" src="/static/imgs/jthx.png" alt="">旧梯换新
</div>
<div class="item" :class="{selected:formField.appointment_type.includes('新梯采购')}"
@click="pickType('新梯采购')">
<img class="img" src="/static/imgs/xtcg.png" alt="">新梯采购
</div>
<div class="item" :class="{selected:formField.appointment_type.includes('旧楼加装')}"
@click="pickType('旧楼加装')">
<img class="img" src="/static/imgs/jljz.png" alt="">旧楼加装
</div>
</div>
</uv-form-item>
<uv-form-item label="需求补充" prop="remark">
<uv-input v-model="formField.remark" border="none" placeholder="请输入需求补充">
</uv-input>
</uv-form-item>
<uv-button type="primary" text="提交" customStyle="margin-top: 10px" @click="submit"></uv-button>
</uv-form>
</div>
</view>
</template>
<script setup>
import {
computed,
onMounted,
ref
} from "vue";
import {
onShow
} from "@dcloudio/uni-app";
import {
useAuthStore,
useUserStore
} from "@/store";
import {
regions
} from '/static/json/regions.js'
import HeaderCustom from '/components/HeaderCustom/HeaderCustom.vue'
import RPC from "@/utils/request";
const authStore = useAuthStore()
const userStore = useUserStore()
onShow(() => {
if (!authStore?.isLoggedIn) {
uni.switchTab({
url: `/pages/index/index`,
});
uni.showToast({
title: "请先登录",
icon: "none",
})
}
})
const form = ref(null)
const formField = ref({
name: '',
phone: '',
email: '',
adress: '',
appointment_type: [],
remark: '',
})
const pickType = type => {
const index = formField.value.appointment_type.findIndex(item => item === type)
if (index >= 0) {
formField.value.appointment_type.splice(index, 1)
} else {
formField.value.appointment_type.push(type)
}
}
const rules = {
'name': {
type: 'string',
required: true,
message: '请填写姓名',
trigger: ['blur', 'change']
},
'phone': {
type: 'string',
required: true,
message: '请填写手机号码',
trigger: ['blur', 'change']
},
'email': {
type: 'string',
required: true,
message: '请填写邮箱',
trigger: ['blur', 'change']
},
'adress': {
type: 'string',
required: true,
message: '请选择地址',
trigger: ['blur', 'change']
},
'appointment_type': {
type: 'array',
required: true,
message: '请选择咨询业务类型',
trigger: ['blur', 'change']
},
}
const submit = () => {
// 如果有错误会在catch中返回报错信息数组校验通过则在then中返回true
form.value.validate().then(res => {
const params = {
...formField.value,
appointment_type: formField.value.appointment_type.join(',')
}
RPC.post('/appointment/create',params).then(() => {
uni.showToast({
icon: 'success',
title: '预约成功'
})
formField.value = {
name: '',
phone: '',
email: '',
adress: '',
appointment_type: [],
remark: '',
}
})
}).catch(errors => {
})
}
const provinces = ref([])
const citys = ref([])
const areas = ref([])
const addressList = computed(() => [provinces.value, citys.value, areas.value])
const addressPicker = ref(null)
const pickerValue = ref(['0', '0', '0'])
const defaultValue = ref(['3442', '1', '2'])
const addressChange = e => {
const {
columnIndex,
index,
indexs
} = e
// 改变了省
if (columnIndex === 0) {
citys.value = provinces.value[index]?.children || []
areas.value = citys.value[0]?.children || []
addressPicker.value.setIndexs([index, 0, 0], true)
} else if (columnIndex === 1) {
areas.value = citys.value[index]?.children || []
addressPicker.value.setIndexs(indexs, true)
}
}
const confirm = e => {
// console.log('确认选择的地区:', e);
// uni.showToast({
// icon: 'none',
// title: `${e.value[0].name}/${e.value[1].name}/${e.value[2].name}`
// })
formField.value.adress = `${e.value[0].name}/${e.value[1].name}/${e.value[2].name}`
}
const handlePickValueDefault = () => {
pickerValue.value[0] = provinces.value.findIndex(item => Number(item.id) == defaultValue.value[0]);
// 设置市
citys.value = provinces.value[pickerValue.value[0]]?.children || [];
pickerValue.value[1] = citys.value.findIndex(item => Number(item.id) == defaultValue.value[1]);
// 设置区
areas.value = citys.value[pickerValue.value[1]]?.children || [];
pickerValue.value[2] = areas.value.findIndex(item => Number(item.id) == defaultValue.value[2]);
// 重置下位置
addressPicker.value.setIndexs([pickerValue.value[0], pickerValue.value[1], pickerValue.value[2]], true);
}
const openAddressPicker = () => {
addressPicker.value.open()
handlePickValueDefault()
}
const getData = () => {
provinces.value = regions.sort((left, right) => (Number(left.code) > Number(right.code) ?
1 : -1));
handlePickValueDefault()
}
onMounted(() => {
getData()
})
</script>
<style lang="scss" scoped>
.container {
font-size: 14px;
min-height: 100vh;
background-color: #f8f8f8;
}
.titleBox {
background-color: #fff;
padding: 20px 4vw;
.title {
font-size: 16px;
font-weight: 700;
}
.line {
width: 5vw;
height: 2px;
background-color: #3F70FF;
margin-top: 4px;
margin-bottom: 8px;
}
.desc {
font-size: 12px;
font-weight: 500;
line-height: 18px;
}
}
.formBox {
padding: 10px;
:deep(.uv-form) {
background-color: #fff;
padding: 10px;
border-radius: 10px;
.uv-form-item {
background-color: #F4F4F4;
margin-bottom: 10px;
border-radius: 10px;
padding-left: 20px;
}
}
.type_select_box {
display: flex;
flex-wrap: wrap;
gap: 15px;
padding-right: 20px;
margin-top: 10px;
.item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #fff;
font-size: 12px;
width: 90px;
height: 70px;
border-radius: 6px;
.img {
width: 20px;
height: 20px;
margin-bottom: 6px;
}
&.selected {
border: 1px solid #3F70FF;
background-color: rgba(63, 112, 255, 0.1);
}
}
}
}
</style>