瀏覽代碼

fix(inbound): offer node share-address strategy only when a node exists

The `node` share-address strategy resolves to an address only when the
inbound can live on a node; for a local inbound it is always empty and
behaves like `listen`. Drop the `node` option from the picker unless an
enabled, node-eligible node exists, and coerce the value to `listen`
otherwise so the Select never shows an option that does nothing.
MHSanaei 16 小時之前
父節點
當前提交
c47a905ad2
共有 1 個文件被更改,包括 22 次插入4 次删除
  1. 22 4
      frontend/src/pages/inbounds/form/InboundFormModal.tsx

+ 22 - 4
frontend/src/pages/inbounds/form/InboundFormModal.tsx

@@ -176,6 +176,10 @@ export default function InboundFormModal({
   const selectableNodes = (availableNodes || []).filter((n) => n.enable);
   const protocol = (Form.useWatch('protocol', form) ?? '') as string;
   const isNodeEligible = NODE_ELIGIBLE_PROTOCOLS.has(protocol);
+  // The `node` share-address strategy only means something when the inbound can
+  // actually live on a node — otherwise the node address it would resolve to is
+  // always empty. Offer it only then; `listen`/`custom` work for local inbounds.
+  const nodeShareOptionAvailable = selectableNodes.length > 0 && isNodeEligible;
   const sniffingEnabled = Form.useWatch(['sniffing', 'enabled'], form) ?? false;
   const vlessEncryption = Form.useWatch(['settings', 'encryption'], form) ?? '';
   const ssMethod = Form.useWatch(['settings', 'method'], form);
@@ -370,6 +374,18 @@ export default function InboundFormModal({
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [open, wPort, wNodeId, protocol, network, mixedUdpOn, wSsNetwork, wTunnelNetwork]);
 
+  // Keep the strategy value inside the visible option set: when `node` isn't
+  // offered (no node, or a protocol that can't deploy to one) fall back to
+  // `listen`, which yields the same link for a local inbound. Mirrors how the
+  // protocol reset drops a nodeId that no longer applies.
+  useEffect(() => {
+    if (!open) return;
+    if (!nodeShareOptionAvailable && shareAddrStrategy === 'node') {
+      form.setFieldValue('shareAddrStrategy', 'listen');
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [open, nodeShareOptionAvailable, shareAddrStrategy]);
+
   // Why: protocol picker reset cascades through the form — clearing the
   // settings DU branch and dropping a nodeId that no longer applies. The
   // legacy modal did this imperatively in onProtocolChange; here we hook
@@ -532,10 +548,12 @@ export default function InboundFormModal({
         extra={t('pages.inbounds.form.shareAddrStrategyHelp')}
       >
         <Select
-          options={SHARE_ADDR_STRATEGIES.map((strategy) => ({
-            value: strategy,
-            label: t(`pages.inbounds.form.shareAddrStrategyOptions.${strategy}`),
-          }))}
+          options={SHARE_ADDR_STRATEGIES
+            .filter((strategy) => strategy !== 'node' || nodeShareOptionAvailable)
+            .map((strategy) => ({
+              value: strategy,
+              label: t(`pages.inbounds.form.shareAddrStrategyOptions.${strategy}`),
+            }))}
         />
       </Form.Item>