vue3 钉钉扫码登录 最新解决方案

主要是使用方法和踩坑吧,坑踩的挺大,有vue3一起踩坑的可以相互讨论哈

注意看注释,很多注意点在注释和总结那里

往index.html 添加引入

<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>

其他代码

// api。js 可忽略
// 扫码登录
export function scanCode (params) {
    return request({
        url: '/auth',
        method: 'get',
        params
    })
}

login.vue 代码

算个示例吧:核心实现代码

//往登录页面放一个div id为login_container
<div style="" class="qrCode" id="login_container">
</div>


<script setup>
import {reactive, ref, onMounted, watch } from "vue"
import {useRouter, useRoute} from "vue-router"
import {useStore} from 'vuex'

import { scanCode } from '@/api/login'




let goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=appid&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=你的项目vue项目地址或者你发版后页面的地址记得在钉钉回调url一致否则无法登录')
let tmpAuthCode = window.location.search.split("&")[0].split("=")[1]
onMounted(() => {

    DDLogin({
        id: "login_container", //这里需要你在自己的页面定义一个HTML标签并设置id,例如<div id="login_container"></div>或<span id="login_container"></span>
        goto: goto, //请参考注释里的方式
        style: "border:none;background-color:#FFFFFF;",
        width: "270",
        height: "370"
    })

    let handleMessage = function (event) {
        let origin = event.origin
        console.log("origin", event.origin)
        if ( origin == "https://login.dingtalk.com" ) { //判断是否来自ddLogin扫码事件。
            let loginTmpCode = event.data 
            //获取到loginTmpCode后就可以在这里构造跳转链接进行跳转了
		   
            //将loginTmpCodeloginTmpCode拼接到url末尾用于跳转,不要open打开新的标签
            window.location.href = decodeURIComponent(goto + "&loginTmpCode=" + loginTmpCode)          
        }
    }
    if (typeof window.addEventListener != 'undefined') {
 
        if (tmpAuthCode){
            //参数要用这种方式,不要直接拼接url,后端拿不到,这个坑也踩过了
            store.dispatch('scanCodeLogin', {
                code: tmpAuthCode,
                state: 'auth'
            }).then(res => {
                console.log('成功', res)
                window.location.href = 'http://192.168.0.235:2021/' ;// 这个地址要跟redirect_uri的地址一样,不然你跳转后请求后获取的用户信息的丢在redirect_uri的地址了,你肯定拿不到了,记住这个地址要得是redirect_uri的地址,redirect_uri的地址一点得是你项目的地址,不然会有热更新刷新问题【每隔一段时间就会自动刷新页面问题】
            }, err => {
                console.log('失败', err)
            }) 
        }
        window.addEventListener('message', handleMessage, false)
    } else if (typeof window.attachEvent != 'undefined') {
        window.attachEvent('onmessage', handleMessage)
    }
})
</script>

钉钉端配置

redirect_uri的地址配置前端的vue启动的地址,红的的就是

在这里插入图片描述

问题总结

redirect_uri地址必须跟更vue启动的地址一致,也就是说必须 localhost+端口 :http://localhost:2021/、你本地的ip+端口:http://192.168.1.215:2021/;

redirect_uri 的地址必须通过encodeURIComponent进行处理哦

1、踩过使用后端穿透问题,有问题会出现302重定向的问题【就是登录后跳转redirect_uri,再去拿后端的接口不现实,因为redirect跳转是后端的地址前端控制不了】pass了;

2、前端使用钉钉穿透后,把穿透的地址给到后端放到钉钉的回调url里,这样确实是扫码登录后可以打开vue的项目,但是!!!一旦你将vue的穿透地址放到钉钉回调url【:也就是redirect_uri的地址】后有个非常非常严重的问题:【就是自动刷问题,一分钟页面自动刷新:罪魁祸首是 vite 的热更新功能,为什么跟热更新有关呢:因为vite热更新:真的这么智能:改下代码就刷新页面?不是的,是有轮训机制,定时去检测代码,检测的同时发现打开的域名【也就是穿透的地址】跟vue启动的域名不一致,vite始终匹配不上:就会触发window.location.reload()重新刷新,一直不匹配就一直不刷新】;

2的解决方法就是:localhost+端口 :http://localhost:2021/、你本地的ip+端口:http://192.168.1.215:2021/;localhost就没必要使用。配置ip就可以了

这种情况占用问题,昨天还好好的今天就穿透不了的问题:解决方法是【其实已经不用穿透了,在钉钉开发者平台上配置回调redirect_uri地址就是前端vue项目启东的地址就可以,然后前端就没必要穿透了】

//这种穿透的端口是vue项目启动后的端口
//将abcde的换掉就行:ding -config=ding.cfg -subdomain=start 9527   
cd windows_64
ding -config=ding.cfg -subdomain=abcde 8080   

问题效果:

****这一行错误
Version                       1.7/1.7
Forwarding                    127.0.0.1:4044
Forwarding                    127.0.0.1:4044
Web Interface                 127.0.0.1:4040
# Conn                        0
Avg Conn Time                 0.00ms

在这里插入图片描述

还有就是后端接口的:

http://zhangsan.vaiwan.com 这个接口地址是后端用花生壳穿透的,不要用ip

service.interceptors.request.use((config) => {
    if (store.getters.token){
        config.headers['Authentication'] = getCookie('token')
    } else {
        console.log(config)
        if (config.url.includes('/auth')){
            config.baseURL = 'http://zhangsan.vaiwan.com'
        }
        
    }
    console.log("拦截", config)
    return config
}, (error) => {
    return Promise.reject(error)
})

定位问题步骤总结

首先通过打包,确定开发环境是否有问题,还是只在运行项目的时候才有定时重载页面问题;定位到打包后不会刷新;

这个问题触及:vite 和更新源码了:vite 原理:HMR 和 Live Reload

更加vite 热更新原理,webSocket 来进行连接,重载主要在 handleHMRUpdate 负责代码的更新逻辑,当检测文件无法热更新的时候,只能全部加载也就是刷新了,但是这种的缺陷vite也没有做掐断机制以及报错。

在这里插入图片描述

在这里插入图片描述