修复钉钉端内免登循环

This commit is contained in:
chenpei 2026-07-07 14:47:28 +08:00
parent 26c5e01881
commit 2f5bccb7ee

View File

@ -1,7 +1,6 @@
'use client'
import { useEffect, useRef, useState } from 'react'
import { signIn, useSession } from 'next-auth/react'
declare global {
interface Window {
@ -99,19 +98,42 @@ function formatDingtalkError(error: unknown) {
}
}
function submitDingtalkH5Login(authCode: string, redirectPath: string) {
const form = document.createElement('form')
form.method = 'POST'
form.action = `/api/dingtalk/h5-login?redirect=${encodeURIComponent(redirectPath)}`
form.style.display = 'none'
const codeInput = document.createElement('input')
codeInput.type = 'hidden'
codeInput.name = 'code'
codeInput.value = authCode
form.appendChild(codeInput)
document.body.appendChild(form)
form.submit()
}
async function hasActiveSession() {
try {
const response = await fetch('/api/auth/session', {
cache: 'no-store',
credentials: 'include',
})
if (!response.ok) return false
const data = await response.json().catch(() => null)
return Boolean(data?.user)
} catch {
return false
}
}
export default function DingtalkEntryClient({ corpId, redirectPath }: DingtalkEntryClientProps) {
const { status } = useSession()
const startedRef = useRef(false)
const [message, setMessage] = useState('正在通过钉钉确认身份...')
useEffect(() => {
if (status === 'authenticated') {
window.location.replace(redirectPath)
}
}, [redirectPath, status])
useEffect(() => {
if (startedRef.current || status === 'loading' || status === 'authenticated') return
if (startedRef.current) return
startedRef.current = true
const run = async () => {
@ -126,6 +148,12 @@ export default function DingtalkEntryClient({ corpId, redirectPath }: DingtalkEn
}
try {
setMessage('正在检查素材库登录状态...')
if (await hasActiveSession()) {
window.location.replace(redirectPath)
return
}
setMessage('正在加载钉钉免登组件...')
await loadDingtalkJsApi()
@ -133,26 +161,14 @@ export default function DingtalkEntryClient({ corpId, redirectPath }: DingtalkEn
const authCode = await requestDingtalkAuthCode(corpId)
setMessage('正在写入素材库登录状态...')
const result = await signIn('credentials', {
loginType: 'dingtalk_inapp',
authCode,
redirect: false,
})
if (result?.error) {
setMessage(`钉钉免登失败:${result.error}`)
return
}
setMessage('登录成功,正在进入考核调研...')
window.location.replace(redirectPath)
submitDingtalkH5Login(authCode, redirectPath)
} catch (error) {
setMessage(`钉钉免登失败:${formatDingtalkError(error)}`)
}
}
void run()
}, [corpId, redirectPath, status])
}, [corpId, redirectPath])
return (
<main className="flex min-h-screen items-center justify-center bg-slate-950 px-6 text-slate-50">