Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
84526182
Commit
84526182
authored
Mar 24, 2026
by
Liu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:饼图展示效果
parent
ce98b1a5
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
73 additions
and
47 deletions
+73
-47
src/components/MarkdownDetail/index.tsx
+73
-47
No files found.
src/components/MarkdownDetail/index.tsx
View file @
84526182
...
@@ -62,66 +62,79 @@ async function getMermaid() {
...
@@ -62,66 +62,79 @@ async function getMermaid() {
return
mermaidInitPromise
return
mermaidInitPromise
}
}
function
MermaidBlock
({
chart
}:
{
chart
:
string
})
{
const
mermaidSvgCache
=
new
Map
<
string
,
string
>
()
const
mermaidHeightCache
=
new
Map
<
string
,
number
>
()
function
MermaidBlock
({
chart
,
cacheKey
}:
{
chart
:
string
,
cacheKey
:
string
})
{
const
reactId
=
useId
()
const
reactId
=
useId
()
const
renderId
=
useMemo
(()
=>
`mermaid-
${
reactId
.
replace
(
/:/g
,
'-'
)}
`
,
[
reactId
])
const
renderId
=
useMemo
(()
=>
`mermaid-
${
reactId
.
replace
(
/:/g
,
'-'
)}
`
,
[
reactId
])
const
[
svg
,
setSvg
]
=
useState
<
string
>
(
''
)
const
[
svg
,
setSvg
]
=
useState
<
string
>
(
()
=>
mermaidSvgCache
.
get
(
cacheKey
)
??
''
)
const
[
hidden
,
setHidden
]
=
useState
<
boolean
>
(
false
)
const
[
minHeight
,
setMinHeight
]
=
useState
<
number
>
(()
=>
mermaidHeightCache
.
get
(
cacheKey
)
??
0
)
const
svgContainerRef
=
useRef
<
HTMLDivElement
|
null
>
(
null
)
const
svgContainerRef
=
useRef
<
HTMLDivElement
|
null
>
(
null
)
const
lastGoodSvgRef
=
useRef
<
string
>
(
''
)
useEffect
(()
=>
{
useEffect
(()
=>
{
let
cancelled
=
false
const
cached
=
mermaidSvgCache
.
get
(
cacheKey
)
const
code
=
normalizeMermaid
(
chart
)
if
(
cached
)
{
if
(
!
code
)
{
lastGoodSvgRef
.
current
=
cached
// During streaming, chart text may be temporarily empty.
setSvg
(
cached
)
// Keep the previous SVG (if any) to avoid flicker, and only hide when nothing to show.
if
(
!
svg
)
{
setSvg
(
''
)
setHidden
(
true
)
}
return
()
=>
{
cancelled
=
true
}
}
}
const
cachedH
=
mermaidHeightCache
.
get
(
cacheKey
)
if
(
cachedH
)
setMinHeight
(
cachedH
)
},
[
cacheKey
])
;(
async
()
=>
{
useEffect
(()
=>
{
try
{
let
cancelled
=
false
const
mermaid
=
await
getMermaid
()
const
code
=
normalizeMermaid
(
chart
)
mermaid
.
initialize
({
startOnLoad
:
false
,
suppressErrorRendering
:
true
})
// During streaming, chart text is often incomplete. To avoid page flicker:
try
{
// - debounce render work (avoid per-token rerenders)
await
mermaid
.
parse
(
code
)
// - only update SVG on successful parse+render
}
// - keep the last successful SVG visible when parse fails temporarily
catch
{
const
t
=
window
.
setTimeout
(()
=>
{
if
(
!
cancelled
)
{
;(
async
()
=>
{
if
(
!
code
)
{
if
(
!
cancelled
&&
!
lastGoodSvgRef
.
current
)
setSvg
(
''
)
setSvg
(
''
)
setHidden
(
true
)
}
return
return
}
}
try
{
const
mermaid
=
await
getMermaid
()
try
{
await
mermaid
.
parse
(
code
)
}
catch
{
// Keep previous SVG if any.
if
(
!
cancelled
&&
!
lastGoodSvgRef
.
current
)
setSvg
(
''
)
return
}
const
res
=
await
mermaid
.
render
(
renderId
,
code
)
if
(
cancelled
)
return
const
res
=
await
mermaid
.
render
(
renderId
,
code
)
if
(
!
cancelled
)
{
const
outSvg
=
String
(
res
?.
svg
||
''
)
const
outSvg
=
String
(
res
?.
svg
||
''
)
if
(
/Syntax error in text/i
.
test
(
outSvg
))
{
if
(
!
outSvg
||
/Syntax error in text/i
.
test
(
outSvg
))
{
setSvg
(
''
)
if
(
!
lastGoodSvgRef
.
current
)
setHidden
(
true
)
setSvg
(
''
)
}
return
else
{
setSvg
(
outSvg
)
setHidden
(
false
)
}
}
lastGoodSvgRef
.
current
=
outSvg
mermaidSvgCache
.
set
(
cacheKey
,
outSvg
)
setSvg
(
outSvg
)
}
}
}
catch
{
catch
{
if
(
!
cancelled
&&
!
lastGoodSvgRef
.
current
)
if
(
!
cancelled
)
{
setSvg
(
''
)
setSvg
(
''
)
setHidden
(
true
)
}
}
}
}
)()
}
)(
)
}
,
150
)
return
()
=>
{
return
()
=>
{
cancelled
=
true
cancelled
=
true
window
.
clearTimeout
(
t
)
}
}
},
[
chart
,
renderId
])
},
[
chart
,
renderId
])
...
@@ -130,13 +143,23 @@ function MermaidBlock({ chart }: { chart: string }) {
...
@@ -130,13 +143,23 @@ function MermaidBlock({ chart }: { chart: string }) {
if
(
!
el
)
if
(
!
el
)
return
return
el
.
innerHTML
=
svg
el
.
innerHTML
=
svg
if
(
!
svg
)
return
// Measure height after DOM update to reduce layout shift.
const
raf
=
window
.
requestAnimationFrame
(()
=>
{
const
h
=
Math
.
ceil
(
el
.
getBoundingClientRect
().
height
)
if
(
h
>
0
)
{
mermaidHeightCache
.
set
(
cacheKey
,
h
)
setMinHeight
(
prev
=>
(
h
>
prev
?
h
:
prev
))
}
})
return
()
=>
{
window
.
cancelAnimationFrame
(
raf
)
}
},
[
svg
])
},
[
svg
])
if
(
hidden
||
!
svg
)
return
null
return
(
return
(
<
div
className=
"my-[8px] overflow-x-auto"
>
<
div
className=
"my-[8px] overflow-x-auto"
style=
{
{
minHeight
:
minHeight
||
undefined
}
}
>
<
div
ref=
{
svgContainerRef
}
/>
<
div
ref=
{
svgContainerRef
}
/>
</
div
>
</
div
>
)
)
...
@@ -178,7 +201,10 @@ export const MarkdownDetail: React.FC<MarkdownDetailProps> = memo(({ children, d
...
@@ -178,7 +201,10 @@ export const MarkdownDetail: React.FC<MarkdownDetailProps> = memo(({ children, d
||
(
isPie
&&
!
disablePie
)
||
(
isPie
&&
!
disablePie
)
)
{
)
{
const
chart
=
toText
((
first
.
props
as
any
)?.
children
)
const
chart
=
toText
((
first
.
props
as
any
)?.
children
)
return
<
MermaidBlock
chart=
{
chart
}
/>
const
node
:
any
=
(
props
as
any
)?.
node
const
startOffset
=
node
?.
position
?.
start
?.
offset
const
key
=
`${lang || 'mermaid'}:${String(startOffset ?? 'na')}`
return
<
MermaidBlock
chart=
{
chart
}
cacheKey=
{
key
}
/>
}
}
}
}
return
<
pre
{
...
props
}
>
{
children
}
</
pre
>
return
<
pre
{
...
props
}
>
{
children
}
</
pre
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment