/** * 管理后台登录门 - 对接真实 API(演示环境默认 localhost:8081) * 已登录(localStorage 持有 admin token)渲染管理界面;否则显示管理员登录表单 */ 'use client'; import { useState, type ReactNode } from 'react'; import { AdminShell } from '@/components/admin/AdminShell'; /** 演示环境 API 地址(生产替换为真实网关域名) */ const API_BASE = process.env['NEXT_PUBLIC_API_URL'] || 'http://localhost:8081/v1'; export function AdminGate({ children }: { children: ReactNode }) { const [token, setToken] = useState(() => { try { return localStorage.getItem('dotouch_admin_token'); } catch { return null; } }); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [msg, setMsg] = useState(null); const [msgType, setMsgType] = useState<'err' | 'ok'>('err'); const [loading, setLoading] = useState(false); const logout = () => { try { localStorage.removeItem('dotouch_admin_token'); localStorage.removeItem('dotouch_admin_user'); } catch { /* 忽略 */ } setToken(null); }; const login = async () => { if (!email || !password) { setMsg('请输入账号和密码'); setMsgType('err'); return; } setLoading(true); setMsg(null); try { const resp = await fetch(`${API_BASE}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), }); const data = await resp.json().catch(() => ({})); if (resp.ok && data.accessToken && data.user?.role === 'admin') { try { localStorage.setItem('dotouch_admin_token', data.accessToken); localStorage.setItem('dotouch_admin_user', email); } catch { /* 忽略 */ } setToken(data.accessToken); } else if (resp.ok && data.accessToken) { setMsg('该账号无管理员权限(需要 role=admin)'); setMsgType('err'); } else { setMsg(data.message || '登录失败,请检查账号密码'); setMsgType('err'); } } catch { setMsg('无法连接 API,请确认演示服务已启动(localhost:8081)'); setMsgType('err'); } finally { setLoading(false); } }; if (token) { return ( {children} ); } return (
DoTouch.AI
平台管理后台 · 管理员登录
{msg && (
{msg}
)} setEmail(e.target.value)} placeholder="admin@dotouch.ai" className="mb-4 w-full rounded-[10px] border border-white/[0.08] bg-brand-card2 px-[14px] py-[11px] text-sm text-brand-text outline-none focus:border-brand-purple" /> setPassword(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && login()} placeholder="••••••••" className="mb-6 w-full rounded-[10px] border border-white/[0.08] bg-brand-card2 px-[14px] py-[11px] text-sm text-brand-text outline-none focus:border-brand-purple" />
演示账号:admin@dotouch.ai / Admin2026!
); }