Files
Projects/toolbox/codes/ui/stacked_pages/w08_log.py
2025-09-28 18:21:48 +08:00

225 lines
8.8 KiB
Python

from PySide6.QtWidgets import QWidget, QLabel, QMessageBox, QVBoxLayout, QTreeWidget, QHBoxLayout, QPushButton, QFrame, QLineEdit, QCheckBox, QTreeWidgetItem, QDialog
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QColor, QIcon, QFont, QKeySequence, QIntValidator, QShortcut
from codes.common.signal_bus import signal_bus
from codes.common import db_operation
from codes.common import clibs
class PageNumberInput(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.init_ui()
self.setup_slot()
def setup_slot(self):
QShortcut(QKeySequence("Esc"), self).activated.connect(self.reject)
self.le_page_number.returnPressed.connect(self.accept)
self.le_page_number.returnPressed.connect(self.get_page_number)
def init_ui(self):
self.setMinimumSize(300,100)
self.setMaximumSize(400,120)
self.resize(300, 100)
self.setWindowIcon(QIcon(clibs.icon))
self.setWindowTitle("输入页码")
layout_h = QHBoxLayout()
layout_h.addStretch(1)
self.le_page_number = QLineEdit(self)
self.le_page_number.setText("1")
self.le_page_number.selectAll()
self.le_page_number.setFont(QFont('Consolas', 14))
self.le_page_number.setValidator(QIntValidator(0, 9999999, self))
layout_h.addWidget(self.le_page_number, stretch=4)
layout_h.addStretch(1)
self.setLayout(layout_h)
def get_page_number(self):
text = self.le_page_number.text()
return 1 if text == 0 else int(text)
class ClickableLabel(QLabel):
clicked = Signal()
def mousePressEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self.clicked.emit()
super().mousePressEvent(event)
class W08Log(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.predos()
self.ui_init()
self.setup_slot()
self.setup_sc()
def predos(self):
self.records, self.len_records = "", ""
self.is_searching = False
self.max_item_number = clibs.config["log_number_per_page"]
def ui_init(self):
layout_v = QVBoxLayout(self)
self.treeW = QTreeWidget()
self.treeW.setHeaderLabels(["ID", "时间戳", "告警级别", "模块信息", "告警内容"])
layout_v.addWidget(self.treeW, stretch=9)
layout_h = QHBoxLayout()
self.pb_previous = QPushButton("上一页")
layout_h.addWidget(self.pb_previous, stretch=1)
self.lb_page = ClickableLabel("999999/999999")
self.lb_page.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.lb_page.setMinimumWidth(144)
layout_h.addWidget(self.lb_page, stretch=2)
self.pb_next = QPushButton("下一页")
layout_h.addWidget(self.pb_next, stretch=1)
layout_h.addStretch(9)
self.frame_checkbox = QFrame()
layout_h_checkbox = QHBoxLayout()
self.box_info = QCheckBox("通知", parent=self.frame_checkbox)
self.box_info.setChecked(True)
layout_h_checkbox.addWidget(self.box_info, stretch=1)
self.box_warning = QCheckBox("告警", parent=self.frame_checkbox)
self.box_warning.setChecked(True)
layout_h_checkbox.addWidget(self.box_warning, stretch=1)
self.box_error = QCheckBox("错误", parent=self.frame_checkbox)
self.box_error.setChecked(True)
layout_h_checkbox.addWidget(self.box_error, stretch=1)
self.box_exception = QCheckBox("异常", parent=self.frame_checkbox)
self.box_exception.setChecked(True)
layout_h_checkbox.addWidget(self.box_exception, stretch=1)
self.box_unknown = QCheckBox("未知", parent=self.frame_checkbox)
self.box_unknown.setChecked(True)
layout_h_checkbox.addWidget(self.box_unknown, stretch=1)
layout_h.addLayout(layout_h_checkbox, stretch=4)
self.le_search = QLineEdit()
self.le_search.setPlaceholderText("告警内容")
self.le_search.setMinimumWidth(300)
layout_h.addWidget(self.le_search, stretch=5)
self.pb_search = QPushButton("查找")
layout_h.addWidget(self.pb_search, stretch=1)
layout_v.addLayout(layout_h, stretch=1)
self.setLayout(layout_v)
def setup_slot(self):
self.pb_previous.clicked.connect(self.previous_page)
self.pb_next.clicked.connect(self.next_page)
self.pb_search.clicked.connect(self.search_page)
self.le_search.returnPressed.connect(self.search_page)
self.lb_page.clicked.connect(self.goto_page)
signal_bus.stacked_page_switch_log.connect(self.show_latest_page)
def setup_sc(self):
...
def previous_page(self):
if not self.is_searching:
self.records, self.len_records = db_operation.db_query_logs(True)
current, total = self.lb_page.text().split("/")
page_number = int(current) - 1
self.show_page(self.records, self.len_records, page_number=page_number)
def next_page(self):
if not self.is_searching:
self.records, self.len_records = db_operation.db_query_logs(True)
current, total = self.lb_page.text().split("/")
page_number = int(current) + 1
self.show_page(self.records, self.len_records, page_number=page_number)
def search_page(self):
filters = {"info": self.box_info.isChecked(), "warning": self.box_warning.isChecked(), "error": self.box_error.isChecked(), "exception": self.box_exception.isChecked(), "unknown": self.box_unknown.isChecked()}
search_text = self.le_search.text().strip()
flag, levels = False, []
for level, enable in filters.items():
if not enable:
continue
flag = True
levels.append(level)
if not flag:
QMessageBox().warning(None, "警告", "至少选择一个过滤器!")
return
self.records, self.len_records = db_operation.db_query_logs(levels=levels)
if search_text:
# ids = [_[0] for _ in self.records]
# placeholder = ",".join(ids)
# clibs.cursor.execute(f"SELECT * FROM logs WHERE id IN ({placeholder}) and content like ?", (ids + [search_text, ]))
self.records, self.len_records = db_operation.db_query_logs(search_text, self.records)
self.is_searching = True
self.show_page(self.records, self.len_records, page_number=None)
def goto_page(self):
dlg = PageNumberInput()
if dlg.exec() != 1:
return
page_number = dlg.get_page_number()
if not self.is_searching:
self.records, self.len_records = db_operation.db_query_logs(True)
self.show_page(self.records, self.len_records, page_number=page_number)
def show_latest_page(self):
self.records, self.len_records = db_operation.db_query_logs(True)
self.is_searching = False
self.box_info.setChecked(True)
self.box_warning.setChecked(True)
self.box_error.setChecked(True)
self.box_exception.setChecked(True)
self.box_unknown.setChecked(True)
self.le_search.clear()
self.show_page(self.records, self.len_records, page_number=None)
def show_page(self, records, len_records, page_number: int | None):
if len_records == 0:
self.treeW.clear()
return
remainder = len_records % self.max_item_number
total = len_records // self.max_item_number + 1 if remainder else len_records // self.max_item_number
if page_number is None:
current = total
elif page_number <= 0:
current = 1
elif page_number < total:
current = page_number
else:
current = total
self.lb_page.setText(f"{current}/{total}")
if current == 1:
idx_start = 0
idx_end = self.max_item_number if len_records >= self.max_item_number else len_records
elif current == total:
remainder = len_records % self.max_item_number
idx_start = len_records - remainder if remainder else len_records - self.max_item_number
idx_end = len_records
else:
idx_start = self.max_item_number * (current-1)
idx_end = self.max_item_number * current
self.treeW.clear()
for record in records[idx_start:idx_end]:
record = [str(_) for _ in record]
item = QTreeWidgetItem(self.treeW, record)
self.treeW.addTopLevelItem(item)
colors = {"info": QColor(144, 238, 144), "warning": QColor(255, 240, 210), "error": QColor(255, 220, 220), "exception": QColor(255, 220, 220), "unknown": QColor(255, 220, 220)}
color = colors[record[2]]
for col in range(5):
item.setBackground(col, color)
self.treeW.scrollToBottom()