import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import toast from "react-hot-toast"; import { Input } from "@/shadcn-bridge/heroui/input"; import { Button } from "@/shadcn-bridge/heroui/button"; import { Card, CardBody } from "@/shadcn-bridge/heroui/card"; import { Select, SelectItem } from "@/shadcn-bridge/heroui/select"; import { Switch } from "@/shadcn-bridge/heroui/switch"; import { reinitializeBaseURL } from "@/api/network"; import { getConfigByName, updateConfig } from "@/api"; import { type UpdateReleaseChannel, getUpdateReleaseChannel, setUpdateReleaseChannel, } from "@/utils/version-update"; import { isAdmin } from "@/utils/auth"; import { getPanelAddresses, savePanelAddress, setCurrentPanelAddress, deletePanelAddress, validatePanelAddress, } from "@/utils/panel"; interface PanelAddress { name: string; address: string; inx: boolean; } const FORWARD_COMPACT_MODE_CONFIG_KEY = "forward_compact_mode"; export const SettingsPage = () => { const navigate = useNavigate(); const [panelAddresses, setPanelAddresses] = useState([]); const [newName, setNewName] = useState(""); const [newAddress, setNewAddress] = useState(""); const [updateChannel, setUpdateChannel] = useState( getUpdateReleaseChannel(), ); const [forwardCompactMode, setForwardCompactMode] = useState(false); const [forwardCompactModeSaving, setForwardCompactModeSaving] = useState(false); const admin = isAdmin(); const setPanelAddressesFunc = (newAddress: PanelAddress[]) => { setPanelAddresses(newAddress); }; // 加载面板地址列表 const loadPanelAddresses = async () => { (window as any).setPanelAddresses = setPanelAddressesFunc; getPanelAddresses(); }; // 添加新面板地址 const addPanelAddress = async () => { if (!newName.trim() || !newAddress.trim()) { toast.error("请输入名称和地址"); return; } // 验证地址格式 if (!validatePanelAddress(newAddress.trim())) { toast.error( "地址格式不正确,请检查:\n• 必须是完整的URL格式\n• 必须以 http:// 或 https:// 开头\n• 支持域名、IPv4、IPv6 地址\n• 端口号范围:1-65535\n• 示例:http://192.168.1.100:3000", ); return; } (window as any).setPanelAddresses = setPanelAddressesFunc; savePanelAddress(newName.trim(), newAddress.trim()); setNewName(""); setNewAddress(""); toast.success("添加成功"); }; // 设置当前面板地址 const setCurrentPanel = async (name: string) => { (window as any).setPanelAddresses = setPanelAddressesFunc; setCurrentPanelAddress(name); reinitializeBaseURL(); }; // 删除面板地址 const handleDeletePanelAddress = async (name: string) => { (window as any).setPanelAddresses = setPanelAddressesFunc; deletePanelAddress(name); reinitializeBaseURL(); toast.success("删除成功"); }; // 页面加载时获取数据 useEffect(() => { loadPanelAddresses(); loadForwardCompactMode(); }, []); const loadForwardCompactMode = async () => { try { const res = await getConfigByName(FORWARD_COMPACT_MODE_CONFIG_KEY); const enabled = res.code === 0 && typeof res.data?.value === "string" && res.data.value === "true"; setForwardCompactMode(enabled); } catch { setForwardCompactMode(false); } }; const handleForwardCompactModeChange = async (enabled: boolean) => { if (!admin || forwardCompactModeSaving) { return; } const previous = forwardCompactMode; setForwardCompactMode(enabled); setForwardCompactModeSaving(true); try { const response = await updateConfig( FORWARD_COMPACT_MODE_CONFIG_KEY, enabled ? "true" : "false", ); if (response.code === 0) { toast.success(`转发页面精简模式已${enabled ? "开启" : "关闭"}`); window.dispatchEvent( new CustomEvent("forwardCompactModeChanged", { detail: { enabled }, }), ); } else { setForwardCompactMode(previous); toast.error(response.msg || "保存精简模式失败"); } } catch { setForwardCompactMode(previous); toast.error("保存精简模式失败"); } finally { setForwardCompactModeSaving(false); } }; const handleUpdateChannelChange = (channel: UpdateReleaseChannel) => { setUpdateChannel(channel); setUpdateReleaseChannel(channel); toast.success( `更新通道已切换为${channel === "stable" ? "稳定版" : "开发版"}`, ); }; return (
{/* 顶部导航 */}

面板设置

{/* 内容区域 */}

更新设置

版本提示会根据该通道检查最新版本。

显示设置

转发页面精简模式

开启后,转发页面列表使用 2.1.6-alpha8 样式。

{!admin && (

仅管理员可修改该全局配置。

)}
{/* 添加新地址 */}

添加新面板地址

setNewName(e.target.value)} /> setNewAddress(e.target.value)} />
{/* 地址列表 */}

已保存的面板地址

{panelAddresses.length === 0 ? (

暂无保存的面板地址

) : (
{panelAddresses.map((panel, index) => (
{panel.name} {panel.inx && ( 当前 )}

{panel.address}

{!panel.inx && ( )}
))}
)}
); };