邮箱发送验证码逻辑封装

master
pan 3 years ago
parent fd1c8a6693
commit 4b99cfdda1
  1. 19
      src/App.vue
  2. 48
      src/components/Email.vue
  3. 64
      src/components/EmailCode.vue
  4. 26
      src/components/Login.vue
  5. 9
      src/components/Register.vue
  6. 31
      src/components/User.vue
  7. 22
      src/request.ts
  8. 61
      src/router.ts

@ -3,20 +3,20 @@
<el-header>
<el-row>
<el-col :span="4">
<h1>直播间开播通知</h1>
<h1>bilibili直播通知后台管理</h1>
</el-col>
<el-col :span="20" v-if="![loginPath,registerPath].includes($route.fullPath)">
<el-menu mode="horizontal" :router="true" :default-active="store.state.route">
<el-menu mode="horizontal" :router="true" :default-active="configPath">
<el-submenu index="1">
<template v-slot:title>推送配置</template>
<el-menu-item index="/config">当前配置</el-menu-item>
<el-menu-item index="/config/telegram">修改telegram bot</el-menu-item>
<el-menu-item :index="configPath">当前配置</el-menu-item>
<el-menu-item :index="telegramPath">修改telegram bot</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template v-slot:title>个人信息</template>
<el-menu-item index="/password">修改密码</el-menu-item>
<el-menu-item index="/email">修改邮箱</el-menu-item>
<el-menu-item :index="managerPasswordPath">修改密码</el-menu-item>
<el-menu-item :index="managerEmailPath">修改邮箱</el-menu-item>
<el-menu-item @click="logout">退出登录</el-menu-item>
</el-submenu>
</el-menu>
@ -34,7 +34,7 @@
import {defineComponent} from 'vue'
import Config from "./components/Config.vue";
import {useStore} from "vuex";
import {loginPath, registerPath} from "./router";
import {configPath, loginPath, managerEmailPath, managerPasswordPath, registerPath, telegramPath} from "./router";
//@ts-ignore
import crumbs from 'crumbsjs';
import {useRouter} from "vue-router";
@ -51,7 +51,10 @@ export default defineComponent({
router.replace(loginPath)
}
return {store, loginPath, registerPath, logout}
return {
store, loginPath, registerPath, logout, configPath, telegramPath
, managerEmailPath, managerPasswordPath
}
}
})
</script>

