fix: 注册功能接口变更
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useCountDown, useLoading } from '@sa/hooks';
|
import { useCountDown, useLoading } from '@sa/hooks';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import {REG_EMAIL} from '@/constants/reg';
|
import { REG_EMAIL } from '@/constants/reg';
|
||||||
import {useAuthStore} from "@/store/modules/auth";
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
|
|
||||||
export function useCaptcha() {
|
export function useCaptcha() {
|
||||||
const { loading, startLoading, endLoading } = useLoading();
|
const { loading, startLoading, endLoading } = useLoading();
|
||||||
@@ -39,20 +39,17 @@ export function useCaptcha() {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取验证码方法
|
//获取验证码方法
|
||||||
async function getCaptcha(email: string) {
|
async function getCaptcha(email: string) {
|
||||||
console.log(email)
|
const valid = isEmailValid(email);
|
||||||
//const valid = isPhoneValid(phone);
|
|
||||||
const valid = isEmailValid(email);
|
|
||||||
if (!valid || loading.value) {
|
if (!valid || loading.value) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
startLoading();
|
startLoading();
|
||||||
|
|
||||||
await authStore.captcha(
|
const data = await authStore.captcha(email);
|
||||||
email,
|
|
||||||
);
|
|
||||||
await new Promise(resolve => {
|
await new Promise(resolve => {
|
||||||
setTimeout(resolve, 500);
|
setTimeout(resolve, 500);
|
||||||
});
|
});
|
||||||
@@ -62,6 +59,7 @@ export function useCaptcha() {
|
|||||||
start();
|
start();
|
||||||
|
|
||||||
endLoading();
|
endLoading();
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -13,21 +13,24 @@ export function fetchLogin(body: Api.Auth.LoginBody) {
|
|||||||
data: body
|
data: body
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//邮箱验证码接口
|
//邮箱验证码接口
|
||||||
export function sendCaptcha(body:Api.Auth.EmailCaptcha){
|
export function sendCaptcha(body: Api.Auth.EmailCaptcha) {
|
||||||
return request({
|
return request({
|
||||||
url:`/system/email/code?email=${body.email}`,
|
url: `/code?email=${body.email}`,
|
||||||
method:'get',
|
method: 'get'
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//验证注册
|
//验证注册
|
||||||
export function doCheckUserRepeat(body:Api.Auth.CheckBody){
|
export function doCheckUserRepeat(body: Api.Auth.CheckBody) {
|
||||||
return request<boolean>({
|
return request<boolean>({
|
||||||
url:'/u/user/checkRepeat',
|
url: '/auth/checkRepeat',
|
||||||
method:'post',
|
method: 'post',
|
||||||
data:body
|
data: body
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//添加注册
|
//添加注册
|
||||||
export function fetchRegister(body: Api.Auth.RegisterBody) {
|
export function fetchRegister(body: Api.Auth.RegisterBody) {
|
||||||
return request({
|
return request({
|
||||||
@@ -36,6 +39,7 @@ export function fetchRegister(body: Api.Auth.RegisterBody) {
|
|||||||
data: body
|
data: body
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** logout */
|
/** logout */
|
||||||
export function doDeleteLogout() {
|
export function doDeleteLogout() {
|
||||||
return request<App.Service.Response<null>>({
|
return request<App.Service.Response<null>>({
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { localStg } from '@/utils/storage';
|
|||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import { useRouteStore } from '../route';
|
import { useRouteStore } from '../route';
|
||||||
import { clearAuthStorage, emptyInfo, getToken } from './shared';
|
import { clearAuthStorage, emptyInfo, getToken } from './shared';
|
||||||
import {doCheckUserRepeat, sendCaptcha} from "@/service/api/auth";
|
import { doCheckUserRepeat, sendCaptcha } from '@/service/api/auth';
|
||||||
|
|
||||||
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
@@ -122,12 +122,11 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//check User
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查用户信息是否已存在
|
* 检查用户信息是否已存在
|
||||||
*/
|
*/
|
||||||
async function checkUserRepeat(checkForm:Api.Auth.CheckBody) {
|
async function checkUserRepeat(checkForm: Api.Auth.CheckBody) {
|
||||||
const { data, error } = await doCheckUserRepeat(checkForm);
|
const { data, error } = await doCheckUserRepeat(checkForm);
|
||||||
return { exists: data, error };
|
return { exists: data, error };
|
||||||
}
|
}
|
||||||
@@ -149,16 +148,13 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
endLoading();
|
endLoading();
|
||||||
return !error;
|
return !error;
|
||||||
}
|
}
|
||||||
async function captcha(email:string){
|
|
||||||
|
async function captcha(email: string) {
|
||||||
if (!email) {
|
if (!email) {
|
||||||
return;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await sendCaptcha({ email }); // 这里调用后端接口发送验证码
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const { data, error } = await sendCaptcha({ email }); // 这里调用后端接口发送验证码
|
||||||
|
return { data, error };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -173,6 +169,6 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
refreshUserInfo,
|
refreshUserInfo,
|
||||||
register,
|
register,
|
||||||
captcha,
|
captcha,
|
||||||
checkUserRepeat,
|
checkUserRepeat
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
1
src/typings/api.d.ts
vendored
1
src/typings/api.d.ts
vendored
@@ -156,6 +156,7 @@ declare namespace Api {
|
|||||||
username?: string;
|
username?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
phonenumber?:string;
|
phonenumber?:string;
|
||||||
|
authType: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, reactive, ref} from 'vue';
|
import { computed, reactive, ref } from 'vue';
|
||||||
import {useI18n} from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import {useAuthStore} from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
import {useRouterPush} from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
import {useFormRules} from '@/hooks/common/form';
|
import { useFormRules } from '@/hooks/common/form';
|
||||||
import {useCaptcha} from '@/hooks/business/captcha';
|
import { useCaptcha } from '@/hooks/business/captcha';
|
||||||
import {useWindowSize} from '@vueuse/core';
|
import { useWindowSize } from '@vueuse/core';
|
||||||
import {registerTerms} from '@/views/_builtin/login/modules/terms';
|
import { registerTerms } from '@/views/_builtin/login/modules/terms';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import type {Rule} from 'ant-design-vue/es/form';
|
import type { Rule } from 'ant-design-vue/es/form';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
@@ -31,17 +31,19 @@ const currentStep = ref(0);
|
|||||||
|
|
||||||
// 是否同意协议
|
// 是否同意协议
|
||||||
const agreeTerms = ref(false);
|
const agreeTerms = ref(false);
|
||||||
|
|
||||||
// 定义一个统一的数据模型
|
// 定义一个统一的数据模型
|
||||||
interface RegisterModel {
|
interface RegisterModel {
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
email: string;
|
email: string;
|
||||||
fullName: string;
|
fullName: string;
|
||||||
age:0,
|
age: 0;
|
||||||
gender: string;
|
gender: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
address: string;
|
address: string;
|
||||||
code: string;
|
code: string;
|
||||||
|
uuid: string;
|
||||||
authType: string;
|
authType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,11 +53,12 @@ const model = reactive<RegisterModel>({
|
|||||||
password: '',
|
password: '',
|
||||||
email: '',
|
email: '',
|
||||||
fullName: '',
|
fullName: '',
|
||||||
age:0,
|
age: 0,
|
||||||
gender: '',
|
gender: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
address: '',
|
address: '',
|
||||||
code: '',
|
code: '',
|
||||||
|
uuid: '',
|
||||||
authType: 'u'
|
authType: 'u'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -82,6 +85,7 @@ const basicModel = reactive<BasicFormModel>({
|
|||||||
interface SecurityFormModel {
|
interface SecurityFormModel {
|
||||||
email: string;
|
email: string;
|
||||||
code: string;
|
code: string;
|
||||||
|
uuid: string;
|
||||||
password: string;
|
password: string;
|
||||||
confirmPassword: string;
|
confirmPassword: string;
|
||||||
}
|
}
|
||||||
@@ -89,6 +93,7 @@ interface SecurityFormModel {
|
|||||||
const securityModel = reactive<SecurityFormModel>({
|
const securityModel = reactive<SecurityFormModel>({
|
||||||
email: '',
|
email: '',
|
||||||
code: '',
|
code: '',
|
||||||
|
uuid: '',
|
||||||
password: '',
|
password: '',
|
||||||
confirmPassword: ''
|
confirmPassword: ''
|
||||||
});
|
});
|
||||||
@@ -100,7 +105,7 @@ const basicRules = computed<Record<string, Rule | Rule[]>>(() => {
|
|||||||
return Promise.reject(t('page.login.register.usernameLengthLimit'));
|
return Promise.reject(t('page.login.register.usernameLengthLimit'));
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
const { exists } = await authStore.checkUserRepeat({ username: value });
|
const { exists } = await authStore.checkUserRepeat({ username: value, authType: 'u' });
|
||||||
if (exists) {
|
if (exists) {
|
||||||
return Promise.reject(t('page.login.register.usernameExists'));
|
return Promise.reject(t('page.login.register.usernameExists'));
|
||||||
}
|
}
|
||||||
@@ -117,7 +122,7 @@ const basicRules = computed<Record<string, Rule | Rule[]>>(() => {
|
|||||||
return Promise.reject(t('page.login.register.phoneInvalid'));
|
return Promise.reject(t('page.login.register.phoneInvalid'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const { exists } = await authStore.checkUserRepeat({ phonenumber: value });
|
const { exists } = await authStore.checkUserRepeat({ phonenumber: value, authType: 'u' });
|
||||||
if (exists) {
|
if (exists) {
|
||||||
return Promise.reject(t('page.login.register.phoneExists'));
|
return Promise.reject(t('page.login.register.phoneExists'));
|
||||||
}
|
}
|
||||||
@@ -150,7 +155,7 @@ const securityRules = computed<Record<string, Rule | Rule[]>>(() => {
|
|||||||
return Promise.reject(t('page.login.register.emailInvalid'));
|
return Promise.reject(t('page.login.register.emailInvalid'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const { exists } = await authStore.checkUserRepeat({ email: value });
|
const { exists } = await authStore.checkUserRepeat({ email: value, authType: 'u' });
|
||||||
if (exists) {
|
if (exists) {
|
||||||
return Promise.reject(t('page.login.register.emailExists'));
|
return Promise.reject(t('page.login.register.emailExists'));
|
||||||
}
|
}
|
||||||
@@ -197,11 +202,23 @@ async function nextStep() {
|
|||||||
console.error('Validation failed:', error);
|
console.error('Validation failed:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//返回
|
|
||||||
|
// 返回
|
||||||
function prevStep() {
|
function prevStep() {
|
||||||
currentStep.value -= 1;
|
currentStep.value -= 1;
|
||||||
}
|
}
|
||||||
//注册按钮
|
|
||||||
|
async function handleCaptcha() {
|
||||||
|
const res = await getCaptcha(securityModel.email);
|
||||||
|
if (res) {
|
||||||
|
securityModel.uuid = res.data.uuid;
|
||||||
|
if (res.data?.text) {
|
||||||
|
securityModel.code = res.data.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册按钮
|
||||||
async function handleSubmit() {
|
async function handleSubmit() {
|
||||||
try {
|
try {
|
||||||
await securityFormRef.value?.validate();
|
await securityFormRef.value?.validate();
|
||||||
@@ -209,18 +226,19 @@ async function handleSubmit() {
|
|||||||
// 整合表单数据
|
// 整合表单数据
|
||||||
model.username = basicModel.username;
|
model.username = basicModel.username;
|
||||||
model.password = securityModel.password;
|
model.password = securityModel.password;
|
||||||
model.email = securityModel.email; // 使用第三步的 email
|
model.email = securityModel.email; // 使用第三步的 email
|
||||||
model.fullName = basicModel.fullName;
|
model.fullName = basicModel.fullName;
|
||||||
model.gender = basicModel.gender;
|
model.gender = basicModel.gender;
|
||||||
model.phone = basicModel.phone;
|
model.phone = basicModel.phone;
|
||||||
model.address = basicModel.address;
|
model.address = basicModel.address;
|
||||||
model.code = securityModel.code;
|
model.code = securityModel.code;
|
||||||
|
model.uuid = securityModel.uuid;
|
||||||
|
|
||||||
const success = await authStore.register({
|
const success = await authStore.register({
|
||||||
...model,
|
...model,
|
||||||
age: dayjs().diff(dayjs(basicModel.birthDate), 'year'),
|
age: dayjs().diff(dayjs(basicModel.birthDate), 'year'),
|
||||||
sex: model.gender,
|
sex: model.gender,
|
||||||
phonenumber: model.phone,
|
phonenumber: model.phone
|
||||||
});
|
});
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -238,179 +256,179 @@ const showSteps = computed(() => !isMobile.value);
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="register-container">
|
<div class="register-container">
|
||||||
<ASteps
|
<ASteps
|
||||||
v-if="showSteps"
|
v-if="showSteps"
|
||||||
:current="currentStep"
|
:current="currentStep"
|
||||||
size="small"
|
size="small"
|
||||||
class="max-w-full mb-16px"
|
class="max-w-full mb-16px"
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
:responsive="false"
|
:responsive="false"
|
||||||
>
|
>
|
||||||
<AStep :title="t('page.login.register.basicInfo')" />
|
<AStep :title="t('page.login.register.basicInfo')" />
|
||||||
<AStep :title="t('page.login.register.terms')" />
|
<AStep :title="t('page.login.register.terms')" />
|
||||||
<AStep :title="t('page.login.register.security')" />
|
<AStep :title="t('page.login.register.security')" />
|
||||||
</ASteps>
|
</ASteps>
|
||||||
|
|
||||||
<div v-else class="mobile-step-indicator mb-16px text-center">
|
<div v-else class="mobile-step-indicator mb-16px text-center">
|
||||||
{{ currentStep + 1 }}/3: {{
|
{{ currentStep + 1 }}/3: {{
|
||||||
currentStep === 0
|
currentStep === 0
|
||||||
? t('page.login.register.basicInfo')
|
? t('page.login.register.basicInfo')
|
||||||
: currentStep === 1
|
: currentStep === 1
|
||||||
? t('page.login.register.terms')
|
? t('page.login.register.terms')
|
||||||
: t('page.login.register.security')
|
: t('page.login.register.security')
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step-content">
|
<div class="step-content">
|
||||||
<!-- 第一步:基本信息 -->
|
<!-- 第一步:基本信息 -->
|
||||||
<div v-show="currentStep === 0">
|
<div v-show="currentStep === 0">
|
||||||
<AForm
|
<AForm
|
||||||
ref="basicFormRef"
|
ref="basicFormRef"
|
||||||
:model="basicModel"
|
:model="basicModel"
|
||||||
:rules="basicRules"
|
:rules="basicRules"
|
||||||
:label-wrap="true"
|
:label-wrap="true"
|
||||||
:label-col="{ span: 8 }"
|
:label-col="{ span: 8 }"
|
||||||
:wrapper-col="{ span: 16 }"
|
:wrapper-col="{ span: 16 }"
|
||||||
>
|
>
|
||||||
<ARow :gutter="[8,2]">
|
<ARow :gutter="[8,2]">
|
||||||
<ACol :span="24" :lg="24">
|
<ACol :span="24" :lg="24">
|
||||||
<AFormItem name="username" :label="t('page.login.register.username')">
|
<AFormItem name="username" :label="t('page.login.register.username')">
|
||||||
<AInput v-model:value="basicModel.username" />
|
<AInput v-model:value="basicModel.username" />
|
||||||
</AFormItem>
|
</AFormItem>
|
||||||
</ACol>
|
</ACol>
|
||||||
<ACol :span="24" :lg="24">
|
<ACol :span="24" :lg="24">
|
||||||
<AFormItem name="fullName" :label="t('page.login.register.fullName')">
|
<AFormItem name="fullName" :label="t('page.login.register.fullName')">
|
||||||
<AInput v-model:value="basicModel.fullName" />
|
<AInput v-model:value="basicModel.fullName" />
|
||||||
</AFormItem>
|
</AFormItem>
|
||||||
</ACol>
|
</ACol>
|
||||||
<ACol :xs="12" :sm="12" :lg="24">
|
<ACol :xs="12" :sm="12" :lg="24">
|
||||||
<AFormItem name="birthDate" :label="t('page.login.register.birthDate')">
|
<AFormItem name="birthDate" :label="t('page.login.register.birthDate')">
|
||||||
<ADatePicker
|
<ADatePicker
|
||||||
v-model:value="basicModel.birthDate"
|
v-model:value="basicModel.birthDate"
|
||||||
class="!w-full birth-date-picker"
|
class="!w-full birth-date-picker"
|
||||||
:placeholder="t('page.login.register.birthDatePlaceholder')"
|
:placeholder="t('page.login.register.birthDatePlaceholder')"
|
||||||
:disabled-date="(current: dayjs.Dayjs) => current && current.isAfter(dayjs())"
|
:disabled-date="(current: dayjs.Dayjs) => current && current.isAfter(dayjs())"
|
||||||
|
/>
|
||||||
|
</AFormItem>
|
||||||
|
</ACol>
|
||||||
|
<ACol :xs="12" :sm="12" :lg="24">
|
||||||
|
<AFormItem name="gender" :label="t('page.login.register.gender')">
|
||||||
|
<ASelect v-model:value="basicModel.gender">
|
||||||
|
<ASelectOption value="0">{{ t('page.login.register.male') }}</ASelectOption>
|
||||||
|
<ASelectOption value="1">{{ t('page.login.register.female') }}</ASelectOption>
|
||||||
|
</ASelect>
|
||||||
|
</AFormItem>
|
||||||
|
</ACol>
|
||||||
|
<ACol :lg="24" :span="24">
|
||||||
|
<AFormItem name="phone" :label="t('page.login.register.phone')">
|
||||||
|
<AInput v-model:value="basicModel.phone" />
|
||||||
|
</AFormItem>
|
||||||
|
</ACol>
|
||||||
|
<ACol :lg="24" :span="24">
|
||||||
|
<AFormItem name="address" :label="t('page.login.register.address')">
|
||||||
|
<ATextarea v-model:value="basicModel.address" :rows="2" />
|
||||||
|
</AFormItem>
|
||||||
|
</ACol>
|
||||||
|
<ACol :lg="24" :span="24">
|
||||||
|
<ASpace direction="vertical" size="small" class="w-full">
|
||||||
|
<AButton type="primary" block size="small" @click="nextStep">
|
||||||
|
{{ t('page.login.register.next') }}
|
||||||
|
</AButton>
|
||||||
|
<AButton block size="small" @click="toggleLoginModule('pwd-login')">
|
||||||
|
{{ t('page.login.common.back') }}
|
||||||
|
</AButton>
|
||||||
|
</ASpace>
|
||||||
|
</ACol>
|
||||||
|
</ARow>
|
||||||
|
</AForm>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二步:协议 -->
|
||||||
|
<div v-show="currentStep === 1">
|
||||||
|
<ATextarea
|
||||||
|
:value="terms"
|
||||||
|
:rows="12"
|
||||||
|
readonly
|
||||||
|
class="mb-16px"
|
||||||
|
size="small"
|
||||||
|
:style="{ fontSize: '14px', lineHeight: '1.6' }"
|
||||||
|
/>
|
||||||
|
<div class="mb-16px">
|
||||||
|
<ACheckbox
|
||||||
|
v-model:checked="agreeTerms"
|
||||||
|
class="terms-checkbox"
|
||||||
|
>
|
||||||
|
{{ t('page.login.register.agreeTerms') }}
|
||||||
|
</ACheckbox>
|
||||||
|
</div>
|
||||||
|
<ASpace direction="vertical" size="small" class="w-full">
|
||||||
|
<AButton type="primary" block size="small" :disabled="!agreeTerms" @click="nextStep">
|
||||||
|
{{ t('page.login.register.next') }}
|
||||||
|
</AButton>
|
||||||
|
<AButton block size="small" @click="prevStep">
|
||||||
|
{{ t('page.login.register.prev') }}
|
||||||
|
</AButton>
|
||||||
|
</ASpace>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第三步:安全信息 -->
|
||||||
|
<div v-show="currentStep === 2">
|
||||||
|
<AForm
|
||||||
|
ref="securityFormRef"
|
||||||
|
:model="securityModel"
|
||||||
|
:rules="securityRules"
|
||||||
|
:label-wrap="true"
|
||||||
|
:label-col="{ span: 8 }"
|
||||||
|
:wrapper-col="{ span: 16 }"
|
||||||
|
class="compact-form"
|
||||||
|
>
|
||||||
|
<AFormItem name="email" :label="t('page.login.register.email')">
|
||||||
|
<AInput
|
||||||
|
v-model:value="securityModel.email"
|
||||||
|
:placeholder="t('page.login.common.emailPlaceholder')"
|
||||||
|
/>
|
||||||
|
</AFormItem>
|
||||||
|
<AFormItem name="code" :label="t('page.login.register.code')">
|
||||||
|
<div class="w-full flex-y-center gap-8px">
|
||||||
|
<AInput
|
||||||
|
v-model:value="securityModel.code"
|
||||||
|
:placeholder="t('page.login.common.codePlaceholder')"
|
||||||
/>
|
/>
|
||||||
</AFormItem>
|
<AButton
|
||||||
</ACol>
|
size="small"
|
||||||
<ACol :xs="12" :sm="12" :lg="24">
|
:disabled="isCounting"
|
||||||
<AFormItem name="gender" :label="t('page.login.register.gender')">
|
:loading="loading"
|
||||||
<ASelect v-model:value="basicModel.gender">
|
@click="handleCaptcha()"
|
||||||
<ASelectOption value="male">{{ t('page.login.register.male') }}</ASelectOption>
|
>
|
||||||
<ASelectOption value="female">{{ t('page.login.register.female') }}</ASelectOption>
|
{{ label }}
|
||||||
</ASelect>
|
|
||||||
</AFormItem>
|
|
||||||
</ACol>
|
|
||||||
<ACol :lg="24" :span="24">
|
|
||||||
<AFormItem name="phone" :label="t('page.login.register.phone')">
|
|
||||||
<AInput v-model:value="basicModel.phone" />
|
|
||||||
</AFormItem>
|
|
||||||
</ACol>
|
|
||||||
<ACol :lg="24" :span="24">
|
|
||||||
<AFormItem name="address" :label="t('page.login.register.address')">
|
|
||||||
<ATextarea v-model:value="basicModel.address" :rows="2" />
|
|
||||||
</AFormItem>
|
|
||||||
</ACol>
|
|
||||||
<ACol :lg="24" :span="24">
|
|
||||||
<ASpace direction="vertical" size="small" class="w-full">
|
|
||||||
<AButton type="primary" block size="small" @click="nextStep">
|
|
||||||
{{ t('page.login.register.next') }}
|
|
||||||
</AButton>
|
</AButton>
|
||||||
<AButton block size="small" @click="toggleLoginModule('pwd-login')">
|
</div>
|
||||||
{{ t('page.login.common.back') }}
|
</AFormItem>
|
||||||
|
<AFormItem name="password" :label="t('page.login.register.password')">
|
||||||
|
<AInputPassword
|
||||||
|
v-model:value="securityModel.password"
|
||||||
|
:placeholder="t('page.login.common.passwordPlaceholder')"
|
||||||
|
/>
|
||||||
|
</AFormItem>
|
||||||
|
<AFormItem name="confirmPassword" :label="t('page.login.register.confirmPassword')">
|
||||||
|
<AInputPassword
|
||||||
|
v-model:value="securityModel.confirmPassword"
|
||||||
|
:placeholder="t('page.login.common.confirmPasswordPlaceholder')"
|
||||||
|
/>
|
||||||
|
</AFormItem>
|
||||||
|
<AFormItem :wrapper-col="{ xs: { span: 24 }, sm: { span: 24 } }">
|
||||||
|
<ASpace direction="vertical" size="small" class="w-full">
|
||||||
|
<AButton type="primary" block size="small" @click="handleSubmit">
|
||||||
|
{{ t('common.confirm') }}
|
||||||
|
</AButton>
|
||||||
|
<AButton block size="small" @click="prevStep">
|
||||||
|
{{ t('page.login.register.prev') }}
|
||||||
</AButton>
|
</AButton>
|
||||||
</ASpace>
|
</ASpace>
|
||||||
</ACol>
|
</AFormItem>
|
||||||
</ARow>
|
</AForm>
|
||||||
</AForm>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 第二步:协议 -->
|
|
||||||
<div v-show="currentStep === 1">
|
|
||||||
<ATextarea
|
|
||||||
:value="terms"
|
|
||||||
:rows="12"
|
|
||||||
readonly
|
|
||||||
class="mb-16px"
|
|
||||||
size="small"
|
|
||||||
:style="{ fontSize: '14px', lineHeight: '1.6' }"
|
|
||||||
/>
|
|
||||||
<div class="mb-16px">
|
|
||||||
<ACheckbox
|
|
||||||
v-model:checked="agreeTerms"
|
|
||||||
class="terms-checkbox"
|
|
||||||
>
|
|
||||||
{{ t('page.login.register.agreeTerms') }}
|
|
||||||
</ACheckbox>
|
|
||||||
</div>
|
</div>
|
||||||
<ASpace direction="vertical" size="small" class="w-full">
|
|
||||||
<AButton type="primary" block size="small" :disabled="!agreeTerms" @click="nextStep">
|
|
||||||
{{ t('page.login.register.next') }}
|
|
||||||
</AButton>
|
|
||||||
<AButton block size="small" @click="prevStep">
|
|
||||||
{{ t('page.login.register.prev') }}
|
|
||||||
</AButton>
|
|
||||||
</ASpace>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 第三步:安全信息 -->
|
|
||||||
<div v-show="currentStep === 2">
|
|
||||||
<AForm
|
|
||||||
ref="securityFormRef"
|
|
||||||
:model="securityModel"
|
|
||||||
:rules="securityRules"
|
|
||||||
:label-wrap="true"
|
|
||||||
:label-col="{ span: 8 }"
|
|
||||||
:wrapper-col="{ span: 16 }"
|
|
||||||
class="compact-form"
|
|
||||||
>
|
|
||||||
<AFormItem name="email" :label="t('page.login.register.email')">
|
|
||||||
<AInput
|
|
||||||
v-model:value="securityModel.email"
|
|
||||||
:placeholder="t('page.login.common.emailPlaceholder')"
|
|
||||||
/>
|
|
||||||
</AFormItem>
|
|
||||||
<AFormItem name="code" :label="t('page.login.register.code')">
|
|
||||||
<div class="w-full flex-y-center gap-8px">
|
|
||||||
<AInput
|
|
||||||
v-model:value="securityModel.code"
|
|
||||||
:placeholder="t('page.login.common.codePlaceholder')"
|
|
||||||
/>
|
|
||||||
<AButton
|
|
||||||
size="small"
|
|
||||||
:disabled="isCounting"
|
|
||||||
:loading="loading"
|
|
||||||
@click="getCaptcha(securityModel.email)"
|
|
||||||
>
|
|
||||||
{{ label }}
|
|
||||||
</AButton>
|
|
||||||
</div>
|
|
||||||
</AFormItem>
|
|
||||||
<AFormItem name="password" :label="t('page.login.register.password')">
|
|
||||||
<AInputPassword
|
|
||||||
v-model:value="securityModel.password"
|
|
||||||
:placeholder="t('page.login.common.passwordPlaceholder')"
|
|
||||||
/>
|
|
||||||
</AFormItem>
|
|
||||||
<AFormItem name="confirmPassword" :label="t('page.login.register.confirmPassword')">
|
|
||||||
<AInputPassword
|
|
||||||
v-model:value="securityModel.confirmPassword"
|
|
||||||
:placeholder="t('page.login.common.confirmPasswordPlaceholder')"
|
|
||||||
/>
|
|
||||||
</AFormItem>
|
|
||||||
<AFormItem :wrapper-col="{ xs: { span: 24 }, sm: { span: 24 } }">
|
|
||||||
<ASpace direction="vertical" size="small" class="w-full">
|
|
||||||
<AButton type="primary" block size="small" @click="handleSubmit">
|
|
||||||
{{ t('common.confirm') }}
|
|
||||||
</AButton>
|
|
||||||
<AButton block size="small" @click="prevStep">
|
|
||||||
{{ t('page.login.register.prev') }}
|
|
||||||
</AButton>
|
|
||||||
</ASpace>
|
|
||||||
</AFormItem>
|
|
||||||
</AForm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -504,6 +522,7 @@ const showSteps = computed(() => !isMobile.value);
|
|||||||
:deep(.ant-form-item-label) {
|
:deep(.ant-form-item-label) {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
> label {
|
> label {
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
|
|||||||
Reference in New Issue
Block a user