feat(onboarding): add first-run membership activation
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
"""First-run membership activation dialog."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
QCheckBox,
|
||||
QDialog,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from .widgets import (
|
||||
BUTTON_BASE_STYLE,
|
||||
COLOR_DANGER,
|
||||
COLOR_INFO,
|
||||
COLOR_MUTED,
|
||||
COLOR_SUCCESS,
|
||||
_primary_button_style,
|
||||
)
|
||||
|
||||
|
||||
class MembershipActivationDialog(QDialog):
|
||||
"""Collect one membership API key and report asynchronous validation state."""
|
||||
|
||||
validationRequested = Signal(str)
|
||||
memberCenterRequested = Signal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._validating = False
|
||||
self.setObjectName("membershipActivationDialog")
|
||||
self.setWindowTitle("激活蝦皮圈优化助手")
|
||||
self.setModal(True)
|
||||
self.setWindowModality(Qt.WindowModal)
|
||||
self.setMinimumWidth(520)
|
||||
self.setStyleSheet(BUTTON_BASE_STYLE)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(24, 22, 24, 22)
|
||||
layout.setSpacing(12)
|
||||
|
||||
heading = QLabel("首次使用需要绑定会员账号")
|
||||
heading.setObjectName("membershipActivationHeading")
|
||||
heading.setStyleSheet("font-size: 16px; font-weight: 600; color: #24292f;")
|
||||
layout.addWidget(heading)
|
||||
|
||||
description = QLabel(
|
||||
"请从线上会员中心复制会员 API Key。程序会先验证账号和套餐,"
|
||||
"验证通过后再开放业务功能。"
|
||||
)
|
||||
description.setObjectName("membershipActivationDescription")
|
||||
description.setWordWrap(True)
|
||||
description.setStyleSheet(f"color: {COLOR_MUTED};")
|
||||
layout.addWidget(description)
|
||||
|
||||
key_label = QLabel("会员 API Key")
|
||||
key_label.setObjectName("membershipApiKeyLabel")
|
||||
layout.addWidget(key_label)
|
||||
|
||||
self.api_key_edit = QLineEdit()
|
||||
self.api_key_edit.setObjectName("membershipApiKeyEdit")
|
||||
self.api_key_edit.setEchoMode(QLineEdit.Password)
|
||||
self.api_key_edit.setPlaceholderText("粘贴会员 API Key")
|
||||
self.api_key_edit.setClearButtonEnabled(True)
|
||||
self.api_key_edit.returnPressed.connect(self._request_validation)
|
||||
key_label.setBuddy(self.api_key_edit)
|
||||
layout.addWidget(self.api_key_edit)
|
||||
|
||||
self.show_key_checkbox = QCheckBox("显示 API Key")
|
||||
self.show_key_checkbox.setObjectName("showMembershipApiKeyCheckbox")
|
||||
self.show_key_checkbox.toggled.connect(self._toggle_key_visibility)
|
||||
layout.addWidget(self.show_key_checkbox)
|
||||
|
||||
storage_hint = QLabel(
|
||||
"API Key 在输入框和设置页中打码显示,但会以本机明文配置保存,"
|
||||
"仅用于会员验证和默认网关请求。"
|
||||
)
|
||||
storage_hint.setObjectName("membershipApiKeyStorageHint")
|
||||
storage_hint.setWordWrap(True)
|
||||
storage_hint.setStyleSheet(f"color: {COLOR_MUTED};")
|
||||
layout.addWidget(storage_hint)
|
||||
|
||||
self.status_label = QLabel("")
|
||||
self.status_label.setObjectName("membershipActivationStatusLabel")
|
||||
self.status_label.setWordWrap(True)
|
||||
self.status_label.setMinimumHeight(36)
|
||||
layout.addWidget(self.status_label)
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.setSpacing(8)
|
||||
self.member_center_button = QPushButton("前往会员中心获取 API Key")
|
||||
self.member_center_button.setObjectName("membershipCenterButton")
|
||||
self.member_center_button.clicked.connect(self.memberCenterRequested.emit)
|
||||
button_layout.addWidget(self.member_center_button)
|
||||
button_layout.addStretch(1)
|
||||
|
||||
self.exit_button = QPushButton("退出程序")
|
||||
self.exit_button.setObjectName("membershipActivationExitButton")
|
||||
self.exit_button.clicked.connect(self.reject)
|
||||
button_layout.addWidget(self.exit_button)
|
||||
|
||||
self.validate_button = QPushButton("验证并开始使用")
|
||||
self.validate_button.setObjectName("membershipActivationValidateButton")
|
||||
self.validate_button.setDefault(True)
|
||||
self.validate_button.setStyleSheet(
|
||||
_primary_button_style("membershipActivationValidateButton")
|
||||
)
|
||||
self.validate_button.clicked.connect(self._request_validation)
|
||||
button_layout.addWidget(self.validate_button)
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
self.api_key_edit.setFocus()
|
||||
|
||||
def api_key(self) -> str:
|
||||
return self.api_key_edit.text().strip()
|
||||
|
||||
def set_validating(self, validating: bool) -> None:
|
||||
self._validating = bool(validating)
|
||||
self.api_key_edit.setEnabled(not self._validating)
|
||||
self.show_key_checkbox.setEnabled(not self._validating)
|
||||
self.validate_button.setEnabled(not self._validating)
|
||||
self.validate_button.setText(
|
||||
"正在验证会员账号..." if self._validating else "验证并开始使用"
|
||||
)
|
||||
if self._validating:
|
||||
self.set_status("正在验证会员账号,请稍候。", level="info")
|
||||
|
||||
def set_status(self, message: str, *, level: str = "muted") -> None:
|
||||
color = {
|
||||
"danger": COLOR_DANGER,
|
||||
"info": COLOR_INFO,
|
||||
"success": COLOR_SUCCESS,
|
||||
}.get(str(level), COLOR_MUTED)
|
||||
self.status_label.setStyleSheet(f"color: {color};")
|
||||
self.status_label.setText(str(message or ""))
|
||||
|
||||
def focus_api_key(self) -> None:
|
||||
self.api_key_edit.setFocus()
|
||||
self.api_key_edit.selectAll()
|
||||
|
||||
def accept_activation(self) -> None:
|
||||
self.set_validating(False)
|
||||
self.accept()
|
||||
|
||||
def _request_validation(self) -> None:
|
||||
if self._validating:
|
||||
return
|
||||
key = self.api_key()
|
||||
if not key:
|
||||
self.set_status("请输入会员 API Key。", level="danger")
|
||||
self.focus_api_key()
|
||||
return
|
||||
self.validationRequested.emit(key)
|
||||
|
||||
def _toggle_key_visibility(self, checked: bool) -> None:
|
||||
mode = QLineEdit.Normal if checked else QLineEdit.Password
|
||||
self.api_key_edit.setEchoMode(mode)
|
||||
Reference in New Issue
Block a user