完成页面统计图渲染
This commit is contained in:
@@ -10,11 +10,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chart.js": "^4.4.8",
|
"chart.js": "^4.4.8",
|
||||||
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"eventsource-client": "^1.1.3",
|
"eventsource-client": "^1.1.3",
|
||||||
"licia": "^1.46.0",
|
"licia": "^1.46.0",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"markdown-it-container": "^4.0.0",
|
|
||||||
"mermaid": "^11.4.1",
|
"mermaid": "^11.4.1",
|
||||||
"mermaid-it-markdown": "^1.0.8",
|
"mermaid-it-markdown": "^1.0.8",
|
||||||
"vue": "^3.5.13"
|
"vue": "^3.5.13"
|
||||||
|
|||||||
29
client/pnpm-lock.yaml
generated
29
client/pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
|||||||
chart.js:
|
chart.js:
|
||||||
specifier: ^4.4.8
|
specifier: ^4.4.8
|
||||||
version: 4.4.8
|
version: 4.4.8
|
||||||
|
chartjs-adapter-moment:
|
||||||
|
specifier: ^1.0.1
|
||||||
|
version: 1.0.1(chart.js@4.4.8)(moment@2.30.1)
|
||||||
echarts:
|
echarts:
|
||||||
specifier: ^5.6.0
|
specifier: ^5.6.0
|
||||||
version: 5.6.0
|
version: 5.6.0
|
||||||
@@ -23,9 +26,6 @@ importers:
|
|||||||
markdown-it:
|
markdown-it:
|
||||||
specifier: ^14.1.0
|
specifier: ^14.1.0
|
||||||
version: 14.1.0
|
version: 14.1.0
|
||||||
markdown-it-container:
|
|
||||||
specifier: ^4.0.0
|
|
||||||
version: 4.0.0
|
|
||||||
mermaid:
|
mermaid:
|
||||||
specifier: ^11.4.1
|
specifier: ^11.4.1
|
||||||
version: 11.4.1
|
version: 11.4.1
|
||||||
@@ -758,6 +758,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==, tarball: https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz}
|
resolution: {integrity: sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==, tarball: https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz}
|
||||||
engines: {pnpm: '>=8'}
|
engines: {pnpm: '>=8'}
|
||||||
|
|
||||||
|
chartjs-adapter-moment@1.0.1:
|
||||||
|
resolution: {integrity: sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==}
|
||||||
|
peerDependencies:
|
||||||
|
chart.js: '>=3.0.0'
|
||||||
|
moment: ^2.10.2
|
||||||
|
|
||||||
chevrotain-allstar@0.3.1:
|
chevrotain-allstar@0.3.1:
|
||||||
resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==}
|
resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1047,7 +1053,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||||
|
|
||||||
eventsource-client@1.1.3:
|
eventsource-client@1.1.3:
|
||||||
resolution: {integrity: sha512-6GJGePDMxin/6VH1Dex7RqnZRguweO1BVKhXpBYwKcQbVLOZPLfeDr9vYSb9ra88kjs0NpT8FaEDz5rExedDkg==, tarball: https://registry.npmjs.org/eventsource-client/-/eventsource-client-1.1.3.tgz}
|
resolution: {integrity: sha512-6GJGePDMxin/6VH1Dex7RqnZRguweO1BVKhXpBYwKcQbVLOZPLfeDr9vYSb9ra88kjs0NpT8FaEDz5rExedDkg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
eventsource-parser@3.0.0:
|
eventsource-parser@3.0.0:
|
||||||
@@ -1240,9 +1246,6 @@ packages:
|
|||||||
magic-string@0.30.17:
|
magic-string@0.30.17:
|
||||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||||
|
|
||||||
markdown-it-container@4.0.0:
|
|
||||||
resolution: {integrity: sha512-HaNccxUH0l7BNGYbFbjmGpf5aLHAMTinqRZQAEQbMr2cdD3z91Q6kIo1oUn1CQndkT03jat6ckrdRYuwwqLlQw==}
|
|
||||||
|
|
||||||
markdown-it@13.0.2:
|
markdown-it@13.0.2:
|
||||||
resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
|
resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -1291,6 +1294,9 @@ packages:
|
|||||||
mlly@1.7.4:
|
mlly@1.7.4:
|
||||||
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
|
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
|
||||||
|
|
||||||
|
moment@2.30.1:
|
||||||
|
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||||
|
|
||||||
mrmime@2.0.1:
|
mrmime@2.0.1:
|
||||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -2363,6 +2369,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@kurkle/color': 0.3.4
|
'@kurkle/color': 0.3.4
|
||||||
|
|
||||||
|
chartjs-adapter-moment@1.0.1(chart.js@4.4.8)(moment@2.30.1):
|
||||||
|
dependencies:
|
||||||
|
chart.js: 4.4.8
|
||||||
|
moment: 2.30.1
|
||||||
|
|
||||||
chevrotain-allstar@0.3.1(chevrotain@11.0.3):
|
chevrotain-allstar@0.3.1(chevrotain@11.0.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
chevrotain: 11.0.3
|
chevrotain: 11.0.3
|
||||||
@@ -2865,8 +2876,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.0
|
'@jridgewell/sourcemap-codec': 1.5.0
|
||||||
|
|
||||||
markdown-it-container@4.0.0: {}
|
|
||||||
|
|
||||||
markdown-it@13.0.2:
|
markdown-it@13.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse: 2.0.1
|
argparse: 2.0.1
|
||||||
@@ -2952,6 +2961,8 @@ snapshots:
|
|||||||
pkg-types: 1.3.1
|
pkg-types: 1.3.1
|
||||||
ufo: 1.5.4
|
ufo: 1.5.4
|
||||||
|
|
||||||
|
moment@2.30.1: {}
|
||||||
|
|
||||||
mrmime@2.0.1: {}
|
mrmime@2.0.1: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|||||||
@@ -1,9 +1,27 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted, ref} from 'vue'
|
import {onMounted, ref, toRaw} from 'vue'
|
||||||
import MarkdownIt from 'markdown-it'
|
import MarkdownIt from 'markdown-it'
|
||||||
import MarkDownMermaidPlugin from 'mermaid-it-markdown'
|
|
||||||
import {createEventSource} from 'eventsource-client'
|
import {createEventSource} from 'eventsource-client'
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
import {CategoryScale, Chart, LinearScale, LineController, LineElement, PointElement, Title,} from 'chart.js'
|
||||||
|
import 'chartjs-adapter-moment'
|
||||||
|
import mermaid from 'mermaid'
|
||||||
|
import {each, isEqual, isJson, nextTick} from 'licia'
|
||||||
|
|
||||||
|
Chart.register(
|
||||||
|
LineController,
|
||||||
|
LineElement,
|
||||||
|
PointElement,
|
||||||
|
LinearScale,
|
||||||
|
Title,
|
||||||
|
CategoryScale
|
||||||
|
)
|
||||||
|
|
||||||
|
const chartsMap = ref({
|
||||||
|
echarts: {},
|
||||||
|
chartjs: {},
|
||||||
|
mermaid: {},
|
||||||
|
})
|
||||||
// 初始化 markdown-it 实例
|
// 初始化 markdown-it 实例
|
||||||
const md = new MarkdownIt({
|
const md = new MarkdownIt({
|
||||||
html: true, // 启用 HTML 标签
|
html: true, // 启用 HTML 标签
|
||||||
@@ -11,7 +29,33 @@ const md = new MarkdownIt({
|
|||||||
linkify: true, // 自动转换 URL 为链接
|
linkify: true, // 自动转换 URL 为链接
|
||||||
typographer: true, // 启用一些语言中性的替换 + 引号美化
|
typographer: true, // 启用一些语言中性的替换 + 引号美化
|
||||||
})
|
})
|
||||||
md.use(MarkDownMermaidPlugin)
|
md.use(function (md) {
|
||||||
|
md.renderer.rules.fence = function (tokens, idx, options, env, slf) {
|
||||||
|
// console.log('tokens', tokens, tokens[idx].info)
|
||||||
|
const content = tokens[idx].content
|
||||||
|
// 此处判断是否为 echarts 代码块
|
||||||
|
if (tokens[idx].info === 'echarts') {
|
||||||
|
if (isJson(content)) {
|
||||||
|
chartsMap.value.echarts[idx] = JSON.parse(content) //此处表示将内容存起来,存到当前页面的变量去
|
||||||
|
}
|
||||||
|
return `<div id="echarts-${idx}" style="width: 600px;height:400px;"></div>`
|
||||||
|
} else if (tokens[idx].info === 'chartjs') {
|
||||||
|
// 此处判断是否为 chartjs 代码块
|
||||||
|
if (isJson(content)) {
|
||||||
|
chartsMap.value.chartjs[idx] = JSON.parse(content)
|
||||||
|
}
|
||||||
|
return `<canvas id="chartjs-${idx}"></canvas>`
|
||||||
|
} else if (tokens[idx].info === 'mermaid') {
|
||||||
|
// 此处判断是否为 mermaidChart 代码块
|
||||||
|
const code = content.trim()
|
||||||
|
chartsMap.value.mermaid[idx] = code
|
||||||
|
return `<div id="mermaid-${idx}">${code}</div>`
|
||||||
|
} else {
|
||||||
|
// 其他代码块
|
||||||
|
return `<pre><code class='languge-${tokens[idx].info}'>${content}</code></pre>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const question = ref('')
|
const question = ref('')
|
||||||
const answer = ref('')
|
const answer = ref('')
|
||||||
@@ -33,12 +77,25 @@ const showToast = ref(false)
|
|||||||
const toastMessage = ref('')
|
const toastMessage = ref('')
|
||||||
const toastMessageType = ref('success')
|
const toastMessageType = ref('success')
|
||||||
|
|
||||||
|
const onEventSourceClose = (eventSource) => {
|
||||||
|
console.log(answer.value)
|
||||||
|
console.log(renderedAnswer.value)
|
||||||
|
console.log(chartsMap.value)
|
||||||
|
eventSource.close()
|
||||||
|
renderCharts()
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (!question.value.trim() || loading.value) return
|
if (!question.value.trim() || loading.value) return
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
answer.value = ''
|
answer.value = ''
|
||||||
renderedAnswer.value = ''
|
renderedAnswer.value = ''
|
||||||
|
chartsMap.value = {
|
||||||
|
echarts: {},
|
||||||
|
chartjs: {},
|
||||||
|
mermaid: {},
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = 'http://localhost:7891/chat/stream'
|
const url = 'http://localhost:7891/chat/stream'
|
||||||
@@ -59,18 +116,18 @@ const handleSubmit = async () => {
|
|||||||
url: url,
|
url: url,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
onDisconnect: () => {
|
|
||||||
console.log(answer.value)
|
|
||||||
console.log(renderedAnswer.value)
|
|
||||||
eventSource.close()
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
for await (const { data } of eventSource) {
|
for await (const { data } of eventSource) {
|
||||||
|
if (isEqual(data, '#CLOSE#')) {
|
||||||
|
onEventSourceClose(eventSource)
|
||||||
|
break
|
||||||
|
}
|
||||||
answer.value += data.replaceAll(/#\/#/g, '')
|
answer.value += data.replaceAll(/#\/#/g, '')
|
||||||
renderedAnswer.value = md.render(answer.value)
|
renderedAnswer.value = md.render(answer.value)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('请求出错:', error)
|
console.error('请求出错:', error)
|
||||||
|
console.log(answer.value)
|
||||||
answer.value = '抱歉,请求出现错误'
|
answer.value = '抱歉,请求出现错误'
|
||||||
renderedAnswer.value = answer.value
|
renderedAnswer.value = answer.value
|
||||||
showToastMessage('请求失败,请检查服务器连接', 'error')
|
showToastMessage('请求失败,请检查服务器连接', 'error')
|
||||||
@@ -141,8 +198,25 @@ const handleCloseSettings = () => {
|
|||||||
showToastMessage('设置已保存', 'success')
|
showToastMessage('设置已保存', 'success')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const renderCharts = () => {
|
||||||
|
const map = toRaw(chartsMap.value)
|
||||||
|
each(map.echarts, (value, key) => {
|
||||||
|
echarts.init(document.getElementById(`echarts-${key}`)).setOption(value)
|
||||||
|
})
|
||||||
|
each(map.chartjs, (value, key) => {
|
||||||
|
new Chart(document.getElementById(`chartjs-${key}`), value)
|
||||||
|
})
|
||||||
|
each(map.mermaid, (value, key) => {
|
||||||
|
mermaid.initialize({ startOnLoad: true })
|
||||||
|
mermaid.init(undefined, document.getElementById(`mermaid-${key}`))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 在组件挂载时加载设置
|
// 在组件挂载时加载设置
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
renderCharts()
|
||||||
|
})
|
||||||
loadSettingsFromStorage()
|
loadSettingsFromStorage()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -350,6 +424,10 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.mermaid {
|
||||||
|
font-family: 'Arial', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-container {
|
.chat-container {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|||||||
Reference in New Issue
Block a user