""" 全局聊天记录浏览窗口 """ from PyQt5.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QTextEdit, QSplitter, QFrame, QPushButton, QComboBox ) from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtGui import QColor import html from datetime import datetime class HistoryWindow(QWidget): refresh_requested = pyqtSignal() search_requested = pyqtSignal(str) # keyword def __init__(self, username, parent=None): super().__init__(parent) self.username = username self.all_messages = [] self._init_ui() def _init_ui(self): self.setWindowTitle("聊天记录浏览器") self.setGeometry(150, 150, 900, 650) self.setMinimumSize(650, 450) layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) # 顶部工具栏 toolbar = QFrame() toolbar.setStyleSheet("QFrame { background: #f8fafc; border-bottom: 1px solid #e2e8f0; }") tl = QHBoxLayout(toolbar) tl.setContentsMargins(14, 8, 14, 8) tl.setSpacing(8) title = QLabel("📜 聊天记录") title.setStyleSheet("font-size: 15px; font-weight: bold; color: #1e293b;") tl.addWidget(title) # 分类筛选 self.filter_combo = QComboBox() self.filter_combo.addItems(["全部消息", "私聊消息", "群聊消息"]) self.filter_combo.setStyleSheet(""" QComboBox { padding: 4px 10px; border: 1px solid #ddd; border-radius: 5px; background: white; font-size: 12px; } """) self.filter_combo.currentIndexChanged.connect(self._apply_filter) tl.addWidget(self.filter_combo) tl.addStretch() refresh_btn = QPushButton("🔄 刷新") refresh_btn.setStyleSheet(""" QPushButton { padding: 5px 14px; border: 1px solid #ddd; border-radius: 5px; background: white; font-size: 12px; } QPushButton:hover { background: #f0f0f0; } """) refresh_btn.clicked.connect(self.refresh_requested.emit) tl.addWidget(refresh_btn) layout.addWidget(toolbar) # 主区域 splitter = QSplitter(Qt.Horizontal) # 左侧消息列表 left_frame = QFrame() left_frame.setStyleSheet("QFrame { background: white; }") ll = QVBoxLayout(left_frame) ll.setContentsMargins(0, 0, 0, 0) ll.setSpacing(0) self.msg_list = QListWidget() self.msg_list.setStyleSheet(""" QListWidget { border: none; background: white; outline: none; } QListWidget::item { padding: 8px 12px; border-bottom: 1px solid #f1f5f9; font-size: 12px; } QListWidget::item:hover { background: #f8fafc; } QListWidget::item:selected { background: #eef2ff; } """) self.msg_list.itemClicked.connect(self._show_detail) ll.addWidget(self.msg_list) splitter.addWidget(left_frame) # 右侧详情 right_frame = QFrame() right_frame.setStyleSheet("QFrame { background: #fafbfc; }") rl = QVBoxLayout(right_frame) rl.setContentsMargins(0, 0, 0, 0) rl.setSpacing(0) detail_header = QWidget() detail_header.setFixedHeight(36) detail_header.setStyleSheet("background: #fafafa; border-bottom: 1px solid #eee;") dhl = QHBoxLayout(detail_header) dhl.setContentsMargins(12, 0, 12, 0) dhl.addWidget(QLabel("消息详情")) rl.addWidget(detail_header) self.detail_view = QTextEdit() self.detail_view.setReadOnly(True) self.detail_view.setStyleSheet(""" QTextEdit { border: none; background: #fafbfc; font-size: 13px; line-height: 1.6; padding: 14px; } """) self.detail_view.setPlaceholderText("选择左侧一条消息查看详情...") rl.addWidget(self.detail_view) splitter.addWidget(right_frame) splitter.setSizes([350, 550]) layout.addWidget(splitter) def load_messages(self, messages): """加载消息列表""" self.all_messages = messages self._apply_filter() def _apply_filter(self): self.msg_list.clear() filter_idx = self.filter_combo.currentIndex() filtered = self.all_messages if filter_idx == 1: # 私聊 filtered = [m for m in self.all_messages if m.get('chat_type') == 'private'] elif filter_idx == 2: # 群聊 filtered = [m for m in self.all_messages if m.get('chat_type') == 'group'] for msg in filtered: self._add_list_item(msg) def _add_list_item(self, msg): sender = msg.get('sender', '?') content = msg.get('content', '') timestamp = msg.get('timestamp', '') chat_type = msg.get('chat_type', 'private') target = msg.get('target_name', '') msg_type = msg.get('msg_type', 'text') icon = "👥" if chat_type == 'group' else "💬" if msg_type == 'image': preview = '[图片]' else: preview = content[:50] + '...' if len(content) > 50 else content time_short = timestamp.split(' ')[-1][:5] if ' ' in timestamp else timestamp[:5] text = f"{icon} {sender} → {target} {time_short}\n {preview}" item = QListWidgetItem(text) item.setData(Qt.UserRole, msg) self.msg_list.addItem(item) def _show_detail(self, item): msg = item.data(Qt.UserRole) if not msg: return sender = msg.get('sender', '?') content = msg.get('content', '') timestamp = msg.get('timestamp', '') chat_type = msg.get('chat_type', 'private') target = msg.get('target_name', '?') msg_type = msg.get('msg_type', 'text') type_label = "群聊" if chat_type == 'group' else "私聊" if msg_type == 'image': content_html = f'
[图片消息]
' else: content_html = f'
{html.escape(content)}
' detail_html = f"""
发送者:{html.escape(sender)}
类型:{type_label}
对象:{html.escape(target)}
时间:{html.escape(timestamp)}
消息内容:

{content_html}
""" self.detail_view.setHtml(detail_html) def closeEvent(self, event): self.all_messages.clear() event.accept()