This commit is contained in:
iqudoo
2026-06-14 18:02:18 +08:00
parent b4c2cf07d0
commit 8c9b53b1b6
7 changed files with 229 additions and 35 deletions

View File

@@ -3,6 +3,12 @@ import { TemplateElement } from '../types';
import { mmToPx } from '../utils';
import { renderLabelToDataUrl } from '../labelRenderer';
/** 离屏单元素渲染时预留描边空间,避免画布边缘裁切表格线 */
function getFloatPreviewPaddingMm(element: TemplateElement): number {
if (element.type !== 'table') return 0;
return (element.tableBorderWidth ?? 0.2) / 2 + 0.1;
}
interface ElementFloatPreviewProps {
element: TemplateElement;
renderScale: number;
@@ -17,10 +23,11 @@ export async function renderElementFloatPreview(
renderScale: number,
variableDefaults?: Record<string, string> | null
): Promise<string> {
const padMm = getFloatPreviewPaddingMm(element);
return renderLabelToDataUrl({
widthMm: element.width,
heightMm: element.height,
elements: [{ ...element, x: 0, y: 0 }],
widthMm: element.width + padMm * 2,
heightMm: element.height + padMm * 2,
elements: [{ ...element, x: padMm, y: padMm }],
rowData: null,
rowIndex: 0,
showBorder: false,

View File

@@ -1,7 +1,7 @@
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { createPortal } from 'react-dom';
import { LabelTemplate, TemplateElement } from '../types';
import { mmToPx, MM_TO_PX, shouldRenderElement } from '../utils';
import { mmToPx, MM_TO_PX, shouldRenderElement, centerElementOnLabel } from '../utils';
import type { ElementClipboardActions } from '../hooks/useElementClipboard';
import {
createDefaultTableElement,
@@ -327,8 +327,7 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
id,
type: 'image',
name: `图片 ${n}`,
x: 5,
y: 5,
...centerElementOnLabel(template.width, template.height, 30, 30),
width: 30,
height: 30,
content: src,
@@ -421,6 +420,14 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
};
}
const centered = centerElementOnLabel(
template.width,
template.height,
newElement.width,
newElement.height
);
newElement = { ...newElement, ...centered };
onChange({
...template,
elements: [...template.elements, newElement],

View File

@@ -997,7 +997,9 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
const renderPropertiesPanelBody = () => (
<>
<div className="pb-3 border-b border-[#3a3a3a]">{renderPreviewReferenceBackgroundFields()}</div>
{!selectedElem && (
<div className="pb-3 border-b border-[#3a3a3a]">{renderPreviewReferenceBackgroundFields()}</div>
)}
{/* Label Canvas Dimensions */}
{!selectedElem && (
<div className="space-y-4">
@@ -1684,13 +1686,15 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
value={selectedElem.width}
onCommit={(val) => {
const wVal = Math.max(2, Number(val) || 2);
let updated = { ...selectedElem, width: wVal };
if (selectedElem.type === 'qrcode') {
updated.height = wVal;
handleElemChange({ ...selectedElem, width: wVal, height: wVal });
} else if (selectedElem.type === 'table') {
updated = scaleTableElementSize(updated, wVal, updated.height);
handleElemChange(
scaleTableElementSize(selectedElem, wVal, selectedElem.height)
);
} else {
handleElemChange({ ...selectedElem, width: wVal });
}
handleElemChange(updated);
}}
className="ps-field font-mono"
/>

View File

@@ -14,6 +14,8 @@ import {
updateTableCells,
updateTableColWidth,
updateTableRowHeight,
equalizeTableColWidths,
equalizeTableRowHeights,
getTableColWidths,
getTableRowHeights,
getCellRawContent,
@@ -90,7 +92,17 @@ export const TablePropertyFields: React.FC<TablePropertyFieldsProps> = ({
</div>
<div className="space-y-1.5">
<span className="text-[10px] font-semibold text-[#aaa]"> (mm)</span>
<div className="flex items-center justify-between gap-2">
<span className="text-[10px] font-semibold text-[#aaa]"> (mm)</span>
<button
type="button"
onClick={() => onChange(equalizeTableRowHeights(elem))}
className="text-[9px] text-[#31a8ff] hover:underline cursor-pointer shrink-0"
title="将各行高度恢复为相等"
>
</button>
</div>
<div className="grid grid-cols-3 gap-1.5">
{rowHeights.map((h, i) => (
<div key={`rh-${i}`}>
@@ -111,7 +123,17 @@ export const TablePropertyFields: React.FC<TablePropertyFieldsProps> = ({
</div>
<div className="space-y-1.5">
<span className="text-[10px] font-semibold text-[#aaa]"> (mm)</span>
<div className="flex items-center justify-between gap-2">
<span className="text-[10px] font-semibold text-[#aaa]"> (mm)</span>
<button
type="button"
onClick={() => onChange(equalizeTableColWidths(elem))}
className="text-[9px] text-[#31a8ff] hover:underline cursor-pointer shrink-0"
title="将各列宽度恢复为相等"
>
</button>
</div>
<div className="grid grid-cols-3 gap-1.5">
{colWidths.map((w, i) => (
<div key={`cw-${i}`}>
@@ -287,7 +309,9 @@ export const TableCellContentFields: React.FC<TableCellContentFieldsProps> = ({
export function scaleTableElementSize(
elem: TemplateElement,
newWidth: number,
newHeight: number
newHeight: number,
startWidth = elem.width,
startHeight = elem.height
): TemplateElement {
if (elem.type !== 'table') {
return { ...elem, width: newWidth, height: newHeight };
@@ -296,8 +320,8 @@ export function scaleTableElementSize(
elem,
newWidth,
newHeight,
elem.width,
elem.height,
startWidth,
startHeight,
getTableRowHeights(elem),
getTableColWidths(elem)
);