diff --git a/app/services/wechat_service.py b/app/services/wechat_service.py
index 9ce75a2..cfa10b1 100644
--- a/app/services/wechat_service.py
+++ b/app/services/wechat_service.py
@@ -38,6 +38,7 @@ class WeChatService:
self._encoding_aes_key = ""
self._access_token = ""
self._token_expire_at = 0
+ self._service_base_url = ""
# 缓存 response_code,用于更新卡片状态
# key: task_id (alarm_id), value: response_code
self._response_codes: Dict[str, str] = {}
@@ -50,6 +51,8 @@ class WeChatService:
self._secret = config.secret
self._token = config.token
self._encoding_aes_key = config.encoding_aes_key
+ self._service_base_url = getattr(config, "service_base_url", "").rstrip("/")
+ self._group_chat_id = getattr(config, "group_chat_id", "")
if self._enabled:
logger.info(f"企微通知服务已启用: corp_id={self._corp_id}")
@@ -64,6 +67,12 @@ class WeChatService:
def agent_id_int(self) -> int:
return int(self._agent_id) if self._agent_id else 0
+ def _alarm_detail_url(self, alarm_id: str) -> str:
+ """构造告警详情页 URL"""
+ if self._service_base_url:
+ return f"{self._service_base_url}/aiot/alarm/list?alarmId={alarm_id}"
+ return ""
+
async def _get_access_token(self) -> str:
"""获取企微 access_token(带缓存)"""
if self._access_token and time.time() < self._token_expire_at - 60:
@@ -236,7 +245,7 @@ class WeChatService:
],
"card_action": {
"type": 1,
- "url": "https://work.weixin.qq.com",
+ "url": self._alarm_detail_url(alarm_id) or "https://work.weixin.qq.com",
},
"button_list": [
{
@@ -548,8 +557,9 @@ class WeChatService:
article = {
"title": title,
"description": description,
- "url": url or "https://work.weixin.qq.com",
}
+ if url:
+ article["url"] = url
if picurl:
article["picurl"] = picurl
@@ -585,11 +595,10 @@ class WeChatService:
mention_user_ids: Optional[List[str]] = None,
) -> bool:
"""
- 发送告警组合消息到群聊(3条消息)
+ 发送告警通知到群聊(2条消息)
- 1. image: 告警截图
- 2. news: 告警详情图文卡片
- 3. text: @相关人员提醒处理
+ 1. image: 告警截图(可点击放大查看)
+ 2. markdown: 告警详情 + @人员
"""
if not self._enabled:
return False
@@ -598,7 +607,7 @@ class WeChatService:
level_name = ALARM_LEVEL_NAMES.get(alarm_level, "普通")
success = True
- # ---- 1. 发送告警截图(image 消息) ----
+ # ---- 1. 发送告警截图(image 消息,可点击放大) ----
if snapshot_url:
media_id = await self.upload_media_from_url(snapshot_url)
if media_id:
@@ -609,35 +618,26 @@ class WeChatService:
else:
logger.warning(f"截图上传企微失败,跳过图片消息: alarm={alarm_id}")
- # ---- 2. 发送告警详情(news 图文卡片) ----
- news_title = f"【{level_name}】{type_name}告警"
- news_desc = (
- f"{description}\n\n"
- f"告警区域:{area_name or '未知区域'}\n"
- f"摄像头:{camera_name or '未知'}\n"
- f"告警时间:{event_time}\n"
- f"告警ID:{alarm_id}"
- )
- # news 卡片的 picurl 可用 COS 预签名 URL(缩略图)
- sent = await self.send_group_news(
- chat_id=chat_id,
- title=news_title,
- description=news_desc,
- picurl=snapshot_url if snapshot_url and snapshot_url.startswith("http") else "",
+ # ---- 2. 告警详情 + @人员(markdown 消息) ----
+ mention_text = ""
+ if mention_user_ids:
+ mentions = " ".join(f"<@{uid}>" for uid in mention_user_ids)
+ mention_text = f"\n{mentions} 请及时处理"
+
+ md_content = (
+ f"**【{level_name}】{type_name}告警**\n"
+ f">告警区域:{area_name or '未知区域'}\n"
+ f">摄像头:{camera_name or '未知'}\n"
+ f">告警时间:{event_time}\n"
+ f">描述:{description}"
+ f"{mention_text}"
)
+ sent = await self.send_group_markdown(chat_id, md_content)
if not sent:
success = False
- # ---- 3. @相关人员(markdown 消息,@渲染更可靠) ----
- if mention_user_ids:
- mentions = " ".join(f"<@{uid}>" for uid in mention_user_ids)
- md_content = f"{mentions} 请及时处理以上**{type_name}告警**"
- sent = await self.send_group_markdown(chat_id, md_content)
- if not sent:
- success = False
-
if success:
- logger.info(f"群聊组合消息已发送: alarm={alarm_id}, chatid={chat_id}")
+ logger.info(f"群聊告警通知已发送: alarm={alarm_id}, chatid={chat_id}")
return success