From 99220b6daffe13645c506a3c8e15652c97f91e57 Mon Sep 17 00:00:00 2001 From: TianyangZhang Date: Wed, 25 Mar 2026 15:51:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=B9=E4=B8=BA=E9=82=AE=E7=AE=B1?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=E6=B3=A8=E5=86=8C=EF=BC=8C=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E5=AE=8C=E6=88=90=E5=90=8E=E8=87=AA=E5=8A=A8=E7=99=BB?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端改动: - RegisterSerializer 改为接收用户名+邮箱+手机号+验证码 - 验证邮箱是否已存在、用户名是否已存在 - 验证验证码有效性和正确性 - RegisterView 返回 JWT token,实现自动登入 前端改动: - RegisterView.vue 改为邮箱验证码注册流程 - 保留用户名、邮箱、手机号字段 - 获取验证码后输入验证码完成注册 - 注册成功后自动保存 token 并跳转到首页 流程:用户名+邮箱+手机号 → 获取验证码 → 输入验证码 → 注册完成并自动登入 → 跳转首页 Co-Authored-By: Claude Haiku 4.5 --- offer_backend/apps/accounts/serializers.py | 56 ++++- offer_backend/apps/accounts/views.py | 26 ++- .../src/views/auth/RegisterView.vue | 199 ++++++++++++++++-- 3 files changed, 253 insertions(+), 28 deletions(-) diff --git a/offer_backend/apps/accounts/serializers.py b/offer_backend/apps/accounts/serializers.py index deadfca..9112c6b 100644 --- a/offer_backend/apps/accounts/serializers.py +++ b/offer_backend/apps/accounts/serializers.py @@ -5,15 +5,59 @@ from .models import VerificationCode User = get_user_model() -class RegisterSerializer(serializers.ModelSerializer): - password = serializers.CharField(write_only=True, min_length=6) +class RegisterSerializer(serializers.Serializer): + """邮箱验证码注册 serializer""" + username = serializers.CharField(max_length=150) + email = serializers.EmailField() + phone = serializers.CharField(max_length=20) + code = serializers.CharField(max_length=6, min_length=6) - class Meta: - model = User - fields = ['username', 'email', 'phone', 'password'] + def validate_username(self, value): + """验证用户名是否已存在""" + if User.objects.filter(username=value).exists(): + raise serializers.ValidationError('用户名已存在') + return value + + def validate_email(self, value): + """验证邮箱是否已存在""" + if User.objects.filter(email=value).exists(): + raise serializers.ValidationError('邮箱已被注册') + return value + + def validate(self, attrs): + """验证邮箱和验证码""" + email = attrs.get('email') + code = attrs.get('code') + + # 检查验证码 + try: + vc = VerificationCode.objects.filter(email=email).latest('created_at') + except VerificationCode.DoesNotExist: + raise serializers.ValidationError({'code': '请先获取验证码'}) + + # 检查验证码是否有效 + if not vc.is_valid(): + raise serializers.ValidationError({'code': '验证码已过期或已使用'}) + + # 验证码是否正确 + if vc.code != code: + vc.increment_attempts() + raise serializers.ValidationError({'code': '验证码错误'}) + + attrs['vc'] = vc + return attrs def create(self, validated_data): - return User.objects.create_user(**validated_data, role='seeker') + """创建用户并标记验证码为已使用""" + vc = validated_data.pop('vc') + user = User.objects.create_user( + username=validated_data['username'], + email=validated_data['email'], + phone=validated_data['phone'], + role='seeker' + ) + vc.mark_as_verified() + return user class UserSerializer(serializers.ModelSerializer): diff --git a/offer_backend/apps/accounts/views.py b/offer_backend/apps/accounts/views.py index 00e5adb..73cfccd 100644 --- a/offer_backend/apps/accounts/views.py +++ b/offer_backend/apps/accounts/views.py @@ -77,10 +77,32 @@ class CustomTokenObtainPairView(TokenObtainPairView): return token -class RegisterView(generics.CreateAPIView): - serializer_class = RegisterSerializer +class RegisterView(APIView): + """邮箱验证码注册""" permission_classes = [AllowAny] + def post(self, request): + serializer = RegisterSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + # 创建用户 + user = serializer.save() + + # 生成 JWT token + from rest_framework_simplejwt.tokens import RefreshToken + refresh = RefreshToken.for_user(user) + + return Response({ + 'user': { + 'id': user.id, + 'username': user.username, + 'email': user.email, + 'role': user.role, + }, + 'refresh': str(refresh), + 'access': str(refresh.access_token), + }, status=status.HTTP_201_CREATED) + class MeView(APIView): permission_classes = [IsAuthenticated] diff --git a/offer_frontend/src/views/auth/RegisterView.vue b/offer_frontend/src/views/auth/RegisterView.vue index faf7b19..2b1c3d8 100644 --- a/offer_frontend/src/views/auth/RegisterView.vue +++ b/offer_frontend/src/views/auth/RegisterView.vue @@ -3,42 +3,201 @@

求职者注册

- - - - - 注册 + + + + + + + + + + + + + + + 获取验证码 + + + + + +
+ + + {{ codeCountdown > 0 ? `${codeCountdown}s` : '重新获取' }} + +
+
+ + + + 注册 +
-
- 已有账号?立即登录 + +
+ 已有账号?立即登录
+ +