diff --git a/package.json b/package.json index 59d428e..14e8bff 100644 --- a/package.json +++ b/package.json @@ -52,4 +52,4 @@ "vite-plugin-svg-icons": "1.0.5", "vite-plugin-vue-setup-extend": "^0.4.0" } -} +} \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 841f7d2..5609df6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -53,4 +53,8 @@ watch( 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') diff --git a/src/api/system/login.js b/src/api/system/login.js index 303333a..dd83927 100644 --- a/src/api/system/login.js +++ b/src/api/system/login.js @@ -1,12 +1,13 @@ import request from '@/utils/request' // 登录方法 -export function login(username, password, code, uuid) { +export function login(username, password, code, uuid, clientId) { const data = { username, password, code, - uuid + uuid, + clientId } return request({ url: '/login', @@ -67,3 +68,29 @@ export function oauthCallback(data, 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 + }) +} diff --git a/src/assets/styles/login.scss b/src/assets/styles/login.scss index e00fc01..2e075d6 100644 --- a/src/assets/styles/login.scss +++ b/src/assets/styles/login.scss @@ -21,6 +21,7 @@ background: #ffffff; // background-color: hsla(0, 0%, 100%, 0.3); width: var(--base-login-width); + height: 300px; padding: 35px 15px 5px 15px; position: relative; @@ -109,4 +110,6 @@ flex-direction: column; text-align: center; align-items: center; + height: 200px; + justify-content: space-around; } diff --git a/src/store/modules/user.js b/src/store/modules/user.js index b215ff6..90ae764 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,7 +1,7 @@ import { login, logout, getInfo, oauthCallback } from '@/api/system/login' import { getToken, setToken, removeToken } from '@/utils/auth' import defAva from '@/assets/images/profile.jpg' - +import cache from '@/plugins/cache' import md5 from 'crypto-js/md5' const useUserStore = defineStore('user', { @@ -14,7 +14,8 @@ const useUserStore = defineStore('user', { permissions: [], userId: 0, authSource: '', - userName: '' + userName: '', + clientId: cache.local.get('clientId') }), actions: { setAuthSource(source) { @@ -26,9 +27,10 @@ const useUserStore = defineStore('user', { const password = md5(userInfo.password).toString() const code = userInfo.code const uuid = userInfo.uuid + const clientId = this.clientId return new Promise((resolve, reject) => { - login(username, password, code, uuid) + login(username, password, code, uuid, clientId) .then((res) => { if (res.code == 200) { 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() { return new Promise((resolve, reject) => { @@ -124,6 +135,10 @@ const useUserStore = defineStore('user', { removeToken() resolve() }) + }, + setClientId(clientId) { + this.clientId = clientId + cache.local.set('clientId', clientId) } } }) diff --git a/src/views/login.vue b/src/views/login.vue index d0301c6..05ef81d 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -84,7 +84,17 @@ import starBackground from '@/views/components/starBackground.vue' import LangSelect from '@/components/LangSelect/index.vue' import useUserStore from '@/store/modules/user' 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 router = useRouter() const route = useRoute() @@ -179,6 +189,7 @@ function handleForgetPwd() { proxy.$modal.msg('请联系管理员') } +const interval = ref(null) const showQrLogin = ref(false) function handleShowQrLogin() { showQrLogin.value = !showQrLogin.value @@ -187,18 +198,65 @@ function handleShowQrLogin() { nextTick(() => { generateCode() }) + } else { + clearQr() } } // 生成二维码 function generateCode() { - document.getElementById('imgContainer').innerHTML = '' - 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', - width: 200, - height: 200 - }) -} + clearQr() + var uuid = getUuid() + 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() getCookie()