120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { ChevronLeft, Printer, Undo2, Redo2 } from 'lucide-react';
|
||
import { LabelTemplate, PaperConfig } from '../types';
|
||
import type { TableCellCoord } from '../tableUtils';
|
||
import type { ElementClipboardActions } from '../hooks/useElementClipboard';
|
||
import { LabelDesigner } from './LabelDesigner';
|
||
import { PropSidebar, MobilePropModule } from './PropSidebar';
|
||
|
||
interface MobileDesignViewProps {
|
||
template: LabelTemplate;
|
||
paper: PaperConfig;
|
||
selectedElementIds: string[];
|
||
onSelectElements: (ids: string[]) => void;
|
||
selectedTableCells: TableCellCoord[];
|
||
onSelectTableCells: (cells: TableCellCoord[]) => void;
|
||
onChangeTemplate: (updated: LabelTemplate) => void;
|
||
canUndo: boolean;
|
||
canRedo: boolean;
|
||
onUndo: () => void;
|
||
onRedo: () => void;
|
||
onBack: () => void;
|
||
onExport: () => void;
|
||
elementClipboard: ElementClipboardActions;
|
||
}
|
||
|
||
export const MobileDesignView: React.FC<MobileDesignViewProps> = ({
|
||
template,
|
||
paper,
|
||
selectedElementIds,
|
||
onSelectElements,
|
||
selectedTableCells,
|
||
onSelectTableCells,
|
||
onChangeTemplate,
|
||
canUndo,
|
||
canRedo,
|
||
onUndo,
|
||
onRedo,
|
||
onBack,
|
||
onExport,
|
||
elementClipboard,
|
||
}) => {
|
||
const [mobileModule, setMobileModule] = useState<MobilePropModule>('properties');
|
||
|
||
return (
|
||
<div className="mobile-design-view">
|
||
<header className="mobile-design-header">
|
||
<button type="button" onClick={onBack} className="mobile-export-back" aria-label="返回">
|
||
<ChevronLeft className="w-5 h-5" />
|
||
</button>
|
||
<div className="min-w-0 flex-1 px-1">
|
||
<p className="text-sm font-semibold text-slate-100 truncate">{template.name}</p>
|
||
<p className="text-[11px] text-slate-400">
|
||
{template.width}×{template.height} mm
|
||
</p>
|
||
</div>
|
||
<div className="flex items-center gap-0.5 shrink-0">
|
||
<button
|
||
type="button"
|
||
onClick={onUndo}
|
||
disabled={!canUndo}
|
||
className="mobile-design-header-icon-btn"
|
||
aria-label="撤销"
|
||
>
|
||
<Undo2 className="w-4 h-4" />
|
||
</button>
|
||
<button
|
||
type="button"
|
||
onClick={onRedo}
|
||
disabled={!canRedo}
|
||
className="mobile-design-header-icon-btn"
|
||
aria-label="恢复"
|
||
>
|
||
<Redo2 className="w-4 h-4" />
|
||
</button>
|
||
<button
|
||
type="button"
|
||
onClick={onExport}
|
||
className="inline-flex items-center gap-1 ml-1 px-2.5 py-1.5 bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800 text-white text-[11px] font-semibold rounded-lg"
|
||
>
|
||
<Printer className="w-3.5 h-3.5" />
|
||
生成
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div className="mobile-design-canvas-wrap">
|
||
<LabelDesigner
|
||
variant="mobile"
|
||
template={template}
|
||
onChange={onChangeTemplate}
|
||
selectedElementIds={selectedElementIds}
|
||
onSelectElements={onSelectElements}
|
||
selectedTableCells={selectedTableCells}
|
||
onSelectTableCells={onSelectTableCells}
|
||
suppressSelectionChrome={mobileModule === 'nudge'}
|
||
elementClipboard={elementClipboard}
|
||
/>
|
||
</div>
|
||
|
||
<div className="mobile-design-props-wrap">
|
||
<PropSidebar
|
||
variant="mobile"
|
||
template={template}
|
||
onChangeTemplate={onChangeTemplate}
|
||
selectedElementIds={selectedElementIds}
|
||
onSelectElements={onSelectElements}
|
||
selectedTableCells={selectedTableCells}
|
||
onSelectTableCells={onSelectTableCells}
|
||
activeTab="element"
|
||
onChangeTab={() => {}}
|
||
paper={paper}
|
||
mobileModule={mobileModule}
|
||
onMobileModuleChange={setMobileModule}
|
||
elementClipboard={elementClipboard}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|