6d4e2b56 by 柴进

增加登陆日志留存模块

1 parent af04bd07
......@@ -27,6 +27,8 @@ from google import genai
from google.genai import types
import hashlib
import pymysql
import socket
import requests
from datetime import datetime
......@@ -117,10 +119,12 @@ class LoginDialog(QDialog):
# Username field
username_label = QLabel("用户名")
username_label.setObjectName("field_label")
main_layout.addWidget(username_label)
self.username_entry = QLineEdit()
self.username_entry.setText(self.last_user)
self.username_entry.setFixedHeight(40)
main_layout.addWidget(self.username_entry)
main_layout.addSpacing(10)
......@@ -132,6 +136,7 @@ class LoginDialog(QDialog):
self.password_entry = QLineEdit()
self.password_entry.setEchoMode(QLineEdit.Password)
self.password_entry.setFixedHeight(40)
# Handle saved password placeholder
if self.saved_password_hash:
......@@ -159,6 +164,7 @@ class LoginDialog(QDialog):
# Login button
self.login_button = QPushButton("登录")
self.login_button.setObjectName("login_button")
self.login_button.setFixedHeight(40)
self.login_button.clicked.connect(self.on_login)
main_layout.addWidget(self.login_button)
......@@ -287,9 +293,13 @@ class LoginDialog(QDialog):
self.success = True
self.authenticated_user = username
self.current_password_hash = password_hash
# 记录用户登录日志
self.log_user_login(username)
self.accept() # Close dialog with success
else:
self.show_error("用户名或密码错误")
self.show_error("用户名或密码错误,联系[柴进]重置密码")
self.password_entry.clear()
self.password_changed = False
self.login_button.setEnabled(True)
......@@ -303,8 +313,96 @@ class LoginDialog(QDialog):
self.show_error(f"认证失败: {str(e)}")
self.login_button.setEnabled(True)
def get_local_ip(self):
"""获取局域网IP地址"""
try:
# 尝试获取真实的局域网IP,而不是127.0.0.1
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
# 如果获取到的是127.0.0.1,尝试连接外部地址获取本地IP
if local_ip.startswith('127.'):
# 创建一个UDP socket连接到公共DNS服务器
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('8.8.8.8', 80))
local_ip = s.getsockname()[0]
except:
pass
finally:
s.close()
return local_ip
except:
return "127.0.0.1"
def get_public_ip(self):
"""获取公网IP地址,失败返回None"""
try:
# 使用多个API作为备选
apis = [
'https://api.ipify.org',
'https://ifconfig.me',
'https://ipinfo.io/ip'
]
for api in apis:
try:
response = requests.get(api, timeout=3)
if response.status_code == 200:
public_ip = response.text.strip()
# 简单验证IP格式
if len(public_ip.split('.')) == 4 or ':' in public_ip:
return public_ip
except:
continue
return None
except:
return None
def get_device_name(self):
"""获取设备名称"""
try:
return socket.gethostname()
except:
return "Unknown"
def log_user_login(self, username):
"""静默记录用户登录日志,支持双IP"""
try:
local_ip = self.get_local_ip()
public_ip = self.get_public_ip()
device_name = self.get_device_name()
conn = pymysql.connect(
host=self.db_config['host'],
port=self.db_config.get('port', 3306),
user=self.db_config['user'],
password=self.db_config['password'],
database=self.db_config['database'],
connect_timeout=5
)
try:
with conn.cursor() as cursor:
sql = """INSERT INTO nano_banana_user_log
(user_name, local_ip, public_ip, device_name, login_time)
VALUES (%s, %s, %s, %s, %s)"""
cursor.execute(sql, (username, local_ip, public_ip, device_name, datetime.now()))
conn.commit()
finally:
conn.close()
except Exception:
# 静默处理,不影响登录流程
pass
def show_error(self, message):
"""Display error message"""
"""显示错误弹窗和标签"""
# 显示弹窗错误提示
QMessageBox.critical(self, "登录错误", message)
# 同时保留标签显示
self.error_label.setText(message)
self.error_label.setStyleSheet("QLabel { color: #ff3b30; }")
......