From 3c83f2664707c22af5d4161a811c51873556a1b1 Mon Sep 17 00:00:00 2001 From: RoyirinRosmontis Date: Sun, 23 Aug 2026 13:47:56 +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=E5=BA=95=E9=83=A8=E6=8F=90=E7=A4=BA=E8=A1=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=EF=BC=9A=E5=B7=A6=E5=AF=B9=E9=BD=90"=E8=AF=B7?= =?UTF-8?q?=E5=8B=BF=E4=BA=8C=E6=AC=A1=E5=88=86=E5=8F=91=E6=AD=A4=E8=BD=AF?= =?UTF-8?q?=E4=BB=B6=EF=BC=81"+=20=E5=8F=B3=E5=AF=B9=E9=BD=90"=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE"=E5=85=A5=E5=8F=A3=EF=BC=88hover=20=E4=B8=8B=E5=88=92?= =?UTF-8?q?=E7=BA=BF+=E6=89=8B=E5=9E=8B=EF=BC=8C=E4=B8=8E=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=A0=87=E7=AD=BE=E4=B8=80=E8=87=B4=EF=BC=89=20-=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=AE=BE=E7=BD=AE=E5=BC=B9=E7=AA=97=EF=BC=88?= =?UTF-8?q?=E9=A3=8E=E6=A0=BC=E4=B8=8E=E7=99=BB=E5=BD=95=E6=A1=86=E4=B8=80?= =?UTF-8?q?=E8=87=B4=EF=BC=89=EF=BC=8C=E7=9B=AE=E5=89=8D=E4=BB=85=E5=90=AB?= =?UTF-8?q?"=E9=80=80=E5=87=BA=E7=99=BB=E5=BD=95"=EF=BC=9A=E6=B8=85?= =?UTF-8?q?=E9=99=A4=E5=8A=A0=E5=AF=86=E5=87=AD=E6=8D=AE=E4=B8=8E=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E8=8A=82=E7=82=B9=E9=85=8D=E7=BD=AE=EF=BC=8C=E4=B8=8B?= =?UTF-8?q?=E6=AC=A1=E5=90=AF=E5=8A=A8/=E5=BC=80=E5=90=AF=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E6=97=B6=E8=A6=81=E6=B1=82=E9=87=8D=E6=96=B0=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lite/proxy_lite.py | 86 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/lite/proxy_lite.py b/lite/proxy_lite.py index 377a156..9757e26 100644 --- a/lite/proxy_lite.py +++ b/lite/proxy_lite.py @@ -1139,21 +1139,24 @@ _NL_BASE = f"color: {C_TITLE}; font-size: 12px;" _NL_HOVER = _NL_BASE + " text-decoration: underline;" class NodeLabel(QLabel): - """节点标签:hover 显示下划线+手型光标,点击发出 clicked 信号。""" + """可点击标签:hover 显示下划线+手型光标,点击发出 clicked 信号。""" clicked = pyqtSignal() - def __init__(self, text=""): + def __init__(self, text="", tooltip="点击切换节点", base=None, hover=None): super().__init__(text) - self.setStyleSheet(_NL_BASE) - self.setToolTip("点击切换节点") + self._base = base or _NL_BASE + self._hover = hover or self._base + " text-decoration: underline;" + self.setStyleSheet(self._base) + if tooltip: + self.setToolTip(tooltip) def enterEvent(self, e): - self.setStyleSheet(_NL_HOVER) + self.setStyleSheet(self._hover) self.setCursor(Qt.PointingHandCursor) super().enterEvent(e) def leaveEvent(self, e): - self.setStyleSheet(_NL_BASE) + self.setStyleSheet(self._base) self.unsetCursor() super().leaveEvent(e) @@ -1309,6 +1312,57 @@ class LoginDialog(QDialog): self.lb_err.setText(info) self.lb_err.show() +# ── 设置弹窗 ───────────────────────────────────────── + +class SettingsDialog(QDialog): + """设置弹窗(当前仅含退出登录:清除凭据与本地节点配置)。""" + + def __init__(self, parent=None): + super().__init__(parent) + self.setWindowTitle("设置") + self.setWindowIcon(load_icon()) + self.setFixedSize(280, 150) + self.setStyleSheet(f""" + QDialog {{ background-color: {C_BG}; }} + QLabel {{ color: {C_TEXT}; font-family: "Microsoft YaHei", "Segoe UI", sans-serif; font-size: 12px; }} + """) + + layout = QVBoxLayout(self) + layout.setSpacing(12) + layout.setContentsMargins(20, 16, 20, 16) + + title = QLabel("设置") + title.setStyleSheet(f"color: {C_TITLE}; font-size: 15px; font-weight: bold;") + title.setAlignment(Qt.AlignCenter) + layout.addWidget(title) + + 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; + }} + QPushButton:hover {{ background-color: #ffecec; }} + """) + btn_logout.setToolTip("清除登录凭据与本地节点配置,下次启动需重新登录") + btn_logout.clicked.connect(self._logout) + layout.addWidget(btn_logout) + + layout.addStretch() + + def _logout(self): + """退出登录:删除加密凭据与本地节点配置,清空内存缓存。""" + global _NODES + for name in ("auth.json", "nodes.json"): + try: + (_USER_DIR / name).unlink(missing_ok=True) + except Exception: + pass + _NODES = None + log("已退出登录:凭据与节点配置已清除,下次启动或开启代理时需重新登录") + self.accept() + # ── 状态指示灯(小圆点) ─────────────────────────────── class StatusDot(QLabel): @@ -1529,10 +1583,20 @@ class MainWindow(QWidget): hints_layout.setContentsMargins(0, 0, 0, 0) hints_layout.setSpacing(1) + # 第一行:左对齐警示 + 右对齐"设置"入口 + top_row = QHBoxLayout() + top_row.setContentsMargins(0, 0, 0, 0) warn_label = QLabel("请勿二次分发此软件!") warn_label.setStyleSheet(f"color: {C_RED}; font-size: 11px;") - warn_label.setAlignment(Qt.AlignCenter) - hints_layout.addWidget(warn_label) + top_row.addWidget(warn_label) + top_row.addStretch() + self.link_settings = NodeLabel( + "设置", tooltip="设置", + base=f"color: {C_SUBTEXT}; font-size: 11px;", + hover=f"color: {C_TEXT}; font-size: 11px; text-decoration: underline;") + self.link_settings.clicked.connect(self._show_settings_dialog) + top_row.addWidget(self.link_settings) + hints_layout.addLayout(top_row) privacy_label = QLabel("使用此软件将会收集并上报您的 IP 地址及部分设备信息") privacy_label.setStyleSheet("color: #c8ccd4; font-size: 9px;") @@ -1668,6 +1732,12 @@ class MainWindow(QWidget): self._op_done.emit("stop", False) + # ── 设置 ── + def _show_settings_dialog(self): + """打开设置弹窗;退出登录后刷新节点标题。""" + SettingsDialog(self).exec_() + self._refresh_subtitle() + # ── 节点登录 ── def _maybe_show_login(self): """启动时节点未配置:隐藏主窗口只显示登录框;登录成功恢复,取消则退出。"""