完善通讯录群详情展示:补齐群公告/群主/群管理信息
变更项: 1. 数据层新增群资料聚合查询,直接复用 is_owner/is_admin 字段返回群主与管理员列表。 2. 同步群信息时兼容提取群公告并落库,历史库启动时自动补齐 chat_room_announcement 字段。 3. 新增 /contacts/api/group_profile/<roomid> 接口,统一返回群公告、群主、管理员、成员数。 4. 通讯录群详情弹窗新增群主/群成员数/群管理/群公告展示,并在打开详情时自动加载。 5. 补充群成员精简查询头像字段,更新初始化 SQL 中 t_chatrooms 公告字段定义。
This commit is contained in:
@@ -427,6 +427,23 @@ def api_group_members(roomid):
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@contacts_bp.route('/api/group_profile/<roomid>', methods=['GET'])
|
||||
@login_required
|
||||
def api_group_profile(roomid):
|
||||
"""获取指定群的资料信息(群公告、群主、管理员、成员数)"""
|
||||
try:
|
||||
server = current_app.dashboard_server
|
||||
# 直接复用联系人库中已有身份字段,按群聚合成页面可展示的资料结构。
|
||||
profile = server.contact_db.get_chatroom_profile(roomid)
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": profile
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"获取群资料失败: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@contacts_bp.route('/api/group_member_context/<roomid>/<wxid>', methods=['GET'])
|
||||
@login_required
|
||||
def api_group_member_context(roomid, wxid):
|
||||
|
||||
@@ -187,6 +187,31 @@
|
||||
<el-descriptions :column="1" 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-item label="群主">
|
||||
<span>{% raw %}{{ currentGroupProfile.owner_name || currentGroupProfile.owner_wxid || '未知' }}{% endraw %}</span>
|
||||
<span class="detail-inline-note" v-if="currentGroupProfile.owner_wxid && currentGroupProfile.owner_name && currentGroupProfile.owner_name !== currentGroupProfile.owner_wxid">
|
||||
({% raw %}{{ currentGroupProfile.owner_wxid }}{% endraw %})
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="群成员数">
|
||||
{% raw %}{{ currentGroupProfile.member_count || 0 }}{% endraw %}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="群管理">
|
||||
<div class="feature-chip-list">
|
||||
<el-tag
|
||||
v-for="admin in (currentGroupProfile.admins || [])"
|
||||
:key="admin.wxid"
|
||||
size="small"
|
||||
type="warning"
|
||||
effect="plain">
|
||||
{% raw %}{{ admin.display_name }}{% endraw %}
|
||||
</el-tag>
|
||||
<span v-if="!(currentGroupProfile.admins || []).length" class="empty-inline">暂无管理员数据</span>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="群公告">
|
||||
<span class="group-announcement">{% raw %}{{ currentGroupProfile.announcement || '暂无群公告' }}{% endraw %}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="机器人状态">
|
||||
<el-tag :type="currentGroup.robot_status === 'enabled' ? 'success' : 'info'">
|
||||
{% raw %}{{ currentGroup.robot_status === 'enabled' ? '已启用' : '未启用' }}{% endraw %}
|
||||
@@ -751,6 +776,8 @@
|
||||
managedGroupMap: {},
|
||||
groupPermissions: [],
|
||||
groupPermissionsLoading: false,
|
||||
// 当前群基础资料:用于展示群主、群公告、管理员、成员数等信息。
|
||||
currentGroupProfile: { owner_wxid: '', owner_name: '', announcement: '', member_count: 0, admin_count: 0, admins: [] },
|
||||
groupInsight: null,
|
||||
groupInsightLoading: false,
|
||||
groupMembersList: [], groupMembersCurrentPage: 1, groupMembersPageSize: 10, groupMemberSearchQuery: '', groupMembersLoading: false,
|
||||
@@ -866,6 +893,8 @@
|
||||
viewGroupDetails(group) {
|
||||
this.currentGroup = { ...group };
|
||||
this.groupDetailDialogVisible = true;
|
||||
// 进入群详情时先加载群资料,保证群主/公告/管理员信息第一时间可见。
|
||||
this.loadGroupProfile(group.wxid);
|
||||
this.loadGroupMembers(group.wxid);
|
||||
this.loadGroupPermissions(group.wxid);
|
||||
this.loadGroupInsights(group.wxid);
|
||||
@@ -915,6 +944,22 @@
|
||||
})
|
||||
.finally(() => { this.groupInsightLoading = false; });
|
||||
},
|
||||
loadGroupProfile(groupId) {
|
||||
// 每次进入详情都拉最新资料,避免“更新通讯录后页面仍是旧数据”的错觉。
|
||||
this.currentGroupProfile = { owner_wxid: '', owner_name: '', announcement: '', member_count: 0, admin_count: 0, admins: [] };
|
||||
axios.get(`/contacts/api/group_profile/${groupId}`)
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
this.currentGroupProfile = response.data.data || this.currentGroupProfile;
|
||||
} else {
|
||||
this.$message.error('加载群资料失败');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载群资料失败:', error);
|
||||
this.$message.error('加载群资料失败');
|
||||
});
|
||||
},
|
||||
toggleGroupPermission(permission) {
|
||||
const newStatus = permission.statusBool ? 'enabled' : 'disabled';
|
||||
axios.post(`/robot/api/group/${this.currentGroup.wxid}/permissions`, {
|
||||
@@ -1494,6 +1539,7 @@
|
||||
.detail-card-sub { font-size: 12px; color: #94a3b8; font-weight: 500; }
|
||||
.feature-chip-list { display: flex; gap: 8px; flex-wrap: wrap; min-height: 60px; align-items: flex-start; }
|
||||
.empty-inline, .detail-inline-note { font-size: 12px; color: #64748b; }
|
||||
.group-announcement { white-space: pre-wrap; line-height: 1.7; color: #334155; }
|
||||
.detail-inline-note { margin-top: 12px; line-height: 1.6; }
|
||||
.suggestion-list { display: flex; flex-direction: column; gap: 12px; }
|
||||
.suggestion-item { border-radius: 14px; }
|
||||
|
||||
@@ -101,6 +101,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
remark_quan_pin VARCHAR(256) COMMENT '备注全拼',
|
||||
chat_room_notify TINYINT COMMENT '群通知',
|
||||
chat_room_owner VARCHAR(64) COMMENT '群主微信ID',
|
||||
chat_room_announcement TEXT COMMENT '群公告内容',
|
||||
small_head_img_url TEXT COMMENT '群头像URL',
|
||||
member_list TEXT COMMENT '成员列表(JSON)',
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
@@ -108,6 +109,11 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
UNIQUE KEY `idx_chatroom_id` (`chatroom_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信群信息表';
|
||||
""")
|
||||
# 兼容历史库:老版本表可能没有群公告字段,这里启动时自动补齐。
|
||||
self.execute_update("""
|
||||
ALTER TABLE t_chatrooms
|
||||
ADD COLUMN IF NOT EXISTS chat_room_announcement TEXT COMMENT '群公告内容'
|
||||
""")
|
||||
self.LOG.info("成功创建或确认微信群信息表存在")
|
||||
except Exception as e:
|
||||
self.LOG.error(f"创建微信联系人表或群成员表失败: {e}")
|
||||
@@ -516,6 +522,15 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
return val.get("string", default)
|
||||
return val if val is not None else default
|
||||
|
||||
# 群公告在不同协议/版本里字段名不一致,这里做一次兼容提取,避免前端拿不到内容。
|
||||
announcement = (
|
||||
get_str('ChatRoomAnnouncement')
|
||||
or get_str('Announcement')
|
||||
or get_str('Annoucement')
|
||||
or get_str('AnnouncementContent')
|
||||
or get_str('chatRoomAnnouncement')
|
||||
)
|
||||
|
||||
data = {
|
||||
'chatroom_id': get_str('UserName'),
|
||||
'nick_name': get_str('NickName',"未知群名"),
|
||||
@@ -527,6 +542,7 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
'remark_quan_pin': get_str('RemarkQuanPin'),
|
||||
'chat_room_notify': chatroom_data.get('ChatRoomNotify', 0),
|
||||
'chat_room_owner': chatroom_data.get('ChatRoomOwner', ''),
|
||||
'chat_room_announcement': announcement,
|
||||
'small_head_img_url': chatroom_data.get('SmallHeadImgUrl', ''),
|
||||
# 成员列表可选存储为JSON字符串
|
||||
'member_list': json.dumps(chatroom_data.get('NewChatroomData', {}).get('ChatRoomMember', []),
|
||||
@@ -673,7 +689,11 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
def get_chatroom_small_member_list(self, chatroom_id: str) -> List[dict]:
|
||||
"""获取群成员列表"""
|
||||
try:
|
||||
sql = "SELECT wxid,nick_name,display_name,status,latest_active_time FROM t_chatroom_member WHERE chatroom_id = %s"
|
||||
sql = """
|
||||
SELECT wxid, nick_name, display_name, status, latest_active_time, small_head_img_url
|
||||
FROM t_chatroom_member
|
||||
WHERE chatroom_id = %s
|
||||
"""
|
||||
results = self.execute_query(sql, (chatroom_id,))
|
||||
|
||||
for row in results:
|
||||
@@ -685,6 +705,65 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
self.LOG.error(f"获取群{chatroom_id}成员列表失败: {e}")
|
||||
return []
|
||||
|
||||
def get_chatroom_profile(self, chatroom_id: str) -> Dict[str, Any]:
|
||||
"""获取群资料(群公告、群主、管理员、成员数)用于通讯录详情展示。"""
|
||||
try:
|
||||
# 先取群基础信息 + 群主展示名 + 成员数。
|
||||
info_sql = """
|
||||
SELECT
|
||||
c.chatroom_id,
|
||||
c.nick_name,
|
||||
c.chat_room_owner,
|
||||
c.chat_room_announcement,
|
||||
COALESCE(NULLIF(owner_member.display_name, ''), owner_member.nick_name, c.chat_room_owner, '') AS owner_name,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM t_chatroom_member m
|
||||
WHERE m.chatroom_id = c.chatroom_id AND m.status = 1
|
||||
) AS member_count
|
||||
FROM t_chatrooms c
|
||||
LEFT JOIN t_chatroom_member owner_member
|
||||
ON owner_member.chatroom_id = c.chatroom_id
|
||||
AND owner_member.wxid = c.chat_room_owner
|
||||
WHERE c.chatroom_id = %s
|
||||
LIMIT 1
|
||||
"""
|
||||
info = self.execute_query(info_sql, (chatroom_id,), fetch_one=True) or {}
|
||||
|
||||
# 使用既有身份字段 is_admin 组装管理员列表,直接复用现有数据。
|
||||
admin_sql = """
|
||||
SELECT
|
||||
wxid,
|
||||
COALESCE(NULLIF(display_name, ''), nick_name, wxid) AS display_name
|
||||
FROM t_chatroom_member
|
||||
WHERE chatroom_id = %s AND is_admin = 1 AND status = 1
|
||||
ORDER BY display_name
|
||||
"""
|
||||
admins = self.execute_query(admin_sql, (chatroom_id,)) or []
|
||||
|
||||
return {
|
||||
"chatroom_id": chatroom_id,
|
||||
"nick_name": info.get("nick_name", ""),
|
||||
"owner_wxid": info.get("chat_room_owner", "") or "",
|
||||
"owner_name": info.get("owner_name", "") or "",
|
||||
"announcement": info.get("chat_room_announcement", "") or "",
|
||||
"member_count": int(info.get("member_count") or 0),
|
||||
"admin_count": len(admins),
|
||||
"admins": admins,
|
||||
}
|
||||
except Exception as e:
|
||||
self.LOG.error(f"获取群{chatroom_id}资料失败: {e}")
|
||||
return {
|
||||
"chatroom_id": chatroom_id,
|
||||
"nick_name": "",
|
||||
"owner_wxid": "",
|
||||
"owner_name": "",
|
||||
"announcement": "",
|
||||
"member_count": 0,
|
||||
"admin_count": 0,
|
||||
"admins": [],
|
||||
}
|
||||
|
||||
# 获取群成员的昵称信息
|
||||
def get_chatroom_member_list_name_all(self) -> List[dict]:
|
||||
"""获取群成员列表"""
|
||||
|
||||
@@ -121,6 +121,7 @@ create or replace table message_archive.t_chatrooms
|
||||
remark_quan_pin varchar(256) null comment '备注全拼',
|
||||
chat_room_notify tinyint null comment '群通知',
|
||||
chat_room_owner varchar(64) null comment '群主微信ID',
|
||||
chat_room_announcement text null comment '群公告内容',
|
||||
small_head_img_url text null comment '群头像URL',
|
||||
member_list text null comment '成员列表(JSON)',
|
||||
create_time datetime default current_timestamp() not null comment '创建时间',
|
||||
|
||||
Reference in New Issue
Block a user