'use client'; import { useEffect, useState } from 'react'; import { CheckCircle2, Database, ShieldCheck, UserRound, Wrench } from 'lucide-react'; type SetupStatus = { ok: boolean; dataDir: string; configured: boolean; config: { myNicknames: string[]; demoMode: boolean; privacyConfirmed: boolean; defaultSyncDays: number }; checks: { wxInstalled: boolean; wxDaemonRunning: boolean; wxDaemonPid: number | null }; }; export default function SetupPage() { const [status, setStatus] = useState(null); const [names, setNames] = useState(''); const [demoMode, setDemoMode] = useState(false); const [privacyConfirmed, setPrivacyConfirmed] = useState(false); const [defaultSyncDays, setDefaultSyncDays] = useState(7); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); useEffect(() => { (async () => { const res = await fetch('/api/setup', { cache: 'no-store' }); const json = (await res.json()) as SetupStatus; setStatus(json); setNames(json.config.myNicknames.join(', ')); setDemoMode(json.config.demoMode); setPrivacyConfirmed(json.config.privacyConfirmed); setDefaultSyncDays(json.config.defaultSyncDays ?? 7); })(); }, []); async function submit() { setBusy(true); setError(null); try { const res = await fetch('/api/setup', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ myNicknames: names.split(',').map((name) => name.trim()).filter(Boolean), demoMode, privacyConfirmed, defaultSyncDays, }), }); const json = await res.json(); if (!res.ok || !json.ok) throw new Error(json.error ?? '保存失败'); window.location.href = '/'; } catch (e) { setError(e instanceof Error ? e.message : '保存失败'); } finally { setBusy(false); } } return (
WeChat Radar Setup

配置微信雷达

首次运行需要确认本地环境、填写你的微信名,并选择是否使用示例数据。所有数据默认保存在本机。

} title="环境检查" />
} title="你的微信名" /> setNames(e.target.value)} placeholder="张三, San Zhang, zhangsan" className="control-surface mt-2 w-full rounded-md px-3 py-2 text-[13px] outline-none" />

用于识别 @我的、自己相关讨论和提醒。

} title="数据模式" />
} title="隐私确认" />
{error &&
{error}
}
); } function SectionTitle({ icon, title }: { icon: React.ReactNode; title: string }) { return
{icon}{title}
; } function CheckRow({ label, ok, detail }: { label: string; ok: boolean; detail: string }) { return (
{label} {detail}
); }