Эх сурвалжийг харах

feat(family): S-cfc-66 family.invite.joinRequiredInfoFrontend 加入申请表单补出生日期/性别必填项

- join-form.vue: form 增加 birthday/gender,出生日期(date picker)+性别(男/女 picker) 必填项带 * 标记
- prefill 从 userInfo 带出 birthday/gender;submit 校验三项非空+日期格式,updateUserInfo 透传 birthday/gender
- 契约单测 join-form.required-info.test.js 由 12 失败/6 通过 → 18 通过/1 跳过
Agnes Agent 4 өдөр өмнө
parent
commit
2c65d98f7

+ 70 - 2
cfc-frontend/pages/invite/join-form.vue

@@ -2,7 +2,7 @@
 	<view class="join-form-container" :style="{ '--font-scale': fontScale }">
 		<view class="header">
 			<text class="title">加入家庭</text>
-			<text class="subtitle">请填写您的真实姓名,提交后等待邀请人确认</text>
+			<text class="subtitle">请填写真实姓名、出生日期与性别,提交后等待邀请人确认</text>
 		</view>
 
 		<view class="form-section">
@@ -12,6 +12,26 @@
 				<input type="text" v-model="form.realName" placeholder="请输入真实姓名" class="input" maxlength="20" />
 			</view>
 
+			<!-- 出生日期(必填) -->
+			<view class="form-item">
+				<text class="label">出生日期 <text class="required">*</text></text>
+				<picker mode="date" :value="form.birthday" start="1900-01-01" @change="onBirthdayChange">
+					<view class="picker-input">
+						<text>{{ form.birthday || '请选择出生日期' }}</text>
+					</view>
+				</picker>
+			</view>
+
+			<!-- 性别(必填) -->
+			<view class="form-item">
+				<text class="label">性别 <text class="required">*</text></text>
+				<picker :range="['男','女']" @change="onGenderChange">
+					<view class="picker-input">
+						<text>{{ genderText }}</text>
+					</view>
+				</picker>
+			</view>
+
 			<!-- 昵称(选填,默认用户+手机尾号) -->
 			<view class="form-item">
 				<text class="label">昵称</text>
@@ -51,12 +71,21 @@ export default {
 			familyInviteCode: '',
 			form: {
 				realName: '',
+				birthday: '',
+				gender: '',
 				nickname: '',
 				avatar: ''
 			},
 			submitting: false
 		}
 	},
+	computed: {
+		genderText() {
+			if (this.form.gender === 'male') return '男'
+			if (this.form.gender === 'female') return '女'
+			return '请选择性别'
+		}
+	},
 	onLoad(options) {
 		// 接收家庭邀请码:join.vue 传 familyInviteCode;登录页衔接传 pendingFamilyInviteCode 对应值
 		var code = (options && options.familyInviteCode) || uni.getStorageSync('pendingFamilyInviteCode') || ''
@@ -71,9 +100,34 @@ export default {
 		prefill() {
 			var userInfo = uni.getStorageSync('userInfo') || {}
 			if (userInfo.realName) this.form.realName = userInfo.realName
+			if (userInfo.birthday) this.form.birthday = userInfo.birthday
+			if (userInfo.gender) this.form.gender = userInfo.gender
 			if (userInfo.nickname) this.form.nickname = userInfo.nickname
 			if (userInfo.avatar) this.form.avatar = userInfo.avatar
 		},
+		onBirthdayChange(e) {
+			if (e && e.detail && e.detail.value) this.form.birthday = e.detail.value
+		},
+		onGenderChange(e) {
+			var idx = (e && e.detail && e.detail.value !== undefined) ? e.detail.value : 0
+			// 男 → male、女 → female
+			this.form.gender = idx === 1 ? 'female' : 'male'
+		},
+		isValidBirthday(str) {
+			// yyyy-MM-dd、合法日期、不早于 1900-01-01、不晚于今天(年龄不设上限)
+			if (!str || !/^\d{4}-\d{2}-\d{2}$/.test(str)) return false
+			var parts = str.split('-')
+			var y = parseInt(parts[0], 10)
+			var m = parseInt(parts[1], 10)
+			var d = parseInt(parts[2], 10)
+			if (y < 1900 || m < 1 || m > 12 || d < 1) return false
+			var maxDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1]
+			if (m === 2 && ((y % 4 === 0 && y % 100 !== 0) || y % 400 === 0)) maxDays = 29
+			if (d > maxDays) return false
+			var today = new Date()
+			var ts = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
+			return str <= ts
+		},
 		chooseAvatar() {
 			var self = this
 			pickImage({
@@ -89,16 +143,30 @@ export default {
 				uni.showToast({ title: '请输入真实姓名', icon: 'none' })
 				return
 			}
+			if (!this.form.birthday) {
+				uni.showToast({ title: '请选择出生日期', icon: 'none' })
+				return
+			}
+			if (!this.isValidBirthday(this.form.birthday)) {
+				uni.showToast({ title: '出生日期格式不正确', icon: 'none' })
+				return
+			}
+			if (!this.form.gender) {
+				uni.showToast({ title: '请选择性别', icon: 'none' })
+				return
+			}
 			if (!this.familyInviteCode) {
 				uni.showToast({ title: '缺少家庭邀请码', icon: 'none' })
 				return
 			}
 			this.submitting = true
 			try {
-				// 先保存基本信息(真实姓名/昵称/头像),失败不阻塞加入申请
+				// 先保存基本信息(真实姓名/出生日期/性别/昵称/头像),失败不阻塞加入申请
 				try {
 					await updateUserInfo({
 						realName: this.form.realName.trim(),
+						birthday: this.form.birthday,
+						gender: this.form.gender,
 						nickname: this.form.nickname ? this.form.nickname.trim() : '',
 						avatar: this.form.avatar
 					})