feat: auto-start feishu login in client

This commit is contained in:
2026-05-25 15:05:26 +08:00
parent d246563dc1
commit 486a682320
4 changed files with 49 additions and 7 deletions

View File

@@ -1,7 +1,7 @@
"use client"
import type { FormEvent } from "react"
import { useEffect, useMemo, useState } from "react"
import { useEffect, useMemo, useRef, useState } from "react"
import {
ArrowRight,
Building2,
@@ -21,8 +21,26 @@ type AuthConfig = {
feishu_enabled?: boolean
}
function normalizeNextPath(value: string | null | undefined) {
const next = (value || "/").trim() || "/"
if (!next.startsWith("/") || next.startsWith("//")) return "/"
return next
}
function loginNextPath() {
if (typeof window === "undefined") return "/"
return normalizeNextPath(new URLSearchParams(window.location.search).get("next"))
}
function isFeishuClient() {
if (typeof window === "undefined") return false
const ua = window.navigator.userAgent.toLowerCase()
return ua.includes("feishu") || ua.includes("lark")
}
export default function LoginPage() {
const [authConfig, setAuthConfig] = useState<AuthConfig | null>(null)
const [nextPath] = useState(loginNextPath)
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
const [remember, setRemember] = useState(true)
@@ -31,6 +49,7 @@ export default function LoginPage() {
const [hasError, setHasError] = useState(false)
const [status, setStatus] = useState<LoginStatus>("idle")
const [eyeOffset, setEyeOffset] = useState({ x: 0, y: 0 })
const autoFeishuAttemptedRef = useRef(false)
useEffect(() => {
let cancelled = false
@@ -63,6 +82,16 @@ export default function LoginPage() {
const feishuEnabled = Boolean(authConfig?.feishu_enabled)
const passwordEnabled = authConfig?.password_enabled ?? true
useEffect(() => {
if (!feishuEnabled || status !== "idle" || autoFeishuAttemptedRef.current || !isFeishuClient()) return
const attemptKey = `skg-feishu-auto-login:${nextPath}`
if (window.sessionStorage.getItem(attemptKey) === "1") return
window.sessionStorage.setItem(attemptKey, "1")
autoFeishuAttemptedRef.current = true
setStatus("loading")
window.location.href = `/api/auth/feishu/start?next=${encodeURIComponent(nextPath)}`
}, [feishuEnabled, nextPath, status])
const mood: LoginCharacterMood = useMemo(() => {
if (status === "success") return "success"
if (hasError) return "error"
@@ -92,7 +121,7 @@ export default function LoginPage() {
}
setStatus("success")
window.setTimeout(() => {
window.location.href = "/"
window.location.href = nextPath
}, 420)
} catch {
setStatus("idle")
@@ -102,7 +131,7 @@ export default function LoginPage() {
function onFeishuLogin() {
setStatus("loading")
window.location.href = "/api/auth/feishu/start?next=/"
window.location.href = `/api/auth/feishu/start?next=${encodeURIComponent(nextPath)}`
}
return (