新增功能:
- 消息自动滚动到底部
- AI 回复支持 Markdown 渲染
1)web安装依赖
npm install marked dompurify
2) web/src/App.vue
javascript
import { computed, ref, watch, onMounted, nextTick } from 'vue'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
新增状态
csharp
const chatBoxRef = ref(null)
新增方法
ini
const renderMarkdown = content => {
const rawHtml = marked.parse(content || '')
return DOMPurify.sanitize(rawHtml)
}
const scrollToBottom = async () => {
await nextTick()
if (chatBoxRef.value) {
chatBoxRef.value.scrollTop = chatBoxRef.value.scrollHeight
}
}
新增监听
scss
watch(
() => currentMessages.value.length,
() => {
scrollToBottom()
}
)
scss
watch(
() => currentMessages.value[currentMessages.value.length - 1]?.content,
() => {
scrollToBottom()
}
)
onMounted
scss
onMounted(() => {
fetchMemories()
scrollToBottom()
})
聊天框节点
ini
<div ref="chatBoxRef" class="chat-box">
<div
v-for="(item, index) in currentMessages"
:key="index"
:class="['msg', item.role]"
>
<div class="role">
{{
item.role === 'user'
? '我'
: item.role === 'assistant'
? 'AI'
: 'system'
}}
</div>
<div v-if="item.role === 'assistant'" class="content markdown-body" v-html="renderMarkdown(item.content)" />
<div v-else class="content">{{ item.content }}</div>
</div>
<div v-if="loading" class="msg assistant">
<div class="role">AI</div>
<div class="content">思考中...</div>
</div>
</div>
补充样式
css
.markdown-body :deep(p) {
margin: 0 0 8px;
}
.markdown-body :deep(pre) {
background: #111827;
color: #f9fafb;
padding: 12px;
border-radius: 10px;
overflow-x: auto;
margin: 8px 0;
}
.markdown-body :deep(code) {
background: rgba(0, 0, 0, 0.06);
padding: 2px 6px;
border-radius: 6px;
font-size: 13px;
}
.markdown-body :deep(pre code) {
background: transparent;
padding: 0;
}
.markdown-body :deep(ul),
.markdown-body :deep(ol) {
padding-left: 20px;
margin: 8px 0;
}
.markdown-body :deep(h1),
.markdown-body :deep(h2),
.markdown-body :deep(h3),
.markdown-body :deep(h4) {
margin: 10px 0 8px;
font-size: 16px;
}
.markdown-body :deep(blockquote) {
margin: 8px 0;
padding-left: 12px;
border-left: 4px solid #d1d5db;
color: #4b5563;
}
.markdown-body :deep(table) {
border-collapse: collapse;
width: 100%;
margin: 8px 0;
}
.markdown-body :deep(th),
.markdown-body :deep(td) {
border: 1px solid #e5e7eb;
padding: 8px;
text-align: left;
}
3)验证
比如输入这个内容:
请用 markdown 格式给我一份 Vue3 学习计划,包含标题、列表、代码块
- 回复会带标题、列表、代码块样式
- 每次新消息或流式更新时,聊天框会自动滚到底部