@ -15,16 +15,7 @@
<span v-if="userEmail === newEmail">新邮箱不能和当前邮箱一致</span>
</el-col>
</el-row>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="6">
<el-input v-model="code">
<template v-slot:prepend>验证码</template>
</el-input>
</el-col>
<el-col :span="2">
<el-button type="primary" :disabled="!allowSendCode" @click="sendCode">{{ sendCodeTip }}</el-button>
</el-col>
</el-row>
<EmailCode :allowSendCode="allowSendCode"/>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="2">
<el-button type="primary" class="btn-block" :disabled="!checkCode" @click="changeEmail">更换邮箱</el-button>
@ -37,18 +28,20 @@
</template>
<script lang="ts">
import {computed, defineComponent, ref} from "vue";
import {computed, defineComponent, provide, Ref, ref} from "vue";
import {changeEmail as _changeEmail, JSONResponse, message, sendCode as _sendCode} from "../request";
import {changeEmail as _changeEmail, message} from "../request";
import {updateRoute} from "../router";
import {useRouter} from "vue-router";
import {emailRegexp} from "../validate";
// @ts-ignore
import crumbs from 'crumbsjs';
import {email_cookie_key} from "../global";
import EmailCode from "./EmailCode.vue";
export default defineComponent({
name: 'Email',
components: {EmailCode},
setup(props) {
const newEmail = ref<string>('')
const code = ref<string>('')
@ -59,41 +52,21 @@ export default defineComponent({
const userEmail = crumbs.get(email_cookie_key)
const sendCode = () => {
second.value = 10
_sendCode(userEmail).then(res => res.json()).then((res: JSONResponse) => {
message(res)
if (res.result === 'OK') {
console.info('发送验证码成功')
const t = setInterval(function () {
if (second.value === 0) {
clearInterval(t)
} else {
second.value--
}
}, 1000)
} else {
second.value = 0
}
})
}
const changeEmail = () => _changeEmail(userEmail, newEmail.value, code.value).then(res => res.json()).then(
res => {
message(res)
crumbs.set(email_cookie_key, newEmail.value)
if (res.result === 'OK') {
router.replace('/config')
}
}
)
provide<Ref<string>>('code', code)
provide<Ref<number>>('second', second)
const allowSendCode = computed<boolean>(() => second.value === 0 && userEmail !== newEmail.value && emailRegexp.test(newEmail.value))
const sendCodeTip = computed<string>(() => second.value > 0 ? second.value + '秒后重发' : '发送验证码')
const allowSendCode = computed<boolean>(() => second.value === 0 && userEmail !== newEmail.value && emailRegexp.test(newEmail.value))
const checkCode = computed<boolean>(() => /^\d{6}$/.test(code.value))
@ -101,12 +74,9 @@ export default defineComponent({
return {
newEmail,
code,
allowSendCode,
sendCodeTip,
checkCode,
second,
sendCode,
userEmail,
changeEmail
}

@ -0,0 +1,64 @@
<template>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="6">
<el-input v-model="code" ref="headline">
<template v-slot:prepend>验证码</template>
</el-input>
<span v-if="allowInput">请先发送验证码</span>
</el-col>
<el-col :span="2">
<el-button type="primary" :disabled="allowSendCode!==undefined&&!allowSendCode" @click="sendCode">{{
sendCodeTip
}}
</el-button>
</el-col>
</el-row>
</template>
<script lang="ts">
import {computed, defineComponent, inject, Ref, ref} from "vue";
import {sendCode as _sendCode} from "../request";
import {email_cookie_key} from "../global";
// @ts-ignore
import crumbs from 'crumbsjs';
export default defineComponent({
name: "EmailCode",
props: {
allowSendCode: {
type: Boolean,
require: false
}
},
setup(props) {
const code = inject<Ref<string>>('code')
const second = inject<Ref<number>>('second')
const allowInput = ref<boolean>(true)
const sendCodeTip = computed<string>(() => second && second.value > 0 ? `${second.value}秒后重发` : `发送验证码`)
const userEmail = crumbs.get(email_cookie_key)
const headline = ref(null);
const sendCode = () => {
_sendCode(userEmail, _second => {
if (second) {
second.value = _second
}
}, () => {
allowInput.value = false
})
}
return {sendCodeTip, sendCode, code, allowInput, headline}
}
})
</script>
<style scoped>
</style>

@ -1,17 +1,6 @@
<!--登录-->
<template>
<el-row justify="center" type="flex">
<el-col :span="8"><h1>后台登陆</h1></el-col>
</el-row>
<el-row justify="center" type="flex">
<el-col :span="8">
<el-input v-model="user">
<template v-slot:prepend>管理员邮箱</template>
</el-input>
<span v-if="user===''">邮箱不能为空</span>
<span v-else-if="!checkUser">邮箱不合法</span>
</el-col>
</el-row>
<User/>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="8">
<span>密码必须包含数字字母6-10</span>
@ -24,29 +13,34 @@
</el-row>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="8">
<el-button type="primary" class="btn-block" :disabled="user===''||password===''" @click="requestLogin">登录
<el-button type="primary" class="btn-block" :disabled="!(checkUser&&checkPwd)" @click="requestLogin">登录
</el-button>
</el-col>
</el-row>
</template>
<script lang="ts">
import {computed, defineComponent, ref} from "vue";
import {computed, defineComponent, provide, Ref, ref} from "vue";
import {emailRegexp, passwordRegexp} from "../validate";
import {JSONResponse, login, message} from "../request";
//@ts-ignore
import crumbs from 'crumbsjs';
import {useRouter} from "vue-router";
import {email_cookie_key, token_cookie_key} from "../global";
import User from "./User.vue";
import {configPath} from "../router";
export default defineComponent({
name: "Login",
components: {User},
setup() {
const user = ref<string>('')
const password = ref<string>('')
const checkUser = computed<boolean>(() => emailRegexp.test(user.value))
provide<Ref<string>>('user', user)
const checkPwd = computed<boolean>(() => passwordRegexp.test(password.value))
const router = useRouter()
@ -58,12 +52,12 @@ export default defineComponent({
if (res.result === 'OK') {
crumbs.set(token_cookie_key, res.body.token)
crumbs.set(email_cookie_key, res.body.userEmail)
router.replace('/')
router.replace(configPath)
}
})
}
return {user, password, checkUser, checkPwd, requestLogin}
return {user, password, checkPwd, requestLogin, checkUser}
}
})
</script>

@ -23,11 +23,14 @@
<el-input v-model="userEmail">
<template v-slot:prepend>管理员邮箱</template>
</el-input>
<span v-if="user===''">邮箱不能为空</span>
<span v-else-if="!checkUser">邮箱不合法</span>
</el-col>
</el-row>
<EmailCode/>
<el-row type="flex" justify="center" class="mt-1">
<el-col :span="8">
<el-input v-model="code" placeholder="请输入验证码"/>
<el-col :span="2">
<el-button type="primary" class="btn-block">注册</el-button>
</el-col>
</el-row>
</template>
@ -35,9 +38,11 @@
<script lang="ts">
import {defineComponent, ref} from "vue";
import EmailCode from "./EmailCode.vue";
export default defineComponent({
name: "Register",
components: {EmailCode},
setup() {
const step = ref<number>(1)
const userEmail = ref<string>('')

@ -0,0 +1,31 @@
<template>
<el-row justify="center" type="flex">
<el-col :span="8">
<el-input v-model="user">
<template v-slot:prepend>邮箱账号</template>
</el-input>
<span v-if="user===''">邮箱不能为空</span>
<span v-else-if="!checkUser">邮箱不合法</span>
</el-col>
</el-row>
</template>
<script lang="ts">
import {computed, defineComponent, inject, Ref} from 'vue'
import {emailRegexp} from "../validate";
export default defineComponent({
name: "User",
setup(props) {
const user = inject<Ref<string>>('user')
//@ts-ignore
const checkUser = computed<boolean>(() => emailRegexp.test(user.value))
return {user, checkUser}
}
})
</script>
<style scoped>
</style>

@ -13,9 +13,29 @@ import {Message} from 'element3/src/components/Message'
/**
*
* @param userEmail
* @param callback
* @param success
*/
export function sendCode(userEmail: string) {
export function sendCode(userEmail: string, callback: (second: number) => void, success: () => void) {
let second = 10
return fetch(new Request(sendCodeApi, {method: 'POST', body: JSON.stringify({userEmail})}))
.then(res => res.json()).then((res: JSONResponse) => {
message(res)
if (res.result === 'OK') {
console.info('发送验证码成功')
callback(second)
success()
const t = setInterval(function () {
if (second === 0) {
clearInterval(t)
} else {
callback(--second)
}
}, 1000)
} else {
second = 0
}
})
}
/**

@ -12,16 +12,21 @@ import {checkAdmin, JSONResponse} from "./request";
import crumbs from 'crumbsjs';
import {token_cookie_key} from "./global";
export const registerPath = '/register'
export const loginPath = '/login'
const backend = '/backend'
export const registerPath = `${backend}/register`
export const loginPath = `${backend}/login`
export const configPath = `${backend}/config`
export const telegramPath = `${configPath}/telegram`
export const managerEmailPath = `${backend}/email`
export const managerPasswordPath = `${backend}/password`
const routes = [
{path: '/', redirect: '/config'},
{path: backend, redirect: configPath},
{path: registerPath, component: Register},
{path: '/config', component: Config},
{path: '/config/telegram', component: TelegramBot},
{path: '/email', component: Email},
{path: '/password', component: Password},
{path: configPath, component: Config},
{path: telegramPath, component: TelegramBot},
{path: managerEmailPath, component: Email},
{path: managerPasswordPath, component: Password},
{path: loginPath, component: Login}
]
@ -32,27 +37,33 @@ export const router = createRouter({
})
//路由导航守卫
router.beforeEach(async (to, from) => {
let res: JSONResponse = await checkAdmin().then(res => res.json())
if (![registerPath, loginPath].includes(to.fullPath)) {
if (res.body && crumbs.get(token_cookie_key)) {
return true
} else if (res.body) {
alert('请登录')
return loginPath
if (crumbs.get(token_cookie_key)) {
if ([registerPath, loginPath].includes(to.fullPath)) {
console.info('存在cookie,访问的路由是登录或注册,重定向到主页')
return '/'
} else {
alert('请进行应用初始化操作')
return registerPath
console.info('放通路由')
return true
}
} else if (to.fullPath === loginPath && crumbs.get(token_cookie_key)) {
return '/'
} else if (to.fullPath === loginPath && !res.body) {
return registerPath
} else if (to.fullPath === registerPath && res.body) {
return loginPath
} else {
return true
let res: JSONResponse = await checkAdmin().then(res => res.json())
if (res.body) {
if (to.fullPath === loginPath) {
console.info('放通路由')
return true
} else {
console.info('存在管理员,访问的不是登录路由,重定向到登录')
return loginPath
}
} else {
if (to.fullPath === registerPath) {
console.info('放通路由')
return true
} else {
console.info('不存在管理员,访问的不是注册路由,重定向到注册')
return registerPath
}
}
}
})

Loading…
Cancel
Save