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() # ── 节点登录 ──