Initial commit
This commit is contained in:
@@ -0,0 +1,496 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<scroll-view class="content-scroll" direction="vertical">
|
||||
<view class="page-back-action" @tap="handleBackToLogin">
|
||||
<text class="page-back-text">返回登录</text>
|
||||
</view>
|
||||
<!-- 步骤进度 -->
|
||||
<view class="step-indicator">
|
||||
<view class="step-item">
|
||||
<view class="step-dot step-dot-completed"></view>
|
||||
<text class="step-text">扫码绑定孩子</text>
|
||||
</view>
|
||||
<view class="step-line step-line-completed"></view>
|
||||
<view class="step-item step-active">
|
||||
<view class="step-dot step-dot-active"></view>
|
||||
<text class="step-text step-text-active">家长账号与密码</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-dot"></view>
|
||||
<text class="step-text">注册完成</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 已绑定学生展示 -->
|
||||
<view class="student-summary">
|
||||
<view class="summary-title-row">
|
||||
<text class="summary-title">已绑定学生</text>
|
||||
<uni-badge-view :text="students.length.toString()" badge-class="student-count-badge"></uni-badge-view>
|
||||
</view>
|
||||
<view class="student-card" v-for="student in students" :key="student.id">
|
||||
<image class="student-avatar-small" :src="student.avatar || '/static/avatar-default.png'" mode="aspectFill"></image>
|
||||
<text class="student-name-small">{{ student.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 表单区域 -->
|
||||
<view class="form-section">
|
||||
<text class="form-title">设置家长账号信息</text>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">家长姓名</text>
|
||||
<input
|
||||
class="form-input"
|
||||
type="text"
|
||||
v-model="form.parentName"
|
||||
placeholder="请输入家长姓名"
|
||||
maxlength="10"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">手机号</text>
|
||||
<input
|
||||
class="form-input"
|
||||
type="number"
|
||||
v-model="form.phone"
|
||||
placeholder="请输入手机号"
|
||||
maxlength="11"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">与学生的关系</text>
|
||||
<picker class="relationship-picker" :value="relationshipIndex" :range="relationshipOptions" @change="handleRelationshipChange">
|
||||
<view class="relationship-picker-content">
|
||||
<text :class="form.relationship ? 'relationship-value' : 'relationship-placeholder'">{{ form.relationship || '请选择与学生的关系' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">登录密码</text>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="form-input-inner"
|
||||
type="password"
|
||||
v-model="form.password"
|
||||
placeholder="请设置登录密码(6-20位)"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">确认密码</text>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="form-input-inner"
|
||||
type="password"
|
||||
v-model="form.confirmPassword"
|
||||
placeholder="请再次输入密码"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer-button-container">
|
||||
<view
|
||||
class="footer-button"
|
||||
:class="canSubmit ? '' : 'footer-button-disabled'"
|
||||
@tap="handleSubmit"
|
||||
>
|
||||
<text class="footer-button-text" :class="canSubmit ? '' : 'footer-button-text-disabled'">完成注册</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { apiRegister } from '../../api/auth'
|
||||
import { apiCheckPhone } from '../../api/student'
|
||||
import { registrationStudents } from '../../store/registration'
|
||||
import { setUserInfo } from '../../store/user'
|
||||
|
||||
type ParentAccountForm = {
|
||||
parentName: string
|
||||
phone: string
|
||||
relationship: string
|
||||
password: string
|
||||
confirmPassword: string
|
||||
}
|
||||
|
||||
const form = reactive<ParentAccountForm>({
|
||||
parentName: '',
|
||||
phone: '',
|
||||
relationship: '',
|
||||
password: '',
|
||||
confirmPassword: ''
|
||||
})
|
||||
|
||||
const students = registrationStudents
|
||||
const relationshipOptions = ['爸爸', '妈妈', '爷爷', '奶奶', '外公', '外婆', '其他亲属']
|
||||
const relationshipIndex = ref(0)
|
||||
|
||||
const canSubmit = computed((): boolean => {
|
||||
const parentNameReg = /^[\u4e00-\u9fa5]{2,10}$/
|
||||
const phoneReg = /^1[3-9]\d{9}$/
|
||||
return (
|
||||
parentNameReg.test(form.parentName) &&
|
||||
phoneReg.test(form.phone) &&
|
||||
form.relationship.length > 0 &&
|
||||
form.password.length >= 6 &&
|
||||
form.password.length <= 20 &&
|
||||
form.password === form.confirmPassword
|
||||
)
|
||||
})
|
||||
|
||||
function handleRelationshipChange(event: UniPickerChangeEvent) {
|
||||
const index = event.detail.value as number
|
||||
relationshipIndex.value = index
|
||||
form.relationship = relationshipOptions[index]
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交注册
|
||||
*/
|
||||
async function handleSubmit() {
|
||||
if (!canSubmit.value) {
|
||||
if (!form.parentName) {
|
||||
uni.showToast({ title: '请输入家长姓名', icon: 'none' })
|
||||
} else if (!/^[\u4e00-\u9fa5]{2,10}$/.test(form.parentName)) {
|
||||
uni.showToast({ title: '请输入正确的家长姓名(2-10个汉字)', icon: 'none' })
|
||||
} else if (!form.phone) {
|
||||
uni.showToast({ title: '请输入手机号', icon: 'none' })
|
||||
} else if (!/^1[3-9]\d{9}$/.test(form.phone)) {
|
||||
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
|
||||
} else if (!form.relationship) {
|
||||
uni.showToast({ title: '请选择与学生的关系', icon: 'none' })
|
||||
} else if (form.password.length < 6 || form.password.length > 20) {
|
||||
uni.showToast({ title: '密码长度应为6-20位', icon: 'none' })
|
||||
} else if (form.password !== form.confirmPassword) {
|
||||
uni.showToast({ title: '两次输入的密码不一致', icon: 'none' })
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 检查手机号是否已注册
|
||||
uni.showLoading({ title: '检查中...' })
|
||||
const checkRes = await apiCheckPhone(form.phone)
|
||||
uni.hideLoading()
|
||||
|
||||
if (checkRes && checkRes.data && checkRes.data.exists) {
|
||||
uni.showToast({
|
||||
title: '该手机号已注册,请直接登录',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 提交注册
|
||||
uni.showLoading({ title: '注册中...' })
|
||||
|
||||
const studentIds = students.value.map(s => s.id)
|
||||
const res = await apiRegister({
|
||||
parentName: form.parentName,
|
||||
phone: form.phone,
|
||||
relationship: form.relationship,
|
||||
password: form.password,
|
||||
students: studentIds
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
if (res && res.code === 0 && res.data) {
|
||||
// 保存用户信息
|
||||
setUserInfo(res.data)
|
||||
|
||||
// 跳转到注册完成页
|
||||
uni.redirectTo({
|
||||
url: '/pages/register/complete'
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res?.message || '注册失败,请稍后重试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function handleBackToLogin() {
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
padding: 16px 16px calc(96px + var(--uni-safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.page-back-action {
|
||||
align-self: flex-start;
|
||||
padding: 8px 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.page-back-text {
|
||||
font-size: 14px;
|
||||
color: #6C63FF;
|
||||
}
|
||||
|
||||
/* 步骤指示器 */
|
||||
.step-indicator {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: #E5E5E5;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.step-dot-completed {
|
||||
background-color: #10B981;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.step-dot-active {
|
||||
background-color: #6C63FF;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.footer-button-text-disabled {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-size: 11px;
|
||||
color: #999999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.step-text-active {
|
||||
color: #6C63FF;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.step-line {
|
||||
flex: 1;
|
||||
height: 2px;
|
||||
background-color: #E5E5E5;
|
||||
margin: 0 4px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.step-line-completed {
|
||||
background-color: #10B981;
|
||||
}
|
||||
|
||||
/* 学生摘要 */
|
||||
.student-summary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.student-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
background-color: #F8F9FA;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.student-avatar-small {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
margin-right: 8px;
|
||||
background-color: #E5E5E5;
|
||||
}
|
||||
|
||||
.student-name-small {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.form-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
background-color: #F8F9FA;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #E5E5E5;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.relationship-picker {
|
||||
height: 44px;
|
||||
background-color: #F8F9FA;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
.relationship-picker-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.summary-title-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.student-count-badge {
|
||||
background-color: #6C63FF;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.relationship-value {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.relationship-placeholder {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.relationship-picker-arrow {
|
||||
font-size: 16px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: 44px;
|
||||
background-color: #F8F9FA;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #E5E5E5;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.form-input-inner {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
/* 底部按钮 */
|
||||
.footer-button-container {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 16px 16px calc(16px + var(--uni-safe-area-inset-bottom));
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.footer-button {
|
||||
height: 48px;
|
||||
background-color: #6C63FF;
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.footer-button-disabled {
|
||||
background-color: #E5E5E5;
|
||||
}
|
||||
|
||||
.footer-button-text {
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.footer-button-text-disabled {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user