新增移动端扫码登录

This commit is contained in:
不做码农 2023-08-26 15:53:37 +08:00
parent 92e032c948
commit e40da9d7cd
6 changed files with 121 additions and 14 deletions

View File

@ -52,4 +52,4 @@
"vite-plugin-svg-icons": "1.0.5", "vite-plugin-svg-icons": "1.0.5",
"vite-plugin-vue-setup-extend": "^0.4.0" "vite-plugin-vue-setup-extend": "^0.4.0"
} }
} }

View File

@ -53,4 +53,8 @@ watch(
immediate: true immediate: true
} }
) )
console.log('🎉源码地址: https://gitee.com/izory/ZrAdminNetCore')
console.log('📖官方文档http://www.izhaorui.cn/doc')
console.log('💰打赏作者http://www.izhaorui.cn/doc/support.html')
console.log('📱移动端体验http://www.izhaorui.cn/h5')
</script> </script>

View File

@ -1,12 +1,13 @@
import request from '@/utils/request' import request from '@/utils/request'
// 登录方法 // 登录方法
export function login(username, password, code, uuid) { export function login(username, password, code, uuid, clientId) {
const data = { const data = {
username, username,
password, password,
code, code,
uuid uuid,
clientId
} }
return request({ return request({
url: '/login', url: '/login',
@ -67,3 +68,29 @@ export function oauthCallback(data, params) {
params: params params: params
}) })
} }
/**
* 生成二维码
* @param {*} data
* @returns
*/
export function generateQrcode(data) {
return request({
url: '/GenerateQrcode',
method: 'GET',
params: data
})
}
/**
* 刷新二维码
* @param {*} data
* @returns
*/
export function verifyScan(data) {
return request({
url: '/VerifyScan',
method: 'post',
data: data
})
}

View File

@ -21,6 +21,7 @@
background: #ffffff; background: #ffffff;
// background-color: hsla(0, 0%, 100%, 0.3); // background-color: hsla(0, 0%, 100%, 0.3);
width: var(--base-login-width); width: var(--base-login-width);
height: 300px;
padding: 35px 15px 5px 15px; padding: 35px 15px 5px 15px;
position: relative; position: relative;
@ -109,4 +110,6 @@
flex-direction: column; flex-direction: column;
text-align: center; text-align: center;
align-items: center; align-items: center;
height: 200px;
justify-content: space-around;
} }

View File

@ -1,7 +1,7 @@
import { login, logout, getInfo, oauthCallback } from '@/api/system/login' import { login, logout, getInfo, oauthCallback } from '@/api/system/login'
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from '@/utils/auth'
import defAva from '@/assets/images/profile.jpg' import defAva from '@/assets/images/profile.jpg'
import cache from '@/plugins/cache'
import md5 from 'crypto-js/md5' import md5 from 'crypto-js/md5'
const useUserStore = defineStore('user', { const useUserStore = defineStore('user', {
@ -14,7 +14,8 @@ const useUserStore = defineStore('user', {
permissions: [], permissions: [],
userId: 0, userId: 0,
authSource: '', authSource: '',
userName: '' userName: '',
clientId: cache.local.get('clientId')
}), }),
actions: { actions: {
setAuthSource(source) { setAuthSource(source) {
@ -26,9 +27,10 @@ const useUserStore = defineStore('user', {
const password = md5(userInfo.password).toString() const password = md5(userInfo.password).toString()
const code = userInfo.code const code = userInfo.code
const uuid = userInfo.uuid const uuid = userInfo.uuid
const clientId = this.clientId
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
login(username, password, code, uuid) login(username, password, code, uuid, clientId)
.then((res) => { .then((res) => {
if (res.code == 200) { if (res.code == 200) {
setToken(res.data) setToken(res.data)
@ -72,6 +74,15 @@ const useUserStore = defineStore('user', {
}) })
}) })
}, },
// 扫码登录
scanLogin(data) {
return new Promise((resolve, reject) => {
setToken(data.token)
this.token = data.token
resolve(data.token) //then处理
})
},
// 获取用户信息 // 获取用户信息
getInfo() { getInfo() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -124,6 +135,10 @@ const useUserStore = defineStore('user', {
removeToken() removeToken()
resolve() resolve()
}) })
},
setClientId(clientId) {
this.clientId = clientId
cache.local.set('clientId', clientId)
} }
} }
}) })

