Skip to content

Commit d07894c

Browse files
committed
feat: Add user register page (#122)
1 parent a290664 commit d07894c

File tree

9 files changed

+242
-5
lines changed

9 files changed

+242
-5
lines changed

mock/modules/user.mock.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,12 @@ export default defineMock([
5656
return builder(res)
5757
},
5858
},
59+
{
60+
url: '/api/user/register',
61+
delay: 1000,
62+
body: () => {
63+
const res = true
64+
return builder(res)
65+
},
66+
},
5967
])

src/api/user.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ export function getEmailCode(): Promise<any> {
3434
export function resetPassword(): Promise<any> {
3535
return request.post('/user/reset-password')
3636
}
37+
38+
export function register(): Promise<any> {
39+
return request.post('/user/register')
40+
}

src/locales/en-US.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"unocssExample": "🎨 Unocss example",
1212
"keepAlive": "🧡 KeepAlive Demo",
1313
"login": "🔒 Login",
14+
"register": "Register",
1415
"settings": "Settings",
1516
"basicSettings": "Basic Settings",
1617
"exampleComponents": "Example components",
@@ -66,7 +67,26 @@
6667
"getCode": "Get code",
6768
"gettingCode": "Getting code",
6869
"sendCodeSuccess": "Sent, the code is",
69-
"passwordResetSuccee": "Password reset succeeded"
70+
"passwordResetSuccess": "Password reset succeeded"
71+
},
72+
"register": {
73+
"email": "Email",
74+
"code": "Code",
75+
"nickname": "Nickname",
76+
"password": "Password",
77+
"comfirmPassword": "Password again",
78+
"pleaseEnterEmail": "Please enter email",
79+
"pleaseEnterCode": "Please enter code",
80+
"pleaseEnterNickname": "Please enter nickname",
81+
"pleaseEnterPassword": "Please enter password",
82+
"pleaseEnterConfirmPassword": "Please enter password again",
83+
"passwordsDoNotMatch": "Passwords do not match",
84+
"confirm": "Confirm",
85+
"backToLogin": "Back to login",
86+
"getCode": "Get code",
87+
"gettingCode": "Getting code",
88+
"sendCodeSuccess": "Sent, the code is",
89+
"registerSuccess": "Register succeeded"
7090
},
7191
"settings": {
7292
"logout": "Sign Out",

src/locales/zh-CN.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"unocssExample": "🎨 Unocss 示例",
1212
"keepAlive": "🧡 KeepAlive 演示",
1313
"login": "🔒 用户登录",
14+
"register": "用户注册",
1415
"settings": "设置",
1516
"basicSettings": "基本设置",
1617
"exampleComponents": "示例组件",
@@ -66,7 +67,26 @@
6667
"getCode": "获取验证码",
6768
"gettingCode": "获取中",
6869
"sendCodeSuccess": "已发送,验证码为",
69-
"passwordResetSuccee": "密码重置成功"
70+
"passwordResetSuccess": "密码重置成功"
71+
},
72+
"register": {
73+
"email": "邮箱",
74+
"code": "验证码",
75+
"nickname": "昵称",
76+
"password": "密码",
77+
"comfirmPassword": "再次输入密码",
78+
"pleaseEnterEmail": "请输入邮箱",
79+
"pleaseEnterCode": "请输入验证码",
80+
"pleaseEnterNickname": "请输入昵称",
81+
"pleaseEnterPassword": "请输入密码",
82+
"pleaseEnterConfirmPassword": "请再次输入密码",
83+
"passwordsDoNotMatch": "两次输入的密码不一致",
84+
"confirm": "确认",
85+
"backToLogin": "返回登录",
86+
"getCode": "获取验证码",
87+
"gettingCode": "获取中",
88+
"sendCodeSuccess": "已发送,验证码为",
89+
"registerSuccess": "注册成功"
7090
},
7191
"settings": {
7292
"logout": "退出登录",

src/pages/forgot-password/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async function reset() {
4040
const res = await userStore.reset()
4141
4242
if (res.code === 0) {
43-
showNotify({ type: 'success', message: t('forgot-password.passwordResetSuccee') })
43+
showNotify({ type: 'success', message: t('forgot-password.passwordResetSuccess') })
4444
router.push({ name: 'login' })
4545
}
4646
}

src/pages/login/index.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ async function login(values: any) {
5353
function handleReset() {
5454
router.push({ name: 'forgot-password' })
5555
}
56+
57+
function handleRegister() {
58+
router.push({ name: 'register' })
59+
}
5660
</script>
5761

5862
<template>
@@ -93,7 +97,7 @@ function handleReset() {
9397
</div>
9498
</van-form>
9599

96-
<div class="mt-16 text-12 text-[var(--van-primary-color)]">
100+
<div class="mt-16 text-12 text-[var(--van-primary-color)]" @click="handleRegister">
97101
{{ $t('login.sign-up') }}
98102
</div>
99103

src/pages/register/index.vue

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<script setup lang="ts">
2+
import { useRouter } from 'vue-router'
3+
import type { FieldRule } from 'vant'
4+
import { useUserStore } from '@/stores'
5+
6+
const { t } = useI18n()
7+
const router = useRouter()
8+
const userStore = useUserStore()
9+
const loading = ref(false)
10+
11+
const postData = reactive({
12+
email: '',
13+
code: '',
14+
nickname: '',
15+
password: '',
16+
confirmPassword: '',
17+
})
18+
19+
const validatorPassword = (val: string) => val === postData.password
20+
21+
const rules = reactive({
22+
email: [
23+
{ required: true, message: t('register.pleaseEnterEmail') },
24+
],
25+
code: [
26+
{ required: true, message: t('register.pleaseEnterCode') },
27+
],
28+
nickname: [
29+
{ required: true, message: t('register.pleaseEnterNickname') },
30+
],
31+
password: [
32+
{ required: true, message: t('register.pleaseEnterPassword') },
33+
],
34+
confirmPassword: [
35+
{ required: true, message: t('register.pleaseEnterConfirmPassword') },
36+
{ required: true, validator: validatorPassword, message: t('register.passwordsDoNotMatch') },
37+
] as FieldRule[],
38+
})
39+
40+
async function register() {
41+
try {
42+
loading.value = true
43+
44+
const res = await userStore.register()
45+
46+
if (res.code === 0) {
47+
showNotify({ type: 'success', message: t('register.registerSuccess') })
48+
router.push({ name: 'login' })
49+
}
50+
}
51+
finally {
52+
loading.value = false
53+
}
54+
}
55+
56+
const isGettingCode = ref(false)
57+
58+
const buttonText = computed(() => {
59+
return isGettingCode.value ? t('register.gettingCode') : t('register.getCode')
60+
})
61+
62+
async function getCode() {
63+
if (!postData.email) {
64+
showNotify({ type: 'warning', message: t('register.pleaseEnterEmail') })
65+
return
66+
}
67+
68+
isGettingCode.value = true
69+
const res = await userStore.getCode()
70+
if (res.code === 0) {
71+
showNotify({ type: 'success', message: `${t('register.sendCodeSuccess')}: ${res.result}` })
72+
}
73+
74+
isGettingCode.value = false
75+
}
76+
77+
function handleBackLogin() {
78+
router.push({ name: 'login' })
79+
}
80+
</script>
81+
82+
<template>
83+
<div class="m-x-a w-7xl text-center">
84+
<van-form :model="postData" :rules="rules" validate-trigger="onSubmit" @submit="register">
85+
<div class="overflow-hidden rounded-3xl">
86+
<van-field
87+
v-model.trim="postData.email"
88+
:rules="rules.email"
89+
name="email"
90+
:placeholder="t('register.email')"
91+
/>
92+
</div>
93+
94+
<div class="mt-16 overflow-hidden rounded-3xl">
95+
<van-field
96+
v-model.trim="postData.code"
97+
:rules="rules.code"
98+
name="code"
99+
:placeholder="t('register.code')"
100+
>
101+
<template #button>
102+
<van-button size="small" type="primary" plain @click="getCode">
103+
{{ buttonText }}
104+
</van-button>
105+
</template>
106+
</van-field>
107+
</div>
108+
109+
<div class="mt-16 overflow-hidden rounded-3xl">
110+
<van-field
111+
v-model.trim="postData.nickname"
112+
:rules="rules.nickname"
113+
name="nickname"
114+
:placeholder="t('register.nickname')"
115+
/>
116+
</div>
117+
118+
<div class="mt-16 overflow-hidden rounded-3xl">
119+
<van-field
120+
v-model.trim="postData.password"
121+
type="password"
122+
:rules="rules.password"
123+
name="password"
124+
:placeholder="t('register.password')"
125+
/>
126+
</div>
127+
128+
<div class="mt-16 overflow-hidden rounded-3xl">
129+
<van-field
130+
v-model.trim="postData.confirmPassword"
131+
type="password"
132+
:rules="rules.confirmPassword"
133+
name="confirmPassword"
134+
:placeholder="t('register.comfirmPassword')"
135+
/>
136+
</div>
137+
138+
<div class="mt-16">
139+
<van-button
140+
:loading="loading"
141+
type="primary"
142+
native-type="submit"
143+
round block
144+
>
145+
{{ $t('register.confirm') }}
146+
</van-button>
147+
</div>
148+
</van-form>
149+
150+
<div class="mt-16 text-12 text-[var(--van-primary-color)]" @click="handleBackLogin">
151+
{{ $t('register.backToLogin') }}
152+
</div>
153+
</div>
154+
</template>
155+
156+
<route lang="json">
157+
{
158+
"name": "register",
159+
"meta": {
160+
"i18n": "menus.register"
161+
}
162+
}
163+
</route>

src/stores/modules/user.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
import { defineStore } from 'pinia'
22
import type { LoginData, UserState } from '@/api/user'
3-
import { getEmailCode, getUserInfo, resetPassword, login as userLogin, logout as userLogout } from '@/api/user'
43
import { clearToken, setToken } from '@/utils/auth'
54

5+
import {
6+
getEmailCode,
7+
getUserInfo,
8+
resetPassword,
9+
login as userLogin,
10+
logout as userLogout,
11+
register as userRegister,
12+
} from '@/api/user'
13+
614
const InitUserInfo = {
715
uid: 0,
816
nickname: '',
@@ -65,13 +73,22 @@ export const useUserStore = defineStore('user', () => {
6573
catch {}
6674
}
6775

76+
const register = async () => {
77+
try {
78+
const data = await userRegister()
79+
return data
80+
}
81+
catch {}
82+
}
83+
6884
return {
6985
userInfo,
7086
info,
7187
login,
7288
logout,
7389
getCode,
7490
reset,
91+
register,
7592
}
7693
}, {
7794
persist: true,

src/types/typed-router.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ declare module 'vue-router/auto-routes' {
2727
'login': RouteRecordInfo<'login', '/login', Record<never, never>, Record<never, never>>,
2828
'mock': RouteRecordInfo<'mock', '/mock', Record<never, never>, Record<never, never>>,
2929
'profile': RouteRecordInfo<'profile', '/profile', Record<never, never>, Record<never, never>>,
30+
'register': RouteRecordInfo<'register', '/register', Record<never, never>, Record<never, never>>,
3031
'settings': RouteRecordInfo<'settings', '/settings', Record<never, never>, Record<never, never>>,
3132
'unocss': RouteRecordInfo<'unocss', '/unocss', Record<never, never>, Record<never, never>>,
3233
}

0 commit comments

Comments
 (0)