修复老库群公告字段缺失导致群详情报错
变更项: 1. 新增字段探测与补列逻辑:启动时通过 information_schema 检查 t_chatrooms.chat_room_announcement,不依赖 ADD COLUMN IF NOT EXISTS。 2. save_chatroom_info 改为字段存在才写入群公告,避免 Unknown column。 3. get_chatroom_profile 增加降级查询:字段不存在时返回空公告,不再直接引用缺失列。 4. 增加字段可用性缓存与中文注释,降低重复探测开销。
This commit is contained in:
@@ -19,6 +19,52 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
def __init__(self, db_manager: DBConnectionManager):
|
||||
super().__init__(db_manager)
|
||||
self.LOG = logger
|
||||
# 缓存群公告字段是否存在,避免反复查询 information_schema。
|
||||
self._chatroom_announcement_column_ready: Optional[bool] = None
|
||||
|
||||
def _column_exists(self, table_name: str, column_name: str) -> bool:
|
||||
"""检查当前数据库中指定表字段是否存在。"""
|
||||
try:
|
||||
sql = """
|
||||
SELECT COUNT(1) AS cnt
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = %s
|
||||
AND COLUMN_NAME = %s
|
||||
"""
|
||||
result = self.execute_query(sql, (table_name, column_name), fetch_one=True) or {}
|
||||
return int(result.get("cnt") or 0) > 0
|
||||
except Exception as e:
|
||||
self.LOG.error(f"检查字段存在性失败: {table_name}.{column_name}, error={e}")
|
||||
return False
|
||||
|
||||
def _ensure_chatroom_announcement_column(self) -> bool:
|
||||
"""确保群公告字段存在;老库不支持 IF NOT EXISTS 时也可兼容。"""
|
||||
if self._chatroom_announcement_column_ready is True:
|
||||
return True
|
||||
if self._chatroom_announcement_column_ready is False:
|
||||
return False
|
||||
|
||||
# 先探测:存在则直接标记成功。
|
||||
if self._column_exists("t_chatrooms", "chat_room_announcement"):
|
||||
self._chatroom_announcement_column_ready = True
|
||||
return True
|
||||
|
||||
# 再补列:不使用 IF NOT EXISTS,兼容较低版本 MySQL。
|
||||
alter_sql = """
|
||||
ALTER TABLE t_chatrooms
|
||||
ADD COLUMN chat_room_announcement TEXT COMMENT '群公告内容'
|
||||
"""
|
||||
ok = self.execute_update(alter_sql)
|
||||
if ok or self._column_exists("t_chatrooms", "chat_room_announcement"):
|
||||
self._chatroom_announcement_column_ready = True
|
||||
self.LOG.info("已确认 t_chatrooms.chat_room_announcement 字段可用")
|
||||
return True
|
||||
|
||||
# 失败时降级,后续查询将不再引用该字段,避免 Unknown column。
|
||||
self._chatroom_announcement_column_ready = False
|
||||
self.LOG.warning("t_chatrooms.chat_room_announcement 字段不可用,将按无公告字段模式运行")
|
||||
return False
|
||||
|
||||
def _ensure_table_exists(self):
|
||||
"""确保联系人表存在"""
|
||||
@@ -109,11 +155,8 @@ 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._ensure_chatroom_announcement_column()
|
||||
self.LOG.info("成功创建或确认微信群信息表存在")
|
||||
except Exception as e:
|
||||
self.LOG.error(f"创建微信联系人表或群成员表失败: {e}")
|
||||
@@ -542,12 +585,14 @@ 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', []),
|
||||
ensure_ascii=False)
|
||||
}
|
||||
# 字段存在才写群公告,避免老库 Unknown column。
|
||||
if self._ensure_chatroom_announcement_column():
|
||||
data['chat_room_announcement'] = announcement
|
||||
|
||||
fields = ', '.join(data.keys())
|
||||
placeholders = ', '.join(['%s'] * len(data))
|
||||
@@ -708,13 +753,19 @@ class ContactsDBOperator(BaseDBOperator):
|
||||
def get_chatroom_profile(self, chatroom_id: str) -> Dict[str, Any]:
|
||||
"""获取群资料(群公告、群主、管理员、成员数)用于通讯录详情展示。"""
|
||||
try:
|
||||
# 公告字段在老库可能不存在:不存在则降级为空串,避免 SQL 报错。
|
||||
announcement_expr = (
|
||||
"c.chat_room_announcement"
|
||||
if self._ensure_chatroom_announcement_column()
|
||||
else "''"
|
||||
)
|
||||
# 先取群基础信息 + 群主展示名 + 成员数。
|
||||
info_sql = """
|
||||
info_sql = f"""
|
||||
SELECT
|
||||
c.chatroom_id,
|
||||
c.nick_name,
|
||||
c.chat_room_owner,
|
||||
c.chat_room_announcement,
|
||||
{announcement_expr} AS chat_room_announcement,
|
||||
COALESCE(NULLIF(owner_member.display_name, ''), owner_member.nick_name, c.chat_room_owner, '') AS owner_name,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
|
||||
Reference in New Issue
Block a user