feat: add report html rendering

This commit is contained in:
qixinbo
2026-03-18 22:42:18 +08:00
parent a0e72111cd
commit baec21c774
+32 -3
View File
@@ -35,6 +35,21 @@ interface MessageViz {
error?: string | null; error?: string | null;
} }
const REPORT_HTML_BLOCK_REGEX = /<!--\s*REPORT_HTML_START\s*-->([\s\S]*?)<!--\s*REPORT_HTML_END\s*-->/i;
const splitReportHtml = (content: string): { markdown: string; reportHtml: string | null } => {
if (!content) {
return { markdown: "", reportHtml: null };
}
const match = content.match(REPORT_HTML_BLOCK_REGEX);
if (!match) {
return { markdown: content, reportHtml: null };
}
const reportHtml = (match[1] || "").trim();
const markdown = content.replace(REPORT_HTML_BLOCK_REGEX, "").trim();
return { markdown, reportHtml: reportHtml || null };
};
interface ModelConfig { interface ModelConfig {
id: string; id: string;
name?: string; name?: string;
@@ -898,7 +913,9 @@ export function ChatInterface() {
</div> </div>
) : ( ) : (
<div className="max-w-3xl mx-auto px-4 py-8 space-y-8"> <div className="max-w-3xl mx-auto px-4 py-8 space-y-8">
{messages.map((msg) => ( {messages.map((msg) => {
const { markdown, reportHtml } = splitReportHtml(msg.content);
return (
<div <div
key={msg.id} key={msg.id}
className={`flex gap-4 ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`} className={`flex gap-4 ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
@@ -948,11 +965,23 @@ export function ChatInterface() {
</div> </div>
) : ( ) : (
<> <>
{markdown ? (
<div className="prose prose-sm prose-zinc max-w-none prose-p:leading-normal prose-p:my-2 prose-headings:my-3 prose-ul:my-2 prose-li:my-0.5 prose-pre:bg-zinc-50 prose-pre:text-zinc-800 prose-pre:border prose-pre:border-zinc-200"> <div className="prose prose-sm prose-zinc max-w-none prose-p:leading-normal prose-p:my-2 prose-headings:my-3 prose-ul:my-2 prose-li:my-0.5 prose-pre:bg-zinc-50 prose-pre:text-zinc-800 prose-pre:border prose-pre:border-zinc-200">
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}> <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
{msg.content} {markdown}
</ReactMarkdown> </ReactMarkdown>
</div> </div>
) : null}
{reportHtml ? (
<div className="mt-3 rounded-xl border border-zinc-200 overflow-hidden bg-white">
<iframe
title={`report-${msg.id}`}
srcDoc={reportHtml}
sandbox="allow-same-origin"
className="w-full h-[620px] bg-white"
/>
</div>
) : null}
{msg.viz ? ( {msg.viz ? (
<div className="mt-3 pt-3 border-t border-zinc-100"> <div className="mt-3 pt-3 border-t border-zinc-100">
<InlineVisualizationCard viz={msg.viz} /> <InlineVisualizationCard viz={msg.viz} />
@@ -971,7 +1000,7 @@ export function ChatInterface() {
</div> </div>
)} )}
</div> </div>
))} )})}
<div ref={scrollRef} /> <div ref={scrollRef} />
</div> </div>
)} )}