feat(mini-program): 添加 Markdown 渲染组件支持回溯过去页面

- 创建 Markdown.vue 组件,解析并渲染 Markdown 格式内容
- 支持分割线 (---)、四级标题 (####)、列表项 (*-)、段落
- 更新 RecordView.vue 使用 Markdown 组件渲染事件内容和 AI 回复
- 样式采用紫色主题,与整体设计保持一致

解决 issues: 小程序回溯过去页面的 Markdown 内容以纯文本显示的问题
This commit is contained in:
2026-04-07 21:00:39 +08:00
parent c498c6ca42
commit ee067ad1cb
2 changed files with 145 additions and 40 deletions
+134
View File
@@ -0,0 +1,134 @@
<template>
<view class="markdown-container">
<view v-for="(block, index) in parsedBlocks" :key="index" :class="block.type">
<!-- 分割线 -->
<view v-if="block.type === 'hr'" class="markdown-hr"></view>
<!-- 标题 -->
<text v-else-if="block.type === 'h4'" class="markdown-h4">{{ block.content }}</text>
<!-- 列表项 -->
<view v-else-if="block.type === 'li'" class="markdown-li">
<text class="li-bullet"> </text>
<text class="li-content">{{ block.content }}</text>
</view>
<!-- 普通段落 -->
<text v-else class="markdown-p">{{ block.content }}</text>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
content: {
type: String,
default: ''
}
})
// 解析 Markdown 内容
const parsedBlocks = computed(() => {
if (!props.content) return []
const lines = props.content.split('\n')
const blocks = []
for (const line of lines) {
const trimmed = line.trim()
// 跳过空行
if (trimmed === '') continue
// 分割线
if (trimmed === '---' || trimmed === '***' || trimmed === '___') {
blocks.push({ type: 'hr', content: '' })
continue
}
// 四级标题 ####
const h4Match = trimmed.match(/^####\s+(.+)/)
if (h4Match) {
blocks.push({ type: 'h4', content: h4Match[1] })
continue
}
// 列表项 * 或 -
const liMatch = trimmed.match(/^[*\-]\s+(.+)/)
if (liMatch) {
blocks.push({ type: 'li', content: liMatch[1] })
continue
}
// 普通段落
blocks.push({ type: 'p', content: trimmed })
}
return blocks
})
</script>
<style scoped>
.markdown-container {
display: flex;
flex-direction: column;
gap: 16rpx;
}
/* 分割线 */
.markdown-hr {
height: 2rpx;
background: linear-gradient(to right,
rgba(168, 85, 247, 0.1) 0%,
rgba(168, 85, 247, 0.4) 50%,
rgba(168, 85, 247, 0.1) 100%
);
margin: 24rpx 0;
border-radius: 2rpx;
}
/* 标题 */
.markdown-h4 {
display: block;
font-size: 28rpx;
font-weight: 600;
color: rgba(243, 232, 255, 0.95);
margin: 16rpx 0 8rpx 0;
line-height: 1.4;
}
/* 列表项 */
.markdown-li {
display: flex;
flex-direction: row;
align-items: flex-start;
gap: 12rpx;
padding: 8rpx 0;
}
.li-bullet {
color: #C084FC;
font-size: 24rpx;
line-height: 1.5;
flex-shrink: 0;
}
.li-content {
flex: 1;
color: rgba(243, 232, 255, 0.8);
font-size: 24rpx;
line-height: 1.6;
word-break: break-all;
}
/* 普通段落 */
.markdown-p {
display: block;
color: rgba(243, 232, 255, 0.75);
font-size: 24rpx;
line-height: 1.6;
word-break: break-all;
}
</style>