dd-login.js源码
! function(e) {
var t = {};
function r(n) {
if (t[n]) return t[n].exports;
var o = t[n] = {
i: n,
l: !1,
exports: {}
};
return e[n].call(o.exports, o, o.exports, r), o.l = !0, o.exports
}
r.m = e, r.c = t, r.d = function(e, t, n) {
r.o(e, t) || Object.defineProperty(e, t, {
enumerable: !0,
get: n
})
}, r.r = function(e) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
value: "Module"
}), Object.defineProperty(e, "__esModule", {
value: !0
})
}, r.t = function(e, t) {
if (1 & t && (e = r(e)), 8 & t) return e;
if (4 & t && "object" == typeof e && e && e.__esModule) return e;
var n = Object.create(null);
if (r.r(n), Object.defineProperty(n, "default", {
enumerable: !0,
value: e
}), 2 & t && "string" != typeof e)
for (var o in e) r.d(n, o, function(t) {
return e[t]
}.bind(null, o));
return n
}, r.n = function(e) {
var t = e && e.__esModule ? function() {
return e.default
} : function() {
return e
};
return r.d(t, "a", t), t
}, r.o = function(e, t) {
return Object.prototype.hasOwnProperty.call(e, t)
}, r.p = "", r(r.s = 1382)
}({
1382: function(e, t) {
var r = function(e, t) {
var r = e.match(new RegExp("[?&]" + t + "=([^&]+)"));
return r ? r[1] : null
};
window.DTFrameLogin = function(e, t, n, o) {
var i, u = e.id && document.getElementById(e.id) || null,
c = document.createElement("iframe");
t.client_id && t.redirect_uri && t.response_type && t.scope ? u ? (u.innerHTML = "", u.appendChild(c), c && c.contentWindow && c.contentWindow.postMessage && window.addEventListener ? (c.src = "https://" + ((i = t)
.isPre ? "pre-login" : "login") + ".dingtalk.com/oauth2/auth?iframe=true&redirect_uri=" + i.redirect_uri + "&response_type=" + i.response_type + "&client_id=" + i.client_id + "&scope=" + i.scope + (i.prompt ? "&prompt=" + i.prompt : "") + (i.state ? "&state=" + i.state : "") + (i.org_type ? "&org_type=" + i.org_type : "") + (i.corpId ? "&corpId=" + i.corpId : "") + (i.exclusiveLogin ? "&exclusiveLogin=" + i.exclusiveLogin : "") + (i.exclusiveCorpId ? "&exclusiveCorpId=" + i.exclusiveCorpId : ""), c.width = "" + (e.width || 300), c.height = "" + (e.height || 300), c.frameBorder = "0", c.scrolling = "no", window.addEventListener("message", (function(e) {
var t = e.data,
i = e.origin;
if (/login\.dingtalk\.com/.test(i) && t)
if (t.success && t.redirectUrl) {
var u = t.redirectUrl,
c = r(u, "authCode") || "",
d = r(u, "state") || "",
s = r(u, "error") || "";
c ? n && n({
redirectUrl: u,
authCode: c,
state: d
}) : o && o(s)
} else o && o(t.errorMsg)
}))) : o && o("Browser not support")) : o && o("Element not found") : o && o("Missing parameters")
}
}
});
在源码中注册了 window.addEventListener("message",fn)事件但是没有 在适当的时候注销掉该事件可能会出现回调函数多次执行的问题。
一般的话可以使用具名函数,或者在页面卸载的时候取消监听器。
window.addEventListener("beforeunload", function() {
window.removeEventListener("message", messageHandler);
});
下面是钉钉扫码多次回调的解决方案
// 业务代码登录的回调函数
let doLoginByDD = (authCode: string) => {
// 这里可以直接进行重定向
// window.location.href = redirectUrl;
// 也可以在不跳转页面的情况下,使用code进行授权
useUserStoreHook()
.loginBydingdingScan({
code: authCode
})
.then(r => {
if (r.code === 200) {
// 获取后端路由
initRouter().then(() => {
router.push(getTopMenu(true).path);
message("登录成功", { type: "success" });
doLoginByDD = null;//登录成功后清空函数
});
}
});
};
const ddLoginInit = () => {
(window as any).DTFrameLogin(
{
id: "dingdingLoginFrame",
width: 300,
height: 300
},
{
redirect_uri: encodeURIComponent(VITE_DINGDING_REDIRECT_URI),
client_id: "你的钉钉ClienId",
scope: "openid",
response_type: "code",
state: "xxxxxxxxx",
prompt: "consent"
},
loginResult => {
const { redirectUrl, authCode, state } = loginResult;
// 这个回调下,用户登录成功后,退出,再次重新登录,会出现回调叠加。
if (doLoginByDD) {
doLoginByDD(authCode);
}
},
errorMsg => {
// 这里一般需要展示登录失败的具体原因,可以使用toast等轻提示
console.error(`errorMsg of errorCbk: ${errorMsg}`);
}
);
//页面卸载 清空掉回调函数
onBeforeUnmount(() => {
doLoginByDD = null;
});