mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: 支持通过echarts_rander标签 渲染图表
This commit is contained in:
parent
0eaa04e8a4
commit
b8f387eb99
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div ref="chartsRef" :style="style" v-resize="changeChartSize"></div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, nextTick, watch, onBeforeUnmount, ref } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
const props = defineProps({
|
||||
option: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
const chartsRef = ref()
|
||||
|
||||
const style = ref({
|
||||
height: '220px',
|
||||
width: '100%'
|
||||
})
|
||||
|
||||
function initChart() {
|
||||
if (chartsRef.value) {
|
||||
let myChart = echarts?.getInstanceByDom(chartsRef.value)
|
||||
if (myChart === null || myChart === undefined) {
|
||||
myChart = echarts.init(chartsRef.value)
|
||||
}
|
||||
const option = JSON.parse(props.option)
|
||||
if (option.actionType === 'EVAL') {
|
||||
myChart.setOption(evalParseOption(option), true)
|
||||
} else {
|
||||
myChart.setOption(jsonParseOption(option), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
function jsonParseOption(option: any) {
|
||||
if (option.style) {
|
||||
style.value = option.style
|
||||
}
|
||||
|
||||
if (option.option) {
|
||||
// 渲染数据
|
||||
return option.option
|
||||
}
|
||||
return option
|
||||
}
|
||||
function evalParseOption(option_json: any) {
|
||||
let option = {}
|
||||
eval(option_json.option)
|
||||
return option
|
||||
}
|
||||
|
||||
function changeChartSize() {
|
||||
echarts?.getInstanceByDom(chartsRef.value)?.resize()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.option,
|
||||
(val) => {
|
||||
if (val) {
|
||||
nextTick(() => {
|
||||
initChart()
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
initChart()
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
echarts.getInstanceByDom(chartsRef.value)?.dispose()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -10,7 +10,10 @@
|
|||
{{ item.content }}
|
||||
</div>
|
||||
<HtmlRander v-else-if="item.type === 'html_rander'" :source="item.content"></HtmlRander>
|
||||
|
||||
<EchartsRander
|
||||
v-else-if="item.type === 'echarts_rander'"
|
||||
:option="item.content"
|
||||
></EchartsRander>
|
||||
<MdPreview
|
||||
v-else
|
||||
noIconfont
|
||||
|
|
@ -26,6 +29,7 @@
|
|||
import { computed, ref } from 'vue'
|
||||
import { config } from 'md-editor-v3'
|
||||
import HtmlRander from './HtmlRander.vue'
|
||||
import EchartsRander from './EchartsRander.vue'
|
||||
config({
|
||||
markdownItConfig(md) {
|
||||
md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
|
||||
|
|
@ -64,8 +68,9 @@ const md_view_list = computed(() => {
|
|||
return md_img_list[Math.floor(index / 2)]
|
||||
}
|
||||
})
|
||||
return split_html_rander(split_quick_question(result))
|
||||
return split_echarts_rander(split_html_rander(split_quick_question(result)))
|
||||
})
|
||||
|
||||
const split_quick_question = (result: Array<string>) => {
|
||||
return result
|
||||
.map((item) => split_quick_question_(item))
|
||||
|
|
@ -133,6 +138,41 @@ const split_html_rander_ = (source: string, type: string) => {
|
|||
})
|
||||
return result
|
||||
}
|
||||
|
||||
const split_echarts_rander = (result: Array<any>) => {
|
||||
return result
|
||||
.map((item) => split_echarts_rander_(item.content, item.type))
|
||||
.reduce((x: any, y: any) => {
|
||||
return [...x, ...y]
|
||||
}, [])
|
||||
}
|
||||
|
||||
const split_echarts_rander_ = (source: string, type: string) => {
|
||||
const temp_md_quick_question_list = source.match(/<echarts_rander>[\d\D]*?<\/echarts_rander>/g)
|
||||
const md_quick_question_list = temp_md_quick_question_list
|
||||
? temp_md_quick_question_list.filter((i) => i)
|
||||
: []
|
||||
const split_quick_question_value = source
|
||||
.split(/<echarts_rander>[\d\D]*?<\/echarts_rander>/g)
|
||||
.filter((item) => item !== undefined)
|
||||
.filter((item) => !md_quick_question_list?.includes(item))
|
||||
const result = Array.from(
|
||||
{ length: md_quick_question_list.length + split_quick_question_value.length },
|
||||
(v, i) => i
|
||||
).map((index) => {
|
||||
if (index % 2 == 0) {
|
||||
return { type: type, content: split_quick_question_value[Math.floor(index / 2)] }
|
||||
} else {
|
||||
return {
|
||||
type: 'echarts_rander',
|
||||
content: md_quick_question_list[Math.floor(index / 2)]
|
||||
.replace('<echarts_rander>', '')
|
||||
.replace('</echarts_rander>', '')
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.problem-button {
|
||||
|
|
|
|||
Loading…
Reference in New Issue