This commit is contained in:
iqudoo
2026-06-14 02:52:51 +08:00
parent 6cdae2f69c
commit fff6cb98ae
8 changed files with 325 additions and 256 deletions

View File

@@ -7,10 +7,10 @@ import {
getTableColWidths,
getTableRowHeights,
iterTableCells,
getCellRectMm,
toggleTableCellSelection,
scaleTableTracks,
getCellAnchor,
getCellRectPx,
type TableCellCoord,
} from '../tableUtils';
import { useIsNarrowScreen } from '../hooks/useIsMobile';
@@ -1860,11 +1860,8 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
onSelectTableCells && (
<div className="absolute inset-0 z-10 pointer-events-none">
{iterTableCells(overlayElement).map(({ row, col }) => {
const rect = getCellRectMm(overlayElement, row, col);
const cellX = mmToPx(rect.x, displayZoom);
const cellY = mmToPx(rect.y, displayZoom);
const cellW = mmToPx(rect.width, displayZoom);
const cellH = mmToPx(rect.height, displayZoom);
const { x: cellX, y: cellY, width: cellW, height: cellH } =
getCellRectPx(overlayElement, row, col, canvasRenderScale);
const isCellSelected = selectedTableCells.some((c) => {
const anchor = getCellAnchor(overlayElement, c.row, c.col);
return anchor.row === row && anchor.col === col;
@@ -1872,16 +1869,19 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
return (
<div
key={`cell-${row}-${col}`}
className={`absolute pointer-events-auto cursor-grab active:cursor-grabbing border touch-none ${
className={`absolute pointer-events-auto cursor-grab active:cursor-grabbing touch-none ${
isCellSelected
? 'bg-[#31a8ff]/25 border-[#31a8ff]'
: 'border-transparent hover:bg-[#31a8ff]/10 hover:border-[#31a8ff]/40'
? 'bg-[#31a8ff]/25'
: 'hover:bg-[#31a8ff]/10'
}`}
style={{
left: `${cellX}px`,
top: `${cellY}px`,
width: `${cellW}px`,
height: `${cellH}px`,
boxShadow: isCellSelected
? 'inset 0 0 0 1px #31a8ff'
: undefined,
}}
onPointerDown={(e) =>
handleTableCellPointerDown(e, overlayElement, row, col)

View File

@@ -482,7 +482,7 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
<div className="space-y-3">
<div className="text-[10px] font-bold text-[#31a8ff]"></div>
<p className="text-[10px] text-[#666] leading-relaxed mb-3">
</p>
{templateVariables.map((v) => {
const inUse = isTemplateVariableInUse(template, v);
@@ -501,7 +501,7 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
type="text"
value={template.variableDefaults?.[v] ?? ''}
onChange={(e) => setVariableDefault(v, e.target.value)}
placeholder="预览默认值"
placeholder="预览值"
className="ps-field font-mono text-[10px] w-full min-w-0"
/>
<div className="flex items-center justify-center w-[44px] shrink-0">
@@ -661,6 +661,17 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
)}
{selectedElem.type !== 'table' && (
<>
<div className="flex items-center justify-between gap-2">
<label className="ps-field-label"></label>
<button
type="button"
disabled={!selectedElem.content}
onClick={() => handleElemChange({ ...selectedElem, content: '' })}
className="text-[9px] text-[#31a8ff] hover:underline cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed disabled:no-underline shrink-0"
>
</button>
</div>
<PropTextarea
value={selectedElem.content}
onCommit={(val) => handleElemChange({ ...selectedElem, content: val })}
@@ -691,6 +702,31 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
)}
</>
)}
{(selectedElem.type === 'barcode' ||
selectedElem.type === 'qrcode' ||
selectedElem.type === 'image') && (
<label className="flex items-start gap-2 pt-1">
<input
type="checkbox"
checked={selectedElem.showWhenContentEmpty ?? false}
onChange={(e) =>
handleElemChange({
...selectedElem,
showWhenContentEmpty: e.target.checked ? true : undefined,
})
}
className="ps-checkbox mt-0.5"
/>
<span className="text-xs text-[#ccc] leading-normal">
{selectedElem.type === 'image' && (
<span className="block text-[9px] text-[#777] mt-0.5">
</span>
)}
</span>
</label>
)}
{selectedElem.type === 'table' && (
<p className="text-[10px] text-[#777] leading-normal">
@@ -1407,6 +1443,45 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
<option value="fill"> (fill)</option>
</FieldSelect>
</div>
<div>
<label className="ps-field-label"></label>
<p className="text-[9px] text-[#777] leading-normal mb-1.5">
使
</p>
<label className="ps-btn text-[10px] cursor-pointer mb-1.5 inline-flex">
<Upload className="w-3.5 h-3.5" />
<input
type="file"
accept="image/*"
className="hidden"
onChange={(e) => {
const file = e.target.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = () =>
handleElemChange({
...selectedElem,
defaultImage: reader.result as string,
});
reader.readAsDataURL(file);
e.target.value = '';
}}
/>
</label>
<PropTextarea
value={selectedElem.defaultImage ?? ''}
onCommit={(val) =>
handleElemChange({
...selectedElem,
defaultImage: val.trim() || undefined,
})
}
rows={2}
className="ps-field resize-none"
placeholder="默认图片 URL 或 data URI"
/>
</div>
</div>
)}

View File

@@ -58,7 +58,17 @@ export const TableCellTextFields: React.FC<TableCellTextFieldsProps> = ({
)}
<div>
<label className="ps-field-label"></label>
<div className="flex items-center justify-between gap-2">
<label className="ps-field-label"></label>
<button
type="button"
disabled={!textElem.content}
onClick={() => patchText({ ...textElem, content: '' })}
className="text-[9px] text-[#31a8ff] hover:underline cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed disabled:no-underline shrink-0"
>
</button>
</div>
<textarea
value={textElem.content}
rows={2}

View File

@@ -242,7 +242,17 @@ export const TableCellContentFields: React.FC<TableCellContentFieldsProps> = ({
return (
<div className="space-y-2 pt-2 border-t border-[#3a3a3a]">
<label className="ps-field-label">{selectedCells.length} </label>
<div className="flex items-center justify-between gap-2">
<label className="ps-field-label">{selectedCells.length} </label>
<button
type="button"
disabled={!content}
onClick={() => onChange(updateTableCells(elem, selectedCells, { content: '' }))}
className="text-[9px] text-[#31a8ff] hover:underline cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed disabled:no-underline shrink-0"
>
</button>
</div>
<textarea
value={content}
rows={2}