From da1cf5bd028cf29a7b4104fae6300803eeb5ac2f Mon Sep 17 00:00:00 2001 From: liuwei Date: Thu, 16 Apr 2026 17:09:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=80=81=E5=BA=93=E7=BE=A4?= =?UTF-8?q?=E5=85=AC=E5=91=8A=E5=AD=97=E6=AE=B5=E7=BC=BA=E5=A4=B1=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=BE=A4=E8=AF=A6=E6=83=85=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 变更项: 1. 新增字段探测与补列逻辑:启动时通过 information_schema 检查 t_chatrooms.chat_room_announcement,不依赖 ADD COLUMN IF NOT EXISTS。 2. save_chatroom_info 改为字段存在才写入群公告,避免 Unknown column。 3. get_chatroom_profile 增加降级查询:字段不存在时返回空公告,不再直接引用缺失列。 4. 增加字段可用性缓存与中文注释,降低重复探测开销。 --- db/contacts_db.py | 67 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/db/contacts_db.py b/db/contacts_db.py index 8bec6c7..b7245f7 100644 --- a/db/contacts_db.py +++ b/db/contacts_db.py @@ -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(*)