Files
wangxiaowei 5edfca8ff2 完善功能
2026-04-13 01:53:05 +08:00

793 lines
29 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-bg">
<navbar title="完善信息" bg="#F6F7F8"></navbar>
<view class="container" style="padding-top: 20px;">
<!-- 青年卡-基本信息 -->
<view class="form-card" v-if="id == 1">
<view class="section-title">
基本信息 <text class="required">*</text>
</view>
<view class="form-item">
<view class="label">姓名</view>
<input class="input" type="text" placeholder="请填写姓名" placeholder-class="placeholder-style"
v-model="formData.youth.name" />
</view>
<view class="form-item">
<view class="label">出生年月</view>
<picker mode="date" :end="endDate" @change="onYouthDateChange">
<view class="picker-view" :class="{ 'has-value': formData.youth.both }">
<text>{{ formData.youth.both || '请选择出生年月' }}</text>
<image src="https://xh.stnav.com/uploads/sport/icon_down.png"
style="width: 36rpx; height: 36rpx;" mode="aspectFit"></image>
</view>
</picker>
</view>
<view class="form-item no-border">
<view class="label">身份证号</view>
<input class="input" type="idcard" placeholder="请输入身份证号码" placeholder-class="placeholder-style"
v-model="formData.youth.card" />
</view>
</view>
<!-- 成人卡-基本信息 -->
<view class="form-card" v-if="id == 2">
<view class="section-title">
基本信息 <text class="required">*</text>
</view>
<view class="form-item">
<view class="label">姓名</view>
<input class="input" type="text" placeholder="请填写姓名" placeholder-class="placeholder-style"
v-model="formData.adult.name" />
</view>
<view class="form-item">
<view class="label">出生年月</view>
<picker mode="date" :end="endDate" @change="onAdultDateChange">
<view class="picker-view" :class="{ 'has-value': formData.adult.both }">
<text>{{ formData.adult.both || '请选择出生年月' }}</text>
<image src="https://xh.stnav.com/uploads/sport/icon_down.png"
style="width: 36rpx; height: 36rpx;" mode="aspectFit"></image>
</view>
</picker>
</view>
<view class="form-item no-border">
<view class="label">身份证号</view>
<input class="input" type="idcard" placeholder="请输入身份证号码" placeholder-class="placeholder-style"
v-model="formData.adult.card" />
</view>
</view>
<!-- 家长1基本信息 -->
<view class="form-card" v-if="id == 3 || id == 4">
<view class="section-title">
家长1基本信息 <text class="required">*</text>
</view>
<view class="form-item">
<view class="label">姓名</view>
<input class="input" type="text" placeholder="请填写姓名" placeholder-class="placeholder-style"
v-model="formData.parents[0].name" />
</view>
<view class="form-item">
<view class="label">出生年月</view>
<picker mode="date" :end="endDate" @change="(e) => onParentDateChange(e, 0)">
<view class="picker-view" :class="{ 'has-value': formData.parents[0].both }">
<text>{{ formData.parents[0].both || '请选择出生年月' }}</text>
<image src="https://xh.stnav.com/uploads/sport/icon_down.png"
style="width: 36rpx; height: 36rpx;" mode="aspectFit"></image>
</view>
</picker>
</view>
<view class="form-item no-border">
<view class="label">身份证号</view>
<input class="input" type="idcard" placeholder="请输入身份证号码" placeholder-class="placeholder-style"
v-model="formData.parents[0].card" />
</view>
</view>
<!-- 家长基本信息2 -->
<view class="form-card" v-if="id == 3 || id == 4">
<view class="section-title">
家长2基本信息 <text class="required">*</text>
</view>
<view class="form-item">
<view class="label">姓名</view>
<input class="input" type="text" placeholder="请填写姓名" placeholder-class="placeholder-style"
v-model="formData.parents[1].name" />
</view>
<view class="form-item">
<view class="label">出生年月</view>
<picker mode="date" :end="endDate" @change="(e) => onParentDateChange(e, 1)">
<view class="picker-view" :class="{ 'has-value': formData.parents[1].both }">
<text>{{ formData.parents[1].both || '请选择出生年月' }}</text>
<image src="https://xh.stnav.com/uploads/sport/icon_down.png"
style="width: 36rpx; height: 36rpx;" mode="aspectFit"></image>
</view>
</picker>
</view>
<view class="form-item no-border">
<view class="label">身份证号</view>
<input class="input" type="idcard" placeholder="请输入身份证号码" placeholder-class="placeholder-style"
v-model="formData.parents[1].card" />
</view>
</view>
<!-- 随行子女1信息 -->
<view class="form-card" v-if="id == 3 || id == 4">
<view class="section-title">
随行子女1信息 <text class="required">*</text>
</view>
<view class="form-item">
<view class="label">姓名</view>
<input class="input" type="text" placeholder="请填写姓名" placeholder-class="placeholder-style"
v-model="formData.child[0].name" />
</view>
<view class="form-item">
<view class="label">出生年月</view>
<picker mode="date" :end="endDate" @change="(e) => onChildDateChange(e, 0)">
<view class="picker-view" :class="{ 'has-value': formData.child[0].both }">
<text>{{ formData.child[0].both || '请选择出生年月' }}</text>
<image src="https://xh.stnav.com/uploads/sport/icon_down.png"
style="width: 36rpx; height: 36rpx;" mode="aspectFit"></image>
</view>
</picker>
</view>
<view class="form-item no-border">
<view class="label">身份证号</view>
<input class="input" type="idcard" placeholder="请输入身份证号码" placeholder-class="placeholder-style"
v-model="formData.child[0].card" />
</view>
</view>
<!-- 随行子女2信息 -->
<view class="form-card" v-if="id == 4">
<view class="section-title">
随行子女2信息 <text class="required">*</text>
</view>
<view class="form-item">
<view class="label">姓名</view>
<input class="input" type="text" placeholder="请填写姓名" placeholder-class="placeholder-style"
v-model="formData.child[1].name" />
</view>
<view class="form-item">
<view class="label">出生年月</view>
<picker mode="date" :end="endDate" @change="(e) => onChildDateChange(e, 1)">
<view class="picker-view" :class="{ 'has-value': formData.child[1].both }">
<text>{{ formData.child[1].both || '请选择出生年月' }}</text>
<image src="https://xh.stnav.com/uploads/sport/icon_down.png"
style="width: 36rpx; height: 36rpx;" mode="aspectFit"></image>
</view>
</picker>
</view>
<view class="form-item no-border">
<view class="label">身份证号</view>
<input class="input" type="idcard" placeholder="请输入身份证号码" placeholder-class="placeholder-style"
v-model="formData.child[1].card" />
</view>
</view>
<!-- 联系方式 -->
<view class="form-card">
<view class="section-title">
联系方式 <text class="required">*</text>
</view>
<view class="form-item-row no-border">
<view class="label">联系电话</view>
<input class="input-grey" type="number" placeholder="请填写联系方式"
placeholder-class="placeholder-style-small" v-model="formData.mobile" />
</view>
</view>
<!-- 提示信息 -->
<view class="tips">
*提交表单申请工作人员将在3个工作日内进行审核如需及时了解请直接电话咨询我们将在第一时间解答
</view>
<!-- 底部按钮 -->
<view class="footer-bar">
<view class="btn btn-default" @click="contactUs">联系我们</view>
<view class="btn btn-primary" @click="submitForm">提交申请</view>
</view>
<!-- 提交成功弹窗 -->
<view class="modal-container" v-if="showSuccessPopup">
<view class="modal-mask" @click="confirmSuccess"></view>
<view class="modal-content">
<!-- 根据设计图比例此处设为280rpx猜测28rpx属于笔误 -->
<image class="modal-icon" src="https://xh.stnav.com/uploads/sport/add-success.png"
style="width: 280rpx; height: 280rpx;"></image>
<view class="modal-title">信息提交成功</view>
<view class="modal-desc">请您耐心等候我们将尽快为您审核</view>
<view class="modal-btn" @click="confirmSuccess">好的</view>
</view>
</view>
</view>
</view>
</template>
<script>
import navbar from '@/components/navbar.vue';
export default {
components: {
navbar,
},
computed: {
endDate() {
const date = new Date();
date.setDate(date.getDate() - 1);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
},
data() {
return {
showSuccessPopup: false,
comboType: 'adult', // 套餐类型adult(成人卡) youth(青年卡) family(亲子卡)
formData: {
youth: {
name: '',
both: '',
card: '',
},
adult: {
name: '',
both: '',
card: '',
},
parents: [
{ id: 0, name: '', both: '', card: '' },
{ id: 0, name: '', both: '', card: '' }
],
child: [
{ id: 0, name: '', both: '', card: '' },
{ id: 0, name: '', both: '', card: '' }
],
phone: '',
group_id: 0
},
id: 0,
isSubmitting: false,
setting: {
company: {}
},
info: {}, // 用户信息数据
}
},
onLoad(args) {
this.comboType = args.type || 'adult'
this.id = args.id
this.formData.group_id = this.id
this.handleInit()
this.handleGetSetting()
},
methods: {
handleInit() {
let self = this;
self._post(
'ground.group/getGroupData',
{
group_id: self.id
},
result => {
if (result.code && result.data) {
const data = result.data;
self.info = data;
self.formData.mobile = data.mobile || '';
if (data.group_id == 1 ) {
// 青年卡
self.formData.youth = {
name: data.name,
both: data.both,
card: data.card,
}
}
if (data.group_id == 2) {
// 成人卡
self.formData.adult = {
name: data.name,
both: data.both,
card: data.card,
}
}
if (data.group_id == 3 || data.group_id == 4) {
// 亲子卡
if (data.parent && data.parent.length > 0) {
self.$set(self.formData.parents, 0, {
id: data.parent[0].id,
name: data.parent[0].name,
both: data.parent[0].both,
card: data.parent[0].card,
});
}
if (data.parent && data.parent.length > 1) {
self.$set(self.formData.parents, 1, {
id: data.parent[1].id,
name: data.parent[1].name,
both: data.parent[1].both,
card: data.parent[1].card,
});
}
if (data.child && data.child.length > 0) {
self.$set(self.formData.child, 0, {
id: data.child[0].id,
name: data.child[0].name,
both: data.child[0].both,
card: data.child[0].card,
});
} else {
self.$set(self.formData.child, 0, {
id: 0,
name: data.name || '',
both: data.both || '',
card: data.card || '',
});
}
if (data.child && data.child.length > 1) {
self.$set(self.formData.child, 1, {
id: data.child[1].id,
name: data.child[1].name,
both: data.child[1].both,
card: data.child[1].card,
});
}
}
}
},
false,
() => {
}
);
},
handleGetSetting() {
let self = this;
self._post(
'ground.ground/groundSetting',
{
app_id: self.getAppId()
},
function(res) {
if (res.code) {
self.info = res.data;
}
}
)
},
onYouthDateChange(e) {
this.formData.youth.both = e.detail.value;
},
onAdultDateChange(e) {
this.formData.adult.both = e.detail.value;
},
onParentDateChange(e, index) {
this.formData.parents[index].both = e.detail.value;
},
onChildDateChange(e, index) {
this.formData.child[index].both = e.detail.value;
},
contactUs() {
console.log("🚀 ~ this.setting:", this.setting)
uni.makePhoneCall({
phoneNumber: this.setting.company.contact
});
},
submitForm() {
let self = this;
const regex = /^[1-9]\d{5}(18|19|20)?\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
const validateCardAndAgeMatch = (card, both, prefix, ageRule) => {
let idBirthStr = card.length === 15 ? '19' + card.substring(6, 12) : card.substring(6, 14);
let idDateStr = `${idBirthStr.substring(0, 4)}-${idBirthStr.substring(4, 6)}-${idBirthStr.substring(6, 8)}`;
if (idDateStr !== both) {
return `${prefix}出生日期选错了与身份证不符`;
}
if (ageRule) {
const today = new Date();
let age = today.getFullYear() - parseInt(idBirthStr.substring(0, 4));
const m = (today.getMonth() + 1) - parseInt(idBirthStr.substring(4, 6));
if (m < 0 || (m === 0 && today.getDate() < parseInt(idBirthStr.substring(6, 8)))) {
age--;
}
if (ageRule === 'adult' && age < 18) {
return `${prefix}必须满18周岁`;
}
if (ageRule === 'child' && age >= 18) {
return `${prefix}须未满18周岁`;
}
}
return null;
};
// id == 1 验证 youth 属性
if (self.id == 1) {
let youth = self.formData.youth;
if (!youth || !youth.name || !youth.both || !youth.card) {
return uni.showToast({ title: '请填写完整基本信息', icon: 'none' });
}
if (!regex.test(youth.card)) {
return uni.showToast({ title: '请输入正确的身份证号码', icon: 'none' });
}
let err = validateCardAndAgeMatch(youth.card, youth.both, '', 'child');
if (err) return uni.showToast({ title: err, icon: 'none' });
}
// 成人卡
if (self.id == 2) {
// 购买成人卡时,需要验证 adult 属性
let adult = self.formData.adult;
if (!adult || !adult.name || !adult.both || !adult.card) {
return uni.showToast({ title: '请填写完整基本信息', icon: 'none' });
}
if (!regex.test(adult.card)) {
return uni.showToast({ title: '请输入正确的身份证号码', icon: 'none' });
}
let err = validateCardAndAgeMatch(adult.card, adult.both, '', 'adult');
if (err) return uni.showToast({ title: err, icon: 'none' });
}
// id == 3(第一个亲子卡) 或 4 时,验证 parents[0] 和 child 属性
if (self.id == 3 || self.id == 4) {
let p0 = self.formData.parents[0];
if (!p0 || !p0.name || !p0.both || !p0.card) {
return uni.showToast({ title: '请填写完整家长1基本信息', icon: 'none' });
}
if (!regex.test(p0.card)) {
return uni.showToast({ title: '请输入正确的家长1身份证号码', icon: 'none' });
}
let err0 = validateCardAndAgeMatch(p0.card, p0.both, '家长1', 'adult');
if (err0) return uni.showToast({ title: err0, icon: 'none' });
let p1 = self.formData.parents[1];
if (!p1 || !p1.name || !p1.both || !p1.card) {
return uni.showToast({ title: '请填写完整家长2基本信息', icon: 'none' });
}
if (!regex.test(p1.card)) {
return uni.showToast({ title: '请输入正确的家长2身份证号码', icon: 'none' });
}
let err1 = validateCardAndAgeMatch(p1.card, p1.both, '家长2', 'adult');
if (err1) return uni.showToast({ title: err1, icon: 'none' });
let child0 = self.formData.child[0];
if (!child0 || !child0.name || !child0.both || !child0.card) {
return uni.showToast({ title: '请填写完整随行子女1信息', icon: 'none' });
}
if (!regex.test(child0.card)) {
return uni.showToast({ title: '请输入正确的子女1身份证号码', icon: 'none' });
}
let errC0 = validateCardAndAgeMatch(child0.card, child0.both, '子女1', 'child');
if (errC0) return uni.showToast({ title: errC0, icon: 'none' });
// id == 4 时(第二个亲子卡),还需要额外验证 child[1] 属性
if (self.id == 4) {
let child1 = self.formData.child[1];
if (!child1 || !child1.name || !child1.both || !child1.card) {
return uni.showToast({ title: '请填写完整随行子女2信息', icon: 'none' });
}
if (!regex.test(child1.card)) {
return uni.showToast({ title: '请输入正确的子女2身份证号码', icon: 'none' });
}
let errC1 = validateCardAndAgeMatch(child1.card, child1.both, '子女2', 'child');
if (errC1) return uni.showToast({ title: errC1, icon: 'none' });
}
}
// 所有场景必填联系电话
if (!self.formData.mobile) {
return uni.showToast({ title: '请填写联系电话', icon: 'none' });
}
const phoneReg = /^1[3-9]\d{9}$/;
if (!phoneReg.test(self.formData.mobile)) {
return uni.showToast({ title: '请输入正确的手机号码', icon: 'none' });
}
if (self.isSubmitting) return;
self.isSubmitting = true;
uni.showLoading({ title: '提交中...', mask: true });
let submitData = {
...self.formData,
youth: JSON.stringify(self.formData.youth),
adult: JSON.stringify(self.formData.adult),
parents: JSON.stringify(self.formData.parents),
child: JSON.stringify(self.formData.child)
};
self._post(
'ground.group/submitGroupData',
submitData,
result => {
uni.hideLoading();
if (result.code) {
self.formData = {
youth: { name: '', both: '', card: '' },
adult: { name: '', both: '', card: '' },
parents: [
{ name: '', both: '', card: '' },
{ name: '', both: '', card: '' }
],
child: [
{ name: '', both: '', card: '' },
{ name: '', both: '', card: '' }
],
phone: '',
group_id: self.id
};
self.showSuccessPopup = true;
} else {
uni.showToast({ title: '提交失败', icon: 'none' });
}
},
false,
() => {
uni.hideLoading();
self.isSubmitting = false;
}
)
},
confirmSuccess() {
this.showSuccessPopup = false;
// 点击好的之后,可以跳转或返回上一页
uni.navigateBack();
this.getOpenerEventChannel().emit('data', {notice: 'success'});
}
}
}
</script>
<style lang="scss">
page {
background-color: #F6F7F8;
}
.page-bg {
background-color: #F6F7F8;
min-height: 100vh;
}
.container {
padding: 24rpx 30rpx 200rpx;
}
.form-card {
background-color: #FFFFFF;
border-radius: 12rpx;
padding: 40rpx 30rpx;
margin-bottom: 24rpx;
}
.section-title {
font-size: 32rpx;
color: #333333;
font-weight: 500;
margin-bottom: 30rpx;
display: flex;
align-items: center;
.required {
color: #E53935;
margin-left: 8rpx;
font-weight: normal;
}
}
.form-item {
margin-bottom: 10rpx;
border-bottom: 2rpx solid #F5F5F5;
padding-bottom: 16rpx;
&.no-border {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.label {
font-size: 28rpx;
color: #666666;
margin-bottom: 20rpx;
margin-top: 30rpx;
}
.input {
font-size: 30rpx;
color: #333333;
width: 100%;
height: 60rpx;
}
.picker-view {
font-size: 30rpx;
color: #CCCCCC;
height: 60rpx;
display: flex;
align-items: center;
justify-content: space-between;
&.has-value {
color: #333333;
}
.arrow-down {
font-size: 30rpx;
color: #CCCCCC;
margin-left: 10rpx;
transform: scaleY(0.6);
}
}
}
.form-item-row {
display: flex;
align-items: center;
margin-top: 30rpx;
.label {
font-size: 30rpx;
color: #333333;
width: 160rpx;
}
.input-grey {
flex: 1;
background-color: #F6F7F8;
height: 80rpx;
border-radius: 8rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333333;
}
}
.placeholder-style {
color: #CCCCCC;
font-size: 30rpx;
}
.placeholder-style-small {
color: #CCCCCC;
font-size: 28rpx;
}
.tips {
font-size: 26rpx;
color: #666666;
line-height: 1.6;
padding: 20rpx 10rpx;
}
.footer-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 2;
background-color: #F6F7F8;
padding: 20rpx 30rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
display: flex;
justify-content: space-between;
.btn {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
border-radius: 8rpx;
}
.btn-default {
background-color: #FFFFFF;
color: #333333;
margin-right: 20rpx;
}
.btn-primary {
background-color: #3B5B9B;
color: #FFFFFF;
}
}
.modal-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100; // 遮罩层要在最上面
display: flex;
align-items: flex-end;
justify-content: center;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4); // 半透明黑色背景
}
.modal-content {
position: relative;
width: 100%;
box-sizing: border-box;
background-color: #FFFFFF;
border-radius: 48rpx 48rpx 0 0;
padding: 70rpx 50rpx;
padding-bottom: calc(70rpx + env(safe-area-inset-bottom));
display: flex;
flex-direction: column;
align-items: center;
z-index: 101; // 内容在遮罩层上方
.modal-icon {
margin-bottom: 40rpx;
}
.modal-title {
font-size: 36rpx;
color: #333333;
font-weight: 500;
margin-bottom: 20rpx;
}
.modal-desc {
font-size: 26rpx;
color: #999999;
margin-bottom: 174rpx;
text-align: center;
}
.modal-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
text-align: center;
background-color: #3B5B9B;
color: #FFFFFF;
font-size: 32rpx;
border-radius: 8rpx;
}
}
</style>