diff --git a/plugins/message_summary/main.py b/plugins/message_summary/main.py index f1e07e7..74a21ee 100644 --- a/plugins/message_summary/main.py +++ b/plugins/message_summary/main.py @@ -521,15 +521,71 @@ class MessageSummaryPlugin(MessagePluginInterface): # 约束:模板只负责展示,正文仍然由模型生成并在此做安全转义后注入。 renderer = HtmlTemplateRenderer() summary_html = self._summary_markdown_to_html(summary_text) + # 说明: + # 1. 这里注入“本地字体 CSS”到模板,避免依赖 Google Fonts 等外网资源; + # 2. 字体文件统一从仓库根目录 fonts/ 下读取,便于部署时统一管理; + # 3. 若字体文件缺失,自动回退系统字体,不影响功能可用性。 + local_font_css = self._build_local_font_css() return renderer.render( self._summary_image_template_path, { "title": f"{group_name} 群聊总结", "generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "summary_html": Markup(summary_html), + "local_font_css": Markup(local_font_css), }, ) + def _build_local_font_css(self) -> str: + """构建模板可注入的本地字体 CSS。""" + # 说明: + # 1. 使用绝对 file:/// URI,确保 Playwright set_content 场景下也能正确定位字体文件; + # 2. 按存在性逐个注册字体,避免硬编码导致不存在文件时报错; + # 3. 仅返回 CSS 字符串,不在此处抛异常,保证模板渲染链路稳定。 + try: + project_root = Path(__file__).resolve().parents[2] + font_dir = project_root / "fonts" + + simhei_path = font_dir / "simhei.ttf" + simsun_path = font_dir / "simsun.ttf" + + css_parts: List[str] = [] + if simhei_path.exists(): + css_parts.append( + "@font-face {" + "font-family: 'ABotSimHei'; " + f"src: url('{simhei_path.resolve().as_uri()}') format('truetype'); " + "font-weight: 400 900; " + "font-style: normal; " + "font-display: swap; " + "}" + ) + if simsun_path.exists(): + css_parts.append( + "@font-face {" + "font-family: 'ABotSimSun'; " + f"src: url('{simsun_path.resolve().as_uri()}') format('truetype'); " + "font-weight: 400 700; " + "font-style: normal; " + "font-display: swap; " + "}" + ) + + # 说明: + # 1. 通过 CSS 变量统一字体栈,模板端只需引用变量即可; + # 2. 先使用本地字体,再回退系统字体,兼顾一致性和容错性。 + css_parts.append( + ":root { " + "--abot-font-sans: 'ABotSimHei', 'ABotSimSun', 'PingFang SC', " + "'Microsoft YaHei', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; " + "--abot-font-code: 'Cascadia Mono', 'JetBrains Mono', 'Consolas', 'SFMono-Regular', Menlo, monospace; " + "}" + ) + return "\n".join(css_parts) + except Exception as e: + self.LOG.warning(f"构建本地字体 CSS 失败,回退系统字体: {e}") + return "" + async def _render_summary_image( self, answer: str, diff --git a/plugins/message_summary/templates/gemini_summary_card.html b/plugins/message_summary/templates/gemini_summary_card.html index 7ec3c83..617401d 100644 --- a/plugins/message_summary/templates/gemini_summary_card.html +++ b/plugins/message_summary/templates/gemini_summary_card.html @@ -5,8 +5,8 @@