View File

@ -84,7 +84,17 @@ import starBackground from '@/views/components/starBackground.vue'
import LangSelect from '@/components/LangSelect/index.vue' import LangSelect from '@/components/LangSelect/index.vue'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import QRCode from 'qrcodejs2-fixes' import QRCode from 'qrcodejs2-fixes'
import { verifyScan, generateQrcode } from '@/api/system/login'
var visitorId = ''
const fpPromise = import('https://openfpcdn.io/fingerprintjs/v3').then((FingerprintJS) => FingerprintJS.load())
// Get the visitor identifier when you need it.
fpPromise
.then((fp) => fp.get())
.then((result) => {
// This is the visitor identifier:
visitorId = result.visitorId
useUserStore().setClientId(visitorId)
})
const userStore = useUserStore() const userStore = useUserStore()
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
@ -179,6 +189,7 @@ function handleForgetPwd() {
proxy.$modal.msg('请联系管理员') proxy.$modal.msg('请联系管理员')
} }
const interval = ref(null)
const showQrLogin = ref(false) const showQrLogin = ref(false)
function handleShowQrLogin() { function handleShowQrLogin() {
showQrLogin.value = !showQrLogin.value showQrLogin.value = !showQrLogin.value
@ -187,18 +198,65 @@ function handleShowQrLogin() {
nextTick(() => { nextTick(() => {
generateCode() generateCode()
}) })
} else {
clearQr()
} }
} }
// //
function generateCode() { function generateCode() {
document.getElementById('imgContainer').innerHTML = '' clearQr()
new QRCode(document.getElementById('imgContainer'), { var uuid = getUuid()
text: 'https://qm.qq.com/cgi-bin/qm/qr?k=kgt4HsckdljU0VM-0kxND6d_igmfuPlL&authKey=r55YUbruiKQ5iwC/folG7KLCmZ++Y4rQVgNlvLbUniUMkbk24Y9+zNuOmOnjAjRc&noverify=0',
width: 200,
height: 200
})
}
document.getElementById('imgContainer').innerHTML = '正在生成中...'
generateQrcode({ uuid, deviceId: visitorId }).then((res) => {
const { code, data } = res
document.getElementById('imgContainer').innerHTML = ''
if (code == 200) {
new QRCode(document.getElementById('imgContainer'), {
// text: 'https://qm.qq.com/cgi-bin/qm/qr?k=kgt4HsckdljU0VM-0kxND6d_igmfuPlL&authKey=r55YUbruiKQ5iwC/folG7KLCmZ++Y4rQVgNlvLbUniUMkbk24Y9+zNuOmOnjAjRc&noverify=0',
text: JSON.stringify(data.codeContent),
width: 200,
height: 200
})
}
})
interval.value = setInterval(() => {
verifyScan({ uuid: uuid })
.then((res) => {
const { code, data } = res
if (data.status == -1) {
clearQr()
document.getElementById('imgContainer').innerHTML = '二维码已过期'
} else if (data.status == 2) {
userStore
.scanLogin(data)
.then(() => {
proxy.$modal.msgSuccess(proxy.$t('login.loginSuccess'))
router.push({ path: redirect.value || '/' })
})
.catch((error) => {
console.error(error)
proxy.$modal.msgError(error.msg)
})
clearQr()
}
})
.catch(() => {
clearQr()
})
}, 1000)
}
function clearQr() {
clearInterval(interval.value)
interval.value = null
}
function getUuid() {
var temp_url = URL.createObjectURL(new Blob())
var uuid = temp_url.toString().replace('-', '') // blob:https://xxx.com/b250d159-e1b6-4a87-9002-885d90033be3
URL.revokeObjectURL(temp_url)
return uuid.substr(uuid.lastIndexOf('/') + 1)
}
getCode() getCode()
getCookie() getCookie()
</script> </script>