09. 开发用户注册功能
优化建议
- 注意设置** label-width="0px"**
- router-link
- await router.push("/login")
完善登录页面表单校验
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="0px"
style="width: 100%"
@keyup.enter="login"
>
</el-form>
const formRef = ref()
const rules = {
username: [
{ required: true, message: '请输入账号', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
]
}
const login = async () => {
const valid = await formRef.value.validate().catch(() => false)
if (!valid) return
loadingValue.value = true
try {
const res = await loginApi(form)
if (res.code === 200) {
saveLoginData(res.data)
ElMessage.success('登录成功')
await router.push('/manager/home')
}
} finally {
loadingValue.value = false
}
}
</scrip实现用户注册后端接口
注册参数 Schema
class RegisterRequest(BaseModel):
username: str
password: str
name: str | None = NoneAPI 层
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.common.response import Response
from app.database import get_db
from app.schemas.auth import LoginRequest, RegisterRequest
from app.services import auth as auth_service
router = APIRouter(prefix="/auth", tags=["权限验证"])
@router.post("/login")
def login(data: LoginRequest, db: Session = Depends(get_db)):
result = auth_service.login(db, data)
return Response.success(message="登录成功", data=result)
@router.post("/register")
def register(data: RegisterRequest, db: Session = Depends(get_db)):
auth_service.register(db, data)
return Response.success(message="注册成功")Service 层
from sqlalchemy.orm import Session
from app.common.exceptions import BusinessException
from app.models.user import User
from app.schemas.auth import LoginRequest, LoginResponse, RegisterRequest
from app.schemas.user import UserResponse
from app.utils.jwt import create_access_token
from app.utils.password import hash_password, verify_password
def login(db: Session, data: LoginRequest) -> LoginResponse:
user = db.query(User).filter(User.username == data.username).first()
if not user or not verify_password(data.password, user.password):
raise BusinessException(message="账号或密码错误")
if user.status != 1:
raise BusinessException(message="账号被禁用")
token = create_access_token(user.id)
return LoginResponse(
token=token,
user=UserResponse.model_validate(user),
)
def register(db: Session, data: RegisterRequest) -> None:
exists = db.query(User).filter(User.username == data.username).first()
if exists:
raise BusinessException(message="账号已存在")
user = User(
username=data.username,
password=hash_password(data.password),
name=data.name or data.username,
role="student",
status=1,
)
db.add(user)
db.commit()
db.refresh(user)注册功能前后端联调
注册 api 调用 api/auth.js
export function registerApi(data) {
return request({
url: '/api/auth/register',
method: 'post',
data
})
}注册页面 Register.vue
<template>
<div class="register-container">
<div class="register-box">
<h1 style="font-size: 24px; margin-bottom: 30px">欢迎注册实验室预约系统</h1>
<el-form ref="formRef" :rules="rules" :model="form" label-width="0px" style="width: 100%">
<el-form-item prop="username">
<el-input
size="large"
v-model="form.username"
placeholder="请输入账号"
:prefix-icon="User"
/>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
size="large"
v-model="form.password"
placeholder="请输入密码"
:prefix-icon="Lock"
show-password
/>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
type="password"
size="large"
v-model="form.confirmPassword"
placeholder="请确认密码"
:prefix-icon="Lock"
show-password
/>
</el-form-item>
<div>
<el-button
size="large"
type="primary"
:loading="loadingValue"
style="width: 100%"
@click="register"
>注 册</el-button
>
<div style="text-align: right; margin-top: 20px">
已有账号?请
<router-link style="color: var(--el-color-primary)" to="/login">登录</router-link>
</div>
</div>
</el-form>
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { User, Lock } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { registerApi } from '@/api/auth'
import router from '@/router'
const form = reactive({
username: '',
password: '',
confirmPassword: ''
})
const loadingValue = ref(false)
const formRef = ref()
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请确认密码'))
} else {
if (value !== form.password) {
callback(new Error('两次密码输入不一致'))
} else {
callback()
}
}
}
const rules = {
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
confirmPassword: [{ validator: validatePass, trigger: 'blur' }]
}
const register = async () => {
const valid = await formRef.value.validate().catch(() => false)
if (!valid) return
loadingValue.value = true
try {
const res = await registerApi(form)
if (res.code === 200) {
ElMessage.success('注册成功')
await router.push('/login')
}
} finally {
loadingValue.value = false
}
}
</script>
<style scoped>
.register-container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.register-box {
width: 380px;
border-radius: 8px;
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);
padding: 30px;
text-align: center;
background-color: white;
}
</style>