appointment_system/miniprogram/src/pages/appointment/insurance-consultation-page.vue
2025-12-20 20:29:21 +08:00

315 lines
9.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>