From 97d05ce612da907b1ba6bcf9d8b979bea32fa891 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Fri, 6 Feb 2026 12:19:28 +0800 Subject: [PATCH] feat: Add explicit Apply button to Sandbox Node Binding UI --- .../components/SandboxNodeBindingPanel.tsx | 139 +++++++++++------- 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/src/modules/extensions/builtin/user-center/management/components/SandboxNodeBindingPanel.tsx b/src/modules/extensions/builtin/user-center/management/components/SandboxNodeBindingPanel.tsx index 4628d5d..230ab77 100644 --- a/src/modules/extensions/builtin/user-center/management/components/SandboxNodeBindingPanel.tsx +++ b/src/modules/extensions/builtin/user-center/management/components/SandboxNodeBindingPanel.tsx @@ -44,65 +44,102 @@ export default function SandboxNodeBindingPanel() { }) const [message, setMessage] = useState(null) - const current = getSandboxNodeBinding() - const selectedAddress = current?.address ?? '' + const currentBinding = useMemo(() => getSandboxNodeBinding(), []) + const [draftAddress, setDraftAddress] = useState(currentBinding?.address ?? '') - const selectedNode = useMemo( - () => nodes?.find((node) => node.address === selectedAddress) ?? null, - [nodes, selectedAddress], - ) + const isChanged = useMemo(() => { + const current = getSandboxNodeBinding() + return (current?.address ?? '') !== draftAddress + }, [draftAddress]) + + const handleApply = () => { + const address = draftAddress.trim() + if (!address) { + clearSandboxNodeBinding() + setMessage('已成功清空绑定节点') + } else { + const node = nodes?.find((item) => item.address === address) + if (!node) { + setMessage('错误:选择的节点不存在') + return + } + setSandboxNodeBinding({ + address: node.address, + name: node.name, + updatedBy: 'root', + }) + setMessage(`应用成功:已绑定至 ${node.name || node.address}`) + } + } + + const currentActive = getSandboxNodeBinding() return ( -
-

Root 管理员专用:Sandbox Node 绑定节点

-

仅允许绑定 1 个节点,Sandbox@svc.plus 会使用该节点生成 VLESS 配置。

+
+
+

Root 管理员专用:Sandbox Node 绑定节点

+

选择并“确认应用”后,Sandbox@svc.plus 将固定使用该节点生成配置。

+
- + + +
- {selectedNode ? ( -

- 当前绑定:{selectedNode.name || selectedNode.address} +

+ {currentActive ? ( +
+
+ 当前活跃绑定:{currentActive.name || currentActive.address} +
+ ) : ( +
+
+ 当前未绑定任何节点 +
+ )} + {currentActive?.updatedAt && ( +

+ 最后更新时间:{new Date(currentActive.updatedAt).toLocaleString()} +

+ )} +
+ + {error &&

⚠️ 节点列表加载失败:{error.message}

} + {message && ( +

+ {message}

- ) : null} - {current?.updatedAt ? ( -

最后更新:{new Date(current.updatedAt).toLocaleString()}

- ) : null} - {error ?

节点加载失败:{error.message}

: null} - {message ?

{message}

: null} + )}
)