import dd from "dingtalk-jsapi"; import { getDingTalkConfig, loginWithDingTalk } from "@/api/auth"; import type { AuthTokenData } from "@/types/auth"; declare global { interface Window { dingtalk?: { platform?: { invokeAPI?: unknown } }; DingTalkJSBridge?: unknown; } } export function isDingTalkContainer() { if (typeof window === "undefined" || typeof navigator === "undefined") return false; const userAgent = navigator.userAgent || (navigator as Navigator & { swuserAgent?: string }).swuserAgent || ""; return Boolean( /DingTalk|dingtalk-win|dd-web/i.test(userAgent) || window.DingTalkJSBridge || window.dingtalk?.platform?.invokeAPI || // DingTalk desktop can expose its container identity through window.name // even when the embedded browser omits DingTalk from userAgent. /dingtalk/i.test(window.name || ""), ); } export async function waitForDingTalkContainer(timeoutMs = 5000) { if (isDingTalkContainer()) return true; const startedAt = Date.now(); while (Date.now() - startedAt < timeoutMs) { await new Promise((resolve) => window.setTimeout(resolve, 100)); if (isDingTalkContainer()) return true; } return false; } export async function authenticateWithDingTalk(): Promise { if (!(await waitForDingTalkContainer())) throw new Error("请从钉钉工作台打开此应用"); const configResponse = await getDingTalkConfig(); const config = configResponse.data.data; if (!config) throw new Error("钉钉免登配置不完整"); const result = await dd.runtime.permission.requestAuthCode({ corpId: config.corpId, }); const authCode = result?.code; if (!authCode) throw new Error("钉钉未返回免登授权码"); const response = await loginWithDingTalk(authCode); if (!response.data.data) throw new Error("钉钉登录响应为空"); return response.data.data; }