feat: add PLT double cut option to plotter export

This commit is contained in:
hyper 2026-07-23 20:08:51 +08:00
parent 8c9506c106
commit 18cad20d2c
3 changed files with 29 additions and 2 deletions

View File

@ -179,6 +179,20 @@ export function PrintPreviewHeader(props: PrintPreviewHeaderProps) {
</label> </label>
</div> </div>
<div class="flex items-center gap-2">
<label class="flex items-center gap-1 cursor-pointer">
<input
type="checkbox"
checked={store.state.pltDoubleCut}
onChange={(e) =>
store.actions.setPltDoubleCut(e.target.checked)
}
class="cursor-pointer"
/>
<span class="text-sm text-gray-600">PLT </span>
</label>
</div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<label class="text-sm text-gray-600">:</label> <label class="text-sm text-gray-600">:</label>
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">

View File

@ -73,6 +73,7 @@ export interface DeckState {
printFrontOddPageOffsetX: number; printFrontOddPageOffsetX: number;
printFrontOddPageOffsetY: number; printFrontOddPageOffsetY: number;
printDoubleSided: boolean; printDoubleSided: boolean;
pltDoubleCut: boolean;
} }
export interface DeckActions { export interface DeckActions {
@ -156,6 +157,7 @@ export interface DeckActions {
setPrintFrontOddPageOffsetX: (offset: number) => void; setPrintFrontOddPageOffsetX: (offset: number) => void;
setPrintFrontOddPageOffsetY: (offset: number) => void; setPrintFrontOddPageOffsetY: (offset: number) => void;
setPrintDoubleSided: (doubleSided: boolean) => void; setPrintDoubleSided: (doubleSided: boolean) => void;
setPltDoubleCut: (doubleCut: boolean) => void;
} }
export interface DeckStore { export interface DeckStore {
@ -197,6 +199,7 @@ export function createDeckStore(initialSrc: string = ""): DeckStore {
printFrontOddPageOffsetX: 0, printFrontOddPageOffsetX: 0,
printFrontOddPageOffsetY: 0, printFrontOddPageOffsetY: 0,
printDoubleSided: false, printDoubleSided: false,
pltDoubleCut: false,
}); });
const updateDimensions = () => { const updateDimensions = () => {
@ -553,6 +556,10 @@ export function createDeckStore(initialSrc: string = ""): DeckStore {
setState({ printDoubleSided: doubleSided }); setState({ printDoubleSided: doubleSided });
}; };
const setPltDoubleCut = (doubleCut: boolean) => {
setState({ pltDoubleCut: doubleCut });
};
const actions: DeckActions = { const actions: DeckActions = {
setSizeW, setSizeW,
setSizeH, setSizeH,
@ -599,6 +606,7 @@ export function createDeckStore(initialSrc: string = ""): DeckStore {
setPrintFrontOddPageOffsetX, setPrintFrontOddPageOffsetX,
setPrintFrontOddPageOffsetY, setPrintFrontOddPageOffsetY,
setPrintDoubleSided, setPrintDoubleSided,
setPltDoubleCut,
}; };
return { state, actions }; return { state, actions };

View File

@ -35,6 +35,7 @@ export function usePlotterExport(store: DeckStore): UsePlotterExportReturn {
const cardHeight = () => store.state.dimensions?.cardHeight || 88; const cardHeight = () => store.state.dimensions?.cardHeight || 88;
const shape = () => store.state.shape; const shape = () => store.state.shape;
const orientation = () => store.state.printOrientation || 'landscape'; const orientation = () => store.state.printOrientation || 'landscape';
const doubleCut = () => store.state.pltDoubleCut;
/** /**
* PLT * PLT
@ -60,7 +61,7 @@ export function usePlotterExport(store: DeckStore): UsePlotterExportReturn {
// 将卡片路径转换为相对于 frameBoundsWithMargin 的坐标 // 将卡片路径转换为相对于 frameBoundsWithMargin 的坐标
// 原点在 frameBoundsWithMargin 的左上角 // 原点在 frameBoundsWithMargin 的左上角
const relativePaths = layout.cardPaths.map(cardPath => { const relativePaths = layout.cardPaths.flatMap(cardPath => {
const relativePoints = cardPath.points.map(([x, y]) => { const relativePoints = cardPath.points.map(([x, y]) => {
// 转换为相对于 frameBounds 左上角的坐标 // 转换为相对于 frameBounds 左上角的坐标
const relativeX = x - frameBounds.x; const relativeX = x - frameBounds.x;
@ -71,7 +72,11 @@ export function usePlotterExport(store: DeckStore): UsePlotterExportReturn {
// 所以 plotterY = pltHeight - relativeY // 所以 plotterY = pltHeight - relativeY
return [relativeX, pltHeight - relativeY] as [number, number]; return [relativeX, pltHeight - relativeY] as [number, number];
}); });
return relativePoints; if (doubleCut()) {
// 重复一次:某些切割机需要每张卡牌切两次
return [relativePoints, relativePoints];
}
return [relativePoints];
}); });
// 起点和终点都在 frameBoundsWithMargin 的左上角 (0, pltHeight) // 起点和终点都在 frameBoundsWithMargin 的左上角 (0, pltHeight)