feat: register

This commit is contained in:
KUN1007 2023-09-22 00:54:05 +08:00
parent a51761f8f4
commit cc909e30ff
9 changed files with 180 additions and 118 deletions

View file

@ -12,7 +12,6 @@ export interface RegisterRequestData {
email: string
password: string
code: string
ip?: string
}
// 发送验证码请求数据格式

View file

@ -1,27 +1,24 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
// 使
import { useKUNGalgameMessageStore } from '@/store/modules/message'
const info = useKUNGalgameMessageStore()
//
const props = defineProps(['send'])
const props = defineProps<{
email: string
isSendCode: boolean
}>()
const isSending = ref(false)
const countdown = ref(0)
const register = () => {
// TODO:
info.info(
'验证码已发送,您可以在邮箱中查看,注意查看垃圾邮件,如果未收到邮件,您可以在 30 秒后尝试重新发送邮箱验证码'
)
}
const sendCode = () => {
//
if (!props.send) {
if (!props.isSendCode) {
return
}
@ -37,7 +34,12 @@ const sendCode = () => {
}
}, 1000)
register()
//
useKUNGalgameUserStore().sendCode(props.email)
info.info(
'验证码已发送,您可以在邮箱中查看,注意查看垃圾邮件,如果未收到邮件,您可以在 30 秒后尝试重新发送邮箱验证码'
)
}
}
</script>

View file

