From e2e3e5bd6d41118276321a6c53ed3b46517181ad Mon Sep 17 00:00:00 2001 From: webjoin111 <455457521@qq.com> Date: Tue, 30 Sep 2025 16:39:33 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(ui):=20=E6=88=AA=E6=96=ADUI?= =?UTF-8?q?=E8=B0=83=E8=AF=95HTML=E6=97=A5=E5=BF=97=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E9=95=BFbase64=E5=9B=BE=E7=89=87=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zhenxun/services/renderer/service.py | 11 ++++++----- zhenxun/utils/log_sanitizer.py | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/zhenxun/services/renderer/service.py b/zhenxun/services/renderer/service.py index 8ff11010..61a8650c 100644 --- a/zhenxun/services/renderer/service.py +++ b/zhenxun/services/renderer/service.py @@ -22,6 +22,7 @@ from zhenxun.configs.config import Config from zhenxun.configs.path_config import THEMES_PATH, UI_CACHE_PATH from zhenxun.services.log import logger from zhenxun.utils.exception import RenderingError +from zhenxun.utils.log_sanitizer import sanitize_for_logging from zhenxun.utils.pydantic_compat import _dump_pydantic_obj from .config import RESERVED_TEMPLATE_KEYS @@ -470,10 +471,7 @@ class RendererService: ) from e async def render( - self, - component: Renderable, - use_cache: bool = False, - **render_options, + self, component: Renderable, use_cache: bool = False, **render_options ) -> bytes: """ 统一的、多态的渲染入口,直接返回图片字节。 @@ -504,9 +502,12 @@ class RendererService: ) result = await self._render_component(context) if Config.get_config("UI", "DEBUG_MODE") and result.html_content: + sanitized_html = sanitize_for_logging( + result.html_content, context="ui_html" + ) logger.info( f"--- [UI DEBUG] HTML for {component.__class__.__name__} ---\n" - f"{result.html_content}\n" + f"{sanitized_html}\n" f"--- [UI DEBUG] End of HTML ---" ) if result.image_bytes is None: diff --git a/zhenxun/utils/log_sanitizer.py b/zhenxun/utils/log_sanitizer.py index b792aaf3..2884da5c 100644 --- a/zhenxun/utils/log_sanitizer.py +++ b/zhenxun/utils/log_sanitizer.py @@ -1,4 +1,5 @@ import copy +import re from typing import Any from nonebot.adapters import Message, MessageSegment @@ -16,6 +17,24 @@ def _truncate_base64_string(value: str, threshold: int = 256) -> str: return value +def _sanitize_ui_html(html_string: str) -> str: + """ + 专门用于净化UI渲染调试HTML的函数。 + 它会查找所有内联的base64数据(如字体、图片)并将其截断。 + """ + if not isinstance(html_string, str): + return html_string + + pattern = re.compile(r"(data:[^;]+;base64,)[A-Za-z0-9+/=\s]{100,}") + + def replacer(match): + prefix = match.group(1) + original_len = len(match.group(0)) - len(prefix) + return f"{prefix}[...base64_omitted_len={original_len}...]" + + return pattern.sub(replacer, html_string) + + def _sanitize_nonebot_message(message: Message) -> Message: """净化nonebot.adapter.Message对象,用于日志记录。""" sanitized_message = copy.deepcopy(message) @@ -173,6 +192,9 @@ def sanitize_for_logging(data: Any, context: str | None = None) -> Any: elif context == "openai_request": if isinstance(data, dict): return _sanitize_openai_request(data) + elif context == "ui_html": + if isinstance(data, str): + return _sanitize_ui_html(data) else: if isinstance(data, str): return _truncate_base64_string(data)