diff --git a/ui-src/src/App.tsx b/ui-src/src/App.tsx index 1cd0410..d091a51 100644 --- a/ui-src/src/App.tsx +++ b/ui-src/src/App.tsx @@ -389,6 +389,33 @@ function profileFormFromStatus(status: StatusPayload | null): ProfileFormState { }; } +function profileFormFromProfile(profile: Profile): ProfileFormState { + const form = profile.form || {}; + return { + ...defaultProfileForm, + name: profile.name, + listen_host: form.listen_host || "", + listen_port: form.listen_port || "", + upstream_base_url: form.upstream_base_url || "", + auth_mode: (form.auth_mode as ProfileFormState["auth_mode"]) || "passthrough", + auth_env: form.auth_env || "", + auth_file: form.auth_file || "", + manual_secret: "", + manual_secret_file: form.manual_secret_file || "", + manual_secret_configured: Boolean(form.manual_secret_configured), + auth_json_path: form.auth_json_path || "", + auth_json_key: form.auth_json_key || "OPENAI_API_KEY", + request_history_limit: form.request_history_limit || defaultProfileForm.request_history_limit, + model_remap: form.model_remap || "", + reasoning_equals: form.reasoning_equals || "", + retryable_status_codes: form.retryable_status_codes || defaultProfileForm.retryable_status_codes, + retryable_error_messages: Array.isArray(form.retryable_error_messages) + ? form.retryable_error_messages.join("\n") + : defaultProfileForm.retryable_error_messages, + endpoints: Array.isArray(form.endpoints) ? form.endpoints.join("\n") : "", + }; +} + function ruleFormFromStatus(status: StatusPayload | null): RuleFormState { const config = status?.config || {}; return { @@ -429,6 +456,7 @@ export default function App() { const [deletingProfile, setDeletingProfile] = useState(""); const [switchingTo, setSwitchingTo] = useState(""); const [restoreRequested, setRestoreRequested] = useState(false); + const [shouldSyncProfileFormToActive, setShouldSyncProfileFormToActive] = useState(true); const metrics = status?.metrics || {}; const tokens = metrics.token_totals || {}; @@ -503,6 +531,12 @@ export default function App() { window.location.hash = page; }, [page]); + useEffect(() => { + if (page === "profiles") { + setShouldSyncProfileFormToActive(true); + } + }, [page]); + useEffect(() => { const onHashChange = () => { const next = window.location.hash.replace("#", "") as PageKey; @@ -529,6 +563,19 @@ export default function App() { return () => window.clearInterval(timer); }); + useEffect(() => { + if (page !== "profiles" || !shouldSyncProfileFormToActive) { + return; + } + const activeProfile = profiles.find((profile) => profile.active); + if (!activeProfile) { + return; + } + setProfileForm(profileFormFromProfile(activeProfile)); + setProfileMessage({ text: "", tone: "" }); + setShouldSyncProfileFormToActive(false); + }, [page, profiles, shouldSyncProfileFormToActive]); + async function saveRules(event: FormEvent) { event.preventDefault(); setRuleMessage({ text: "正在保存配置...", tone: "" }); @@ -608,30 +655,8 @@ export default function App() { } function editProfile(profile: Profile) { - const form = profile.form || {}; - setProfileForm({ - ...defaultProfileForm, - name: profile.name, - listen_host: form.listen_host || "", - listen_port: form.listen_port || "", - upstream_base_url: form.upstream_base_url || "", - auth_mode: (form.auth_mode as ProfileFormState["auth_mode"]) || "passthrough", - auth_env: form.auth_env || "", - auth_file: form.auth_file || "", - manual_secret: "", - manual_secret_file: form.manual_secret_file || "", - manual_secret_configured: Boolean(form.manual_secret_configured), - auth_json_path: form.auth_json_path || "", - auth_json_key: form.auth_json_key || "OPENAI_API_KEY", - request_history_limit: form.request_history_limit || defaultProfileForm.request_history_limit, - model_remap: form.model_remap || "", - reasoning_equals: form.reasoning_equals || "", - retryable_status_codes: form.retryable_status_codes || defaultProfileForm.retryable_status_codes, - retryable_error_messages: Array.isArray(form.retryable_error_messages) - ? form.retryable_error_messages.join("\n") - : defaultProfileForm.retryable_error_messages, - endpoints: Array.isArray(form.endpoints) ? form.endpoints.join("\n") : "", - }); + setShouldSyncProfileFormToActive(false); + setProfileForm(profileFormFromProfile(profile)); setProfileMessage({ text: "编辑后保存 profile env;如果保存的是当前运行 profile,后端会直接后台热应用。", tone: "" }); } @@ -719,6 +744,7 @@ export default function App() { const payload = await fetchJson(api.status); if (payload.config?.profile_name === profileName) { setSwitchingTo(""); + setShouldSyncProfileFormToActive(true); Promise.all([loadStatus(true), loadRequests(), loadProfiles(), loadLogs(false)]).catch(() => {}); return; } @@ -989,6 +1015,7 @@ export default function App() { className="secondary" type="button" onClick={() => { + setShouldSyncProfileFormToActive(false); setProfileForm(profileFormFromStatus(status)); setProfileMessage({ text: "", tone: "" }); }}