【优化】AI Chat 抽离 Markdown 渲染

This commit is contained in:
cherishsince 2024-05-16 16:04:21 +08:00
parent ac9e5846c4
commit 91593d5d40
2 changed files with 7 additions and 185 deletions

View File

@ -29,7 +29,7 @@ const download = {
html: (data: Blob, fileName: string) => { html: (data: Blob, fileName: string) => {
download0(data, fileName, 'text/html') download0(data, fileName, 'text/html')
}, },
// 下载 Markdown 方法 // 下载 MarkdownView 方法
markdown: (data: Blob, fileName: string) => { markdown: (data: Blob, fileName: string) => {
download0(data, fileName, 'text/markdown') download0(data, fileName, 'text/markdown')
} }

View File

@ -107,8 +107,9 @@
<el-text class="time">{{ formatDate(item.createTime) }}</el-text> <el-text class="time">{{ formatDate(item.createTime) }}</el-text>
</div> </div>
<div class="left-text-container" ref="markdownViewRef"> <div class="left-text-container" ref="markdownViewRef">
<div class="left-text markdown-view" v-html="item.content"></div> <!-- <div class="left-text markdown-view" v-html="item.content"></div>-->
<!-- <mdPreview :content="item.content" :delay="false" />--> <!-- <mdPreview :content="item.content" :delay="false" />-->
<MarkdownView class="left-text" :content="item.content" />
</div> </div>
<div class="left-btns"> <div class="left-btns">
<div class="btn-cus" @click="noCopy(item.content)"> <div class="btn-cus" @click="noCopy(item.content)">
@ -135,6 +136,7 @@
</div> </div>
<div class="right-text-container"> <div class="right-text-container">
<div class="right-text">{{ item.content }}</div> <div class="right-text">{{ item.content }}</div>
<!-- <MarkdownView class="right-text" :content="item.content" />-->
</div> </div>
<div class="right-btns"> <div class="right-btns">
<div class="btn-cus" @click="noCopy(item.content)"> <div class="btn-cus" @click="noCopy(item.content)">
@ -198,33 +200,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import MarkdownView from '@/components/MarkdownView/index.vue'
import {ChatMessageApi, ChatMessageVO} from '@/api/ai/chat/message' import {ChatMessageApi, ChatMessageVO} from '@/api/ai/chat/message'
import {ChatConversationApi, ChatConversationVO} from '@/api/ai/chat/conversation' import {ChatConversationApi, ChatConversationVO} from '@/api/ai/chat/conversation'
import ChatConversationUpdateForm from './components/ChatConversationUpdateForm.vue' import ChatConversationUpdateForm from './components/ChatConversationUpdateForm.vue'
import Role from '@/views/ai/chat/role/index.vue' import Role from '@/views/ai/chat/role/index.vue'
import {formatDate} from '@/utils/formatTime' import {formatDate} from '@/utils/formatTime'
import {useClipboard} from '@vueuse/core' import {useClipboard} from '@vueuse/core'
// markdown
import {marked} from 'marked'
// https://highlightjs.org/
import 'highlight.js/styles/vs2015.min.css'
import hljs from 'highlight.js'
const route = useRoute() // const route = useRoute() //
const message = useMessage() // const message = useMessage() //
//
const renderer = {
code(code, language, c) {
const highlightHtml = hljs.highlight(code, {language: language, ignoreIllegals: true}).value
const copyHtml = `<div id="copy" data-copy='${code}' style="position: absolute; right: 10px; top: 5px; color: #fff;cursor: pointer;">复制</div>`
return `<pre>${copyHtml}<code class="hljs">${highlightHtml}</code></pre>`
}
}
marked.use({
renderer: renderer
})
const conversationList = ref([] as ChatConversationVO[]) const conversationList = ref([] as ChatConversationVO[])
const conversationMap = ref<any>({}) const conversationMap = ref<any>({})
// copy // copy
@ -376,7 +362,7 @@ const doSendStream = async (userMessage: ChatMessageVO) => {
// debugger // debugger
content = content + data.receive.content content = content + data.receive.content
const lastMessage = list.value[list.value.length - 1] const lastMessage = list.value[list.value.length - 1]
lastMessage.content = marked(content) as unknown as string lastMessage.content = content
list.value[list.value - 1] = lastMessage list.value[list.value - 1] = lastMessage
} }
// //
@ -404,21 +390,11 @@ const doSendStream = async (userMessage: ChatMessageVO) => {
/** 查询列表 */ /** 查询列表 */
const messageList = async () => { const messageList = async () => {
try { try {
if (!conversationId.value) { if (conversationId.value === null) {
return return
} }
// //
const res = await ChatMessageApi.messageList(conversationId.value) const res = await ChatMessageApi.messageList(conversationId.value)
// markdown
// marked(this.markdownText)
res.map((item) => {
// item.content = marked(item.content)
if (item.type !== 'user') {
item.content = marked(item.content)
}
})
list.value = res list.value = res
// //
@ -961,157 +937,3 @@ onMounted(async () => {
} }
} }
</style> </style>
<style lang="scss">
.markdown-view {
font-family: PingFang SC;
font-size: 0.95rem;
font-weight: 400;
line-height: 1.6rem;
letter-spacing: 0em;
text-align: left;
color: #3b3e55;
max-width: 100%;
pre {
position: relative;
}
pre code.hljs {
width: auto;
}
code.hljs {
border-radius: 6px;
padding-top: 20px;
width: auto;
@media screen and (min-width: 1536px) {
width: 960px;
}
@media screen and (max-width: 1536px) and (min-width: 1024px) {
width: calc(100vw - 400px - 64px - 32px * 2);
}
@media screen and (max-width: 1024px) and (min-width: 768px) {
width: calc(100vw - 32px * 2);
}
@media screen and (max-width: 768px) {
width: calc(100vw - 16px * 2);
}
}
p,
code.hljs {
margin-bottom: 16px;
}
p {
//margin-bottom: 1rem !important;
margin: 0;
margin-bottom: 3px;
}
/* 标题通用格式 */
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--color-G900);
margin: 24px 0 8px;
font-weight: 600;
}
h1 {
font-size: 22px;
line-height: 32px;
}
h2 {
font-size: 20px;
line-height: 30px;
}
h3 {
font-size: 18px;
line-height: 28px;
}
h4 {
font-size: 16px;
line-height: 26px;
}
h5 {
font-size: 16px;
line-height: 24px;
}
h6 {
font-size: 16px;
line-height: 24px;
}
/* 列表(有序,无序) */
ul,
ol {
margin: 0 0 8px 0;
padding: 0;
font-size: 16px;
line-height: 24px;
color: #3b3e55; // var(--color-CG600);
}
li {
margin: 4px 0 0 20px;
margin-bottom: 1rem;
}
ol > li {
list-style-type: decimal;
margin-bottom: 1rem;
// ,
// &:nth-child(n + 10) {
// margin-left: 30px;
// }
// &:nth-child(n + 100) {
// margin-left: 30px;
// }
}
ul > li {
list-style-type: disc;
font-size: 16px;
line-height: 24px;
margin-right: 11px;
margin-bottom: 1rem;
color: #3b3e55; // var(--color-G900);
}
ol ul,
ol ul > li,
ul ul,
ul ul li {
// list-style: circle;
font-size: 16px;
list-style: none;
margin-left: 6px;
margin-bottom: 1rem;
}
ul ul ul,
ul ul ul li,
ol ol,
ol ol > li,
ol ul ul,
ol ul ul > li,
ul ol,
ul ol > li {
list-style: square;
}
}
</style>