加入群成员列表功能

This commit is contained in:
liuwei
2025-04-08 15:10:46 +08:00
parent 65ef82d044
commit e33e0e5263
4 changed files with 163 additions and 23 deletions

View File

@@ -124,4 +124,26 @@ def api_contacts_public():
})
except Exception as e:
logger.error(f"获取公共好友信息失败: {e}")
return jsonify({"success": False, "error": str(e)}), 500
@contacts_bp.route('/api/group_members/<roomid>', methods=['GET'])
@login_required
def api_group_members(roomid):
"""获取指定群的成员列表API
Args:
roomid: 群ID
"""
try:
server = current_app.dashboard_server
group_members = server.contact_manager.get_group_members(roomid)
return jsonify({
"success": True,
"data": {
"members": group_members
}
})
except Exception as e:
logger.error(f"获取群成员列表失败: {e}")
return jsonify({"success": False, "error": str(e)}), 500

View File

@@ -197,12 +197,48 @@
</el-row>
<!-- 群组详情对话框 -->
<el-dialog title="群组详情" {% raw %}:visible.sync="groupDetailDialogVisible"{% endraw %} width="50%">
<el-dialog title="群组详情" {% raw %}:visible.sync="groupDetailDialogVisible"{% endraw %} width="70%">
<el-descriptions {% raw %}:column="1"{% endraw %} border>
<el-descriptions-item label="群ID">{% raw %}{{ currentGroup.wxid }}{% endraw %}</el-descriptions-item>
<el-descriptions-item label="群名称">{% raw %}{{ currentGroup.name }}{% endraw %}</el-descriptions-item>
<!-- 可以添加更多群组相关信息 -->
</el-descriptions>
<!-- 群成员列表 -->
<div style="margin-top: 20px;">
<div class="section-title">
<h3>群成员列表</h3>
<el-input
placeholder="搜索群成员..."
{% raw %}v-model="groupMemberSearchQuery"{% endraw %}
style="width: 200px; float: right; margin-bottom: 10px;"
clearable>
</el-input>
</div>
<el-table
{% raw %}:data="filteredGroupMembers"{% endraw %}
style="width: 100%"
border
{% raw %}v-loading="groupMembersLoading"{% endraw %}>
<el-table-column type="index" width="50"></el-table-column>
<el-table-column prop="wxid" label="成员ID" width="220"></el-table-column>
<el-table-column prop="name" label="成员昵称"></el-table-column>
</el-table>
<!-- 群成员分页 -->
<div class="pagination-container" {% raw %}v-if="groupMembersList.length > 10"{% endraw %}>
<el-pagination
{% raw %}@size-change="handleGroupMembersSizeChange"
@current-change="handleGroupMembersCurrentChange"
:current-page="groupMembersCurrentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="groupMembersPageSize"{% endraw %}
layout="total, sizes, prev, pager, next, jumper"
{% raw %}:total="groupMembersList.length"{% endraw %}>
</el-pagination>
</div>
</div>
</el-dialog>
<!-- 用户详情对话框 -->
@@ -263,7 +299,13 @@
currentGroup: {},
currentUser: {},
currentOfficial: {},
currentPublic: {}
currentPublic: {},
// 新增群成员相关数据
groupMembersList: [],
groupMembersCurrentPage: 1,
groupMembersPageSize: 10,
groupMemberSearchQuery: '',
groupMembersLoading: false
};
},
computed: {
@@ -436,6 +478,7 @@
viewGroupDetails(group) {
this.currentGroup = group;
this.groupDetailDialogVisible = true;
this.loadGroupMembers(group.wxid);
},
viewUserDetails(user) {
this.currentUser = user;
@@ -448,6 +491,38 @@
viewPublicDetails(publicFriend) {
this.currentPublic = publicFriend;
this.publicDetailDialogVisible = true;
},
// 添加加载群成员的方法
loadGroupMembers(roomid) {
this.groupMembersLoading = true;
this.groupMembersList = [];
this.groupMembersCurrentPage = 1;
axios.get(`/contacts/api/group_members/${roomid}`)
.then(response => {
if (response.data.success) {
const members = response.data.data.members;
this.groupMembersList = Object.entries(members).map(([wxid, name]) => ({
wxid,
name
}));
}
})
.catch(error => {
console.error('加载群成员数据失败:', error);
this.$message.error('加载群成员数据失败');
})
.finally(() => {
this.groupMembersLoading = false;
});
},
// 群成员分页方法
handleGroupMembersSizeChange(size) {
this.groupMembersPageSize = size;
},
handleGroupMembersCurrentChange(page) {
this.groupMembersCurrentPage = page;
}
}
});
@@ -472,5 +547,18 @@
margin-top: 20px;
text-align: right;
}
.section-title {
margin: 20px 0 15px 0;
border-bottom: 1px solid #ebeef5;
padding-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.section-title h3 {
margin: 0;
font-size: 18px;
color: #303133;
}
</style>
{% endblock %}

View File

@@ -58,7 +58,7 @@ class Robot(Job):
# 初始化联系人管理器并设置联系人
self.contact_manager = ContactManager.get_instance()
self.allContacts = self.get_all_contacts()
self.contact_manager.set_contacts(self.allContacts, self.wcf.get_friends())
self.contact_manager.set_contacts(self.allContacts, self.wcf)
self.LOG.info(f"DB+REDIS 连接池开始初始化")
# 使用单例模式获取实例
@@ -545,5 +545,5 @@ class Robot(Job):
def refresh_contacts(self):
"""刷新联系人信息"""
self.allContacts = self.get_all_contacts()
self.contact_manager.refresh_contacts(self.allContacts, self.wcf.get_friends())
self.contact_manager.refresh_contacts(self.allContacts, self.wcf)
self.LOG.info("联系人信息已刷新")

View File

@@ -5,6 +5,8 @@
import logging
from typing import Dict, Optional, List, Tuple
from wcferry import Wcf
class ContactManager:
"""联系人管理器单例类"""
@@ -17,6 +19,7 @@ class ContactManager:
_initialized = False
_logger = logging.getLogger("ContactManager")
_friends: List[Dict] = []
_group_contacts_friends: Dict[str, Dict[str, str]] = {}
# 定义公共好友列表
_PUBLIC_FRIENDS = {
'fmessage': '朋友推荐消息',
@@ -46,7 +49,7 @@ class ContactManager:
cls._instance = ContactManager()
return cls._instance
def set_contacts(self, contacts: Dict[str, str], friends: List[Dict]) -> None:
def set_contacts(self, contacts: Dict[str, str], wcf: Wcf) -> None:
"""设置联系人字典
Args:
@@ -62,12 +65,12 @@ class ContactManager:
"gender": gender}
"""
self._contacts = contacts
self._friends = friends
self._friends = wcf.get_friends()
self._logger.info(f"联系人信息已更新,共 {len(contacts)} 个联系人")
# 分类联系人
self._classify_contacts()
self._classify_contacts(wcf)
def _classify_contacts(self) -> None:
def _classify_contacts(self, wcf: Wcf) -> None:
"""将联系人分类为群组、个人联系人、公共好友和公众号"""
self._group_contacts = {}
self._personal_contacts = {}
@@ -84,6 +87,9 @@ class ContactManager:
# 判断是否为群组wxid以@chatroom结尾
elif wxid.endswith('@chatroom'):
self._group_contacts[wxid] = nickname
# 如果是群,这处理群列表内容
self._group_contacts_friends[wxid] = wcf.get_chatroom_members(wxid)
# # 其他为普通好友和群成员
# else:
# self._personal_contacts[wxid] = nickname
@@ -147,9 +153,31 @@ class ContactManager:
"""
return self._contacts.get(wxid, wxid)
def get_group_name(self, roomid: str, wxid: str) -> str:
"""
Args:
roomid: 群ID
wxid: 微信ID
Returns:
对应的昵称如果不存在则返回wxid本身
"""
return self._group_contacts_friends.get(roomid, "").get(wxid, "未知昵称")
def get_group_members(self, roomid: str) -> Dict[str, str]:
"""获取指定群的成员列表
Args:
roomid: 群ID
Returns:
群成员字典,格式为 {"wxid": "NickName"}
"""
return self._group_contacts_friends.get(roomid, {})
def update_contact(self, wxid: str, nickname: str) -> None:
"""更新单个联系人信息
Args:
wxid: 微信ID
nickname: 昵称
@@ -166,30 +194,32 @@ class ContactManager:
self._personal_contacts[wxid] = nickname
self._logger.debug(f"已更新联系人: {wxid} -> {nickname}")
def refresh_contacts(self, new_contacts: Dict[str, str], friends: List[Dict]) -> None:
def refresh_contacts(self, new_contacts: Dict[str, str], wcf: Wcf) -> None:
"""刷新联系人信息
Args:
new_contacts: 新的联系人字典
friends: 好友清单 contact = {
"wxid": cnt.get("wxid", ""),
"code": cnt.get("code", ""),
"remark": cnt.get("remark", ""),
"name": cnt.get("name", ""),
"country": cnt.get("country", ""),
"province": cnt.get("province", ""),
"city": cnt.get("city", ""),
"gender": gender}
wcf :wcf
"""
self._contacts = new_contacts
self._friends = friends
# friends: 好友清单 contact = {
# "wxid": cnt.get("wxid", ""),
# "code": cnt.get("code", ""),
# "remark": cnt.get("remark", ""),
# "name": cnt.get("name", ""),
# "country": cnt.get("country", ""),
# "province": cnt.get("province", ""),
# "city": cnt.get("city", ""),
# "gender": gender}
self._friends = wcf.get_friends()
self._logger.info(f"联系人信息已刷新,共 {len(new_contacts)} 个联系人")
# 重新分类联系人
self._classify_contacts()
self._classify_contacts(wcf)
def get_contact_statistics(self) -> Tuple[int, int, int, int, int]:
"""获取联系人统计信息
Returns:
包含总联系人数、群组数、个人联系人数、公共好友数和公众号数的元组
"""