login-modal.vue 2.06 KB
<script lang="ts" setup>
import {Base64} from "js-base64";
import {v4 as uuid4} from "uuid";
import {useEventSource, useLocalStorage} from "@vueuse/core";
import {computed, ref, StyleValue, watch} from 'vue'
import {set} from 'lodash-es'

import vueQr from "vue-qr/src/packages/vue-qr.vue"

defineProps<{ logo?: string }>()

const visible = useLocalStorage('token', '', {})

const bodyStyle: StyleValue = {textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center'}

const loginCode = ref<string>('')
const loginEvent = ref<any>()
const loginEncryptCode = computed((): string =>
    Base64.encode(JSON.stringify({type: 'loginCode', data: loginCode.value})))


const onRefresh = () => {
    loginEvent.value?.close()

    loginCode.value = uuid4();

    loginEvent.value = useEventSource('/app/subscribeLogin?code=' + loginCode.value, ['message'])

    set(loginEvent.value, 'eventSource.onmessage', (event: any) => {
        if (event.data) {
            visible.value = event.data
            localStorage.setItem('token', event.data)
            loginEvent.value?.close();
        }
    })
}

watch(visible, (value) => !value && onRefresh(), {immediate: true})
</script>

<template>
    <a-modal :visible="!visible" hide-title
             :footer="false" :esc-to-close="false" :closable="false" :mask-closable="false"
             :body-style="bodyStyle" @before-open="onRefresh"
    >
        <div style="color: #666666;font-size: 15px;font-weight: 600">用户授权</div>
        <div style="color: #666666;font-size: 14px;padding: 10px">
            请通过【泡泡留声】App或者小程序,扫描页右上角扫码
            <icon-scan/>
            授权
        </div>
        <vue-qr :size="180" :margin="5" :correct-level="3" :text="loginCode?loginEncryptCode:''"
                :logo-margin="3" :logo-scale="0.2" :logoSrc="logo"
        />
        <icon-refresh class="refresh" :size="18" @click="onRefresh"/>
    </a-modal>
</template>

<style scoped>
.refresh {
    color: #666666;
    margin-top: 4px;

    &:hover {
        cursor: pointer;
    }
}
</style>