diff --git a/lite/config.json b/lite/config.json index 4a51fad..62041e8 100644 --- a/lite/config.json +++ b/lite/config.json @@ -1,5 +1,5 @@ { - "version": "999909181706", + "version": "999909182030", "pac_base_url": "https://cdn.rrrosmontis.icu/RRPP/PAC/", "nodes_url": "https://api.rrrosmontis.icu/v1/rrpp/subscription?method=rrpp_client", "update_url": "https://git.rrrosmontis.icu/api/v1/repos/RoyirinRosmontis/Private-Proxy/releases/latest" diff --git a/lite/main.py b/lite/main.py index 4b0e6f6..4cf24b1 100644 --- a/lite/main.py +++ b/lite/main.py @@ -1368,6 +1368,24 @@ def _set_local_port(port): _settings_save(data) log(f"代理转发端口已保存: {port}(下次开启代理生效)") +def _use_builtin_pac(): + """是否使用固定本地代理承载系统流量、由转发器内部执行 PAC 判断。""" + return bool(_settings_load().get("builtin_pac", False)) + +def _set_builtin_pac(enabled): + """保存内置 PAC 偏好,下一次开启代理时生效。""" + data = _settings_load() + data["builtin_pac"] = bool(enabled) + _settings_save(data) + +def _should_use_system_pac(use_pac, use_builtin_pac): + """决定系统侧是否下发 PAC;内置 PAC 只保留转发器内部智能分流。""" + return bool(use_pac and not use_builtin_pac) + +def _should_use_internal_pac(use_pac, use_builtin_pac): + """决定转发器内部是否启用 PAC 智能直连/代理判断。""" + return bool(use_pac or use_builtin_pac) + def _update_via_proxy(): """更新检查/下载是否走节点隧道(CONNECT);设置项,默认关=直连仓库。""" return bool(_settings_load().get("update_via_proxy", False)) @@ -2612,10 +2630,12 @@ def _settings_services(): load_icon=load_icon, version=VERSION, get_port=lambda: _TLS_LOCAL_PORT, + get_builtin_pac=_use_builtin_pac, get_update_via_proxy=_update_via_proxy, get_skip_update_check=_skip_update_check, parse_port=_parse_port, set_port=_set_local_port, + set_builtin_pac=_set_builtin_pac, set_update_via_proxy=_set_update_via_proxy, set_skip_update_check=_set_skip_update_check, open_whitelist=lambda parent: FixedRouteDialog(_fixed_route_services(), parent).exec_(), @@ -2954,6 +2974,7 @@ class MainWindow(QWidget): # 在 GUI 线程读取控件状态传参,避免子线程直接访问 Qt 控件(非线程安全) use_pac = self.cb_pac.isChecked() use_bypass_lan = self.cb_bypass_lan.isChecked() + use_builtin_pac = _use_builtin_pac() self._start_cancel_event = threading.Event() self._start_in_progress = True # 网络探测可能需要数秒;此时保留按钮给用户取消,而不是把界面锁死。 @@ -2961,12 +2982,12 @@ class MainWindow(QWidget): self.btn_toggle.setEnabled(True) threading.Thread( target=self._start_thread, - args=(use_pac, use_bypass_lan, self._start_cancel_event), + args=(use_pac, use_bypass_lan, use_builtin_pac, self._start_cancel_event), daemon=True, ).start() - def _start_thread(self, use_pac, use_bypass_lan, cancel_event): + def _start_thread(self, use_pac, use_bypass_lan, use_builtin_pac, cancel_event): try: - self._start_proxy(use_pac, use_bypass_lan, cancel_event) + self._start_proxy(use_pac, use_bypass_lan, use_builtin_pac, cancel_event) _raise_if_start_cancelled(cancel_event) self._op_done.emit("start", True) except _StartCancelled: @@ -2991,8 +3012,8 @@ class MainWindow(QWidget): _tls_stop() _stop_pac_server() - def _start_proxy(self, use_pac, use_bypass_lan, cancel_event=None): - """启动本地转发器并设置系统代理(PAC/固定两种模式),可在后台线程调用。""" + def _start_proxy(self, use_pac, use_bypass_lan, use_builtin_pac=False, cancel_event=None): + """启动本地转发器并设置系统代理(普通 PAC、内置 PAC 或固定代理)。""" if _endpoint_domain() == "???": # 未配置节点时禁止开启:否则系统代理会指向连不通任何目标的转发器,导致断网 raise RuntimeError("未配置节点:请先通过 nodes_url 在线更新或 nodes_tool 导入节点配置") @@ -3008,16 +3029,18 @@ class MainWindow(QWidget): if jump_chain: log(f" 跳板路径: {_jump_route_text(current_node)}") # PAC 模式:全部流量进转发器,按域名表/解析 IP 智能分流 - if use_pac: + use_internal_pac = _should_use_internal_pac(use_pac, use_builtin_pac) + if use_internal_pac: _load_cn_ranges() _load_force_proxy_suffixes() _load_direct_domains() _raise_if_start_cancelled(cancel_event) - _tls_start(ep, _endpoint_port(), use_tls=True, bypass_lan=use_bypass_lan, smart=use_pac, + _tls_start(ep, _endpoint_port(), use_tls=True, bypass_lan=use_bypass_lan, + smart=use_internal_pac, jump_chain=jump_chain) try: _raise_if_start_cancelled(cancel_event) - if use_pac: + if _should_use_system_pac(use_pac, use_builtin_pac): # 本地生成全量转发 PAC(不再从服务器拉取),全部流量交给转发器做智能分流 pac_content = _build_pac(f"{PROXY_HOST}:{PROXY_PORT}") if use_bypass_lan: @@ -3035,6 +3058,8 @@ class MainWindow(QWidget): _raise_if_start_cancelled(cancel_event) proxy_on(bypass_lan=use_bypass_lan) self._proxy_set_by_us = True + if use_builtin_pac: + log(f"使用内置 PAC:系统固定代理 127.0.0.1:{PROXY_PORT},转发器内部智能分流") _raise_if_start_cancelled(cancel_event) if use_bypass_lan: log("不代理内网 IP:内网地址将直连") diff --git a/lite/rrpp_ui/dialogs.py b/lite/rrpp_ui/dialogs.py index 7e3dfd8..272a2e0 100644 --- a/lite/rrpp_ui/dialogs.py +++ b/lite/rrpp_ui/dialogs.py @@ -930,10 +930,12 @@ class SettingsServices: load_icon: object version: str get_port: object + get_builtin_pac: object get_update_via_proxy: object get_skip_update_check: object parse_port: object set_port: object + set_builtin_pac: object set_update_via_proxy: object set_skip_update_check: object open_whitelist: object @@ -953,7 +955,7 @@ class SettingsDialog(QDialog): self._services = services self.setWindowTitle("设置") self.setWindowIcon(services.load_icon()) - self.setFixedSize(300, 350) + self.setFixedSize(300, 380) self.setStyleSheet(f""" QDialog {{ background-color: {C_BG}; }} QLabel {{ color: {C_TEXT}; font-family: "Microsoft YaHei", "Segoe UI", sans-serif; font-size: 12px; }} @@ -1056,6 +1058,21 @@ class SettingsDialog(QDialog): port_row.addWidget(self.ed_port) layout.addLayout(port_row) + builtin_pac_row = QHBoxLayout() + builtin_pac_label = QLabel("使用内置 PAC") + builtin_pac_label.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 12px;") + builtin_pac_label.setToolTip( + "系统使用固定的本地代理端口;转发器内部仍按 PAC 规则智能判断直连或代理" + ) + builtin_pac_row.addWidget(builtin_pac_label) + builtin_pac_row.addStretch() + self.cb_builtin_pac = ToggleSwitch(checked=services.get_builtin_pac()) + self.cb_builtin_pac.setToolTip( + "系统固定指向本地代理端口,转发器内部保留 PAC 智能分流" + ) + builtin_pac_row.addWidget(self.cb_builtin_pac) + layout.addLayout(builtin_pac_row) + update_row = QHBoxLayout() update_label = QLabel("使用代理更新") update_label.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 12px;") @@ -1138,6 +1155,7 @@ class SettingsDialog(QDialog): self.lb_hint.setStyleSheet(f"color: {C_RED}; font-size: 11px;") return self._services.set_port(port) + self._services.set_builtin_pac(bool(self.cb_builtin_pac.isChecked())) self._services.set_update_via_proxy(bool(self.cb_update_proxy.isChecked())) self._services.set_skip_update_check(bool(self.cb_skip_update.isChecked())) self.ed_port.setText(str(port))