feat(web-ai): render markdown answers safely

This commit is contained in:
2026-07-19 22:02:49 +08:00
parent 7bd2c540fa
commit c17d83fc59
5 changed files with 225 additions and 2 deletions
+72 -1
View File
@@ -62,7 +62,7 @@
<view class="bubble master">
<text v-if="msg.result.status === 'NO_ANSWER'" class="bubble-noevidence">已找到公开来源,但外部服务未返回可核验答案,请直接查看来源。</text>
<text v-else-if="msg.result.noEvidence" class="bubble-noevidence">未找到可核验的公开依据,本次不生成推断答案。</text>
<text v-else class="bubble-text">{{ msg.result.answer }}</text>
<rich-text v-else class="bubble-text bubble-markdown" :nodes="renderMarkdown(msg.result.answer)" />
<text v-if="msg.result.redacted" class="bubble-redacted">已自动隐藏问题中的个人或门禁信息</text>
<text v-if="msg.result.warning" class="bubble-warning">{{ msg.result.warning }}</text>
@@ -119,6 +119,7 @@ import ChatComposer from '@/components/chat/ChatComposer.vue';
import { isLoggedIn, rememberLoginRedirect } from '@/services/auth';
import { chooseSpeechAudio, createSpeechPlaybackController, MENTOR_VOICE_PROFILE, transcribeSpeechBlob, transcribeSpeechFile } from '@/services/speech';
import { getWebAiCapabilities, queryWebAi } from '@/services/web-ai';
import { renderMarkdown } from '@/utils/markdown';
const path = '/pages/user/web-ai/index';
@@ -505,6 +506,76 @@ onUnload(() => {
white-space: pre-wrap;
}
.bubble-markdown {
white-space: normal;
}
.bubble-markdown :deep(p),
.bubble-markdown :deep(h1),
.bubble-markdown :deep(h2),
.bubble-markdown :deep(h3),
.bubble-markdown :deep(blockquote),
.bubble-markdown :deep(ul),
.bubble-markdown :deep(ol),
.bubble-markdown :deep(pre) {
margin: 0 0 8px;
}
.bubble-markdown :deep(h1),
.bubble-markdown :deep(h2),
.bubble-markdown :deep(h3) {
color: #18202b;
font-weight: 800;
line-height: 1.4;
}
.bubble-markdown :deep(h1) { font-size: 18px; }
.bubble-markdown :deep(h2) { font-size: 17px; }
.bubble-markdown :deep(h3) { font-size: 16px; }
.bubble-markdown :deep(ul),
.bubble-markdown :deep(ol) {
padding-left: 20px;
}
.bubble-markdown :deep(li + li) {
margin-top: 4px;
}
.bubble-markdown :deep(blockquote) {
padding-left: 10px;
border-left: 3px solid #cdd8e4;
color: #5d6875;
}
.bubble-markdown :deep(a) {
color: #315b8f;
text-decoration: underline;
}
.bubble-markdown :deep(code) {
padding: 1px 4px;
border-radius: 4px;
background: #eef1f4;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.9em;
}
.bubble-markdown :deep(pre) {
max-width: 100%;
box-sizing: border-box;
padding: 8px;
overflow-x: auto;
border-radius: 6px;
background: #eef1f4;
white-space: pre;
}
.bubble-markdown :deep(pre code) {
padding: 0;
background: transparent;
}
.bubble-subnote {
display: block;
margin-top: 8px;