feat: 添加手机验证码、邮箱验证码登录
This commit is contained in:
parent
c0f4b7db9b
commit
428be99b77
8
package-lock.json
generated
8
package-lock.json
generated
@ -19,6 +19,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"sass": "^1.87.0",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-vue-devtools": "^7.7.6",
|
||||
@ -2420,6 +2421,13 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/crypto-js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
|
||||
|
@ -20,6 +20,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"sass": "^1.87.0",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-vue-devtools": "^7.7.6",
|
||||
|
41
src/api/user.js
Normal file
41
src/api/user.js
Normal file
@ -0,0 +1,41 @@
|
||||
import service from '@/service'
|
||||
|
||||
export const login = (data) => {
|
||||
return service({
|
||||
method: 'post',
|
||||
url: '/store/login',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const verifyToken = () => {
|
||||
return service({
|
||||
method: 'post',
|
||||
url: '/store/verifyToken',
|
||||
data: {}
|
||||
})
|
||||
}
|
||||
|
||||
export const getSMSCode = (mobile) => {
|
||||
return service({
|
||||
method: 'get',
|
||||
url: '/store/getSMSCode?mobile=' + mobile,
|
||||
data: {}
|
||||
})
|
||||
}
|
||||
|
||||
export const verifyEmail = (email,code) => {
|
||||
return service({
|
||||
method: 'get',
|
||||
url: `/accessory/checkMailVerifyCode?$email=${email}&$code=${code}`,
|
||||
data: {}
|
||||
})
|
||||
}
|
||||
|
||||
export const getEmailCode = (email) => {
|
||||
return service({
|
||||
method: 'get',
|
||||
url: '/accessory/mailVerifyCode?email=' + email,
|
||||
data: {}
|
||||
})
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
import { createRouter,createWebHashHistory } from 'vue-router'
|
||||
import { getToken } from '@/utils'
|
||||
import { verifyToken } from '@/api/user'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
@ -20,13 +22,13 @@ const router = createRouter({
|
||||
routes
|
||||
})
|
||||
|
||||
// router.beforeEach((to, from, next) => {
|
||||
// const isLogin = getToken() ? true : false;
|
||||
// if (to.path == '/login' || to.path == "/register") {
|
||||
// next()
|
||||
// } else {
|
||||
// isLogin ? next() : next('/')
|
||||
// }
|
||||
// })
|
||||
router.beforeEach((to, from, next) => {
|
||||
const isLogin = getToken() ? true : false;
|
||||
if (to.path == '/login' || to.path == "/register") {
|
||||
next()
|
||||
} else {
|
||||
isLogin ? next() : next('/')
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
43
src/service/index.js
Normal file
43
src/service/index.js
Normal file
@ -0,0 +1,43 @@
|
||||
import axios from 'axios'
|
||||
import { getToken,removeToken } from '@/utils'
|
||||
import router from '@/router'
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: '/api',
|
||||
timeout: 40000,
|
||||
})
|
||||
|
||||
service.interceptors.request.use((config) => {
|
||||
config.headers['Jifu-Token'] = getToken()
|
||||
return config
|
||||
},(error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
service.interceptors.response.use((response) => {
|
||||
if(response.data.error == 1001) {
|
||||
removeToken()
|
||||
router.push('/login')
|
||||
}
|
||||
return response
|
||||
},(error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
export const get = (url, params) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
service.get(url, {params})
|
||||
.then(res => resolve(res))
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
export const post = (url, param) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
service.post(url, param)
|
||||
.then(res => resolve(res))
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
export default service
|
19
src/store/index.js
Normal file
19
src/store/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useUserStore = defineStore('user-info',{
|
||||
state: () => {
|
||||
return {
|
||||
userInfo: {}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setInfo(userinfo) {
|
||||
this.userInfo = userinfo
|
||||
},
|
||||
clearInfo() {
|
||||
this.userInfo = {}
|
||||
}
|
||||
},
|
||||
getters: {},
|
||||
persist: true
|
||||
})
|
17
src/utils/index.js
Normal file
17
src/utils/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
export const TOKEN_NAME = 'token'
|
||||
export const getToken = () => localStorage.getItem(TOKEN_NAME)
|
||||
export const setToken = (token) => localStorage.setItem(TOKEN_NAME,token)
|
||||
export const removeToken = () => localStorage.removeItem(TOKEN_NAME)
|
||||
export const stripos = (fHaystack,fNeedle,fOffset=0) => {
|
||||
const haystack = (fHaystack + '').toLowerCase()
|
||||
const needle = (fNeedle + '').toLowerCase()
|
||||
let index = 0
|
||||
if ((index = haystack.indexOf(needle, fOffset)) !== -1) {
|
||||
return index
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const md5 = str => CryptoJS.MD5(str).toString()
|
@ -1,11 +1,27 @@
|
||||
<template>
|
||||
<div>
|
||||
首页
|
||||
<div>
|
||||
<span>欢迎您,</span>
|
||||
<span>{{ userInfo.name }}</span>
|
||||
</div>
|
||||
<el-button @click="logout">退出登录</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/store'
|
||||
import { removeToken } from '@/utils'
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const userInfo = userStore.userInfo
|
||||
|
||||
const logout = () => {
|
||||
userStore.$reset()
|
||||
removeToken()
|
||||
router.push('/login')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -64,18 +64,20 @@
|
||||
class="w-160px"
|
||||
size="large"
|
||||
placeholder="手机号"
|
||||
:readonly="sms_input"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Iphone /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-button
|
||||
:disabled="sms_btn"
|
||||
type="primary"
|
||||
size="large"
|
||||
class="w-75px ml-4px"
|
||||
@click="get_code"
|
||||
>
|
||||
发验证码
|
||||
{{ sms_btn_msg }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-input
|
||||
@ -114,6 +116,7 @@
|
||||
class="w-160px"
|
||||
size="large"
|
||||
placeholder="邮箱号"
|
||||
:readonly="mail_input"
|
||||
>
|
||||
<template #prefix>
|
||||
<i class="fa fa-envelope"></i>
|
||||
@ -123,9 +126,10 @@
|
||||
type="primary"
|
||||
size="large"
|
||||
class="w-75px ml-4px"
|
||||
@click="get_code"
|
||||
:disabled="mail_btn"
|
||||
@click="get_mail_code"
|
||||
>
|
||||
发验证码
|
||||
{{ mail_btn_msg }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-input
|
||||
@ -182,21 +186,20 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref,onMounted } from 'vue'
|
||||
import wxlogin from 'vue-next-wxlogin'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getToken, setToken, removeToken } from '@/utils'
|
||||
import { login, verifyToken,getSMSCode,getEmailCode,verifyEmail } from '@/api/user'
|
||||
import { useUserStore } from '@/store'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const router = useRouter()
|
||||
const user_store = useUserStore()
|
||||
|
||||
const activeName = ref('first')
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const mobile = ref('')
|
||||
const code = ref('')
|
||||
const email = ref('')
|
||||
const ecode = ref('')
|
||||
|
||||
const appId = ref('wxa0a92798871387ba')
|
||||
// wxd18da60b377a9b40
|
||||
// wxa0a92798871387ba
|
||||
const impower_style = `
|
||||
.impowerBox qrcode {width: 200px;margin-top:10px;border: 0;}
|
||||
.impowerBox .title {display: none;}
|
||||
@ -210,26 +213,145 @@
|
||||
const redirect_uri = encodeURIComponent("https://api.jifuyun.cn/")
|
||||
const state = ref(`${parseInt(new Date().getTime() / 1000)}`)
|
||||
|
||||
onMounted(async () => {
|
||||
const token = getToken()
|
||||
if(token) {
|
||||
const { data: res } = await verifyToken()
|
||||
if(res.error == 0) {
|
||||
user_store.setInfo(res.data.user)
|
||||
router.push('/home')
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
user_store.clearInfo()
|
||||
removeToken()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const handleClick = (tab, event) => {
|
||||
console.log(tab, event)
|
||||
}
|
||||
const user_login = () => {
|
||||
console.log(username.value, password.value)
|
||||
}
|
||||
const mobile_login = () => {
|
||||
console.log(mobile.value, code.value)
|
||||
}
|
||||
const email_login = () => {
|
||||
console.log(mobile.value, code.value)
|
||||
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const user_login = async () => {
|
||||
if(username.value == '' || password.value == '') {
|
||||
ElMessage.error('用户名、密码不能为空!')
|
||||
return
|
||||
}
|
||||
const {data: res} = await login({username: username.value, password: password.value})
|
||||
if(res.error == 0) {
|
||||
setToken(res.data.token)
|
||||
user_store.userInfo = res.data.user
|
||||
ElMessage.success('登录成功')
|
||||
router.push('/home')
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
}
|
||||
}
|
||||
|
||||
const get_code = () => {
|
||||
console.log('获取验证码')
|
||||
const mobile = ref('')
|
||||
const code = ref('')
|
||||
const sms_input = ref(false)
|
||||
const sms_btn = ref(false)
|
||||
const sms_btn_msg = ref('发验证码')
|
||||
const mobile_login = async () => {
|
||||
if(mobile.value == '' || code.value == '') {
|
||||
ElMessage.error('手机号和验证码不能为空!')
|
||||
return
|
||||
}
|
||||
const {data: res} = await login({mobile: mobile.value, code: code.value,type: 'mobile'})
|
||||
if(res.error == 0) {
|
||||
setToken(res.data.token)
|
||||
user_store.userInfo = res.data.user
|
||||
ElMessage.success('登录成功')
|
||||
router.push('/home')
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
}
|
||||
}
|
||||
|
||||
const handleWechatLoginSuccess = (data) => {
|
||||
console.log('微信登录成功:', data)
|
||||
router.push('/home')
|
||||
const get_code = async () => {
|
||||
const REG_MOBILE = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
|
||||
if(!REG_MOBILE.test(mobile.value)) {
|
||||
ElMessage.error('无效的手机号!')
|
||||
return
|
||||
}
|
||||
const {data: res} = await getSMSCode(mobile.value)
|
||||
console.log(res)
|
||||
if(res.error == 0) {
|
||||
sms_btn.value = true
|
||||
sms_input.value = true
|
||||
let counter = 300
|
||||
const td = setInterval(() => {
|
||||
sms_btn_msg.value = `${counter}秒重发`
|
||||
counter--
|
||||
if (counter <= 0) {
|
||||
sms_btn.value = false
|
||||
sms_input.value = false
|
||||
sms_btn_msg.value = '发验证码'
|
||||
clearInterval(td)
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
sms_btn.value = false
|
||||
sms_input.value = false
|
||||
sms_btn_msg.value = '发验证码'
|
||||
clearInterval(td)
|
||||
}
|
||||
}
|
||||
|
||||
const email = ref('')
|
||||
const ecode = ref('')
|
||||
const mail_input = ref(false)
|
||||
const mail_btn = ref(false)
|
||||
const mail_btn_msg = ref('发验证码')
|
||||
const email_login = async () => {
|
||||
if(email.value == '' || ecode.value == '') {
|
||||
ElMessage.error('邮箱号和验证码不能为空!')
|
||||
return
|
||||
}
|
||||
const {data: res} = await login({email: email.value, code: ecode.value,type: 'email'})
|
||||
if(res.error == 0) {
|
||||
setToken(res.data.token)
|
||||
user_store.userInfo = res.data.user
|
||||
ElMessage.success('登录成功')
|
||||
router.push('/home')
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
}
|
||||
}
|
||||
|
||||
const get_mail_code = async () => {
|
||||
const REG_MAIL = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
|
||||
if(!REG_MAIL.test(email.value)) {
|
||||
ElMessage.error('无效的邮箱号!')
|
||||
return
|
||||
}
|
||||
const {data: res} = await getEmailCode(email.value)
|
||||
console.log(res)
|
||||
if(res.error == 0) {
|
||||
mail_btn.value = true
|
||||
mail_input.value = true
|
||||
let counter = 300
|
||||
const td = setInterval(() => {
|
||||
mail_btn_msg.value = `${counter}秒重发`
|
||||
counter--
|
||||
if (counter <= 0) {
|
||||
mail_btn.value = false
|
||||
mail_input.value = false
|
||||
mail_btn_msg.value = '发验证码'
|
||||
clearInterval(td)
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
ElMessage.error(res.msg)
|
||||
mail_btn.value = false
|
||||
mail_input.value = false
|
||||
mail_btn_msg.value = '发验证码'
|
||||
clearInterval(td)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user