From f657f436ac1bc77b2da8171443f671d3a33098e8 Mon Sep 17 00:00:00 2001 From: guo zebin Date: Fri, 10 Apr 2026 17:15:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=81=8A=E5=A4=A9=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E5=9C=A8GUI=E6=98=BE=E7=A4=BA=E5=B9=B6=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E5=88=B0=E6=95=B0=E5=AD=97=E4=BA=BA=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fay_core: 提取消息中的 markdown 图片 URL,通过 Images 字段推送到 10002 数字人text/audio通道,并从语音朗读文本中剥离图片语法 - gui: 调整 markdown-body img 缩略样式;修正 convertImagePaths 正则,避免误匹配 HTTP URL 的路径部分 Co-Authored-By: Claude Opus 4.6 --- core/fay_core.py | 20 +++++++++++++++++++- gui/static/css/index.css | 9 +++++++++ gui/static/js/index.js | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/fay_core.py b/core/fay_core.py index 39b8d66..fb85bc2 100644 --- a/core/fay_core.py +++ b/core/fay_core.py @@ -1548,6 +1548,9 @@ class FeiFei: tts_text = self.__remove_prestart_tags(text) if text else text + # 移除 markdown 图片语法,避免TTS朗读图片链接 + if tts_text: + tts_text = re.sub(r'!\[.*?\]\(https?://[^\s\)]+\)', '', tts_text).strip() @@ -2251,6 +2254,13 @@ class FeiFei: content["Data"]["Sentiment"] = sentiment_value + # 提取文本中的 markdown 图片 URL 并附加到消息 + audio_image_urls = re.findall(r'!\[.*?\]\((https?://[^\s\)]+)\)', text or "") + if audio_image_urls: + content["Data"]["Images"] = audio_image_urls + # 从 Text 中移除图片语法,避免语音朗读图片链接 + content["Data"]["Text"] = re.sub(r'!\[.*?\]\(https?://[^\s\)]+\)', '', text).strip() + # 计算 Action action_signal = resolve_action_signal(text) if action_signal: @@ -2888,6 +2898,9 @@ class FeiFei: """ + # 从原始文本中提取 markdown 图片 URL(在清理前提取) + image_urls = re.findall(r'!\[.*?\]\((https?://[^\s\)]+)\)', text or "") + # 移除 prestart 标签内容,不发送给数字人 @@ -2897,7 +2910,9 @@ class FeiFei: full_text = self.__remove_emojis(cleaned_text.replace("*", "")) if cleaned_text else "" - + # 从清理后的文本中移除 markdown 图片语法,避免数字人语音朗读图片链接 + if image_urls: + full_text = re.sub(r'!\[.*?\]\(https?://[^\s\)]+\)', '', full_text).strip() # 如果文本为空且不是结束标记,则不发送,但需保留 is_first @@ -2955,6 +2970,9 @@ class FeiFei: } + if image_urls: + content['Data']['Images'] = image_urls + wsa_server.get_instance().add_cmd(content) diff --git a/gui/static/css/index.css b/gui/static/css/index.css index 3905724..498908e 100644 --- a/gui/static/css/index.css +++ b/gui/static/css/index.css @@ -782,6 +782,15 @@ html { margin: 12px 0; } +.markdown-body img { + max-width: 100%; + max-height: 300px; + border-radius: 6px; + margin: 6px 0; + cursor: pointer; + display: block; +} + .markdown-body strong { font-weight: 600; } diff --git a/gui/static/js/index.js b/gui/static/js/index.js index 40e7b88..58eba2c 100644 --- a/gui/static/js/index.js +++ b/gui/static/js/index.js @@ -1096,7 +1096,7 @@ unadoptText(id) { // Windows: D:\path\to\image.png 或 D:/path/to/image.png // Unix: /path/to/image.png // 支持的图片格式: png, jpg, jpeg, gif, bmp, webp - const imagePathRegex = /([A-Za-z]:[\\\/][^\s<>"']+\.(png|jpg|jpeg|gif|bmp|webp)|\/[^\s<>"']+\.(png|jpg|jpeg|gif|bmp|webp))/gi; + const imagePathRegex = /([A-Za-z]:[\\\/][^\s<>"']+\.(png|jpg|jpeg|gif|bmp|webp))/gi; const baseUrl = window.location.protocol + '//' + window.location.hostname + ':' + window.location.port;