邮箱发送验证码逻辑封装

master
pan 4 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. 55
      src/router.ts

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

@ -15,16 +15,7 @@
<span v-if="userEmail === newEmail">新邮箱不能和当前邮箱一致</span> <span v-if="userEmail === newEmail">新邮箱不能和当前邮箱一致</span>
</el-col> </el-col>
</el-row> </el-row>
<el-row type="flex" justify="center" class="mt-1"> <EmailCode :allowSendCode="allowSendCode"/>
<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>
<el-row type="flex" justify="center" class="mt-1"> <el-row type="flex" justify="center" class="mt-1">
<el-col :span="2"> <el-col :span="2">
<el-button type="primary" class="btn-block" :disabled="!checkCode" @click="changeEmail">更换邮箱</el-button> <el-button type="primary" class="btn-block" :disabled="!checkCode" @click="changeEmail">更换邮箱</el-button>
@ -37,18 +28,20 @@
</template> </template>
<script lang="ts"> <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 {updateRoute} from "../router";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
import {emailRegexp} from "../validate"; import {emailRegexp} from "../validate";
// @ts-ignore // @ts-ignore
import crumbs from 'crumbsjs'; import crumbs from 'crumbsjs';
import {email_cookie_key} from "../global"; import {email_cookie_key} from "../global";
import EmailCode from "./EmailCode.vue";
export default defineComponent({ export default defineComponent({
name: 'Email', name: 'Email',
components: {EmailCode},
setup(props) { setup(props) {
const newEmail = ref<string>('') const newEmail = ref<string>('')
const code = ref<string>('') const code = ref<string>('')
@ -59,41 +52,21 @@ export default defineComponent({
const userEmail = crumbs.get(email_cookie_key) 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( const changeEmail = () => _changeEmail(userEmail, newEmail.value, code.value).then(res => res.json()).then(
res => { res => {
message(res) message(res)
crumbs.set(email_cookie_key, newEmail.value)
if (res.result === 'OK') { if (res.result === 'OK') {
router.replace('/config') 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)) const checkCode = computed<boolean>(() => /^\d{6}$/.test(code.value))
@ -101,12 +74,9 @@ export default defineComponent({
return { return {
newEmail, newEmail,
code,
allowSendCode, allowSendCode,
sendCodeTip,
checkCode, checkCode,
second, second,
sendCode,
userEmail, userEmail,
changeEmail 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> <template>
<el-row justify="center" type="flex"> <User/>
<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>
<el-row type="flex" justify="center" class="mt-1"> <el-row type="flex" justify="center" class="mt-1">
<el-col :span="8"> <el-col :span="8">
<span>密码必须包含数字字母6-10</span> <span>密码必须包含数字字母6-10</span>
@ -24,29 +13,34 @@
</el-row> </el-row>
<el-row type="flex" justify="center" class="mt-1"> <el-row type="flex" justify="center" class="mt-1">
<el-col :span="8"> <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-button>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<script lang="ts"> <script lang="ts">
import {computed, defineComponent, ref} from "vue"; import {computed, defineComponent, provide, Ref, ref} from "vue";
import {emailRegexp, passwordRegexp} from "../validate"; import {emailRegexp, passwordRegexp} from "../validate";
import {JSONResponse, login, message} from "../request"; import {JSONResponse, login, message} from "../request";
//@ts-ignore //@ts-ignore
import crumbs from 'crumbsjs'; import crumbs from 'crumbsjs';
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
import {email_cookie_key, token_cookie_key} from "../global"; import {email_cookie_key, token_cookie_key} from "../global";
import User from "./User.vue";
import {configPath} from "../router";
export default defineComponent({ export default defineComponent({
name: "Login", name: "Login",
components: {User},
setup() { setup() {
const user = ref<string>('') const user = ref<string>('')
const password = ref<string>('') const password = ref<string>('')
const checkUser = computed<boolean>(() => emailRegexp.test(user.value)) const checkUser = computed<boolean>(() => emailRegexp.test(user.value))
provide<Ref<string>>('user', user)
const checkPwd = computed<boolean>(() => passwordRegexp.test(password.value)) const checkPwd = computed<boolean>(() => passwordRegexp.test(password.value))
const router = useRouter() const router = useRouter()
@ -58,12 +52,12 @@ export default defineComponent({
if (res.result === 'OK') { if (res.result === 'OK') {
crumbs.set(token_cookie_key, res.body.token) crumbs.set(token_cookie_key, res.body.token)
crumbs.set(email_cookie_key, res.body.userEmail) 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> </script>

@ -23,11 +23,14 @@
<el-input v-model="userEmail"> <el-input v-model="userEmail">
<template v-slot:prepend>管理员邮箱</template> <template v-slot:prepend>管理员邮箱</template>
</el-input> </el-input>
<span v-if="user===''">邮箱不能为空</span>
<span v-else-if="!checkUser">邮箱不合法</span>
</el-col> </el-col>
</el-row> </el-row>
<EmailCode/>
<el-row type="flex" justify="center" class="mt-1"> <el-row type="flex" justify="center" class="mt-1">
<el-col :span="8"> <el-col :span="2">
<el-input v-model="code" placeholder="请输入验证码"/> <el-button type="primary" class="btn-block">注册</el-button>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@ -35,9 +38,11 @@
<script lang="ts"> <script lang="ts">
import {defineComponent, ref} from "vue"; import {defineComponent, ref} from "vue";
import EmailCode from "./EmailCode.vue";
export default defineComponent({ export default defineComponent({
name: "Register", name: "Register",
components: {EmailCode},
setup() { setup() {
const step = ref<number>(1) const step = ref<number>(1)
const userEmail = ref<string>('') 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 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})})) 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 crumbs from 'crumbsjs';
import {token_cookie_key} from "./global"; import {token_cookie_key} from "./global";
export const registerPath = '/register' const backend = '/backend'
export const loginPath = '/login' 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 = [ const routes = [
{path: '/', redirect: '/config'}, {path: backend, redirect: configPath},
{path: registerPath, component: Register}, {path: registerPath, component: Register},
{path: '/config', component: Config}, {path: configPath, component: Config},
{path: '/config/telegram', component: TelegramBot}, {path: telegramPath, component: TelegramBot},
{path: '/email', component: Email}, {path: managerEmailPath, component: Email},
{path: '/password', component: Password}, {path: managerPasswordPath, component: Password},
{path: loginPath, component: Login} {path: loginPath, component: Login}
] ]
@ -32,27 +37,33 @@ export const router = createRouter({
}) })
//路由导航守卫 //路由导航守卫
router.beforeEach(async (to, from) => { router.beforeEach(async (to, from) => {
if (crumbs.get(token_cookie_key)) {
if ([registerPath, loginPath].includes(to.fullPath)) {
console.info('存在cookie,访问的路由是登录或注册,重定向到主页')
return '/'
} else {
console.info('放通路由')
return true
}
} else {
let res: JSONResponse = await checkAdmin().then(res => res.json()) let res: JSONResponse = await checkAdmin().then(res => res.json())
if (res.body) {
if (to.fullPath === loginPath) {
if (![registerPath, loginPath].includes(to.fullPath)) { console.info('放通路由')
if (res.body && crumbs.get(token_cookie_key)) {
return true return true
} else if (res.body) {
alert('请登录')
return loginPath
} else { } else {
alert('请进行应用初始化操作') console.info('存在管理员,访问的不是登录路由,重定向到登录')
return registerPath
}
} 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 return loginPath
}
} else { } else {
if (to.fullPath === registerPath) {
console.info('放通路由')
return true return true
} else {
console.info('不存在管理员,访问的不是注册路由,重定向到注册')
return registerPath
}
}
} }
}) })

Loading…
Cancel
Save