fix: 优化飞书内免登功能,移除外部 JSBridge SDK 加载
- tt 对象由飞书客户端自动注入,无需加载外部 SDK - 增加轮询超时时间到 10 秒 - 添加更详细的调试日志 - 超时时降级到扫码登录 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-42
@@ -5,49 +5,9 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>frontend</title>
|
<title>frontend</title>
|
||||||
<!-- 飞书扫码登录 SDK -->
|
<!-- 飞书扫码登录 SDK(飞书外扫码登录用) -->
|
||||||
<script src="https://lf-package-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.3.js"></script>
|
<script src="https://lf-package-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.3.js"></script>
|
||||||
<!-- 飞书 H5 JSBridge SDK(多 CDN 备用) -->
|
<!-- 飞书内免登说明:tt 对象由飞书客户端自动注入,无需加载外部 SDK -->
|
||||||
<script>
|
|
||||||
// 尝试加载飞书 JSBridge,如果失败则尝试其他 CDN
|
|
||||||
var scripts = [
|
|
||||||
'https://lf1-cdn-tos.bytegoofy.com/goofy/lark/passport/h5-jsbridge-1.0.3.js',
|
|
||||||
'https://lf9-cn.feishucdn.com/obj/lark/passport/h5-jsbridge-1.0.3.js'
|
|
||||||
];
|
|
||||||
|
|
||||||
function loadScript(url) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.src = url;
|
|
||||||
script.onload = function() { console.log('JSBridge loaded from:', url); resolve(); };
|
|
||||||
script.onerror = function() { reject(url); };
|
|
||||||
document.head.appendChild(script);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按顺序尝试加载 JSBridge
|
|
||||||
function loadJSBridge() {
|
|
||||||
var index = 0;
|
|
||||||
function tryNext() {
|
|
||||||
if (index < scripts.length) {
|
|
||||||
loadScript(scripts[index])
|
|
||||||
.catch(function() {
|
|
||||||
console.warn('JSBridge load failed:', scripts[index]);
|
|
||||||
index++;
|
|
||||||
tryNext();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('All JSBridge CDNs failed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tryNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 页面加载后尝试加载 JSBridge
|
|
||||||
if (navigator.userAgent.includes('Lark') || navigator.userAgent.includes('feishu')) {
|
|
||||||
loadJSBridge();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -79,6 +79,18 @@ export default function Login() {
|
|||||||
console.log('在飞书中:', isInFeishu)
|
console.log('在飞书中:', isInFeishu)
|
||||||
console.log('window.tt:', window.tt)
|
console.log('window.tt:', window.tt)
|
||||||
|
|
||||||
|
// 检查所有可能的飞书相关全局对象
|
||||||
|
const feishuObjects = {}
|
||||||
|
for (const key in window) {
|
||||||
|
if (key.toLowerCase().includes('tt') ||
|
||||||
|
key.toLowerCase().includes('lark') ||
|
||||||
|
key.toLowerCase().includes('feishu') ||
|
||||||
|
key.toLowerCase().includes('bridge')) {
|
||||||
|
feishuObjects[key] = typeof window[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('🔍 飞书相关全局对象:', feishuObjects)
|
||||||
|
|
||||||
// 检查 URL 中是否来自飞书消息通知
|
// 检查 URL 中是否来自飞书消息通知
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
const authCode = urlParams.get('auth_code')
|
const authCode = urlParams.get('auth_code')
|
||||||
@@ -110,20 +122,32 @@ export default function Login() {
|
|||||||
setEnvironment('feishu')
|
setEnvironment('feishu')
|
||||||
handleFeishuAutoLogin()
|
handleFeishuAutoLogin()
|
||||||
} else if (isInFeishu) {
|
} else if (isInFeishu) {
|
||||||
// 飞书内环境,等待 tt 对象加载后尝试免登
|
// 飞书内环境,tt 对象由飞书客户端自动注入
|
||||||
console.log('⏳ 在飞书内环境,等待 tt 对象加载...')
|
// 使用轮询等待 tt 对象可用(最多 10 秒)
|
||||||
|
console.log('⏳ 在飞书内环境,等待飞书客户端注入 tt 对象...')
|
||||||
setEnvironment('feishu')
|
setEnvironment('feishu')
|
||||||
setLoading(false)
|
|
||||||
// 给 tt 对象一些时间来加载(最多 2 秒)
|
let attempts = 0
|
||||||
setTimeout(() => {
|
const maxAttempts = 100 // 100 * 100ms = 10秒
|
||||||
if (window.tt) {
|
|
||||||
console.log('✅ tt 对象已加载,开始免登')
|
const checkInterval = setInterval(() => {
|
||||||
|
attempts++
|
||||||
|
console.log(`🔍 检查 tt 对象 (${attempts}/${maxAttempts}):`, !!window.tt, typeof window.tt)
|
||||||
|
|
||||||
|
if (window.tt && typeof window.tt === 'object') {
|
||||||
|
clearInterval(checkInterval)
|
||||||
|
console.log('✅ tt 对象已由飞书客户端注入,开始免登')
|
||||||
handleFeishuAutoLogin()
|
handleFeishuAutoLogin()
|
||||||
} else {
|
} else if (attempts >= maxAttempts) {
|
||||||
console.log('⚠️ tt 对象仍未加载,显示二维码登录')
|
clearInterval(checkInterval)
|
||||||
|
console.error('❌ 等待 tt 对象超时,最后状态 window.tt:', window.tt, typeof window.tt)
|
||||||
|
console.error('❌ 请检查:1) 飞书开放平台是否正确配置 H5 应用地址 2) 页面是否从飞书应用入口进入')
|
||||||
|
|
||||||
|
// 不自动弹错误,而是显示飞书内登录界面
|
||||||
|
setLoading(false)
|
||||||
setShowQRCode(true)
|
setShowQRCode(true)
|
||||||
}
|
}
|
||||||
}, 2000)
|
}, 100)
|
||||||
} else {
|
} else {
|
||||||
// 飞书外:显示登录选项
|
// 飞书外:显示登录选项
|
||||||
console.log('📱 飞书外环境,显示登录选项')
|
console.log('📱 飞书外环境,显示登录选项')
|
||||||
@@ -135,8 +159,6 @@ export default function Login() {
|
|||||||
// 飞书内静默授权
|
// 飞书内静默授权
|
||||||
const handleFeishuAutoLogin = () => {
|
const handleFeishuAutoLogin = () => {
|
||||||
console.log('🚀 开始飞书免登')
|
console.log('🚀 开始飞书免登')
|
||||||
console.log('🔍 window.tt:', window.tt)
|
|
||||||
console.log('🔍 window.tt 类型:', typeof window.tt)
|
|
||||||
|
|
||||||
// 从 URL 获取 company 参数(可能来自当前 URL 或 redirect URL)
|
// 从 URL 获取 company 参数(可能来自当前 URL 或 redirect URL)
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
@@ -153,60 +175,37 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 详细检查 tt 对象
|
console.log('🔍 window.tt:', window.tt)
|
||||||
if (window.tt) {
|
console.log('🔍 tt 的属性:', Object.keys(window.tt || {}))
|
||||||
console.log('✅ tt 对象存在')
|
|
||||||
console.log('🔍 tt 的所有属性:', Object.keys(window.tt))
|
|
||||||
console.log('🔍 tt.requestAuthCode 类型:', typeof window.tt.requestAuthCode)
|
|
||||||
|
|
||||||
// 检查 requestAuthCode 是否存在
|
if (!window.tt) {
|
||||||
if ('requestAuthCode' in window.tt) {
|
console.error('❌ tt 对象不存在')
|
||||||
console.log('✅ requestAuthCode 属性存在')
|
|
||||||
console.log('🔍 类型:', typeof window.tt.requestAuthCode)
|
|
||||||
} else {
|
|
||||||
console.log('❌ requestAuthCode 属性不存在')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('❌ tt 对象不存在')
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
Toast.show('飞书 API 未加载,请刷新重试')
|
Toast.show('飞书环境异常,请刷新重试')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待一小段时间,确保 tt 完全初始化
|
// 调用 tt.requestAuthCode 获取授权码
|
||||||
setTimeout(() => {
|
try {
|
||||||
console.log('⏰ 延迟后再次检查 tt:', !!window.tt)
|
console.log('🔧 调用 tt.requestAuthCode')
|
||||||
|
|
||||||
if (!window.tt) {
|
// 不传 appId,让飞书自动选择(后端会根据 company 参数处理)
|
||||||
setLoading(false)
|
window.tt.requestAuthCode({
|
||||||
Toast.show('飞书 API 加载失败')
|
success: (res: any) => {
|
||||||
return
|
console.log('✅ 成功获取授权码:', res.code?.substring(0, 30))
|
||||||
}
|
handleFeishuLogin(res.code)
|
||||||
|
},
|
||||||
// 尝试调用 requestAuthCode
|
fail: (error: any) => {
|
||||||
try {
|
console.error('❌ requestAuthCode 失败:', error)
|
||||||
console.log('🔧 调用 tt.requestAuthCode,company:', companyParam)
|
setLoading(false)
|
||||||
|
Toast.show('免登失败:' + (error.errorMessage || error.errMsg || JSON.stringify(error)))
|
||||||
// 不传 appId,让飞书自动选择(后端会根据 company 参数处理)
|
},
|
||||||
window.tt.requestAuthCode({
|
})
|
||||||
success: (res: any) => {
|
} catch (e) {
|
||||||
console.log('✅ 成功获取授权码:', res)
|
console.error('❌ 调用异常:', e)
|
||||||
console.log('✅ code:', res.code?.substring(0, 30))
|
setLoading(false)
|
||||||
handleFeishuLogin(res.code)
|
Toast.show('免登失败,请重试')
|
||||||
},
|
}
|
||||||
fail: (error: any) => {
|
|
||||||
console.error('❌ requestAuthCode 失败:', error)
|
|
||||||
console.error('❌ 错误详情:', JSON.stringify(error))
|
|
||||||
setLoading(false)
|
|
||||||
Toast.show('免登失败:' + (error.errorMessage || error.errMsg || JSON.stringify(error)))
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
console.error('❌ 调用异常:', e)
|
|
||||||
setLoading(false)
|
|
||||||
Toast.show('免登失败,请使用其他方式登录')
|
|
||||||
}
|
|
||||||
}, 500)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 跳转到飞书授权页面(飞书外扫码登录)
|
// 跳转到飞书授权页面(飞书外扫码登录)
|
||||||
|
|||||||
Reference in New Issue
Block a user