新增功能:

- 代理转发端口从内置 config.json 移到设置弹窗:可修改并持久化到用户数据目录 settings.json(下次开启代理生效)
- 取值链:本地设置 > 内置 config.json > 默认 1080;非法输入(非数字/超出 1-65535)拒绝保存
- 代理运行中锁定端口修改(输入框与保存按钮禁用,提示先关闭代理)
This commit is contained in:
RoyirinRosmontis
2026-08-23 13:53:23 +08:00
parent 3c83f26647
commit 40175a144d
+107 -7
View File
@@ -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()
# ── 节点登录 ──