feat: 修改markdown格式化&实时对话sketch
This commit is contained in:
1835
package-lock.json
generated
1835
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@
|
||||
"postinstall": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@crazydos/vue-markdown": "^1.1.4",
|
||||
"@vue-flow/core": "^1.48.2",
|
||||
"axios": "^1.3.6",
|
||||
"crypto-js": "^4.2.0",
|
||||
@@ -21,12 +22,12 @@
|
||||
"element-plus": "^2.13.2",
|
||||
"fabric-with-all": "^5.3.1",
|
||||
"gsap": "^3.13.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"md5": "^2.3.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.0.32",
|
||||
"pinia-persistedstate-plugin": "^0.1.0",
|
||||
"pinia-plugin-persistedstate": "^3.1.0",
|
||||
"rehype-raw": "^7.0.0",
|
||||
"three": "^0.148.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-draggable-plus": "^0.6.1",
|
||||
|
||||
BIN
src/assets/images/link-card.png
Normal file
BIN
src/assets/images/link-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src/assets/images/report-card.png
Normal file
BIN
src/assets/images/report-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
@@ -150,7 +150,8 @@ export default {
|
||||
agent: {
|
||||
copySuccess: 'Text copied to clipboard',
|
||||
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
|
||||
Download: 'Download'
|
||||
Download: 'Download',
|
||||
deleteSuccess: 'Successfully deleted'
|
||||
},
|
||||
|
||||
// Version Tree
|
||||
|
||||
@@ -145,7 +145,8 @@ export default {
|
||||
copySuccess: '文本已复制到剪贴板',
|
||||
copyFaild:
|
||||
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。',
|
||||
Download: '下载'
|
||||
Download: '下载',
|
||||
deleteSuccess:'删除成功'
|
||||
},
|
||||
|
||||
// Version Tree
|
||||
@@ -180,6 +181,6 @@ export default {
|
||||
cancel: '取消'
|
||||
},
|
||||
assistant: {
|
||||
inputPlaceholder: '请输入',
|
||||
inputPlaceholder: '请输入'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,17 +252,22 @@
|
||||
if (event.includes('todo') || event.includes('webAddress')) {
|
||||
break
|
||||
}
|
||||
let hasSketch = false
|
||||
if (event.includes('sketchIDAndUrl')) {
|
||||
hasSketch = true
|
||||
}
|
||||
|
||||
const dataLines = event
|
||||
.split(/\n/)
|
||||
.filter((line) => line.startsWith('data:'))
|
||||
.map((line) => line.replace(/^data:\s*/, '').trim())
|
||||
.filter((content) => content.startsWith('{') || content.startsWith('['))
|
||||
const dataLines = event
|
||||
.split(/\n/)
|
||||
.filter((line) => line.startsWith('data:'))
|
||||
.map((line) => line.replace(/^data:\s*/, '').trim())
|
||||
.filter((content) => content.startsWith('{') || content.startsWith('['))
|
||||
// console.log('dataLInes', dataLines)
|
||||
if (isNodeIdEvent) {
|
||||
params.versionID = dataLines[0]
|
||||
projectStore.setProject({ nodeId: dataLines[0] })
|
||||
}
|
||||
|
||||
if (event.includes('tool')) {
|
||||
MyEvent.emit('loading-sketch')
|
||||
}
|
||||
@@ -274,11 +279,10 @@
|
||||
const jsonData = JSON.parse(jsonText)
|
||||
console.log('jsonData', jsonData)
|
||||
|
||||
// 赋值 project_id 和 version_id
|
||||
// if (jsonData.project_id) params.projectID = jsonData.project_id
|
||||
// if (jsonData.version_id) params.versionID = jsonData.version_id
|
||||
if (jsonData.image_url) {
|
||||
sketchList.value.push(jsonData.image_url)
|
||||
if (hasSketch) {
|
||||
sketchList.value.push({
|
||||
[Object.keys(jsonData)[0]]: jsonData[Object.keys(jsonData)[0]]
|
||||
})
|
||||
}
|
||||
if (
|
||||
jsonData.content &&
|
||||
@@ -382,10 +386,6 @@
|
||||
while (i < dialogue.length) {
|
||||
const item = dialogue[i]
|
||||
|
||||
// if (item.image_url) {
|
||||
// existingImgList.push(item.image_url)
|
||||
// }
|
||||
|
||||
if (item.role === 'user') {
|
||||
// user 角色直接添加
|
||||
result.push({
|
||||
@@ -402,9 +402,6 @@
|
||||
// 继续往后找连续的 assistant 消息
|
||||
let j = i + 1
|
||||
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
||||
// if (dialogue[j].image_url) {
|
||||
// existingImgList.push(dialogue[j].image_url)
|
||||
// }
|
||||
combinedContent += dialogue[j].content || ''
|
||||
j++
|
||||
}
|
||||
|
||||
@@ -19,8 +19,17 @@
|
||||
class="img-item"
|
||||
/>
|
||||
</div>
|
||||
<div class="message-txt markdown-body">
|
||||
<div v-html="formatMessage"></div>
|
||||
<div class="message-txt markdown-body flex flex-col">
|
||||
<!-- <div v-html="formatMessage"></div> -->
|
||||
<VueMarkdown
|
||||
:custom-attrs="customAttrs"
|
||||
:markdown="content.text"
|
||||
:rehype-plugins="[rehypeRaw]"
|
||||
>
|
||||
<template v-slot:s-ReportCard="" {children:children,...attrs}>
|
||||
<ReportCard :report="{ title: attrs.title, content: attrs.content }" />
|
||||
</template>
|
||||
</VueMarkdown>
|
||||
</div>
|
||||
<div class="operate flex" :class="{ 'is-user': content.isUser }">
|
||||
<template v-if="content.isUser">
|
||||
@@ -59,11 +68,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="message-context" v-show="content.streaming">
|
||||
<div class="message-txt">
|
||||
<div v-html="formatMessage"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -74,9 +78,11 @@
|
||||
import gsap from 'gsap'
|
||||
import userThumb from '@/assets/images/user-thumb.jpg'
|
||||
import agentThumb from '@/assets/images/agent-thumb.jpg'
|
||||
import markdownIt from 'markdown-it'
|
||||
|
||||
const md = new markdownIt()
|
||||
import ReportCard from './ReportCard.vue'
|
||||
import UrlCard from './UrlCard.vue'
|
||||
import { VueMarkdown } from '@crazydos/vue-markdown'
|
||||
import type { CustomAttrs } from '@crazydos/vue-markdown'
|
||||
import rehypeRaw from 'rehype-raw'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -85,6 +91,8 @@
|
||||
isLast: Boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['regenerate'])
|
||||
|
||||
const imageList = computed(() => {
|
||||
const { imageUrls } = props.content
|
||||
const list = []
|
||||
@@ -99,12 +107,18 @@
|
||||
return list
|
||||
})
|
||||
|
||||
const formatMessage = computed(() => {
|
||||
const str = md.render(props.content.text)
|
||||
return str
|
||||
})
|
||||
|
||||
const emit = defineEmits(['regenerate'])
|
||||
const customAttrs: CustomAttrs = {
|
||||
img: {
|
||||
style: 'max-width: 100%;'
|
||||
},
|
||||
a: (node, combinedAttrs) => {
|
||||
if (typeof node.properties.href === 'string') {
|
||||
return { target: '_blank', rel: 'noopener noreferrer' }
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const operateList = ref([
|
||||
{
|
||||
@@ -219,7 +233,7 @@
|
||||
.message-context {
|
||||
line-height: 2rem;
|
||||
font-size: 1.4rem;
|
||||
max-width: 82%;
|
||||
width: 82%;
|
||||
}
|
||||
}
|
||||
.operate {
|
||||
@@ -278,5 +292,8 @@
|
||||
code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -64,84 +64,7 @@
|
||||
<span>{{ $t('agent.Download') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题 <br />
|
||||
# 一级标题
|
||||
<br />
|
||||
# 一级标题
|
||||
</div>
|
||||
<div class="content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -158,7 +81,8 @@
|
||||
import { useProjectStore } from '@/stores'
|
||||
const projectStore = useProjectStore()
|
||||
import MyEvent from '@/utils/myEvent'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
const emits = defineEmits(['deleteSketch'])
|
||||
|
||||
// 存储每个图片的加载状态
|
||||
@@ -217,7 +141,7 @@
|
||||
versionNodeId: projectStore.state.nodeId
|
||||
}).then((res) => {
|
||||
if (res) {
|
||||
ElMessage.success('Delete success')
|
||||
ElMessage.success(t('agent.deleteSuccess'))
|
||||
emits('deleteSketch', Object.keys(item)[0])
|
||||
}
|
||||
})
|
||||
@@ -230,8 +154,6 @@
|
||||
watch(
|
||||
() => props.sketchList,
|
||||
(val) => {
|
||||
console.log('-sketchList-', val)
|
||||
|
||||
if (val.length > 0) {
|
||||
showLoading.value = false
|
||||
}
|
||||
|
||||
48
src/views/home/agent/components/ReportCard.vue
Normal file
48
src/views/home/agent/components/ReportCard.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="report-card">
|
||||
<div class="report-card-header">
|
||||
<span>{{ report.title }}</span>
|
||||
</div>
|
||||
<div class="report-card-content">
|
||||
<span>{{ report.content }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
report: any
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.report-card {
|
||||
width:100%;
|
||||
margin: 2.4rem 0;
|
||||
min-height: 11.2rem;
|
||||
background: url('@/assets/images/report-card.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
padding: 2.9rem;
|
||||
overflow: hidden;
|
||||
&:first-of-type{
|
||||
margin-top: 0;
|
||||
}
|
||||
&-header {
|
||||
font-family: 'Medium';
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 1.3rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
line-clamp: 3;
|
||||
}
|
||||
&-content{
|
||||
font-family: 'Regular';
|
||||
font-weight: 300;
|
||||
font-size: 1.6rem;
|
||||
color: #7c7c7c;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
10
src/views/home/agent/components/UrlCard.vue
Normal file
10
src/views/home/agent/components/UrlCard.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<ReportCard :report="{title: 'WebSources', content: 'Destination URL'}"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ReportCard from './ReportCard.vue'
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user