#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 登录对话框 用户登录验证界面 """ from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QComboBox, QLineEdit, QMessageBox, QWidget, QPushButton as QBtn ) from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QFont, QIcon, QPixmap, QPainter, QPen, QBrush, QColor, QPolygon, QPolygonF from PyQt5.QtCore import QPoint, QPointF import requests import json # 尝试导入配置 try: from config import USE_HTTP_API, HTTP_API_BASE_URL except ImportError: USE_HTTP_API = True HTTP_API_BASE_URL = "http://127.0.0.1:5050" class LoginDialog(QDialog): """登录对话框""" def __init__(self, parent=None): super().__init__(parent) self.user_info = None # 存储登录成功后的用户信息 self.setWindowTitle("登录") self.setModal(True) self.setFixedSize(500, 300) # HTTP API 配置 self.use_http_api = USE_HTTP_API self.api_base_url = HTTP_API_BASE_URL self._build_ui() def _create_arrow_icon(self): """创建下拉箭头图标""" pixmap = QPixmap(20, 20) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) painter.setRenderHint(QPainter.Antialiasing) # 绘制三角形箭头 painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(102, 102, 102))) # #666 triangle = QPolygonF([ QPointF(3.75, 5.5), QPointF(16.25, 5.5), QPointF(10, 14.5) ]) painter.drawPolygon(triangle) painter.end() return pixmap def _build_ui(self): """构建界面""" layout = QVBoxLayout(self) layout.setContentsMargins(60, 40, 60, 40) layout.setSpacing(20) # 创建下拉箭头图标 arrow_pixmap = self._create_arrow_icon() # 标题 title_label = QLabel("跌落试验管理系统") title_label.setAlignment(Qt.AlignCenter) title_font = QFont() title_font.setPointSize(18) title_font.setBold(True) title_label.setFont(title_font) title_label.setStyleSheet("color: #333; margin-bottom: 20px;") layout.addWidget(title_label) # 用户名行 username_layout = QHBoxLayout() username_label = QLabel("用户名") username_label.setFixedWidth(80) username_label.setStyleSheet("font-size: 14px; color: #666;") username_layout.addWidget(username_label) # 用户名下拉框(可编辑) self.username_combo = QComboBox() self.username_combo.setEditable(True) self.username_combo.addItems(['test', 'admin', 'topAdmin123']) self.username_combo.setCurrentText('') # 默认为空 # 保存箭头图标以便在样式表中引用 arrow_path = "e:/WORK/DTM-PY-ALL/UI/temp_arrow.png" arrow_pixmap.save(arrow_path, "PNG") # 设置样式,使用图片作为箭头 self.username_combo.setStyleSheet(f""" QComboBox {{ padding: 8px; padding-right: 30px; border: 1px solid #ddd; border-radius: 4px; font-size: 18px; background: white; min-height: 24px; }} QComboBox:hover {{ border: 1px solid #3A84FF; }} QComboBox:editable {{ background: white; }} QComboBox::drop-down {{ subcontrol-origin: padding; subcontrol-position: center right; width: 30px; border-left: 1px solid #ddd; background: #fafafa; }} QComboBox::drop-down:hover {{ background: #f0f0f0; }} QComboBox::down-arrow {{ image: url({arrow_path.replace(chr(92), '/')}); width: 16px; height: 16px; }} """) self.username_combo.lineEdit().setPlaceholderText("请输入用户名") username_layout.addWidget(self.username_combo) layout.addLayout(username_layout) # 密码行 password_layout = QHBoxLayout() password_label = QLabel("密码") password_label.setFixedWidth(80) password_label.setStyleSheet("font-size: 14px; color: #666;") password_layout.addWidget(password_label) self.password_input = QLineEdit() self.password_input.setEchoMode(QLineEdit.Password) self.password_input.setPlaceholderText("*") self.password_input.setStyleSheet(""" QLineEdit { padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; background: white; } QLineEdit:hover { border: 1px solid #3A84FF; } QLineEdit:focus { border: 1px solid #3A84FF; } """) # 按回车键提交 self.password_input.returnPressed.connect(self._on_login) password_layout.addWidget(self.password_input) layout.addLayout(password_layout) layout.addStretch() # 按钮行 btn_layout = QHBoxLayout() btn_layout.addStretch() # 登录按钮 self.login_btn = QPushButton("登录") self.login_btn.setFixedSize(100, 40) self.login_btn.setStyleSheet(""" QPushButton { background-color: #3A84FF; color: white; border: none; border-radius: 4px; font-size: 14px; font-weight: bold; } QPushButton:hover { background-color: #2B6FE6; } QPushButton:pressed { background-color: #1F5BD1; } """) self.login_btn.clicked.connect(self._on_login) btn_layout.addWidget(self.login_btn) # 取消按钮 self.cancel_btn = QPushButton("取消") self.cancel_btn.setFixedSize(100, 40) self.cancel_btn.setStyleSheet(""" QPushButton { background-color: #f5f5f5; color: #666; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; } QPushButton:hover { background-color: #e8e8e8; } QPushButton:pressed { background-color: #d8d8d8; } """) self.cancel_btn.clicked.connect(self.reject) btn_layout.addWidget(self.cancel_btn) layout.addLayout(btn_layout) def _on_login(self): """登录按钮点击事件""" username = self.username_combo.currentText().strip() password = self.password_input.text().strip() if not username: QMessageBox.warning(self, "提示", "请输入用户名") return if not password: QMessageBox.warning(self, "提示", "请输入密码") return # 调用后端 API 验证登录 try: result = self._call_login_api(username, password) if result.get("status") == "success": self.user_info = { 'username': result.get('username'), 'userid': result.get('userid'), 'role': result.get('role'), 'auth': result.get('auth') } print(f"[登录成功] 用户: {self.user_info['username']}, 角色: {self.user_info['role']}") self.accept() # 关闭对话框并返回成功 else: error_msg = result.get("error", "登录失败") QMessageBox.warning(self, "登录失败", f"用户名或密码错误\n{error_msg}") # 不关闭对话框,允许重新输入 except Exception as e: import traceback traceback.print_exc() QMessageBox.critical( self, "错误", f"登录请求失败:{str(e)}\n\n请确保后端服务已启动" ) def _call_login_api(self, username, password): """ 调用后端登录 API Args: username (str): 用户名 password (str): 密码 Returns: dict: API 响应结果 """ url = f"{self.api_base_url}/login" params = { "username": username, "password": password } print(f"\n[登录请求] URL: {url}") print(f"[登录请求] 参数: {json.dumps(params, ensure_ascii=False)}") try: response = requests.post( url, json=params, timeout=10 ) response.raise_for_status() result = response.json() print(f"[登录响应] {json.dumps(result, ensure_ascii=False)}") return result except requests.exceptions.RequestException as e: print(f"[登录错误] HTTP 请求失败: {e}") return { "status": "error", "error": f"网络请求失败: {str(e)}" } except Exception as e: print(f"[登录错误] 未知错误: {e}") import traceback traceback.print_exc() return { "status": "error", "error": f"未知错误: {str(e)}" } def get_user_info(self): """获取登录成功后的用户信息""" return self.user_info