Files
dtm-py-all/UI/views/login_dialog.py

309 lines
9.9 KiB
Python

#!/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(16)
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('test') # 默认test
# 保存箭头图标以便在样式表中引用
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