315 lines
9.5 KiB
Vue
315 lines
9.5 KiB
Vue
<template>
|
||
<view class="page">
|
||
<!-- 固定头部 -->
|
||
<view class="header">
|
||
<view class="center" style="width: 50rpx; height: 50rpx; margin-left: 32rpx;">
|
||
<image src="/static/ic_back.png" @click="back" style="width: 48rpx; height: 48rpx;" mode=""></image>
|
||
</view>
|
||
<text style="font-size: 30rpx;">{{ $t('infoEntry.title') }}</text>
|
||
<view style="width: 50rpx;margin-right: 32rpx;"></view>
|
||
</view>
|
||
|
||
<!-- 可滚动内容区域 -->
|
||
<view class="scroll-content">
|
||
<view class="content">
|
||
<view class=""
|
||
style="width: 680rpx; height: 396rpx; background-image: linear-gradient(-45deg, #60D7FF, #68BBD7); margin-top: 32rpx; border-radius: 20rpx; box-shadow: 0 0 10rpx 10rpx rgba(0, 0, 0, 0.1);">
|
||
</view>
|
||
|
||
<view class="" style="width: 100%; font-size: 40rpx; padding-left: 54rpx; margin-top: 38rpx;">
|
||
{{ $t('infoEntry.personalInfo') }}
|
||
</view>
|
||
|
||
<!-- 真实姓名 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'userName' }"
|
||
style="width: 680rpx; margin-top: 38rpx;" id="fieldUserName">
|
||
<text style="font-size: 30rpx;"><text
|
||
style="color: #FF0000;">*</text>{{ $t('infoEntry.realName') }}</text>
|
||
<up-input :placeholder="$t('infoEntry.realNamePlaceholder')" border="surround"
|
||
v-model="userName"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 微信号 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'contact' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldContact">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>{{ $t('infoEntry.wechat') }}
|
||
({{ $t('infoEntry.contactMethod') }})</text>
|
||
<up-input :placeholder="$t('infoEntry.wechatPlaceholder')" border="surround"
|
||
v-model="userWechat"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 手机号 -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'contact' }"
|
||
style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>{{ $t('infoEntry.phone') }}
|
||
({{ $t('infoEntry.contactMethod') }})</text>
|
||
<view class="row" style="margin-top: 10rpx; margin-bottom: 10rpx;">
|
||
<aure-country-picker v-model="selectedDialCode" :title="$t('infoEntry.selectCountry')"
|
||
:height="'70%'" :width="'60vw'" :duration="350" :position="'bottom'" :round="true"
|
||
:radius="'24rpx'" :mask-closable="true"></aure-country-picker>
|
||
<up-input :placeholder="$t('infoEntry.phonePlaceholder')" border="surround"
|
||
v-model="userPhone"></up-input>
|
||
</view>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- whatsApp -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'contact' }"
|
||
style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>{{ $t('infoEntry.whatsapp') }}
|
||
({{ $t('infoEntry.contactMethod') }})</text>
|
||
<up-input :placeholder="$t('infoEntry.whatsappPlaceholder')" border="surround"
|
||
v-model="userWhats"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 备注 -->
|
||
<view class="column" style="width: 680rpx; margin-top: 14rpx;">
|
||
<text style="font-size: 30rpx;">{{ $t('infoEntry.remark') }}</text>
|
||
<up-input :placeholder="$t('infoEntry.remarkPlaceholder')" border="surround"
|
||
v-model="remark"></up-input>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<!-- 服务预约信息 -->
|
||
<view class="" style="width: 100%; font-size: 40rpx; padding-left: 54rpx; margin-top: 38rpx;">
|
||
{{ $t('infoEntry.serviceInfo') }}
|
||
</view>
|
||
|
||
<!-- 具体需求 (textarea) -->
|
||
<view class="column" :class="{ 'flash-animation': flashingField === 'specificRequirements' }"
|
||
style="width: 680rpx; margin-top: 14rpx;" id="fieldSpecificRequirements">
|
||
<text style="font-size: 30rpx;"><text style="color: #FF0000;">*</text>具体需求</text>
|
||
<up-textarea
|
||
v-model="specificRequirements"
|
||
placeholder="请详细描述您的保险咨询需求,如:保险类型、出行目的地、保障范围、出行时间等"
|
||
:maxlength="1000"
|
||
:count="true"
|
||
height="200"
|
||
border="surround"
|
||
></up-textarea>
|
||
</view>
|
||
<view class="" style="width: 680rpx; height: 2rpx; background-color: #EAEAEA;"></view>
|
||
|
||
<view class="center" @click="checkData()"
|
||
style="width: 642rpx; height: 72rpx; background-color: #57C9DD; border-radius: 16rpx; box-shadow: 0 0 10rpx 10rpx rgba(0, 0, 0, 0.1); margin-top: 50rpx; margin-bottom: 100rpx;">
|
||
{{ $t('common.submit') }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
|
||
<script>
|
||
import { AppServer } from '@/modules/api/AppServer.js'
|
||
const appServer = new AppServer()
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
serviceId: "",
|
||
hotServiceId: "",
|
||
source: "",
|
||
serviceTitle: "",
|
||
userName: "",
|
||
userWechat: "",
|
||
userPhone: "",
|
||
userWhats: "",
|
||
remark: "",
|
||
specificRequirements: "",
|
||
submitting: false,
|
||
flashingField: '',
|
||
selectedDialCode: '86'
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
if (options.id) {
|
||
this.source = options.source || ''
|
||
if (this.source === 'hot') {
|
||
this.hotServiceId = options.id
|
||
} else {
|
||
this.serviceId = options.id
|
||
}
|
||
}
|
||
if (options.title) {
|
||
this.serviceTitle = decodeURIComponent(options.title)
|
||
}
|
||
},
|
||
methods: {
|
||
checkData() {
|
||
const validations = [{
|
||
field: 'userName',
|
||
selector: '#fieldUserName',
|
||
check: () => !this.userName.trim(),
|
||
message: '请输入真实姓名'
|
||
},
|
||
{
|
||
field: 'contact',
|
||
selector: '#fieldContact',
|
||
check: () => !this.userWechat.trim() && !this.userPhone.trim() && !this.userWhats.trim(),
|
||
message: '请至少填写一种联系方式(微信号/手机号/WhatsApp)'
|
||
},
|
||
{
|
||
field: 'specificRequirements',
|
||
selector: '#fieldSpecificRequirements',
|
||
check: () => !this.specificRequirements.trim(),
|
||
message: '请输入具体需求'
|
||
}
|
||
]
|
||
|
||
for (const validation of validations) {
|
||
if (validation.check()) {
|
||
uni.showToast({
|
||
title: validation.message,
|
||
icon: 'none'
|
||
})
|
||
this.scrollToElement(validation.selector)
|
||
this.flashingField = validation.field
|
||
setTimeout(() => {
|
||
this.flashingField = ''
|
||
}, 1500)
|
||
return
|
||
}
|
||
}
|
||
|
||
this.submitAppointment()
|
||
},
|
||
async submitAppointment() {
|
||
if (this.submitting) return
|
||
this.submitting = true
|
||
|
||
uni.showLoading({
|
||
title: '提交中...',
|
||
mask: true
|
||
})
|
||
|
||
try {
|
||
const appointmentData = {
|
||
serviceId: this.serviceId || null,
|
||
hotServiceId: this.hotServiceId ? parseInt(this.hotServiceId) : null,
|
||
serviceType: 'insurance_consultation',
|
||
realName: this.userName.trim(),
|
||
wechatId: this.userWechat.trim() || null,
|
||
phone: this.userPhone.trim() || null,
|
||
phoneCountryCode: this.userPhone.trim() ? this.selectedDialCode : null,
|
||
whatsapp: this.userWhats.trim() || null,
|
||
notes: this.remark.trim() || null,
|
||
specificRequirements: this.specificRequirements.trim(),
|
||
}
|
||
|
||
const result = await appServer.CreateAppointment(appointmentData)
|
||
|
||
uni.hideLoading()
|
||
|
||
if (result.success || result.code === 0) {
|
||
uni.showToast({
|
||
title: '预约提交成功',
|
||
icon: 'success'
|
||
})
|
||
setTimeout(() => {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
})
|
||
}, 1500)
|
||
} else {
|
||
uni.showToast({
|
||
title: result.error?.message || '提交失败,请重试',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
uni.hideLoading()
|
||
console.error('提交预约失败:', error)
|
||
uni.showToast({
|
||
title: '网络错误,请重试',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
this.submitting = false
|
||
}
|
||
},
|
||
scrollToElement(selector) {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
const screenHeight = systemInfo.windowHeight
|
||
const query = uni.createSelectorQuery().in(this)
|
||
query.select(selector).boundingClientRect()
|
||
query.selectViewport().scrollOffset()
|
||
query.exec((res) => {
|
||
if (res[0] && res[1]) {
|
||
const rect = res[0]
|
||
const scrollInfo = res[1]
|
||
const targetScrollTop = scrollInfo.scrollTop + rect.top - (screenHeight / 2) + (rect.height / 2)
|
||
uni.pageScrollTo({
|
||
scrollTop: Math.max(0, targetScrollTop),
|
||
duration: 300
|
||
})
|
||
}
|
||
})
|
||
},
|
||
back() {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
|
||
<style lang="scss">
|
||
.page {
|
||
min-height: 100vh;
|
||
background-color: #F3F3F3;
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
padding-top: 88rpx;
|
||
padding-bottom: 20rpx;
|
||
background-color: #F3F3F3;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.scroll-content {
|
||
padding-top: 140rpx;
|
||
background-color: #F3F3F3;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
background-color: #F3F3F3;
|
||
min-height: 100%;
|
||
}
|
||
|
||
@keyframes flash {
|
||
0% {
|
||
background-color: #F3F3F3;
|
||
}
|
||
|
||
50% {
|
||
background-color: #ff6666;
|
||
}
|
||
|
||
100% {
|
||
background-color: #F3F3F3;
|
||
}
|
||
}
|
||
|
||
.flash-animation {
|
||
animation: flash 0.5s ease-in-out 3;
|
||
}
|
||
</style>
|