From 7f070a0693073a17f048bdcb1abef456f6873c7e Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Tue, 30 Jun 2026 07:01:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(client):=20=E7=9C=8B=E9=97=A8=E7=8B=97=20pa?= =?UTF-8?q?th=20A=20=E4=BB=85=E5=9C=A8=E3=80=8C=E8=BF=9E=E4=B8=8A(on)?= =?UTF-8?q?=E5=90=8E=E6=8E=89=E7=BA=BF=E3=80=8D=E8=A7=A6=E5=8F=91,?= =?UTF-8?q?=E6=8E=92=E9=99=A4=20connecting=20=E6=8F=A1=E6=89=8B=E7=9E=AC?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS NE 连接序列是 off→connecting→off→connecting→on,connecting 期有瞬态 off。原 path A 条件 wasActive 含 connecting → 一连接就在握手瞬态 off 上误报「节点异常」(实际连上了)。 改:仅 phase==on(真正连上过)再非用户主动掉线才判节点异常;connecting→off(握手抖动/ 连接失败)不触发。跨端修复(桌面也更稳)。 Co-Authored-By: Claude Opus 4.8 --- client/lib/state/connection_provider.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/lib/state/connection_provider.dart b/client/lib/state/connection_provider.dart index 6eb2272..90ad956 100644 --- a/client/lib/state/connection_provider.dart +++ b/client/lib/state/connection_provider.dart @@ -216,12 +216,13 @@ class ConnectionController extends StateNotifier { _stopWatchdog(); case VpnStatus.off: case VpnStatus.error: - final wasActive = state.phase == VpnPhase.on || state.phase == VpnPhase.connecting; - // 路径 A:非用户主动、且本来在连/已连 → 节点数据面死导致的意外掉线。 - // 给原因(节点异常)+ 刷节点列表让服务端 down 浮现。_offNotice 让显式断开与本回调统一。 - if (!_userDisconnect && wasActive && _offNotice == null) { + // 路径 A:仅「真正连上过(on)再非用户主动掉线」才判节点异常(数据面死/REALITY 断)。 + // 必须排除 connecting 握手期的瞬态 off——macOS NE 连接序列是 off→connecting→off→ + // connecting→on,connecting 期的 off 是握手抖动、不是异常(否则一连接就误报「节点异常」)。 + final wasConnected = state.phase == VpnPhase.on; + if (!_userDisconnect && wasConnected && _offNotice == null) { _offNotice = _ref.read(appTextProvider).nodeUnhealthyError; - logLine('Watchdog', 'unexpected kernel ${s.name} while $wasActive → node interrupted'); + logLine('Watchdog', 'unexpected kernel ${s.name} after connected → node interrupted'); unawaited(_ref.read(nodesProvider.notifier).refresh()); } state = ConnectionState(phase: VpnPhase.off, error: _offNotice);