import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { Toast } from 'antd-mobile' import { useUserStore } from '@/stores/user' import QRCodeLogin from './QRCodeLogin' import styles from './login.module.css' // 声明飞书 JSAPI 类型 declare global { interface Window { tt?: any h5sdk?: { ready: (callback: () => void) => void } } } export default function Login() { const navigate = useNavigate() const { login } = useUserStore() const [loading, setLoading] = useState(true) const [environment, setEnvironment] = useState<'feishu' | 'external' | null>(null) const [showQRCode, setShowQRCode] = useState(false) // 检查登录状态 useEffect(() => { const token = localStorage.getItem('token') const urlParams = new URLSearchParams(window.location.search) const redirect = urlParams.get('redirect') if (token) { if (redirect) { window.location.href = redirect } else { navigate('/dashboard') } return } // 监听飞书登录成功事件 const handleFeishuLoginSuccess = ((e: any) => { const { user, token } = e.detail login(user, token) }) as EventListener window.addEventListener('feishu-login-success', handleFeishuLoginSuccess) return () => { window.removeEventListener('feishu-login-success', handleFeishuLoginSuccess) } }, [login, navigate]) // 环境检测和免登 useEffect(() => { const ua = navigator.userAgent const isInFeishu = ua.includes('Lark') || ua.includes('feishu') || ua.includes('lark') const urlParams = new URLSearchParams(window.location.search) const authCode = urlParams.get('auth_code') const companyParam = urlParams.get('company') // 如果 URL 中有授权码,直接处理登录 if (authCode) { handleFeishuLogin(authCode, companyParam || undefined) return } if (isInFeishu) { // 飞书内环境,尝试免登 setEnvironment('feishu') attemptFeishuAutoLogin(companyParam || undefined) } else { // 飞书外环境,显示登录选项 setEnvironment('external') setLoading(false) } }, []) // 飞书内免登 const attemptFeishuAutoLogin = async (companyParam?: string) => { // 如果 h5sdk 存在,等待 ready 后再调用 if (window.h5sdk?.ready) { window.h5sdk.ready(() => { console.log('h5sdk ready, 调用免登') performFeishuLoginWithAppId(companyParam) }) return } // 如果 tt 对象已存在,直接使用 if (window.tt) { performFeishuLoginWithAppId(companyParam) return } // 轮询等待 tt 对象(最多 5 秒) let attempts = 0 const maxAttempts = 50 const checkInterval = setInterval(() => { attempts++ if (window.tt) { clearInterval(checkInterval) performFeishuLoginWithAppId(companyParam) } else if (attempts >= maxAttempts) { clearInterval(checkInterval) console.error('等待 tt 对象超时') setLoading(false) } }, 100) } // 获取 appId 并执行免登 const performFeishuLoginWithAppId = async (companyParam?: string) => { let appId: string | undefined | null const urlParams = new URLSearchParams(window.location.search) appId = urlParams.get('app_id') if (!appId && companyParam) { try { const response = await fetch(`/api/v1/auth/feishu-config?company=${companyParam}`) const result = await response.json() if (result.code === 0 && result.data.app_id) { appId = result.data.app_id } } catch (e) { console.error('获取 appId 失败:', e) } } if (!appId) { setLoading(false) Toast.show('飞书应用配置错误') return } performFeishuLogin(companyParam, appId) } // 执行飞书免登 const performFeishuLogin = async (companyParam?: string, appId?: string | null) => { if (!window.tt) { setLoading(false) Toast.show('飞书环境异常,请刷新重试') return } if (!appId) { setLoading(false) Toast.show('飞书应用配置错误') return } try { console.log('=== 开始免登 ===') console.log('appId:', appId) console.log('appId长度:', appId.length) console.log('appId前缀:', appId.substring(0, 4)) console.log('当前URL:', window.location.href) console.log('调用 tt.requestAuthCode') // 调用飞书免登 window.tt.requestAuthCode({ appId: appId, success: (res: any) => { console.log('✅ 免登成功') console.log('code:', res.code) handleFeishuLogin(res.code, companyParam) }, fail: (error: any) => { console.error('❌ 免登失败') console.error('完整错误对象:', JSON.stringify(error)) console.error('errMsg:', error.errMsg) console.error('errorCode:', error.errorCode) setLoading(false) Toast.show('免登失败:' + (error.errMsg || JSON.stringify(error))) }, }) } catch (e) { console.error('❌ 免登异常:', e) setLoading(false) Toast.show('免登失败,请重试') } } // 处理飞书登录 const handleFeishuLogin = async (authCode: string, companyParam?: string) => { try { const urlParams = new URLSearchParams(window.location.search) const urlAppId = urlParams.get('app_id') const response = await fetch('/api/v1/auth/feishu-login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ auth_code: authCode, app_id: urlAppId || undefined, company: companyParam || undefined, }), }) const result = await response.json() if (result.code === 0) { login(result.data.user, result.data.token) Toast.show('登录成功') const urlParams = new URLSearchParams(window.location.search) const redirect = urlParams.get('redirect') if (redirect) { window.location.href = redirect } else { navigate('/dashboard') } } else { Toast.show(result.message || '登录失败') setLoading(false) } } catch (error) { console.error('登录失败:', error) Toast.show('登录失败,请重试') setLoading(false) } } // 邮箱密码登录 const handlePasswordLogin = () => { navigate('/login-simple') } // 飞书扫码登录 const handleQRCodeLogin = () => { setShowQRCode(true) } if (loading) { return (
正在登录...
请选择登录方式
💡 提示:在飞书客户端内打开可自动登录
)}