会员个人中心页面初步完成
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
/** 个人信息页前端校验(与后端手机号规则对齐:^1[3-9]\\d{9}$) */
|
||||
|
||||
const PHONE_REG = /^1[3-9]\d{9}$/
|
||||
const MIN_NAME_LEN = 2
|
||||
const MAX_NAME_LEN = 8
|
||||
const NAME_REG = new RegExp(
|
||||
`^[\\u4e00-\\u9fa5a-zA-Z·\\s]{${MIN_NAME_LEN},${MAX_NAME_LEN}}$`
|
||||
)
|
||||
const MEASURE_REG = /^\d+(\.\d)?$/
|
||||
|
||||
const MIN_HEIGHT = 50
|
||||
const MAX_HEIGHT = 250
|
||||
const MIN_WEIGHT = 20
|
||||
const MAX_WEIGHT = 300
|
||||
const MIN_BIRTH_YEAR = 1900
|
||||
const MIN_AGE = 14
|
||||
const MAX_FITNESS_GOALS = 5
|
||||
|
||||
export function isMaskedPhone(phone) {
|
||||
return String(phone || '').includes('****')
|
||||
}
|
||||
|
||||
export function validateName(name) {
|
||||
const value = String(name ?? '').trim()
|
||||
if (!value) {
|
||||
return { ok: false, message: '请输入姓名' }
|
||||
}
|
||||
if (!NAME_REG.test(value)) {
|
||||
return { ok: false, message: `姓名为${MIN_NAME_LEN}-${MAX_NAME_LEN}个汉字或字母` }
|
||||
}
|
||||
return { ok: true, value }
|
||||
}
|
||||
|
||||
/** 保存时使用:允许保留已脱敏的旧手机号 */
|
||||
export function validatePhone(phone, options = {}) {
|
||||
const { allowMasked = true } = options
|
||||
const raw = String(phone ?? '').trim()
|
||||
if (!raw) {
|
||||
return { ok: false, message: '请绑定手机号' }
|
||||
}
|
||||
if (allowMasked && isMaskedPhone(raw)) {
|
||||
const digits = raw.replace(/\D/g, '')
|
||||
if (digits.length >= 7) {
|
||||
return { ok: true, value: raw }
|
||||
}
|
||||
return { ok: false, message: '手机号格式不正确' }
|
||||
}
|
||||
|
||||
const digits = raw.replace(/\D/g, '')
|
||||
if (!PHONE_REG.test(digits)) {
|
||||
return { ok: false, message: '请输入11位有效手机号' }
|
||||
}
|
||||
return { ok: true, value: digits }
|
||||
}
|
||||
|
||||
/** 换绑时必须输入完整新号 */
|
||||
export function validatePhoneForRebind(phone) {
|
||||
return validatePhone(phone, { allowMasked: false })
|
||||
}
|
||||
|
||||
function parseMeasure(value) {
|
||||
const str = String(value ?? '').trim()
|
||||
if (!str || !MEASURE_REG.test(str)) {
|
||||
return null
|
||||
}
|
||||
const num = Number(str)
|
||||
return Number.isFinite(num) ? num : null
|
||||
}
|
||||
|
||||
function formatMeasure(num) {
|
||||
return Number.isInteger(num) ? String(num) : String(Number(num.toFixed(1)))
|
||||
}
|
||||
|
||||
export function validateHeight(height) {
|
||||
const num = parseMeasure(height)
|
||||
if (num == null) {
|
||||
return { ok: false, message: '请输入有效身高(单位 cm)' }
|
||||
}
|
||||
if (num < MIN_HEIGHT || num > MAX_HEIGHT) {
|
||||
return { ok: false, message: `身高请在 ${MIN_HEIGHT}-${MAX_HEIGHT} cm 之间` }
|
||||
}
|
||||
return { ok: true, value: formatMeasure(num) }
|
||||
}
|
||||
|
||||
export function validateWeight(weight) {
|
||||
const num = parseMeasure(weight)
|
||||
if (num == null) {
|
||||
return { ok: false, message: '请输入有效体重(单位 kg)' }
|
||||
}
|
||||
if (num < MIN_WEIGHT || num > MAX_WEIGHT) {
|
||||
return { ok: false, message: `体重请在 ${MIN_WEIGHT}-${MAX_WEIGHT} kg 之间` }
|
||||
}
|
||||
return { ok: true, value: formatMeasure(num) }
|
||||
}
|
||||
|
||||
export function parseBirthdayChinese(birthday) {
|
||||
const match = String(birthday ?? '').match(/(\d{4})年(\d{2})月(\d{2})日/)
|
||||
if (!match) return null
|
||||
return {
|
||||
year: Number(match[1]),
|
||||
month: Number(match[2]),
|
||||
day: Number(match[3])
|
||||
}
|
||||
}
|
||||
|
||||
export function validateBirthday(birthday) {
|
||||
const parts = parseBirthdayChinese(birthday)
|
||||
if (!parts) {
|
||||
return { ok: false, message: '请选择生日' }
|
||||
}
|
||||
const { year, month, day } = parts
|
||||
if (year < MIN_BIRTH_YEAR) {
|
||||
return { ok: false, message: '生日年份不合理' }
|
||||
}
|
||||
|
||||
const date = new Date(year, month - 1, day)
|
||||
if (
|
||||
date.getFullYear() !== year ||
|
||||
date.getMonth() !== month - 1 ||
|
||||
date.getDate() !== day
|
||||
) {
|
||||
return { ok: false, message: '生日日期无效' }
|
||||
}
|
||||
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
if (date > today) {
|
||||
return { ok: false, message: '生日不能晚于今天' }
|
||||
}
|
||||
|
||||
const minBirth = new Date(
|
||||
today.getFullYear() - MIN_AGE,
|
||||
today.getMonth(),
|
||||
today.getDate()
|
||||
)
|
||||
if (date > minBirth) {
|
||||
return { ok: false, message: `需年满 ${MIN_AGE} 周岁` }
|
||||
}
|
||||
|
||||
return { ok: true, value: `${year}年${String(month).padStart(2, '0')}月${String(day).padStart(2, '0')}日` }
|
||||
}
|
||||
|
||||
export function validateGender(gender) {
|
||||
if (gender === 'male' || gender === 'female') {
|
||||
return { ok: true, value: gender }
|
||||
}
|
||||
return { ok: false, message: '请选择性别' }
|
||||
}
|
||||
|
||||
export function validateFitnessGoals(goals, options = []) {
|
||||
const list = Array.isArray(goals) ? goals : []
|
||||
const allowed = new Set(options)
|
||||
const invalid = list.filter((g) => !allowed.has(g))
|
||||
if (invalid.length) {
|
||||
return { ok: false, message: '健身目标选项无效' }
|
||||
}
|
||||
if (list.length > MAX_FITNESS_GOALS) {
|
||||
return { ok: false, message: `最多选择 ${MAX_FITNESS_GOALS} 个健身目标` }
|
||||
}
|
||||
return { ok: true, value: [...list] }
|
||||
}
|
||||
|
||||
export function validateUserProfile(profile, goalOptions = []) {
|
||||
const nameResult = validateName(profile.name)
|
||||
if (!nameResult.ok) return nameResult
|
||||
|
||||
const phoneResult = validatePhone(profile.phone)
|
||||
if (!phoneResult.ok) return phoneResult
|
||||
|
||||
const genderResult = validateGender(profile.gender)
|
||||
if (!genderResult.ok) return genderResult
|
||||
|
||||
const birthdayResult = validateBirthday(profile.birthday)
|
||||
if (!birthdayResult.ok) return birthdayResult
|
||||
|
||||
const heightResult = validateHeight(profile.height)
|
||||
if (!heightResult.ok) return heightResult
|
||||
|
||||
const weightResult = validateWeight(profile.weight)
|
||||
if (!weightResult.ok) return weightResult
|
||||
|
||||
const goalsResult = validateFitnessGoals(profile.fitnessGoals, goalOptions)
|
||||
if (!goalsResult.ok) return goalsResult
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
value: {
|
||||
...profile,
|
||||
name: nameResult.value,
|
||||
phone: phoneResult.value,
|
||||
gender: genderResult.value,
|
||||
birthday: birthdayResult.value,
|
||||
height: heightResult.value,
|
||||
weight: weightResult.value,
|
||||
fitnessGoals: goalsResult.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function showValidationError(message) {
|
||||
uni.showToast({ title: message, icon: 'none' })
|
||||
}
|
||||
Reference in New Issue
Block a user