|
|
"""
|
|
|
群组详情窗口 - 显示群组信息和成员管理(优化版)
|
|
|
支持:查看成员、邀请好友、退出群组
|
|
|
"""
|
|
|
from PyQt5.QtWidgets import (
|
|
|
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
|
|
QListWidget, QListWidgetItem, QPushButton,
|
|
|
QTextEdit, QScrollArea, QMessageBox, QInputDialog, QFrame
|
|
|
)
|
|
|
from PyQt5.QtCore import Qt, pyqtSignal
|
|
|
from PyQt5.QtGui import QFont, QColor
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
class GroupMemberItem(QListWidgetItem):
|
|
|
def __init__(self, member_info):
|
|
|
super().__init__()
|
|
|
self.member_info = member_info
|
|
|
self.refresh()
|
|
|
|
|
|
def refresh(self):
|
|
|
nick = self.member_info.get('nickname') or self.member_info.get('username', '')
|
|
|
user = self.member_info.get('username', '')
|
|
|
online = self.member_info.get('is_online', False)
|
|
|
dot = " ●" if online else " ○"
|
|
|
is_creator = self.member_info.get('is_creator', False)
|
|
|
crown = " 👑" if is_creator else ""
|
|
|
role = "群主" if is_creator else "成员"
|
|
|
self.setText(f"{nick} ({user}){dot}{crown} — {role}")
|
|
|
self.setForeground(QColor('#10b981') if online else QColor('#94a3b8'))
|
|
|
self.setData(Qt.UserRole, self.member_info)
|
|
|
|
|
|
|
|
|
class GroupDetailWindow(QWidget):
|
|
|
get_group_members_requested = pyqtSignal(int)
|
|
|
leave_group_requested = pyqtSignal(int)
|
|
|
invite_member_requested = pyqtSignal(int, str)
|
|
|
|
|
|
def __init__(self, group_info, current_user_id, parent=None):
|
|
|
super().__init__(parent)
|
|
|
self.group_info = group_info
|
|
|
self.current_user_id = current_user_id
|
|
|
self.members = []
|
|
|
self._init_ui()
|
|
|
self.get_group_members_requested.emit(self.group_info['id'])
|
|
|
|
|
|
def _init_ui(self):
|
|
|
self.setWindowTitle(f"群组详情 - {self.group_info.get('name', '未知群组')}")
|
|
|
self.setFixedSize(480, 640)
|
|
|
self.setStyleSheet("QWidget { background: white; }")
|
|
|
|
|
|
layout = QVBoxLayout(self)
|
|
|
layout.setSpacing(16)
|
|
|
layout.setContentsMargins(20, 20, 20, 20)
|
|
|
|
|
|
# 群组信息卡片
|
|
|
self._build_group_info_card(layout)
|
|
|
|
|
|
# 成员列表
|
|
|
self._build_members_section(layout)
|
|
|
|
|
|
# 操作按钮
|
|
|
self._build_action_buttons(layout)
|
|
|
|
|
|
def _build_group_info_card(self, parent_layout):
|
|
|
card = QFrame()
|
|
|
card.setStyleSheet("""
|
|
|
QFrame {
|
|
|
background: qlineargradient(x1:0,y1:0,x2:1,y2:0,
|
|
|
stop:0 #6366f1, stop:0.5 #4f46e5, stop:1 #4338ca);
|
|
|
border-radius: 14px;
|
|
|
}
|
|
|
""")
|
|
|
card.setFixedHeight(130)
|
|
|
card_layout = QVBoxLayout(card)
|
|
|
card_layout.setContentsMargins(24, 18, 24, 18)
|
|
|
card_layout.setSpacing(8)
|
|
|
|
|
|
name_label = QLabel(self.group_info.get('name', '未知群组'))
|
|
|
name_label.setStyleSheet("font-size: 20px; font-weight: bold; color: white;")
|
|
|
card_layout.addWidget(name_label)
|
|
|
|
|
|
info_layout = QHBoxLayout()
|
|
|
id_label = QLabel(f"群组ID: {self.group_info.get('id', 'N/A')}")
|
|
|
id_label.setStyleSheet("font-size: 12px; color: rgba(255,255,255,0.85);")
|
|
|
info_layout.addWidget(id_label)
|
|
|
info_layout.addStretch()
|
|
|
self.member_count_label = QLabel("成员: 加载中…")
|
|
|
self.member_count_label.setStyleSheet("font-size: 12px; color: rgba(255,255,255,0.85);")
|
|
|
info_layout.addWidget(self.member_count_label)
|
|
|
card_layout.addLayout(info_layout)
|
|
|
|
|
|
if 'created_at' in self.group_info:
|
|
|
time_label = QLabel(f"创建于: {self.group_info['created_at']}")
|
|
|
time_label.setStyleSheet("font-size: 11px; color: rgba(255,255,255,0.7);")
|
|
|
card_layout.addWidget(time_label)
|
|
|
|
|
|
parent_layout.addWidget(card)
|
|
|
|
|
|
def _build_members_section(self, parent_layout):
|
|
|
title_layout = QHBoxLayout()
|
|
|
title_label = QLabel("群组成员")
|
|
|
title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #2c3e50;")
|
|
|
title_layout.addWidget(title_label)
|
|
|
title_layout.addStretch()
|
|
|
|
|
|
invite_btn = QPushButton("➕ 邀请好友")
|
|
|
invite_btn.setStyleSheet("""
|
|
|
QPushButton {
|
|
|
background: #8b5cf6; color: white; border: none;
|
|
|
border-radius: 8px; padding: 7px 14px;
|
|
|
font-size: 12px; font-weight: bold;
|
|
|
}
|
|
|
QPushButton:hover { background: #7c3aed; }
|
|
|
""")
|
|
|
invite_btn.clicked.connect(self._invite_member)
|
|
|
title_layout.addWidget(invite_btn)
|
|
|
parent_layout.addLayout(title_layout)
|
|
|
|
|
|
self.members_list = QListWidget()
|
|
|
self.members_list.setStyleSheet("""
|
|
|
QListWidget {
|
|
|
border: 1px solid #e0e0e0; border-radius: 10px;
|
|
|
background: #fafbfc; outline: none;
|
|
|
}
|
|
|
QListWidget::item {
|
|
|
padding: 10px 14px; border-bottom: 1px solid #f0f0f0;
|
|
|
font-size: 13px;
|
|
|
}
|
|
|
QListWidget::item:hover { background: #f0f2f5; }
|
|
|
QListWidget::item:selected { background: #eef2ff; color: #2c3e50; }
|
|
|
""")
|
|
|
self.members_list.setMaximumHeight(280)
|
|
|
parent_layout.addWidget(self.members_list)
|
|
|
|
|
|
def _build_action_buttons(self, parent_layout):
|
|
|
parent_layout.addStretch()
|
|
|
|
|
|
btn_layout = QHBoxLayout()
|
|
|
btn_layout.addStretch()
|
|
|
|
|
|
leave_btn = QPushButton("🚪 退出群组")
|
|
|
leave_btn.setStyleSheet("""
|
|
|
QPushButton {
|
|
|
background: #ef4444; color: white; border: none;
|
|
|
border-radius: 10px; padding: 10px 24px;
|
|
|
font-size: 13px; font-weight: bold;
|
|
|
}
|
|
|
QPushButton:hover { background: #dc2626; }
|
|
|
""")
|
|
|
leave_btn.clicked.connect(self._leave_group)
|
|
|
btn_layout.addWidget(leave_btn)
|
|
|
parent_layout.addLayout(btn_layout)
|
|
|
|
|
|
def _invite_member(self):
|
|
|
username, ok = QInputDialog.getText(
|
|
|
self, '邀请好友', '请输入要邀请的用户名:')
|
|
|
if ok and username.strip():
|
|
|
self.invite_member_requested.emit(
|
|
|
self.group_info['id'], username.strip())
|
|
|
|
|
|
def _leave_group(self):
|
|
|
reply = QMessageBox.question(
|
|
|
self, '退出群组',
|
|
|
f'确定要退出群组 "{self.group_info.get("name", "")}" 吗?\n退出后将无法接收群组消息。',
|
|
|
QMessageBox.Yes | QMessageBox.No)
|
|
|
|
|
|
if reply == QMessageBox.Yes:
|
|
|
self.leave_group_requested.emit(self.group_info['id'])
|
|
|
self.close()
|
|
|
|
|
|
def update_members(self, members):
|
|
|
self.members = members
|
|
|
self.members_list.clear()
|
|
|
self.member_count_label.setText(f"成员: {len(members)}")
|
|
|
|
|
|
creator_id = self.group_info.get('creator_id')
|
|
|
# 在线成员排前面
|
|
|
sorted_members = sorted(members, key=lambda m: (not m.get('is_online', False), m.get('username', '')))
|
|
|
for member in sorted_members:
|
|
|
member['is_creator'] = (member.get('id') == creator_id)
|
|
|
item = GroupMemberItem(member)
|
|
|
self.members_list.addItem(item)
|
|
|
|
|
|
def update_member_status(self, user_id, username, is_online):
|
|
|
for i in range(self.members_list.count()):
|
|
|
item = self.members_list.item(i)
|
|
|
if isinstance(item, GroupMemberItem):
|
|
|
if item.member_info.get('id') == user_id:
|
|
|
item.member_info['is_online'] = is_online
|
|
|
item.refresh()
|
|
|
break
|