mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-09 01:16:50 +08:00
fix(feishu): add configurable margin to card sections and actions for improved layout with images
This commit is contained in:
@@ -554,15 +554,24 @@ class Feishu:
|
|||||||
return escaped
|
return escaped
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _build_markdown_section(cls, text: Optional[str], text_size: str = "normal") -> Optional[dict]:
|
def _build_markdown_section(
|
||||||
|
cls,
|
||||||
|
text: Optional[str],
|
||||||
|
text_size: str = "normal",
|
||||||
|
margin: Optional[str] = None,
|
||||||
|
) -> Optional[dict]:
|
||||||
content = cls._escape_card_text(text).strip()
|
content = cls._escape_card_text(text).strip()
|
||||||
if not content:
|
if not content:
|
||||||
return None
|
return None
|
||||||
return {
|
section = {
|
||||||
"tag": "markdown",
|
"tag": "markdown",
|
||||||
"text_size": text_size,
|
"text_size": text_size,
|
||||||
"content": content,
|
"content": content,
|
||||||
}
|
}
|
||||||
|
if margin:
|
||||||
|
# 图片卡片需要 body 零边距,文字留白转移到组件外边距上。
|
||||||
|
section["margin"] = margin
|
||||||
|
return section
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _build_message_text(title: Optional[str], text: Optional[str], link: Optional[str] = None) -> str:
|
def _build_message_text(title: Optional[str], text: Optional[str], link: Optional[str] = None) -> str:
|
||||||
@@ -644,7 +653,7 @@ class Feishu:
|
|||||||
return str(callback_data).strip() if callback_data else None
|
return str(callback_data).strip() if callback_data else None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _card_actions(buttons: Optional[List[List[dict]]]) -> List[dict]:
|
def _card_actions(buttons: Optional[List[List[dict]]], margin: Optional[str] = None) -> List[dict]:
|
||||||
"""将统一按钮结构转换为飞书卡片按钮配置。"""
|
"""将统一按钮结构转换为飞书卡片按钮配置。"""
|
||||||
if not buttons:
|
if not buttons:
|
||||||
return []
|
return []
|
||||||
@@ -698,13 +707,14 @@ class Feishu:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
if columns:
|
if columns:
|
||||||
card_rows.append(
|
row = {
|
||||||
{
|
|
||||||
"tag": "column_set",
|
"tag": "column_set",
|
||||||
"flex_mode": "none",
|
"flex_mode": "none",
|
||||||
"columns": columns,
|
"columns": columns,
|
||||||
}
|
}
|
||||||
)
|
if margin:
|
||||||
|
row["margin"] = margin
|
||||||
|
card_rows.append(row)
|
||||||
return card_rows
|
return card_rows
|
||||||
|
|
||||||
def _build_card(
|
def _build_card(
|
||||||
@@ -730,16 +740,20 @@ class Feishu:
|
|||||||
"mode": "fit_horizontal",
|
"mode": "fit_horizontal",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
title_section = self._build_markdown_section(title, text_size="heading")
|
text_margin = "12px 12px 0px 12px" if image_key else None
|
||||||
|
body_margin = "4px 12px 12px 12px" if image_key else None
|
||||||
|
action_margin = "0px 12px 12px 12px" if image_key else None
|
||||||
|
title_section = self._build_markdown_section(title, text_size="heading", margin=text_margin)
|
||||||
body_section = self._build_markdown_section(
|
body_section = self._build_markdown_section(
|
||||||
self._build_message_text(title=None, text=text, link=link),
|
self._build_message_text(title=None, text=text, link=link),
|
||||||
text_size="normal",
|
text_size="normal",
|
||||||
|
margin=body_margin,
|
||||||
)
|
)
|
||||||
if title_section:
|
if title_section:
|
||||||
elements.append(title_section)
|
elements.append(title_section)
|
||||||
if body_section:
|
if body_section:
|
||||||
elements.append(body_section)
|
elements.append(body_section)
|
||||||
elements.extend(self._card_actions(buttons))
|
elements.extend(self._card_actions(buttons, margin=action_margin))
|
||||||
return {
|
return {
|
||||||
# 飞书卡片消息要支持后续 PATCH 更新,发送和更新时都必须显式声明 update_multi。
|
# 飞书卡片消息要支持后续 PATCH 更新,发送和更新时都必须显式声明 update_multi。
|
||||||
"schema": "2.0",
|
"schema": "2.0",
|
||||||
@@ -753,7 +767,7 @@ class Feishu:
|
|||||||
},
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"direction": "vertical",
|
"direction": "vertical",
|
||||||
"padding": "0px 0px 0px 0px",
|
"padding": "0px 0px 0px 0px" if image_key else "12px 12px 12px 12px",
|
||||||
"elements": elements,
|
"elements": elements,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ class TestFeishu(unittest.TestCase):
|
|||||||
self.assertNotIn("card", content)
|
self.assertNotIn("card", content)
|
||||||
self.assertEqual(content["schema"], "2.0")
|
self.assertEqual(content["schema"], "2.0")
|
||||||
self.assertTrue(content["config"]["update_multi"])
|
self.assertTrue(content["config"]["update_multi"])
|
||||||
|
self.assertEqual(content["body"]["padding"], "12px 12px 12px 12px")
|
||||||
self.assertEqual(content["body"]["elements"][0]["text_size"], "heading")
|
self.assertEqual(content["body"]["elements"][0]["text_size"], "heading")
|
||||||
self.assertEqual(content["body"]["elements"][0]["tag"], "markdown")
|
self.assertEqual(content["body"]["elements"][0]["tag"], "markdown")
|
||||||
button = content["body"]["elements"][-1]["columns"][0]["elements"][0]
|
button = content["body"]["elements"][-1]["columns"][0]["elements"][0]
|
||||||
@@ -287,6 +288,9 @@ class TestFeishu(unittest.TestCase):
|
|||||||
image_element = content["body"]["elements"][0]
|
image_element = content["body"]["elements"][0]
|
||||||
self.assertEqual(image_element["tag"], "img")
|
self.assertEqual(image_element["tag"], "img")
|
||||||
self.assertEqual(image_element["img_key"], "img_v2_remote")
|
self.assertEqual(image_element["img_key"], "img_v2_remote")
|
||||||
|
self.assertEqual(content["body"]["elements"][1]["margin"], "12px 12px 0px 12px")
|
||||||
|
self.assertEqual(content["body"]["elements"][2]["margin"], "4px 12px 12px 12px")
|
||||||
|
self.assertEqual(content["body"]["elements"][-1]["margin"], "0px 12px 12px 12px")
|
||||||
self.assertEqual(content["body"]["elements"][-1]["tag"], "column_set")
|
self.assertEqual(content["body"]["elements"][-1]["tag"], "column_set")
|
||||||
|
|
||||||
def test_send_notification_supports_user_id_target(self):
|
def test_send_notification_supports_user_id_target(self):
|
||||||
@@ -586,7 +590,9 @@ class TestFeishu(unittest.TestCase):
|
|||||||
self.assertEqual(content["body"]["padding"], "0px 0px 0px 0px")
|
self.assertEqual(content["body"]["padding"], "0px 0px 0px 0px")
|
||||||
self.assertEqual(content["body"]["elements"][0]["img_key"], "img_v2_uploaded")
|
self.assertEqual(content["body"]["elements"][0]["img_key"], "img_v2_uploaded")
|
||||||
self.assertEqual(content["body"]["elements"][1]["content"], "图片标题")
|
self.assertEqual(content["body"]["elements"][1]["content"], "图片标题")
|
||||||
|
self.assertEqual(content["body"]["elements"][1]["margin"], "12px 12px 0px 12px")
|
||||||
self.assertEqual(content["body"]["elements"][2]["content"], "图片说明")
|
self.assertEqual(content["body"]["elements"][2]["content"], "图片说明")
|
||||||
|
self.assertEqual(content["body"]["elements"][2]["margin"], "4px 12px 12px 12px")
|
||||||
|
|
||||||
def test_send_file_keeps_non_image_file_message_and_caption(self):
|
def test_send_file_keeps_non_image_file_message_and_caption(self):
|
||||||
client = self._build_client()
|
client = self._build_client()
|
||||||
|
|||||||
Reference in New Issue
Block a user