浏览代码

Fix mermaid render (#6088)

Co-authored-by: 靖谦 <jingqian@kaiwu.cloud>
tags/0.6.14
Jinq Qian 1年前
父节点
当前提交
a7b33b55e8
没有帐户链接到提交者的电子邮件
共有 1 个文件被更改,包括 32 次插入43 次删除
  1. 32
    43
      web/app/components/base/mermaid/index.tsx

+ 32
- 43
web/app/components/base/mermaid/index.tsx 查看文件

import React, { useEffect, useRef, useState } from 'react' import React, { useEffect, useRef, useState } from 'react'
import mermaid from 'mermaid' import mermaid from 'mermaid'
import { usePrevious } from 'ahooks'
import CryptoJS from 'crypto-js' import CryptoJS from 'crypto-js'
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline'
import LoadingAnim from '@/app/components/base/chat/chat/loading-anim' import LoadingAnim from '@/app/components/base/chat/chat/loading-anim'


let mermaidAPI: any let mermaidAPI: any
}, ref) => { }, ref) => {
const [svgCode, setSvgCode] = useState(null) const [svgCode, setSvgCode] = useState(null)
const chartId = useRef(`flowchart_${CryptoJS.MD5(props.PrimitiveCode).toString()}`) const chartId = useRef(`flowchart_${CryptoJS.MD5(props.PrimitiveCode).toString()}`)
const [isRender, setIsRender] = useState(false)
const prevPrimitiveCode = usePrevious(props.PrimitiveCode)
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)

const clearFlowchartCache = () => {
for (let i = localStorage.length - 1; i >= 0; --i) {
const key = localStorage.key(i)
if (key && key.startsWith('flowchart_'))
localStorage.removeItem(key)
}
}
const timeRef = useRef<NodeJS.Timeout>()
const [errMsg, setErrMsg] = useState('')


const renderFlowchart = async (PrimitiveCode: string) => { const renderFlowchart = async (PrimitiveCode: string) => {
try { try {
const cachedSvg: any = localStorage.getItem(chartId.current)
if (cachedSvg) {
setSvgCode(cachedSvg)
setIsLoading(false)
return
}

if (typeof window !== 'undefined' && mermaidAPI) { if (typeof window !== 'undefined' && mermaidAPI) {
const svgGraph = await mermaidAPI.render(chartId.current, PrimitiveCode) const svgGraph = await mermaidAPI.render(chartId.current, PrimitiveCode)
const dom = new DOMParser().parseFromString(svgGraph.svg, 'text/xml')
if (!dom.querySelector('g.main'))
throw new Error('empty svg')

const base64Svg: any = await svgToBase64(svgGraph.svg) const base64Svg: any = await svgToBase64(svgGraph.svg)
setSvgCode(base64Svg) setSvgCode(base64Svg)
setIsLoading(false) setIsLoading(false)
} }
} }
catch (error) { catch (error) {
clearFlowchartCache()
// eslint-disable-next-line @typescript-eslint/no-use-before-define
handleReRender()
if (prevPrimitiveCode === props.PrimitiveCode) {
setIsLoading(false)
setErrMsg((error as Error).message)
}
} }
} }


const handleReRender = () => {
setIsRender(false)
setSvgCode(null)
if (chartId.current)
localStorage.removeItem(chartId.current)

setTimeout(() => {
setIsRender(true)
renderFlowchart(props.PrimitiveCode)
}, 100)
}

useEffect(() => { useEffect(() => {
setIsRender(false)
setTimeout(() => {
setIsRender(true)
const cachedSvg: any = localStorage.getItem(chartId.current)
if (cachedSvg) {
setSvgCode(cachedSvg)
setIsLoading(false)
return
}
if (timeRef.current)
clearTimeout(timeRef.current)

timeRef.current = setTimeout(() => {
renderFlowchart(props.PrimitiveCode) renderFlowchart(props.PrimitiveCode)
}, 100)
}, 300)
}, [props.PrimitiveCode]) }, [props.PrimitiveCode])


return ( return (
// @ts-expect-error // @ts-expect-error
<div ref={ref}> <div ref={ref}>
{ {
isRender
&& <div className="mermaid" style={style}>
{svgCode && <img src={svgCode} style={{ width: '100%', height: 'auto' }} alt="Mermaid chart" />}
</div>
svgCode
&& <div className="mermaid" style={style}>
{svgCode && <img src={svgCode} style={{ width: '100%', height: 'auto' }} alt="Mermaid chart" />}
</div>
} }
{isLoading {isLoading
&& <div className='py-4 px-[26px]'> && <div className='py-4 px-[26px]'>
<LoadingAnim type='text' /> <LoadingAnim type='text' />
</div> </div>
} }
{
errMsg
&& <div className='py-4 px-[26px]'>
<ExclamationTriangleIcon className='w-6 h-6 text-red-500' />
&nbsp;
{errMsg}
</div>
}
</div> </div>
) )
}) })

正在加载...
取消
保存