import React, { useState, useEffect, useMemo } from 'react'; import { TemplateElement } from '../types'; import { ContentResolveMode } from '../utils'; import { renderLabelToDataUrl } from '../labelRenderer'; interface CanvasLabelImageProps { widthMm: number; heightMm: number; elements: TemplateElement[]; rowData: any; rowIndex: number; showBorder?: boolean; transparentBackground?: boolean; variableDefaults?: Record | null; /** design=设计预览(空变量显示占位);output=排版/打印(空值隐藏图形元素) */ mode?: ContentResolveMode; referenceBackground?: string; referenceBackgroundOpacity?: number; referenceBackgroundFit?: 'contain' | 'cover' | 'fill'; /** 渲染倍率,设计画布应传 MM_TO_PX * zoom 与显示尺寸 1:1 对齐 */ renderScale?: number; } export const CanvasLabelImage: React.FC = ({ widthMm, heightMm, elements, rowData, rowIndex, showBorder = false, transparentBackground = false, variableDefaults = null, mode = 'design' as ContentResolveMode, referenceBackground, referenceBackgroundOpacity, referenceBackgroundFit, renderScale = 16, }) => { const [dataUrl, setDataUrl] = useState(''); const [initialLoading, setInitialLoading] = useState(true); const elementsKey = useMemo(() => JSON.stringify(elements), [elements]); const rowDataKey = useMemo(() => JSON.stringify(rowData), [rowData]); const variableDefaultsKey = useMemo( () => JSON.stringify(variableDefaults), [variableDefaults] ); useEffect(() => { let active = true; renderLabelToDataUrl({ widthMm, heightMm, elements, rowData, rowIndex, showBorder, transparentBackground, variableDefaults, mode, scale: renderScale, referenceBackground, referenceBackgroundOpacity, referenceBackgroundFit, }) .then((url) => { if (!active) return; const img = new Image(); img.onload = () => { if (active) { setDataUrl(url); setInitialLoading(false); } }; img.onerror = () => { if (active) setInitialLoading(false); }; img.src = url; }) .catch((err) => { console.error('Label graphics rendering error:', err); if (active) setInitialLoading(false); }); return () => { active = false; }; }, [ widthMm, heightMm, elementsKey, rowDataKey, variableDefaultsKey, rowIndex, showBorder, transparentBackground, mode, renderScale, referenceBackground, referenceBackgroundOpacity, referenceBackgroundFit, ]); if (initialLoading && !dataUrl) { return (
绘制中
); } return ( Label Preview ); };