Загрузка данных
import sys
from dataclasses import dataclass
from typing import Optional, List
import pymysql
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QFont
from PyQt6.QtWidgets import (
QApplication,
QDialog,
QFormLayout,
QFrame,
QHBoxLayout,
QLabel,
QLineEdit,
QMainWindow,
QMessageBox,
QPushButton,
QTextBrowser,
QVBoxLayout,
QWidget,
)
# =========================
# НАСТРОЙКИ БД
# =========================
DB_HOST = "127.0.0.1"
DB_USER = "root"
DB_PASSWORD = "root"
DB_NAME = "bookstore"
DB_PORT = 3306
@dataclass
class BasketItem:
genre: str
title: str
price: float
quantity: int
class BookShopDB:
def __init__(self) -> None:
self.conn = None
self._connect()
def _connect(self) -> None:
self.conn = pymysql.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASSWORD,
database=DB_NAME,
port=DB_PORT,
charset="utf8mb4",
cursorclass=pymysql.cursors.DictCursor,
autocommit=True,
)
def auth_user(self, login: str, password: str) -> Optional[dict]:
sql = """
SELECT ID_C, surname_c, name_c, login
FROM customers
WHERE login = %s AND password = %s
LIMIT 1
"""
with self.conn.cursor() as cur:
cur.execute(sql, (login, password))
return cur.fetchone()
def get_basket(self, customer_id: int) -> List[BasketItem]:
# Если у вас есть хранимая процедура, можно заменить запрос на CALL.
sql = """
SELECT g.name_g, b.title, b.price, bs.quantity_bas
FROM basket bs
JOIN books b ON b.ID_B = bs.id_b
LEFT JOIN genes g ON g.ID_G = b.id_g
WHERE bs.id_c = %s
ORDER BY bs.data_bas DESC, b.title
"""
with self.conn.cursor() as cur:
cur.execute(sql, (customer_id,))
rows = cur.fetchall()
result: List[BasketItem] = []
for row in rows:
result.append(
BasketItem(
genre=row.get("name_g") or "",
title=row.get("title") or "",
price=float(row.get("price") or 0),
quantity=int(row.get("quantity_bas") or 0),
)
)
return result
class LoginWindow(QDialog):
def __init__(self, db: BookShopDB) -> None:
super().__init__()
self.db = db
self.user = None
self.setWindowTitle("Авторизация")
self.setFixedSize(480, 330)
self._build_ui()
self._style_ui()
def _build_ui(self) -> None:
root = QVBoxLayout(self)
root.setContentsMargins(16, 16, 16, 16)
root.setSpacing(12)
title = QLabel("BookShop")
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
font = QFont()
font.setPointSize(20)
font.setUnderline(True)
title.setFont(font)
form_frame = QFrame()
form = QFormLayout(form_frame)
form.setLabelAlignment(Qt.AlignmentFlag.AlignLeft)
form.setHorizontalSpacing(14)
form.setVerticalSpacing(10)
self.login_edit = QLineEdit()
self.login_edit.setPlaceholderText("login")
self.pass_edit = QLineEdit()
self.pass_edit.setPlaceholderText("password")
self.pass_edit.setEchoMode(QLineEdit.EchoMode.Password)
form.addRow("Логин", self.login_edit)
form.addRow("Пароль", self.pass_edit)
self.btn_login = QPushButton("Войти")
self.btn_close = QPushButton("Закрыть")
self.btn_login.clicked.connect(self.on_login)
self.btn_close.clicked.connect(self.close)
self.login_edit.returnPressed.connect(self.on_login)
self.pass_edit.returnPressed.connect(self.on_login)
root.addStretch(1)
root.addWidget(title)
root.addStretch(1)
root.addWidget(form_frame)
root.addWidget(self.btn_login)
root.addWidget(self.btn_close)
def _style_ui(self) -> None:
self.setStyleSheet("""
QDialog {
background: #e8c6ff;
}
QLabel {
color: #42153f;
font-size: 16px;
}
QLineEdit {
background: #f8e6ff;
border: 1px solid #a881ba;
padding: 6px;
font-size: 15px;
color: #7b1b1b;
}
QPushButton {
background: #ead2ff;
border: 1px solid #a881ba;
padding: 8px;
font-size: 16px;
color: #42153f;
}
QPushButton:hover {
background: #f5e9ff;
}
""")
def on_login(self) -> None:
login = self.login_edit.text().strip()
password = self.pass_edit.text().strip()
if not login or not password:
QMessageBox.warning(self, "Ошибка", "Введите логин и пароль.")
return
try:
user = self.db.auth_user(login, password)
except Exception as exc:
QMessageBox.critical(self, "Ошибка БД", f"Не удалось выполнить запрос:\n{exc}")
return
if not user:
QMessageBox.warning(self, "Ошибка", "Неверный логин или пароль.")
return
self.user = user
self.accept()
class MainWindow(QMainWindow):
def __init__(self, db: BookShopDB, user: dict) -> None:
super().__init__()
self.db = db
self.user = user
self.setWindowTitle("BookShop")
self.setMinimumSize(760, 540)
self._build_ui()
self._style_ui()
self._load_data()
def _build_ui(self) -> None:
central = QWidget()
self.setCentralWidget(central)
root = QVBoxLayout(central)
root.setContentsMargins(18, 18, 18, 18)
root.setSpacing(12)
self.title_label = QLabel("BookShop")
self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
font = QFont()
font.setPointSize(20)
font.setUnderline(True)
self.title_label.setFont(font)
self.greeting_label = QLabel()
self.greeting_label.setWordWrap(True)
self.greeting_label.setFont(QFont("", 13))
basket_caption = QLabel("Корзина")
basket_caption.setFont(QFont("", 14))
self.basket_view = QTextBrowser()
self.basket_view.setFrameShape(QFrame.Shape.NoFrame)
btn_row = QHBoxLayout()
btn_row.addStretch(1)
self.btn_close = QPushButton("Закрыть")
self.btn_close.setFixedWidth(130)
self.btn_close.clicked.connect(self.close)
btn_row.addWidget(self.btn_close)
root.addWidget(self.title_label)
root.addWidget(self.greeting_label)
root.addWidget(basket_caption)
root.addWidget(self.basket_view, 1)
root.addLayout(btn_row)
def _style_ui(self) -> None:
self.setStyleSheet("""
QMainWindow, QWidget {
background: #e8c6ff;
}
QLabel {
color: #42153f;
}
QTextBrowser {
background: #f8e6ff;
border: 1px solid #a881ba;
color: #42153f;
font-size: 15px;
}
QPushButton {
background: #ead2ff;
border: 1px solid #a881ba;
padding: 8px 14px;
font-size: 15px;
color: #42153f;
}
QPushButton:hover {
background: #f5e9ff;
}
""")
def _load_data(self) -> None:
name = self.user.get("name_c", "")
surname = self.user.get("surname_c", "")
self.greeting_label.setText(f"Здравствуйте, {surname} {name}!")
try:
items = self.db.get_basket(int(self.user["ID_C"]))
except Exception as exc:
self.basket_view.setText(f"Не удалось загрузить корзину:\n{exc}")
return
if not items:
self.basket_view.setText("Корзина пуста.")
return
total = 0.0
lines = []
for i, item in enumerate(items, start=1):
subtotal = item.price * item.quantity
total += subtotal
lines.append(
f"{i}. {item.genre} | {item.title} | "
f"Цена: {item.price:.2f} | Кол-во: {item.quantity} | Сумма: {subtotal:.2f}"
)
lines.append("")
lines.append(f"Итого: {total:.2f}")
self.basket_view.setText("\n".join(lines))
def main() -> None:
app = QApplication(sys.argv)
try:
db = BookShopDB()
except Exception as exc:
QMessageBox.critical(None, "Ошибка", f"Не удалось подключиться к БД:\n{exc}")
sys.exit(1)
login_window = LoginWindow(db)
if login_window.exec() == QDialog.DialogCode.Accepted and login_window.user:
main_window = MainWindow(db, login_window.user)
main_window.show()
sys.exit(app.exec())
sys.exit(0)
if __name__ == "__main__":
main()