|
@@ -28,10 +28,10 @@
|
|
|
</div>
|
|
|
<!-- 个人登录 -->
|
|
|
<div v-show="!isEnterpriseLogin" class="login-tab">
|
|
|
- <v-tabs v-model="tab" align-tabs="center" color="primary" class="mb-10" @update:modelValue="tabChange">
|
|
|
+ <v-tabs v-model="tab" align-tabs="center" color="primary" :class="`mb-${tab === 3 ? 6 : 9}`" @update:modelValue="tabChange">
|
|
|
<v-tab :value="2">账号</v-tab>
|
|
|
<v-tab :value="1">验证码</v-tab>
|
|
|
- <!-- <v-tab :value="3">微信</v-tab> -->
|
|
|
+ <v-tab :value="3">微信扫码</v-tab>
|
|
|
</v-tabs>
|
|
|
<v-window v-model="tab">
|
|
|
<!-- 验证码登录 -->
|
|
@@ -42,25 +42,33 @@
|
|
|
<v-window-item :value="2">
|
|
|
<passwordFrom ref="passRef" @handleEnter="handleLogin"></passwordFrom>
|
|
|
</v-window-item>
|
|
|
- <!-- <v-window-item :value="3">
|
|
|
- <div v-if="showQrCode" class="d-flex align-center flex-column">
|
|
|
- <span class="text-decoration-underline">微信扫描二维码进行登录</span>
|
|
|
- <v-img src="https://minio.citupro.com/dev/menduner/login-qrCode.png" width="150" height="150"></v-img>
|
|
|
+ <v-window-item :value="3">
|
|
|
+ <div v-if="showQrCode" class="d-flex align-center flex-column position-relative">
|
|
|
+ <v-img :src="qrCodeUrl" width="200" height="200"></v-img>
|
|
|
+ <span class="color-666 font-size-13 mt-3">请使用微信扫描二维码登录“门墩儿”</span>
|
|
|
+ <span v-if="remainderZhShow" class="color-warning font-size-13 mt-1">请在{{ remainderZhShow }}内扫码授权登录</span>
|
|
|
+
|
|
|
+ <div v-if="qrCodeDisabled" class="disabledBox">
|
|
|
+ <div class="disabledContent">
|
|
|
+ <div class="color-666">请重新刷新二维码</div>
|
|
|
+ <v-btn color="primary" class="mt-5" elevation="0" @click="disabledClick">点击刷新</v-btn>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div v-else style="height: 150px; line-height: 150px; text-align: center;">
|
|
|
加载中 . . .
|
|
|
</div>
|
|
|
- </v-window-item> -->
|
|
|
+ </v-window-item>
|
|
|
</v-window>
|
|
|
</div>
|
|
|
<div class="font-size-14">
|
|
|
- <span class="float-left tips color-666 cursor-pointer" v-if="tab === 2" @click="router.push(isEnterpriseLogin ? '/forgotPasswordEnt': '/forgotPassword')">忘记密码</span>
|
|
|
- <span class="float-right color-error cursor-pointer border-bottom-error" @click="router.push('/register/selected')">还没有登录账户?去注册</span>
|
|
|
+ <span v-if="tab === 2" class="float-left tips color-666 cursor-pointer" @click="router.push(isEnterpriseLogin ? '/forgotPasswordEnt': '/forgotPassword')">忘记密码</span>
|
|
|
+ <span v-if="tab !== 3" class="float-right color-error cursor-pointer border-bottom-error" @click="router.push('/register/selected')">还没有登录账户?去注册</span>
|
|
|
</div>
|
|
|
- <v-btn :loading="loginLoading" color="primary" class="white--text mt-5" min-width="350" @click.stop="handleLogin">
|
|
|
+ <v-btn v-if="tab !== 3" :loading="loginLoading" color="primary" class="white--text mt-5" min-width="350" @click.stop="handleLogin">
|
|
|
{{ $t('login.login') }}
|
|
|
</v-btn>
|
|
|
- <div class="login-tips mt-3">
|
|
|
+ <div class="login-tips mt-3" v-if="tab !== 3">
|
|
|
<v-icon v-if="isAgree" size="25" color="primary" class="mr-1" @click="isAgree = !isAgree">mdi-check-circle</v-icon>
|
|
|
<v-icon v-else size="25" color="grey" class="mr-1" @click="isAgree = !isAgree">mdi-circle-outline</v-icon>
|
|
|
{{ $t('login.agreeLogin') }}
|
|
@@ -104,6 +112,8 @@ import about from '@/views/about/index.vue'
|
|
|
import { useRoute } from 'vue-router'; const route = useRoute()
|
|
|
import Verify from '@/components/Verifition'
|
|
|
import { useMallStore } from '@/store/mall'
|
|
|
+import { generateUUID } from '@/utils/index'
|
|
|
+import { getWeXinLoginQrCode, checkWeXinLoginAuthorize } from '@/api/common/qrcodeLogin'
|
|
|
|
|
|
const isMobile = ref(false)
|
|
|
onMounted(async () => {
|
|
@@ -116,6 +126,7 @@ onMounted(async () => {
|
|
|
const logoBgUrl = ref('')
|
|
|
const preferred = ref({})
|
|
|
const carouselList = ref([])
|
|
|
+
|
|
|
const getSystemWebContent = async () => {
|
|
|
const data = await getWebContent()
|
|
|
logoBgUrl.value = data.pcLoginBackground && data.pcLoginBackground.length ? data.pcLoginBackground[0].img : 'https://minio.menduner.com/dev/menduner/login-bgc.jpg'
|
|
@@ -223,21 +234,104 @@ const handleLogin = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 微信扫码-小程序授权登录
|
|
|
+const qrCodeUrl = ref(null)
|
|
|
+const showQrCode = ref(true)
|
|
|
+const qrCodeDisabled = ref(true )
|
|
|
+const query = ref({
|
|
|
+ clientId: null
|
|
|
+})
|
|
|
+
|
|
|
+const remainder = ref(0)
|
|
|
+const remainderZhShow = ref('')
|
|
|
+const remainderTimer = ref(null)
|
|
|
+const abortController = ref(null)
|
|
|
+const formatDuration = (time) => {
|
|
|
+ var seconds = Math.floor(time / 1000)
|
|
|
+ var minutes = Math.floor(seconds / 60)
|
|
|
+ var remainingSeconds = seconds % 60
|
|
|
+ minutes = minutes.toString().padStart(2, '0')
|
|
|
+ remainingSeconds = remainingSeconds.toString().padStart(2, '0')
|
|
|
+ return `${minutes}分${remainingSeconds}秒`
|
|
|
+}
|
|
|
+const remainderCalc = () => {
|
|
|
+ remainder.value -= 1000
|
|
|
+ remainderZhShow.value = formatDuration(remainder.value)
|
|
|
+ if (remainder.value <= 0) {
|
|
|
+ qrCodeDisabled.value = true
|
|
|
+ // 取消所有正在进行的请求
|
|
|
+ if (abortController.value) {
|
|
|
+ abortController.value.abort()
|
|
|
+ abortController.value = null
|
|
|
+ }
|
|
|
+ handleAuthorize(true)
|
|
|
+ }
|
|
|
+}
|
|
|
+// 初始化倒计时
|
|
|
+const countdownTime = 60000 * 5 // 倒计时五分钟
|
|
|
+const initIntervalFun = () => {
|
|
|
+ remainder.value = countdownTime // 初始倒计时时间
|
|
|
+ if (remainderTimer.value) clearInterval(remainderTimer.value); remainderTimer.value = null // 每一次点击都清除上一个轮询
|
|
|
+ // 倒计时计算
|
|
|
+ remainderCalc()
|
|
|
+ remainderTimer.value = setInterval(() => { remainderCalc() }, 1000)
|
|
|
+}
|
|
|
+
|
|
|
+// 轮巡查询是否授权成功
|
|
|
+const handleAuthorize = async (stop) => {
|
|
|
+ // 二维码失效停止请求
|
|
|
+ if (stop) return
|
|
|
+ try {
|
|
|
+ abortController.value = new AbortController()
|
|
|
+ const signal = abortController.value.signal
|
|
|
+ const data = await checkWeXinLoginAuthorize(query.value, signal)
|
|
|
+ if (!data) return
|
|
|
+ query.value.clientId = data.clientId
|
|
|
+
|
|
|
+ // 等待扫码授权中
|
|
|
+ if (data.status === '0' || !data.appMdeAuthLoginRespVO || !Object.keys(data.appMdeAuthLoginRespVO).length) {
|
|
|
+ handleAuthorize()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 授权成功,返回登录信息
|
|
|
+ await userStore.handleWeXinQrCodeLogin(data.appMdeAuthLoginRespVO)
|
|
|
+ router.push('/')
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error, 'error')
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序二维码获取
|
|
|
+const getSocialAuthRedirect = async () => {
|
|
|
+ showQrCode.value = false
|
|
|
+ try {
|
|
|
+ const data = await getWeXinLoginQrCode(query.value)
|
|
|
+ qrCodeUrl.value = URL.createObjectURL(data)
|
|
|
+ qrCodeDisabled.value = false
|
|
|
+ showQrCode.value = true
|
|
|
+ initIntervalFun()
|
|
|
+ handleAuthorize()
|
|
|
+ } catch {
|
|
|
+ showQrCode.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-// const getSocialAuthRedirect = async () => {
|
|
|
-// const params = {
|
|
|
-// type: '34',
|
|
|
-// redirectUri: 'https://www.baidu.com'
|
|
|
-// }
|
|
|
-// const res = await socialAuthRedirect(params)
|
|
|
-// const otherUrl = res?.url
|
|
|
-// if (otherUrl) window.open(otherUrl)
|
|
|
-// }
|
|
|
+// 二维码过期重新生成
|
|
|
+const disabledClick = () => {
|
|
|
+ qrCodeDisabled.value = false
|
|
|
+ query.value.clientId = generateUUID()
|
|
|
+ getSocialAuthRedirect()
|
|
|
+}
|
|
|
|
|
|
-// const showQrCode = ref(false)
|
|
|
const tabChange = (val) => {
|
|
|
if (val === 3) {
|
|
|
- // getSocialAuthRedirect()
|
|
|
+ if (abortController.value) {
|
|
|
+ abortController.value.abort()
|
|
|
+ abortController.value = null
|
|
|
+ }
|
|
|
+ query.value.clientId = generateUUID()
|
|
|
+ getSocialAuthRedirect()
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -257,10 +351,25 @@ const verifySuccess = (params) => {
|
|
|
const windowOpen = (url) => {
|
|
|
if (url) window.open(url)
|
|
|
}
|
|
|
-
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
+.disabledBox {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ background: rgb(255 255 255 / 90%);
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.disabledContent {
|
|
|
+ height: 90%;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
.box {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
@@ -305,6 +414,7 @@ const windowOpen = (url) => {
|
|
|
background-color: #fff;
|
|
|
border-radius: 8px;
|
|
|
padding: 36px 50px;
|
|
|
+ height: 392px;
|
|
|
}
|
|
|
.left {
|
|
|
display: flex;
|