From 40175a144d9527defd4affcdf8b060cebe5db7c1 Mon Sep 17 00:00:00 2001 From: RoyirinRosmontis Date: Sun, 23 Aug 2026 13:53:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD=EF=BC=9A?= =?UTF-8?q?=20-=20=E4=BB=A3=E7=90=86=E8=BD=AC=E5=8F=91=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E4=BB=8E=E5=86=85=E7=BD=AE=20config.json=20=E7=A7=BB=E5=88=B0?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=BC=B9=E7=AA=97=EF=BC=9A=E5=8F=AF=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=B9=B6=E6=8C=81=E4=B9=85=E5=8C=96=E5=88=B0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=95=B0=E6=8D=AE=E7=9B=AE=E5=BD=95=20settings.json?= =?UTF-8?q?=EF=BC=88=E4=B8=8B=E6=AC=A1=E5=BC=80=E5=90=AF=E4=BB=A3=E7=90=86?= =?UTF-8?q?=E7=94=9F=E6=95=88=EF=BC=89=20-=20=E5=8F=96=E5=80=BC=E9=93=BE?= =?UTF-8?q?=EF=BC=9A=E6=9C=AC=E5=9C=B0=E8=AE=BE=E7=BD=AE=20>=20=E5=86=85?= =?UTF-8?q?=E7=BD=AE=20config.json=20>=20=E9=BB=98=E8=AE=A4=201080?= =?UTF-8?q?=EF=BC=9B=E9=9D=9E=E6=B3=95=E8=BE=93=E5=85=A5=EF=BC=88=E9=9D=9E?= =?UTF-8?q?=E6=95=B0=E5=AD=97/=E8=B6=85=E5=87=BA=201-65535=EF=BC=89?= =?UTF-8?q?=E6=8B=92=E7=BB=9D=E4=BF=9D=E5=AD=98=20-=20=E4=BB=A3=E7=90=86?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E4=B8=AD=E9=94=81=E5=AE=9A=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=88=E8=BE=93=E5=85=A5=E6=A1=86=E4=B8=8E?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=8C=89=E9=92=AE=E7=A6=81=E7=94=A8=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E5=85=88=E5=85=B3=E9=97=AD=E4=BB=A3=E7=90=86?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lite/proxy_lite.py | 114 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 7 deletions(-) diff --git a/lite/proxy_lite.py b/lite/proxy_lite.py index 9757e26..1d5f1cb 100644 --- a/lite/proxy_lite.py +++ b/lite/proxy_lite.py @@ -539,9 +539,60 @@ def _user_path(name: str): return p return _data_path(name) +# ── 本地设置(settings.json,用户数据目录,明文) ───────────── + +def _settings_path(): + return _USER_DIR / "settings.json" + +def _settings_load(): + """读取本地设置;缺失或损坏返回空字典。""" + try: + import json + f = _settings_path() + if not f.is_file(): + return {} + data = json.loads(f.read_text("utf-8")) + return data if isinstance(data, dict) else {} + except Exception: + return {} + +def _settings_save(data): + """本地设置原子写回。""" + import json + _USER_DIR.mkdir(parents=True, exist_ok=True) + tmp = _settings_path().with_suffix(".json.tmp") + tmp.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", "utf-8") + os.replace(tmp, _settings_path()) + +def _parse_port(text): + """解析端口号;非法(非数字或超出 1-65535)返回 None。""" + try: + port = int(str(text).strip()) + except (TypeError, ValueError): + return None + return port if 1 <= port <= 65535 else None + +def _port_val(): + """代理转发端口:本地设置 > 内置 config.json > 默认 1080。""" + port = _parse_port(_settings_load().get("local_port")) + if port is not None: + return port + port = _parse_port(_config_val("local_port", 1080)) + return port if port is not None else 1080 + +def _set_local_port(port): + """更新代理转发端口并写回设置文件(下次开启代理生效)。""" + global _TLS_LOCAL_PORT, PROXY_PORT + _TLS_LOCAL_PORT = port + PROXY_PORT = port + data = _settings_load() + data["local_port"] = port + _settings_save(data) + log(f"代理转发端口已保存: {port}(下次开启代理生效)") + # 以下模块级取值需在 _data_path 定义之后执行 VERSION = _config_val("version", "999908162319") -_TLS_LOCAL_PORT = int(_config_val("local_port", 1080)) # 本地转发器监听端口 +_TLS_LOCAL_PORT = _port_val() # 本地转发器监听端口(设置 > 内置 config > 1080) PROXY_PORT = _TLS_LOCAL_PORT # ── PAC 数据在线更新(CDN 直连,无需认证) ───────────── @@ -1315,16 +1366,24 @@ class LoginDialog(QDialog): # ── 设置弹窗 ───────────────────────────────────────── class SettingsDialog(QDialog): - """设置弹窗(当前仅含退出登录:清除凭据与本地节点配置)。""" + """设置弹窗:代理转发端口 + 退出登录。""" - def __init__(self, parent=None): + def __init__(self, parent=None, port_locked=False): super().__init__(parent) self.setWindowTitle("设置") self.setWindowIcon(load_icon()) - self.setFixedSize(280, 150) + self.setFixedSize(300, 230) self.setStyleSheet(f""" QDialog {{ background-color: {C_BG}; }} QLabel {{ color: {C_TEXT}; font-family: "Microsoft YaHei", "Segoe UI", sans-serif; font-size: 12px; }} + QLineEdit {{ + background-color: {C_CARD}; + border: 1px solid {C_BORDER}; + border-radius: 6px; + padding: 5px 8px; + color: {C_TEXT}; + font-size: 12px; + }} """) layout = QVBoxLayout(self) @@ -1336,12 +1395,42 @@ class SettingsDialog(QDialog): title.setAlignment(Qt.AlignCenter) layout.addWidget(title) + # 代理转发端口 + port_row = QHBoxLayout() + port_lab = QLabel("代理转发端口") + port_lab.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 12px;") + port_row.addWidget(port_lab) + port_row.addStretch() + self.ed_port = QLineEdit(str(_TLS_LOCAL_PORT)) + self.ed_port.setFixedWidth(80) + self.ed_port.setEnabled(not port_locked) + port_row.addWidget(self.ed_port) + layout.addLayout(port_row) + + self.lb_port = QLabel("代理运行中,关闭代理后可修改" if port_locked else "保存后下次开启代理生效") + self.lb_port.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 11px;") + self.lb_port.setFixedHeight(14) + layout.addWidget(self.lb_port) + + btn_save = QPushButton("保存端口") + btn_save.setStyleSheet(f""" + QPushButton {{ + background-color: {C_GREEN}; color: #fff; border: none; + border-radius: 6px; padding: 5px 14px; + font-size: 12px; font-weight: bold; + }} + QPushButton:disabled {{ background-color: #2a3a2e; color: #666; }} + """) + btn_save.setEnabled(not port_locked) + btn_save.clicked.connect(self._save_port) + layout.addWidget(btn_save) + btn_logout = QPushButton("退出登录") btn_logout.setStyleSheet(f""" QPushButton {{ background-color: {C_CARD}; color: {C_RED}; border: 1px solid {C_RED}; border-radius: 6px; - padding: 7px 16px; font-size: 13px; + padding: 5px 14px; font-size: 12px; }} QPushButton:hover {{ background-color: #ffecec; }} """) @@ -1351,6 +1440,17 @@ class SettingsDialog(QDialog): layout.addStretch() + def _save_port(self): + port = _parse_port(self.ed_port.text()) + if port is None: + self.lb_port.setText("端口应为 1-65535 的数字") + self.lb_port.setStyleSheet(f"color: {C_RED}; font-size: 11px;") + return + _set_local_port(port) + self.ed_port.setText(str(port)) + self.lb_port.setText(f"已保存: {port},下次开启代理生效") + self.lb_port.setStyleSheet(f"color: {C_GREEN}; font-size: 11px;") + def _logout(self): """退出登录:删除加密凭据与本地节点配置,清空内存缓存。""" global _NODES @@ -1734,8 +1834,8 @@ class MainWindow(QWidget): # ── 设置 ── def _show_settings_dialog(self): - """打开设置弹窗;退出登录后刷新节点标题。""" - SettingsDialog(self).exec_() + """打开设置弹窗(代理运行中锁定端口修改);退出登录后刷新节点标题。""" + SettingsDialog(self, port_locked=self._proxy_set_by_us).exec_() self._refresh_subtitle() # ── 节点登录 ──