import { useEffect, useMemo, useState } from "react"; import { Check, ChevronDown, CircleAlert, ExternalLink, Eye, EyeOff, Lock, ShieldCheck } from "lucide-react"; import { readConfig, verifyConfig, writeConfig } from "../ipc"; import type { ConfigFieldState, ConfigFormState, ConfigVerifyResult, WriteResult, } from "../ipc/types"; import { AuthPanel } from "./AuthPanel"; import { MonoChip } from "./MonoChip"; /** 配置表单(视觉规范 §3.4:单列 ≤640px、敏感字段密码框 + 密钥库说明、吸底保存条) * Wave 2.1:字段按官方配置方法渲染 + 保存后「生效检查」 * Wave 2.2:授权/登录层改为可操作授权流程(AuthPanel) */ export function ConfigForm({ id, onAuthChanged }: { id: string; onAuthChanged?: () => void }) { const [state, setState] = useState(null); const [values, setValues] = useState>({}); const [revealed, setRevealed] = useState>({}); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); const [result, setResult] = useState(null); const [verify, setVerify] = useState(null); const [error, setError] = useState(null); const [advancedOpen, setAdvancedOpen] = useState(false); useEffect(() => { let cancelled = false; readConfig(id) .then((s) => { if (cancelled) return; setState(s); const init: Record = {}; for (const f of s.fields) { if (!f.sensitive && f.value != null) init[f.id] = f.value; } setValues(init); setLoading(false); }) .catch((e) => { if (!cancelled) { setError(String(e)); setLoading(false); } }); return () => { cancelled = true; }; }, [id]); const sensitiveSaved = useMemo(() => { const m: Record = {}; state?.fields.forEach((f) => { if (f.sensitive) m[f.id] = f.has_value; }); return m; }, [state]); if (loading) return

配置加载中…

; if (error) return

配置加载失败:{error}

; if (!state) return null; const hasFields = state.fields.length > 0; const authFields = state.fields.filter((f) => f.group === "auth"); const commonFields = state.fields.filter((f) => f.group === "common"); const advancedFields = state.fields.filter((f) => f.group === "advanced"); function renderField(field: ConfigFieldState) { return ( setRevealed((r) => ({ ...r, [field.id]: !r[field.id] }))} onChange={(v) => setValues((x) => ({ ...x, [field.id]: v }))} /> ); } async function onSave() { setSaving(true); setSaved(false); setResult(null); setVerify(null); setError(null); const patch: Record = {}; for (const f of state!.fields) { const v = values[f.id]; if (v != null && v !== "") { patch[f.id] = v; } } if (Object.keys(patch).length === 0) { setError("没有需要保存的改动"); setSaving(false); return; } try { const r = await writeConfig(id, patch); setResult(r); setSaved(true); setValues({}); // 刷新回显 const s = await readConfig(id); setState(s); // 生效检查:写回的配置能否被 CLI 接受(配置文件解析 + CLI 版本探测) try { const v = await verifyConfig(id); setVerify(v); } catch { setVerify(null); } } catch (e) { setError(String(e)); } finally { setSaving(false); } } return (
{!hasFields &&

该 CLI 未声明可配置的中文表单字段。

} {/* 第一层:授权 / 登录(可操作授权流程 + API Key 类字段) */} {(state.auth_modes.length > 0 || authFields.length > 0) && (

授权 / 登录

{state.auth_modes.length > 0 && ( {})} /> )} {authFields.map(renderField)}
)} {/* 第二层:常用配置 */} {commonFields.length > 0 && (

常用配置

{commonFields.map(renderField)}
)} {/* 第三层:高级配置(默认折叠) */} {advancedFields.length > 0 && (

以下为官方支持但少数用户使用的高级项,一般无需修改。

{advancedOpen &&
{advancedFields.map(renderField)}
}
)} {state.files.length > 0 && (
配置文件 {state.files.map((f) => ( {f.path} {f.exists ? (f.parse_ok ? " · 已解析" : " · 解析异常") : " · 尚未创建"} ))}
)} {hasFields && (
{saved && ( )} {verify && ( {verify.ok ? ( )} {result?.backup_path && ( 已备份原文件 · {result.backup_path.split(/[\\/]/).pop()} )} {error && {error}}
)}
); } function Field({ field, value, saved, revealed, onChange, onToggleReveal, }: { field: ConfigFieldState; value: string; saved: boolean; revealed: boolean; onChange: (v: string) => void; onToggleReveal: () => void; }) { const isPassword = field.sensitive; const isEnum = field.field_type === "enum"; const inputType = isPassword ? (revealed ? "text" : "password") : "text"; return (
{isPassword && saved && ( )} {isEnum ? ( ) : ( onChange(e.target.value)} /> )} {isPassword && ( )}
{field.help_zh} {isPassword && ( {saved ? ` · 已加密保存于系统密钥库${field.env_key ? `(${field.env_key})` : ""}` : ` · 保存后写入系统密钥库,绝不明文落盘${field.env_key ? `(${field.env_key})` : ""}`} )} {field.docs_url && ( 官方文档 )}
); }