import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import type { BoardInfo } from '../types' import ThemeToggle from '../components/ThemeToggle' import './Lobby.scss' export function getNickname(): string { return localStorage.getItem('ww_name') || '' } export function setNickname(name: string) { localStorage.setItem('ww_name', name) } export default function Lobby() { const nav = useNavigate() const [name, setName] = useState(getNickname()) const [boards, setBoards] = useState([]) const [board, setBoard] = useState('classic12') const [joinCode, setJoinCode] = useState('') const [health, setHealth] = useState<{ llm_configured: boolean; model: string | null } | null>(null) const [busy, setBusy] = useState(false) const [error, setError] = useState('') useEffect(() => { fetch('/api/health').then((r) => r.json()).then(setHealth).catch(() => {}) fetch('/api/boards').then((r) => r.json()).then((b: BoardInfo[]) => { setBoards(b) if (b.length && !b.some((x) => x.key === board)) setBoard(b[0].key) }).catch(() => {}) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) const ensureName = (): boolean => { if (!name.trim()) { setError('请先输入你的昵称') return false } setNickname(name.trim()) return true } const createRoom = async () => { if (!ensureName()) return setBusy(true) setError('') try { const res = await fetch('/api/rooms', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ board, host_name: name.trim() }), }) const data = await res.json() nav(`/room/${data.code}`) } catch { setError('创建房间失败,请确认后端已启动') } finally { setBusy(false) } } const joinRoom = () => { if (!ensureName()) return const code = joinCode.trim().toUpperCase() if (!code) { setError('请输入房间号') return } nav(`/room/${code}`) } const selectedBoard = boards.find((b) => b.key === board) return (
🌕

狼人杀

WEREWOLVES · 人机混战 · 多人联机

setName(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && createRoom()} />
{selectedBoard &&

共 {selectedBoard.seat_count} 个座位

}
或者
setJoinCode(e.target.value.toUpperCase())} onKeyDown={(e) => e.key === 'Enter' && joinRoom()} />
{error &&

{error}

} {health && (

AI 玩家: {health.llm_configured ? ( 大模型已接入({health.model}) ) : ( 未配置密钥,使用内置启发式 AI )}

)}
) }