Files
Agent-System/web/src/components/doc/blocks/MathBlockView.tsx
T

92 lines
2.7 KiB
TypeScript

import React, { useMemo } from 'react';
import { DocumentBlock } from '../../../types/block';
import katex from 'katex';
import { Calculator } from 'lucide-react';
interface MathBlockViewProps {
block: DocumentBlock;
}
export const MathBlockView: React.FC<MathBlockViewProps> = ({ block }) => {
const renderedHtml = useMemo(() => {
try {
const cleanContent = block.content.trim().replace(/^\\?\$+/, '').replace(/\$+$/, '');
return katex.renderToString(cleanContent, {
displayMode: true,
throwOnError: false,
});
} catch (err: any) {
return `<span style="color:var(--danger)">LaTeX 解析错误: ${err.message}</span>`;
}
}, [block.content]);
const caption = block.properties?.caption || '关键计算判据与物理算法模型';
// 提取公式右侧序号简写,例如 "式 (3-1)" 提取为 "(3-1)"
const formulaTag = block.numbering ? block.numbering.replace(/^式\s*/, '') : '';
return (
<div style={{ margin: '18px 0', display: 'flex', flexDirection: 'column', gap: '6px' }}>
<div
style={{
padding: '16px 20px',
borderRadius: 'var(--r-md)',
background: 'var(--bg-subtle)',
border: '1px solid var(--border)',
overflowX: 'auto',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow: 'var(--shadow-xs)',
position: 'relative',
}}
>
<div
dangerouslySetInnerHTML={{ __html: renderedHtml }}
style={{
fontSize: '15px',
color: 'var(--text-strong)',
maxWidth: '100%',
}}
/>
{/* 国际工程/学术规范:公式右侧常驻对齐编号 */}
{formulaTag && (
<div
style={{
position: 'absolute',
right: '18px',
color: 'var(--text-muted)',
fontFamily: 'var(--font-mono)',
fontSize: '12.5px',
fontWeight: 600,
userSelect: 'none',
}}
title="公式章节编号"
>
{formulaTag}
</div>
)}
</div>
{/* 题注与完整编号 */}
<div
style={{
fontSize: '11px',
fontWeight: 600,
color: 'var(--text-muted)',
textAlign: 'center',
letterSpacing: '0.3px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '4px',
}}
>
<Calculator size={12} color="var(--brand-500)" />
<span>{block.numbering ? `${block.numbering} ` : ''}</span>
<span>{caption}</span>
</div>
</div>
);
};