@ -27,6 +27,7 @@ interface UserState {
export const useKUNGalgameUserStore = defineStore({
id: 'kungalgamer',
persist: true,
// TODO: token 放在 cookie 中,这里临时存放一下
state: (): UserState => ({
uid: 0,
name: '',
@ -68,8 +69,9 @@ export const useKUNGalgameUserStore = defineStore({
})
},
// 发送验证码
sendCode(request: VerificationCodeMailRequestData): Promise<void> {
sendCode(email: string): Promise<void> {
return new Promise((resolve, reject) => {
const request: VerificationCodeMailRequestData = { email }
sendVerificationCodeMailApi(request)
.then((res) => {
resolve(res)

View file

@ -93,7 +93,6 @@ const handleLogin = () => {
if (res.code === 200) {
router.push('/')
info.info(tm('AlertInfo.login.success'))
} else {
}
})
}
@ -103,7 +102,7 @@ const handleLogin = () => {
<!-- 登陆 -->
<div class="login">
<Capture @validate="handleVerify" :isShowValidate="isShowValidate" />
<form class="form" @submit.prevent="handleLogin">
<div class="form">
<h2 class="title">{{ $tm('login.loginTitle') }}</h2>
<input
v-model="loginForm.name"
@ -117,14 +116,18 @@ const handleLogin = () => {
:placeholder="($tm('login.loginPassword') as string)"
class="input"
/>
<!-- 忘记密码 -->
<span class="forget">{{ $tm('login.forget') }}</span>
<span @click="isShowValidate = true" class="capture">{{
$tm('login.capture')
}}</span>
<button class="btn" type="submit">
<!-- 点击登录 -->
<button @click="handleLogin" class="btn" type="submit">
{{ $tm('login.loginTitle') }}
</button>
</form>
</div>
</div>
</template>
@ -146,7 +149,7 @@ const handleLogin = () => {
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 3rem;
padding: 0 50px;
height: 100%;
text-align: center;
}
@ -155,7 +158,7 @@ const handleLogin = () => {
.title {
font-weight: 300;
font-weight: bold;
margin-bottom: 1.25rem;
margin-bottom: 20px;
color: var(--kungalgame-font-color-2);
}
@ -163,8 +166,8 @@ const handleLogin = () => {
border: none;
outline: none;
border-bottom: 1.5px solid var(--kungalgame-blue-0);
padding: 0.9rem 0.9rem;
margin: 0.5rem 0;
padding: 15px;
margin: 7px 0;
width: 100%;
background-color: var(--kungalgame-white);
color: var(--kungalgame-font-color-3);
@ -190,18 +193,17 @@ const handleLogin = () => {
.btn {
position: absolute;
margin-top: 1.5rem;
bottom: 7%;
bottom: 10%;
border-radius: 50px;
background-color: var(--kungalgame-trans-white-5);
border: 1px solid var(--kungalgame-blue-4);
color: var(--kungalgame-blue-4);
cursor: pointer;
font-size: 0.9em;
letter-spacing: 0.1rem;
padding: 0.6rem 4rem;
font-size: 15px;
letter-spacing: 2px;
padding: 7px 50px;
text-transform: uppercase;
transition: transform 80ms ease-in;
transition: all 0.2s;
overflow: hidden;
white-space: nowrap;
}

View file

@ -3,9 +3,9 @@
-->
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
//
import message from '@/components/alert/Message'
import { useKUNGalgameMessageStore } from '@/store/modules/message'
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
import {
isValidEmail,
@ -16,37 +16,36 @@ import {
import Code from '@/components/verification-code/Code.vue'
import Capture from '@/components/capture/Capture.vue'
const info = useKUNGalgameMessageStore()
const isCapturePass = ref(false)import { useI18n } from 'vue-i18n'
const router = useRouter()
const isShowValidate = ref(false)
const isCaptureComplete = ref(false)
const isSendCode = ref(false)
const registerForm = reactive({
username: '',
import { registerFormItem } from './registerForm'
const registerForm = reactive<Record<string, string>>({
name: '',
email: '',
password: '',
code: '',
})
//
const handleCapture = (result: boolean) => {
const handleVerify = (result: boolean) => {
if (result) {
isShowValidate.value = false
message(
'Human-machine identity verification successful',
'人机验证通过',
'success'
)
isCapturePass.value = true
isCaptureComplete.value = true
} else {
isCapturePass.value = false
}
}
//
const isEmptyInput = () => {
if (!registerForm.username.trim()) {
if (!registerForm.name.trim()) {
message('Username cannot be empty!', '用户名不可为空!', 'warn')
return false
} else if (!registerForm.email.trim()) {
@ -65,7 +64,7 @@ const isValidInput = (): boolean => {
if (!isEmptyInput()) {
return false
}
if (!isValidName(registerForm.username)) {
if (!isValidName(registerForm.name)) {
message('Invalid username format!', '非法的用户名格式!', 'warn')
return false
}
@ -80,15 +79,22 @@ const isValidInput = (): boolean => {
return true
}
//
const handleSendCode = () => {
//
//
if (!isValidInput()) {
return
}
//
if (!isCaptureComplete.value) {
//
isShowValidate.value = true
return
}
//
isSendCode.value = true
}
const handleRegister = () => {
@ -101,55 +107,70 @@ const handleRegister = () => {
}
if (!isValidMailConfirmCode(registerForm.code)) {
info.info('非法的邮箱验证码')
message('Invalid email verification code.', '邮箱验证码错误!', 'warn')
return
}
//
useKUNGalgameUserStore()
.register({
name: registerForm.name,
email: registerForm.email,
password: registerForm.password,
code: registerForm.code,
})
.then((res) => {
//
if (res.code === 200) {
router.push('/')
message('Register successfully!', '注册成功!', 'success')
} else {
}
})
.catch((error) => {
console.log(error)
})
}
</script>
<template>
<!-- 注册 -->
<div class="register">
<Capture @validate="handleCapture" :isShowValidate="isCapturePass" />
<form action="#" class="form" @submit.prevent="handleRegister">
<!-- 人机验证 -->
<Capture @validate="handleVerify" :isShowValidate="isShowValidate" />
<!-- 注册表单 -->
<div class="form">
<!-- 标题 -->
<h2 class="title">注册</h2>
<div class="container" v-for="item in registerFormItem" :key="item.index">
<input
v-model="registerForm.username"
type="text"
placeholder="用户名"
class="input"
v-model="registerForm[item.value]"
:type="item.type"
:placeholder="item.placeholder"
:class="item.class"
/>
<input
v-model="registerForm.email"
type="email"
placeholder="邮箱"
class="input"
/>
<input
v-model="registerForm.password"
type="text"
placeholder="密码"
class="input"
/>
<input
v-model="registerForm.code"
type="text"
placeholder="邮箱验证码"
class="input"
/>
<div @click="handleSendCode" class="mail-confirm">
<Code :send="isSendCode" />
</div>
<button class="btn" type="submit">注册</button>
<Code
@click="handleSendCode"
class="code"
:email="registerForm.email"
:isSendCode="isSendCode"
/>
<!-- 注册按钮 -->
<button @click="handleRegister" class="btn" type="submit">注册</button>
<!-- 用户协议提示等 -->
<span class="user-agreement">
点击注册表示您已经同意我们的
<router-link to="/licence"><span>用户协议</span></router-link>
<router-link to="/privacy"><span>隐私政策</span></router-link>
</span>
</form>
</div>
</div>
</template>
@ -168,10 +189,15 @@ const handleRegister = () => {
.title {
font-weight: 300;
font-weight: bold;
margin-bottom: 1.25rem;
margin-bottom: 20px;
color: var(--kungalgame-font-color-2);
}
.container {
width: 100%;
position: relative;
}
/* 表单的设置 */
.form {
background-color: var(--kungalgame-white);
@ -179,17 +205,17 @@ const handleRegister = () => {
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 3rem;
padding: 0 50px;
height: 100%;
text-align: center;
}
//
.input {
border: none;
outline: none;
border-bottom: 1.5px solid var(--kungalgame-blue-0);
padding: 0.9rem 0.9rem;
margin: 0.5rem 0;
padding: 15px;
margin: 7px 0;
width: 100%;
background-color: var(--kungalgame-white);
color: var(--kungalgame-font-color-3);
@ -199,55 +225,48 @@ const handleRegister = () => {
transition: 0.2s linear;
}
.mail-confirm {
.code {
position: absolute;
padding: 5px;
height: 30px;
bottom: 24%;
right: 15%;
}
.mail-confirm:hover {
color: var(--kungalgame-blue-4);
bottom: 120px;
right: 50px;
}
/* 用户协议 */
.user-agreement {
position: absolute;
bottom: 2%;
bottom: 3%;
font-size: x-small;
color: var(--kungalgame-font-color-1);
text-decoration: none;
}
.user-agreement span {
span {
color: var(--kungalgame-red-4);
font-style: oblique;
}
}
.btn {
position: absolute;
bottom: 7%;
bottom: 10%;
border-radius: 50px;
background-color: var(--kungalgame-trans-white-5);
border: 1px solid var(--kungalgame-blue-4);
color: var(--kungalgame-blue-4);
cursor: pointer;
font-size: 0.9em;
letter-spacing: 0.1rem;
padding: 0.6rem 4rem;
font-size: 15px;
letter-spacing: 2px;
padding: 7px 50px;
text-transform: uppercase;
transition: transform 80ms ease-in;
transition: all 0.2s;
margin-top: 30px;
}
.btn:hover {
&:hover {
background-color: var(--kungalgame-blue-4);
color: var(--kungalgame-white);
}
.btn:active {
}
&:active {
transform: scale(0.95);
}
.btn:focus {
}
&:focus {
outline: none;
}
}
</style>

View file

@ -0,0 +1,38 @@
interface RegisterFormItem {
index: number
value: string
type: string
placeholder: string
class: string
}
export const registerFormItem: RegisterFormItem[] = [
{
index: 1,
value: 'name',
type: 'text',
placeholder: '用户名',
class: 'input',
},
{
index: 2,
value: 'email',
type: 'email',
placeholder: '邮箱',
class: 'input',
},
{
index: 3,
value: 'password',
type: 'text',
placeholder: '密码',
class: 'input',
},
{
index: 4,
value: 'code',
type: 'text',
placeholder: '邮箱验证码',
class: 'input',
},
]

View file

@ -9,7 +9,7 @@ import 'dayjs/locale/en' // 导入英文语言包
import { useKUNGalgameSettingsStore } from '@/store/modules/settings'
import { storeToRefs } from 'pinia'
const { time } = defineProps<{
const props = defineProps<{
time?: number
}>()
@ -19,8 +19,8 @@ const { showKUNGalgameLanguage } = storeToRefs(settingsStore)
// 使
dayjs.locale('en')
const formattedCNDate = dayjs(time).format('YYYY年MM月DD日-HH:mm:ss 发布')
const formattedENDate = dayjs(time).format('MMMM D, YYYY - h:mm:ss A')
const formattedCNDate = dayjs(props.time).format('YYYY年MM月DD日-HH:mm:ss 发布')
const formattedENDate = dayjs(props.time).format('MMMM D, YYYY - h:mm:ss A')
const loliTime = computed(() => {
if (showKUNGalgameLanguage.value === 'en') {

View file

@ -15,7 +15,7 @@ import { storeToRefs } from 'pinia'
const { name, uid } = storeToRefs(useKUNGalgameUserStore())
// props
const { tid, rid, to_user } = defineProps<{
const props = defineProps<{
tid: number
rid: number
to_user: {
@ -48,10 +48,10 @@ const handleInputComment = () => {
//
const saveComment = () => {
commentDraft.value.tid = tid
commentDraft.value.rid = rid
commentDraft.value.tid = props.tid
commentDraft.value.rid = props.rid
commentDraft.value.c_uid = uid.value
commentDraft.value.to_uid = to_user.uid
commentDraft.value.to_uid = props.to_user.uid
commentDraft.value.content = commentValue.value
}

View file

@ -13,7 +13,7 @@ import { useKUNGalgameTopicStore } from '@/store/modules/topic'
import { storeToRefs } from 'pinia'
const { commentDraft } = storeToRefs(useKUNGalgameTopicStore())
const { tid, rid, toUser } = defineProps<{
const props = defineProps<{
tid: number
rid: number
toUser: {
@ -41,10 +41,10 @@ const getCommentEmits = (newComment: TopicComment) => {
onMounted(async () => {
//
toUserInfo.name = toUser.name
toUserInfo.uid = toUser.uid
toUserInfo.name = props.toUser.name
toUserInfo.uid = props.toUser.uid
commentsData.value = await getComments(tid, rid)
commentsData.value = await getComments(props.tid, props.rid)
})
//
@ -54,7 +54,7 @@ const handleClickReply = (uid: number, name: string) => {
toUserInfo.uid = uid
//
commentDraft.value.isShowCommentPanelRid = rid
commentDraft.value.isShowCommentPanelRid = props.rid
}
</script>