/
O.S.Prog
/
InstrumentProtocol
Обзор
Документация
Войти
/
O.S.Prog
/
InstrumentProtocol
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
ui/admin_window.py
273 строки
11 KB
O.S.Prog
Initial commit: InstrumentProtocol v2.0
17 июл 2026, 15:11
17 июл 2026, 15:11
1e845bd
Код
Авторство
О чём код?
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTableWidget, QTableWidgetItem, QMessageBox, QInputDialog, QHeaderView, QLineEdit) from PyQt6.QtCore import Qt from core.auth_manager import AuthManager class AdminWindow(QDialog): def __init__(self): super().__init__() self.auth = AuthManager() self.setWindowTitle("Сервисное меню — управление пользователями") self.setFixedSize(550, 450) self.setModal(True) layout = QVBoxLayout() title = QLabel("Управление учётными записями врачей") title.setStyleSheet("font-size: 16px; font-weight: bold; color: #2c3e50;") title.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.addWidget(title) # Таблица пользователей self.table = QTableWidget() self.table.setColumnCount(4) self.table.setHorizontalHeaderLabels(["Логин", "ФИО", "Пароль", ""]) self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch) self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch) self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Stretch) self.table.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed) self.table.setColumnWidth(3, 30) self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows) self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers) layout.addWidget(self.table) # Кнопки управления пользователями btn_layout = QHBoxLayout() add_btn = QPushButton("+ Добавить") add_btn.setStyleSheet(self._btn_style("#27ae60", "#219a52")) add_btn.clicked.connect(self.add_user) btn_layout.addWidget(add_btn) edit_btn = QPushButton("✏️ Изменить") edit_btn.setStyleSheet(self._btn_style("#3498db", "#2980b9")) edit_btn.clicked.connect(self.edit_user) btn_layout.addWidget(edit_btn) reset_pwd_btn = QPushButton("🔑 Сброс пароля") reset_pwd_btn.setStyleSheet(self._btn_style("#f39c12", "#e67e22")) reset_pwd_btn.clicked.connect(self.reset_user_password) btn_layout.addWidget(reset_pwd_btn) delete_btn = QPushButton("- Удалить") delete_btn.setStyleSheet(self._btn_style("#e74c3c", "#c0392b")) delete_btn.clicked.connect(self.delete_user) btn_layout.addWidget(delete_btn) layout.addLayout(btn_layout) # Разделитель layout.addWidget(QLabel("")) layout.addWidget(QLabel("Администрирование:")) layout.addWidget(QLabel("")) # Кнопка смены пароля администратора change_pwd_btn = QPushButton("🔒 Сменить пароль администратора") change_pwd_btn.setStyleSheet(self._btn_style("#e67e22", "#d35400")) change_pwd_btn.clicked.connect(self.change_admin_password) layout.addWidget(change_pwd_btn) # Закрыть close_btn = QPushButton("Закрыть") close_btn.setStyleSheet(self._btn_style("#95a5a6", "#7f8c8d")) close_btn.clicked.connect(self.accept) layout.addWidget(close_btn) self.setLayout(layout) self.load_users() def _btn_style(self, bg, hover): return f""" QPushButton {{ background-color: {bg}; color: white; font-weight: bold; padding: 8px; border: none; border-radius: 5px; }} QPushButton:hover {{ background-color: {hover}; }} """ def load_users(self): """Заполняет таблицу пользователями""" users = self.auth.get_all_users() self.table.setRowCount(len(users)) for row, user in enumerate(users): self.table.setItem(row, 0, QTableWidgetItem(user["login"])) self.table.setItem(row, 1, QTableWidgetItem(user["full_name"])) # Ячейка с паролем (изначально скрыт) pwd_item = QTableWidgetItem("••••••") pwd_item.setData(Qt.ItemDataRole.UserRole, user["login"]) # храним логин self.table.setItem(row, 2, pwd_item) # Кнопка-глазок eye_btn = QPushButton("👁️") eye_btn.setFixedSize(25, 25) eye_btn.setToolTip("Показать/скрыть пароль") eye_btn.setStyleSheet(""" QPushButton { border: none; background: transparent; font-size: 12px; padding: 0px; } QPushButton:hover { background-color: #ecf0f1; border-radius: 3px; } """) eye_btn.clicked.connect(lambda checked, r=row: self._toggle_password(r)) self.table.setCellWidget(row, 3, eye_btn) def _get_selected(self): """Возвращает логин и ФИО выбранного пользователя""" row = self.table.currentRow() if row < 0: QMessageBox.warning(self, "Ошибка", "Выберите пользователя из списка.") return None, None login = self.table.item(row, 0).text() full_name = self.table.item(row, 1).text() return login, full_name def add_user(self): """Добавляет нового врача""" login, ok = QInputDialog.getText(self, "Новый пользователь", "Логин:") if not ok or not login.strip(): return login = login.strip() if login in self.auth.users: QMessageBox.warning(self, "Ошибка", f"Пользователь с логином '{login}' уже существует.") return full_name, ok = QInputDialog.getText(self, "Новый пользователь", "ФИО врача:") if not ok or not full_name.strip(): return password, ok = QInputDialog.getText(self, "Новый пользователь", "Пароль:", QLineEdit.EchoMode.Password) if not ok or not password: return self.auth.add_user(login, full_name.strip(), password) self.load_users() QMessageBox.information(self, "Готово", f"Врач '{full_name}' добавлен.") def edit_user(self): """Изменяет ФИО пользователя""" login, full_name = self._get_selected() if not login: return new_name, ok = QInputDialog.getText(self, "Изменить ФИО", "Новое ФИО врача:", text=full_name) if ok and new_name.strip(): self.auth.users[login]["full_name"] = new_name.strip() self.auth.save() self.load_users() QMessageBox.information(self, "Готово", f"ФИО изменено на '{new_name}'.") def reset_user_password(self): """Сбрасывает пароль пользователя""" login, full_name = self._get_selected() if not login: return new_password, ok = QInputDialog.getText( self, "Сброс пароля", f"Новый пароль для врача '{full_name}':", QLineEdit.EchoMode.Password ) if ok and new_password: self.auth.users[login]["password_hash"] = self.auth._encrypt_password(new_password) self.auth.save() QMessageBox.information(self, "Готово", f"Пароль для '{full_name}' изменён.") def delete_user(self): """Удаляет выбранного врача""" login, full_name = self._get_selected() if not login: return reply = QMessageBox.question( self, "Подтверждение", f"Удалить врача '{full_name}' (логин: {login})?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No ) if reply == QMessageBox.StandardButton.Yes: self.auth.remove_user(login) self.load_users() QMessageBox.information(self, "Готово", f"Врач '{full_name}' удалён.") def change_admin_password(self): """Меняет пароль администратора""" old_password, ok = QInputDialog.getText( self, "Смена пароля", "Введите старый пароль:", QLineEdit.EchoMode.Password ) if not ok or not old_password: return if not self.auth.check_admin_password(old_password): QMessageBox.warning(self, "Ошибка", "Неверный старый пароль.") return new_password, ok = QInputDialog.getText( self, "Смена пароля", "Введите новый пароль:", QLineEdit.EchoMode.Password ) if not ok or not new_password: return confirm, ok = QInputDialog.getText( self, "Смена пароля", "Повторите новый пароль:", QLineEdit.EchoMode.Password ) if not ok or not confirm: return if new_password != confirm: QMessageBox.warning(self, "Ошибка", "Пароли не совпадают.") return self.auth.set_admin_password(new_password) QMessageBox.information(self, "Готово", "Пароль администратора изменён.") def _toggle_password(self, row): """Переключает видимость пароля в строке""" pwd_item = self.table.item(row, 2) if not pwd_item: return current_text = pwd_item.text() login = pwd_item.data(Qt.ItemDataRole.UserRole) if current_text == "••••••": # Показываем пароль password = self.auth.get_user_password(login) if password: pwd_item.setText(password) # Меняем глазок на закрытый eye_btn = self.table.cellWidget(row, 3) if eye_btn: eye_btn.setText("🔒") else: QMessageBox.warning(self, "Ошибка", "Не удалось расшифровать пароль.") else: # Скрываем пароль pwd_item.setText("••••••") eye_btn = self.table.cellWidget(row, 3) if eye_btn: eye_btn.setText("👁️")