// ===== page-admin.jsx ===== const { useState: useSA, useMemo: useMA, useEffect: useEA, useRef: useRA } = React; const ADMIN_STATUSES = { pending: { key: 'pending', label: '待支付', dotClass: 'bg-ink-400' }, uploaded: { key: 'uploaded', label: '已上传待确认', dotClass: 'bg-warn-500' }, processing: { key: 'processing', label: 'LLM 处理中', dotClass: 'bg-brand-500' }, done: { key: 'done', label: '已完成', dotClass: 'bg-ok-500' }, refunded: { key: 'refunded', label: '已退款', dotClass: 'bg-bad-500' }, expired: { key: 'expired', label: '已过期', dotClass: 'bg-ink-300' }, llm_failed: { key: 'llm_failed', label: 'LLM 失败', dotClass: 'bg-bad-600' }, }; // ⚠️ 后台凭证内嵌在前端(按需求降低使用门槛)。 // 一旦域名被公开广泛传播,请改回密码登录(注释掉下面 useEA 块即可)。 const ADMIN_AUTO_USERNAME = 'admin'; const ADMIN_AUTO_PASSWORD = 'JtrZvqHnvRprUtn5gLjg5nH_so4'; function AdminPage({ navigate }) { const [loggedIn, setLoggedIn] = useSA(window.API.isAdminLoggedIn()); useEA(() => { if (!loggedIn) { window.API.saveAdmin(ADMIN_AUTO_USERNAME, ADMIN_AUTO_PASSWORD); setLoggedIn(true); } }, []); if (!loggedIn) { // 首次渲染瞬间的占位(自动登录会立刻完成) return (
); } return { window.API.clearAdmin(); setLoggedIn(false); window.location.hash = '#/'; }} navigate={navigate} />; } function AdminLogin({ onSuccess, navigate }) { const [username, setU] = useSA('admin'); const [password, setP] = useSA(''); const [submitting, setS] = useSA(false); const [error, setE] = useSA(null); const submit = async (e) => { e.preventDefault(); if (!password.trim() || submitting) return; setS(true); setE(null); window.API.saveAdmin(username.trim(), password); try { await window.API.adminStats(); // 用 stats 端点验证凭证 onSuccess(); } catch (err) { window.API.clearAdmin(); setE(err?.message || '登录失败'); } finally { setS(false); } }; return (

墨鉴管理后台

仅限授权人员访问

setU(e.target.value)} autoComplete="username" className="mt-1 w-full h-10 px-3 rounded-lg ring-1 ring-ink-200 bg-white text-[13.5px] focus:outline-none focus:ring-2 focus:ring-brand-500" />
setP(e.target.value)} autoComplete="current-password" className="mt-1 w-full h-10 px-3 rounded-lg ring-1 ring-ink-200 bg-white text-[13.5px] focus:outline-none focus:ring-2 focus:ring-brand-500" />
{error && (
{error}
)}
navigate('home')} className="hover:text-navy-900 cursor-pointer">← 回到主站
); } function AdminDashboard({ onLogout, navigate }) { const [orders, setOrders] = useSA([]); const [total, setTotal] = useSA(0); const [stats, setStats] = useSA(null); const [loading, setLoading] = useSA(true); const [q, setQ] = useSA(''); const [statusFilter, setStatus] = useSA('all'); const [busyId, setBusy] = useSA(null); const [errMsg, setErrMsg] = useSA(null); const refreshTimer = useRA(null); const load = async () => { try { const params = {}; if (statusFilter !== 'all') params.status = statusFilter; if (q.trim()) { // 数字纯尾数搜索 if (/^\d{1,2}$/.test(q.trim())) { params.amount_suffix = parseInt(q.trim(), 10); } else { params.q = q.trim(); } } const [ord, st] = await Promise.all([ window.API.adminListOrders(params), window.API.adminStats(), ]); setOrders(ord.items || []); setTotal(ord.total || 0); setStats(st); setErrMsg(null); } catch (err) { console.error('admin load failed', err); setErrMsg(err?.message || '加载失败'); if (err?.status === 401) { onLogout(); } } finally { setLoading(false); } }; useEA(() => { load(); refreshTimer.current = setInterval(load, 8000); return () => clearInterval(refreshTimer.current); }, [statusFilter, q]); const counts = useMA(() => { return Object.keys(ADMIN_STATUSES).reduce((acc, k) => { acc[k] = orders.filter(o => o.status === k).length; return acc; }, { all: orders.length }); }, [orders]); const confirm = async (id) => { setBusy(id); try { await window.API.adminConfirm(id, ''); await load(); } catch (err) { alert(`确认失败:${err?.message || err}`); } finally { setBusy(null); } }; const refund = async (id) => { if (!confirm_native('确定要标记此订单为已退款?')) return; setBusy(id); try { await window.API.adminRefund(id, '管理员退款'); await load(); } catch (err) { alert(`退款失败:${err?.message || err}`); } finally { setBusy(null); } }; const reprocess = async (id) => { setBusy(id); try { await window.API.adminReprocess(id); await load(); } catch (err) { alert(`重跑失败:${err?.message || err}`); } finally { setBusy(null); } }; return (
墨鉴管理后台
v0.1 · INTERNAL
navigate('home')} className="hover:text-navy-900 cursor-pointer">回到主站 注销
{/* 实时看板 */} {stats && (
)}

订单管理

手动确认支付到账 · 触发 LLM 检测 · 监控订单状态。{loading ? ' · 加载中...' : ` · 共 ${total} 单`}

setQ(e.target.value)} placeholder="搜索金额尾数(0-99) / 订单号 / 文件名" className="h-10 pl-9 pr-3 w-[320px] rounded-lg ring-1 ring-ink-200 bg-white text-[13.5px] focus:outline-none focus:ring-2 focus:ring-brand-500" />
{errMsg && (
{errMsg}
)}
setStatus('all')} /> {Object.values(ADMIN_STATUSES).map(s => ( setStatus(s.key)} /> ))}
{orders.map(o => { const isBusy = busyId === o.id; return ( ); })} {orders.length === 0 && !loading && ( )} {loading && orders.length === 0 && ( )}
订单号 上传时间 文件名 字数 金额 状态 操作
{o.id} {new Date(o.created_at).toLocaleString('zh-CN')} {o.file_name} {o.word_count.toLocaleString()} ¥ {o.amount.toFixed(2)}
{(o.status === 'pending' || o.status === 'uploaded') && ( )} {(o.status === 'llm_failed' || o.status === 'processing') && ( )} {(o.status === 'done' || o.status === 'processing') && o.report_id && ( )} {o.status !== 'refunded' && o.status !== 'expired' && ( )}
暂无订单
加载中...
工作流: 用户上传论文 → 系统生成订单(待支付)→ 用户扫码支付 → 你手机收到支付宝通知 → 在此搜索"金额尾数(如 42)"快速定位 → 点击「确认收款」→ 系统自动进入「LLM 处理中」并在 30 秒后切到「已完成」,用户的等待页会自动跳转到报告。
数据每 8 秒自动刷新。
); } function StatTile({ label, value, accent = 'ink' }) { const accents = { ink: 'text-navy-900', ok: 'text-ok-600', warn: 'text-warn-600', brand: 'text-brand-600', }; return (
{label}
{value}
); } function Th({ children, className = '' }) { return {children}; } function Td({ children, className = '' }) { return {children}; } function FilterChip({ label, count, dot, active, onClick }) { return ( ); } // 浏览器原生 confirm,避免和上面 confirm() 函数重名 function confirm_native(msg) { return window.confirm(msg); } window.AdminPage = AdminPage;