Compare commits
No commits in common. "ec5a00fa9484db92cb8ac4d9c52e03ad34f63ce1" and "e22a8da12a3d0f344a53c7f88d31db9ac6d82ae8" have entirely different histories.
ec5a00fa94
...
e22a8da12a
|
|
@ -36,11 +36,11 @@ export function CardPreview(props: CardPreviewProps) {
|
||||||
let cardRef: HTMLDivElement | undefined;
|
let cardRef: HTMLDivElement | undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center overflow-hidden">
|
||||||
<Show when={store.state.activeTab < store.state.cards.length}>
|
<Show when={store.state.activeTab < store.state.cards.length}>
|
||||||
<div
|
<div
|
||||||
ref={cardRef}
|
ref={cardRef}
|
||||||
class="relative bg-white border border-gray-300 shadow-lg overflow-hidden"
|
class="relative bg-white border border-gray-300 shadow-lg"
|
||||||
style={{
|
style={{
|
||||||
width: `${store.state.dimensions?.cardWidth}mm`,
|
width: `${store.state.dimensions?.cardWidth}mm`,
|
||||||
height: `${store.state.dimensions?.cardHeight}mm`
|
height: `${store.state.dimensions?.cardHeight}mm`
|
||||||
|
|
|
||||||
|
|
@ -24,38 +24,22 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
const { store } = props;
|
const { store } = props;
|
||||||
|
|
||||||
// A4 纸张尺寸(mm):210 x 297
|
// A4 纸张尺寸(mm):210 x 297
|
||||||
const A4_WIDTH_PORTRAIT = 210;
|
const A4_WIDTH = 210;
|
||||||
const A4_HEIGHT_PORTRAIT = 297;
|
const A4_HEIGHT = 297;
|
||||||
const A4_WIDTH_LANDSCAPE = 297;
|
|
||||||
const A4_HEIGHT_LANDSCAPE = 210;
|
|
||||||
const PRINT_MARGIN = 5; // 打印边距
|
const PRINT_MARGIN = 5; // 打印边距
|
||||||
|
|
||||||
// 获取打印设置
|
|
||||||
const orientation = () => store.state.printOrientation;
|
|
||||||
const oddPageOffsetX = () => store.state.printOddPageOffsetX;
|
|
||||||
const oddPageOffsetY = () => store.state.printOddPageOffsetY;
|
|
||||||
|
|
||||||
// 根据方向获取 A4 尺寸
|
|
||||||
const getA4Size = () => {
|
|
||||||
if (orientation() === 'landscape') {
|
|
||||||
return { width: A4_WIDTH_LANDSCAPE, height: A4_HEIGHT_LANDSCAPE };
|
|
||||||
}
|
|
||||||
return { width: A4_WIDTH_PORTRAIT, height: A4_HEIGHT_PORTRAIT };
|
|
||||||
};
|
|
||||||
|
|
||||||
// 计算每张卡牌在 A4 纸上的位置(居中布局)
|
// 计算每张卡牌在 A4 纸上的位置(居中布局)
|
||||||
const pages = createMemo(() => {
|
const pages = createMemo(() => {
|
||||||
const cards = store.state.cards;
|
const cards = store.state.cards;
|
||||||
const cardWidth = store.state.dimensions?.cardWidth || 56;
|
const cardWidth = store.state.dimensions?.cardWidth || 56;
|
||||||
const cardHeight = store.state.dimensions?.cardHeight || 88;
|
const cardHeight = store.state.dimensions?.cardHeight || 88;
|
||||||
const { width: a4Width, height: a4Height } = getA4Size();
|
|
||||||
|
|
||||||
// 每行可容纳的卡牌数量
|
// 每行可容纳的卡牌数量
|
||||||
const usableWidth = a4Width - PRINT_MARGIN * 2;
|
const usableWidth = A4_WIDTH - PRINT_MARGIN * 2;
|
||||||
const cardsPerRow = Math.floor(usableWidth / cardWidth);
|
const cardsPerRow = Math.floor(usableWidth / cardWidth);
|
||||||
|
|
||||||
// 每页可容纳的行数
|
// 每页可容纳的行数
|
||||||
const usableHeight = a4Height - PRINT_MARGIN * 2;
|
const usableHeight = A4_HEIGHT - PRINT_MARGIN * 2;
|
||||||
const rowsPerPage = Math.floor(usableHeight / cardHeight);
|
const rowsPerPage = Math.floor(usableHeight / cardHeight);
|
||||||
|
|
||||||
// 每页的卡牌数量
|
// 每页的卡牌数量
|
||||||
|
|
@ -66,8 +50,8 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
const maxGridHeight = rowsPerPage * cardHeight;
|
const maxGridHeight = rowsPerPage * cardHeight;
|
||||||
|
|
||||||
// 居中偏移量(使卡牌区域在 A4 纸上居中)
|
// 居中偏移量(使卡牌区域在 A4 纸上居中)
|
||||||
const baseOffsetX = (a4Width - maxGridWidth) / 2;
|
const offsetX = (A4_WIDTH - maxGridWidth) / 2;
|
||||||
const baseOffsetY = (a4Height - maxGridHeight) / 2;
|
const offsetY = (A4_HEIGHT - maxGridHeight) / 2;
|
||||||
|
|
||||||
// 分页
|
// 分页
|
||||||
const result: {
|
const result: {
|
||||||
|
|
@ -88,14 +72,9 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
currentPage = { pageIndex, cards: [], bounds: { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity } };
|
currentPage = { pageIndex, cards: [], bounds: { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity } };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 奇数页应用偏移(pageIndex 从 0 开始,所以偶数索引是奇数页)
|
// 使用居中偏移量计算卡牌位置
|
||||||
const isOddPage = pageIndex % 2 === 0;
|
const cardX = offsetX + col * cardWidth;
|
||||||
const pageOffsetX = isOddPage ? oddPageOffsetX() : 0;
|
const cardY = offsetY + row * cardHeight;
|
||||||
const pageOffsetY = isOddPage ? oddPageOffsetY() : 0;
|
|
||||||
|
|
||||||
// 使用居中偏移量 + 奇数页偏移计算卡牌位置
|
|
||||||
const cardX = baseOffsetX + col * cardWidth + pageOffsetX;
|
|
||||||
const cardY = baseOffsetY + row * cardHeight + pageOffsetY;
|
|
||||||
|
|
||||||
currentPage.cards.push({
|
currentPage.cards.push({
|
||||||
data: cards[i],
|
data: cards[i],
|
||||||
|
|
@ -118,10 +97,10 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
return result.map(page => ({
|
return result.map(page => ({
|
||||||
...page,
|
...page,
|
||||||
frameBounds: {
|
frameBounds: {
|
||||||
minX: baseOffsetX + (page.pageIndex % 2 === 0 ? oddPageOffsetX() : 0),
|
minX: offsetX,
|
||||||
minY: baseOffsetY + (page.pageIndex % 2 === 0 ? oddPageOffsetY() : 0),
|
minY: offsetY,
|
||||||
maxX: baseOffsetX + maxGridWidth + (page.pageIndex % 2 === 0 ? oddPageOffsetX() : 0),
|
maxX: offsetX + maxGridWidth,
|
||||||
maxY: baseOffsetY + maxGridHeight + (page.pageIndex % 2 === 0 ? oddPageOffsetY() : 0)
|
maxY: offsetY + maxGridHeight
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
@ -179,128 +158,15 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
|
|
||||||
const visibleLayers = createMemo(() => store.state.layerConfigs.filter((l) => l.visible));
|
const visibleLayers = createMemo(() => store.state.layerConfigs.filter((l) => l.visible));
|
||||||
|
|
||||||
// 渲染单个卡片的 SVG 内容(使用 foreignObject)
|
|
||||||
const renderCardInSvg = (card: { data: typeof store.state.cards[0]; x: number; y: number }, pageIndex: number) => {
|
|
||||||
const cardWidth = store.state.dimensions?.cardWidth || 56;
|
|
||||||
const cardHeight = store.state.dimensions?.cardHeight || 88;
|
|
||||||
const gridOriginX = store.state.dimensions?.gridOriginX || 0;
|
|
||||||
const gridOriginY = store.state.dimensions?.gridOriginY || 0;
|
|
||||||
const gridAreaWidth = store.state.dimensions?.gridAreaWidth || cardWidth;
|
|
||||||
const gridAreaHeight = store.state.dimensions?.gridAreaHeight || cardHeight;
|
|
||||||
const fontSize = store.state.dimensions?.fontSize || 3;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<g class="card-group">
|
|
||||||
<foreignObject
|
|
||||||
x={`${card.x}mm`}
|
|
||||||
y={`${card.y}mm`}
|
|
||||||
width={`${cardWidth}mm`}
|
|
||||||
height={`${cardHeight}mm`}
|
|
||||||
>
|
|
||||||
<div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full bg-white">
|
|
||||||
{/* 网格区域容器 */}
|
|
||||||
<div
|
|
||||||
class="absolute"
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
left: `${gridOriginX}mm`,
|
|
||||||
top: `${gridOriginY}mm`,
|
|
||||||
width: `${gridAreaWidth}mm`,
|
|
||||||
height: `${gridAreaHeight}mm`
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* 渲染每个 layer */}
|
|
||||||
<For each={visibleLayers()}>
|
|
||||||
{(layer) => (
|
|
||||||
<div
|
|
||||||
class="absolute flex items-center justify-center text-center prose prose-sm"
|
|
||||||
style={{
|
|
||||||
...getLayerStyle(layer, store.state.dimensions!),
|
|
||||||
'font-size': `${fontSize}mm`
|
|
||||||
}}
|
|
||||||
innerHTML={renderLayerContent(layer, card.data)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</foreignObject>
|
|
||||||
</g>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="fixed inset-0 bg-black/50 z-50 overflow-auto print:overflow-visible print:absolute">
|
<div class="fixed inset-0 bg-black/50 z-50 overflow-auto print:overflow-visible print:absolute">
|
||||||
{/* 打印样式:根据方向设置 @page 规则 */}
|
|
||||||
<style>{`
|
|
||||||
@media print {
|
|
||||||
@page {
|
|
||||||
size: A4 ${orientation() === 'landscape' ? 'landscape' : 'portrait'};
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
<div class="min-h-screen py-20 px-4 print:p-0">
|
<div class="min-h-screen py-20 px-4 print:p-0">
|
||||||
{/* 打印预览控制栏 */}
|
{/* 打印预览控制栏 */}
|
||||||
<div class="fixed top-0 left-0 right-0 z-50 bg-white shadow-lg rounded-lg mx-4 mt-4 px-4 py-3 flex items-center justify-between gap-4">
|
<div class="fixed top-0 left-0 right-0 z-50 bg-white shadow-lg rounded-lg mx-4 mt-4 px-4 py-1 flex items-center justify-between gap-4">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<h2 class="text-base font-bold mt-0 mb-0">打印预览</h2>
|
<h2 class="text-base font-bold mt-0 mb-0">打印预览</h2>
|
||||||
<p class="text-xs text-gray-500 mb-0">共 {pages().length} 页,{store.state.cards.length} 张卡牌</p>
|
<p class="text-xs text-gray-500 mb-0">共 {pages().length} 页,{store.state.cards.length} 张卡牌</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-4">
|
|
||||||
{/* 方向选择 */}
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<label class="text-sm text-gray-600">方向:</label>
|
|
||||||
<div class="flex gap-1">
|
|
||||||
<button
|
|
||||||
onClick={() => store.actions.setPrintOrientation('portrait')}
|
|
||||||
class={`px-3 py-1 rounded text-sm font-medium cursor-pointer border ${
|
|
||||||
orientation() === 'portrait'
|
|
||||||
? 'bg-blue-600 text-white border-blue-600'
|
|
||||||
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
竖向
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={() => store.actions.setPrintOrientation('landscape')}
|
|
||||||
class={`px-3 py-1 rounded text-sm font-medium cursor-pointer border ${
|
|
||||||
orientation() === 'landscape'
|
|
||||||
? 'bg-blue-600 text-white border-blue-600'
|
|
||||||
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
横向
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* 奇数页偏移 */}
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<label class="text-sm text-gray-600">奇数页偏移:</label>
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-xs text-gray-500">X:</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
value={oddPageOffsetX()}
|
|
||||||
onChange={(e) => store.actions.setPrintOddPageOffsetX(Number(e.target.value))}
|
|
||||||
class="w-16 px-2 py-1 border border-gray-300 rounded text-sm"
|
|
||||||
step="0.1"
|
|
||||||
/>
|
|
||||||
<span class="text-xs text-gray-500 ml-1">mm</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-xs text-gray-500">Y:</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
value={oddPageOffsetY()}
|
|
||||||
onChange={(e) => store.actions.setPrintOddPageOffsetY(Number(e.target.value))}
|
|
||||||
class="w-16 px-2 py-1 border border-gray-300 rounded text-sm"
|
|
||||||
step="0.1"
|
|
||||||
/>
|
|
||||||
<span class="text-xs text-gray-500 ml-1">mm</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={props.onPrint}
|
onClick={props.onPrint}
|
||||||
|
|
@ -318,87 +184,125 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* A4 纸张预览:每页都是一个完整的 SVG */}
|
{/* A4 纸张预览 */}
|
||||||
<div class="flex flex-col items-center gap-8 print-root">
|
<div class="flex flex-col items-center gap-8 print-root">
|
||||||
<For each={pages()}>
|
<For each={pages()}>
|
||||||
{(page) => (
|
{(page) => (
|
||||||
<svg
|
<div
|
||||||
class="bg-white shadow-xl print:shadow-none"
|
class="bg-white shadow-xl print:shadow-none print:w-full"
|
||||||
viewBox={`0 0 ${getA4Size().width}mm ${getA4Size().height}mm`}
|
|
||||||
style={{
|
style={{
|
||||||
width: `${getA4Size().width}mm`,
|
width: `${A4_WIDTH}mm`,
|
||||||
height: `${getA4Size().height}mm`
|
height: `${A4_HEIGHT}mm`
|
||||||
}}
|
}}
|
||||||
data-page={page.pageIndex + 1}
|
data-page={page.pageIndex + 1}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
>
|
||||||
{/* 外围边框:黑色 0.2mm */}
|
|
||||||
<rect
|
|
||||||
x={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.x}mm`}
|
|
||||||
y={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.y}mm`}
|
|
||||||
width={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.width}mm`}
|
|
||||||
height={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.height}mm`}
|
|
||||||
fill="none"
|
|
||||||
stroke="black"
|
|
||||||
stroke-width="0.2"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 水平裁切线 */}
|
|
||||||
<For each={cropMarks()[page.pageIndex]?.horizontalLines}>
|
|
||||||
{(line) => (
|
|
||||||
<>
|
|
||||||
{/* 左侧裁切线(外围框外部) */}
|
|
||||||
<line
|
|
||||||
x1={`${line.xStart}mm`}
|
|
||||||
y1={`${line.y}mm`}
|
|
||||||
x2={`${page.frameBounds.minX}mm`}
|
|
||||||
y2={`${line.y}mm`}
|
|
||||||
stroke="#888"
|
|
||||||
stroke-width="0.1"
|
|
||||||
/>
|
|
||||||
{/* 右侧裁切线(外围框外部) */}
|
|
||||||
<line
|
|
||||||
x1={`${page.frameBounds.maxX}mm`}
|
|
||||||
y1={`${line.y}mm`}
|
|
||||||
x2={`${line.xEnd}mm`}
|
|
||||||
y2={`${line.y}mm`}
|
|
||||||
stroke="#888"
|
|
||||||
stroke-width="0.1"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
{/* 垂直裁切线 */}
|
|
||||||
<For each={cropMarks()[page.pageIndex]?.verticalLines}>
|
|
||||||
{(line) => (
|
|
||||||
<>
|
|
||||||
{/* 上方裁切线(外围框外部) */}
|
|
||||||
<line
|
|
||||||
x1={`${line.x}mm`}
|
|
||||||
y1={`${line.yStart}mm`}
|
|
||||||
x2={`${line.x}mm`}
|
|
||||||
y2={`${page.frameBounds.minY}mm`}
|
|
||||||
stroke="#888"
|
|
||||||
stroke-width="0.1"
|
|
||||||
/>
|
|
||||||
{/* 下方裁切线(外围框外部) */}
|
|
||||||
<line
|
|
||||||
x1={`${line.x}mm`}
|
|
||||||
y1={`${page.frameBounds.maxY}mm`}
|
|
||||||
x2={`${line.x}mm`}
|
|
||||||
y2={`${line.yEnd}mm`}
|
|
||||||
stroke="#888"
|
|
||||||
stroke-width="0.1"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
|
|
||||||
{/* 渲染该页的所有卡牌 */}
|
{/* 渲染该页的所有卡牌 */}
|
||||||
<For each={page.cards}>
|
<div class="relative w-full h-full">
|
||||||
{(card) => renderCardInSvg(card, page.pageIndex)}
|
{/* 裁切线和外围框层 */}
|
||||||
</For>
|
<svg class="absolute inset-0 w-full h-full pointer-events-none" style={{ overflow: 'visible' }}>
|
||||||
</svg>
|
{/* 外围边框:黑色 0.2mm */}
|
||||||
|
<rect
|
||||||
|
x={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.x}mm`}
|
||||||
|
y={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.y}mm`}
|
||||||
|
width={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.width}mm`}
|
||||||
|
height={`${cropMarks()[page.pageIndex]?.frameBoundsWithMargin.height}mm`}
|
||||||
|
fill="none"
|
||||||
|
stroke="black"
|
||||||
|
stroke-width="0.2"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 水平裁切线 */}
|
||||||
|
<For each={cropMarks()[page.pageIndex]?.horizontalLines}>
|
||||||
|
{(line) => (
|
||||||
|
<>
|
||||||
|
{/* 左侧裁切线(外围框外部) */}
|
||||||
|
<line
|
||||||
|
x1={`${line.xStart}mm`}
|
||||||
|
y1={`${line.y}mm`}
|
||||||
|
x2={`${page.frameBounds.minX}mm`}
|
||||||
|
y2={`${line.y}mm`}
|
||||||
|
stroke="#888"
|
||||||
|
stroke-width="0.1"
|
||||||
|
/>
|
||||||
|
{/* 右侧裁切线(外围框外部) */}
|
||||||
|
<line
|
||||||
|
x1={`${page.frameBounds.maxX}mm`}
|
||||||
|
y1={`${line.y}mm`}
|
||||||
|
x2={`${line.xEnd}mm`}
|
||||||
|
y2={`${line.y}mm`}
|
||||||
|
stroke="#888"
|
||||||
|
stroke-width="0.1"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
{/* 垂直裁切线 */}
|
||||||
|
<For each={cropMarks()[page.pageIndex]?.verticalLines}>
|
||||||
|
{(line) => (
|
||||||
|
<>
|
||||||
|
{/* 上方裁切线(外围框外部) */}
|
||||||
|
<line
|
||||||
|
x1={`${line.x}mm`}
|
||||||
|
y1={`${line.yStart}mm`}
|
||||||
|
x2={`${line.x}mm`}
|
||||||
|
y2={`${page.frameBounds.minY}mm`}
|
||||||
|
stroke="#888"
|
||||||
|
stroke-width="0.1"
|
||||||
|
/>
|
||||||
|
{/* 下方裁切线(外围框外部) */}
|
||||||
|
<line
|
||||||
|
x1={`${line.x}mm`}
|
||||||
|
y1={`${page.frameBounds.maxY}mm`}
|
||||||
|
x2={`${line.x}mm`}
|
||||||
|
y2={`${line.yEnd}mm`}
|
||||||
|
stroke="#888"
|
||||||
|
stroke-width="0.1"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<For each={page.cards}>
|
||||||
|
{(card) => (
|
||||||
|
<div
|
||||||
|
class="absolute bg-white"
|
||||||
|
style={{
|
||||||
|
left: `${card.x}mm`,
|
||||||
|
top: `${card.y}mm`,
|
||||||
|
width: `${store.state.dimensions?.cardWidth}mm`,
|
||||||
|
height: `${store.state.dimensions?.cardHeight}mm`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 网格区域容器 */}
|
||||||
|
<div
|
||||||
|
class="absolute"
|
||||||
|
style={{
|
||||||
|
left: `${store.state.dimensions?.gridOriginX}mm`,
|
||||||
|
top: `${store.state.dimensions?.gridOriginY}mm`,
|
||||||
|
width: `${store.state.dimensions?.gridAreaWidth}mm`,
|
||||||
|
height: `${store.state.dimensions?.gridAreaHeight}mm`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 渲染每个 layer */}
|
||||||
|
<For each={visibleLayers()}>
|
||||||
|
{(layer) => (
|
||||||
|
<div
|
||||||
|
class="absolute flex items-center justify-center text-center prose prose-sm"
|
||||||
|
style={{
|
||||||
|
...getLayerStyle(layer, store.state.dimensions!),
|
||||||
|
'font-size': `${store.state.dimensions?.fontSize}mm`
|
||||||
|
}}
|
||||||
|
innerHTML={renderLayerContent(layer, card.data)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -56,11 +56,6 @@ export interface DeckState {
|
||||||
|
|
||||||
// 打印状态
|
// 打印状态
|
||||||
isPrinting: boolean;
|
isPrinting: boolean;
|
||||||
|
|
||||||
// 打印设置
|
|
||||||
printOrientation: 'portrait' | 'landscape';
|
|
||||||
printOddPageOffsetX: number;
|
|
||||||
printOddPageOffsetY: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeckActions {
|
export interface DeckActions {
|
||||||
|
|
@ -106,11 +101,6 @@ export interface DeckActions {
|
||||||
// 打印操作
|
// 打印操作
|
||||||
setPrinting: (printing: boolean) => void;
|
setPrinting: (printing: boolean) => void;
|
||||||
printDeck: () => void;
|
printDeck: () => void;
|
||||||
|
|
||||||
// 打印设置
|
|
||||||
setPrintOrientation: (orientation: 'portrait' | 'landscape') => void;
|
|
||||||
setPrintOddPageOffsetX: (offset: number) => void;
|
|
||||||
setPrintOddPageOffsetY: (offset: number) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeckStore {
|
export interface DeckStore {
|
||||||
|
|
@ -146,10 +136,7 @@ export function createDeckStore(
|
||||||
selectEnd: null,
|
selectEnd: null,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
isPrinting: false,
|
isPrinting: false
|
||||||
printOrientation: 'portrait',
|
|
||||||
printOddPageOffsetX: 0,
|
|
||||||
printOddPageOffsetY: 0
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新尺寸并重新计算 dimensions
|
// 更新尺寸并重新计算 dimensions
|
||||||
|
|
@ -292,18 +279,6 @@ export function createDeckStore(
|
||||||
setState({ isPrinting: true });
|
setState({ isPrinting: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
const setPrintOrientation = (orientation: 'portrait' | 'landscape') => {
|
|
||||||
setState({ printOrientation: orientation });
|
|
||||||
};
|
|
||||||
|
|
||||||
const setPrintOddPageOffsetX = (offset: number) => {
|
|
||||||
setState({ printOddPageOffsetX: offset });
|
|
||||||
};
|
|
||||||
|
|
||||||
const setPrintOddPageOffsetY = (offset: number) => {
|
|
||||||
setState({ printOddPageOffsetY: offset });
|
|
||||||
};
|
|
||||||
|
|
||||||
const actions: DeckActions = {
|
const actions: DeckActions = {
|
||||||
setSizeW,
|
setSizeW,
|
||||||
setSizeH,
|
setSizeH,
|
||||||
|
|
@ -331,10 +306,7 @@ export function createDeckStore(
|
||||||
generateCode,
|
generateCode,
|
||||||
copyCode,
|
copyCode,
|
||||||
setPrinting,
|
setPrinting,
|
||||||
printDeck,
|
printDeck
|
||||||
setPrintOrientation,
|
|
||||||
setPrintOddPageOffsetX,
|
|
||||||
setPrintOddPageOffsetY
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return { state, actions };
|
return { state, actions };
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,8 @@
|
||||||
import { Marked } from 'marked';
|
import { Marked } from 'marked';
|
||||||
import {createDirectives, presetDirectiveConfigs} from 'marked-directive';
|
import { createDirectives } from 'marked-directive';
|
||||||
|
|
||||||
// 使用 marked-directive 来支持指令语法
|
// 使用 marked-directive 来支持指令语法
|
||||||
const marked = new Marked().use(createDirectives([
|
const marked = new Marked().use(createDirectives());
|
||||||
...presetDirectiveConfigs,
|
|
||||||
{
|
|
||||||
marker: '::::',
|
|
||||||
level: 'container'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
marker: ':::::',
|
|
||||||
level: 'container'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
level: 'inline',
|
|
||||||
marker: ':',
|
|
||||||
// :[blah] becomes <i class="icon icon-blah"></i>
|
|
||||||
renderer(token) {
|
|
||||||
if (!token.meta.name) {
|
|
||||||
return `<icon class="icon-${token.text}"></icon>`;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]));
|
|
||||||
|
|
||||||
export function parseMarkdown(content: string): string {
|
export function parseMarkdown(content: string): string {
|
||||||
return marked.parse(content.trimStart()) as string;
|
return marked.parse(content.trimStart()) as string;
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,9 @@
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@page {
|
||||||
|
size: A4;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue