Files
label-designer/src/components/MobileExportPropsPanel.tsx
2026-06-12 21:39:00 +08:00

147 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react';
import { ChevronDown, Settings } from 'lucide-react';
import {
CutLineConfig,
ExportRangeConfig,
LabelTemplate,
PaperConfig,
RecordRow,
} from '../types';
import { PaperSettingsPanel, PageInput } from './PreviewGrid';
interface MobileExportPropsPanelProps {
template: LabelTemplate;
paper: PaperConfig;
onChangePaper: (paper: PaperConfig) => void;
rows: RecordRow[];
exportRange: ExportRangeConfig;
cutLine: CutLineConfig;
onChangeCutLine: (cutLine: CutLineConfig) => void;
locked?: boolean;
}
export const MobileExportPropsPanel: React.FC<MobileExportPropsPanelProps> = ({
template,
paper,
onChangePaper,
rows,
exportRange,
cutLine,
onChangeCutLine,
locked = false,
}) => {
const [open, setOpen] = useState(false);
if (locked) return null;
const paperLabel =
paper.type === 'custom' ? `${paper.width}×${paper.height} mm` : paper.type;
const summary = `${paperLabel} · ${paper.orientation === 'portrait' ? '纵向' : '横向'}${
cutLine.enabled ? ' · 裁切线' : ''
}`;
return (
<section className={`mobile-export-card mobile-export-props-card ${open ? 'is-open' : ''}`}>
<button
type="button"
className="mobile-export-card-head mobile-export-props-head"
onClick={() => setOpen((value) => !value)}
aria-expanded={open}
>
<Settings className="w-4 h-4 text-indigo-500 shrink-0 mt-0.5" />
<div className="flex-1 min-w-0 text-left">
<h2></h2>
<p>{summary}</p>
</div>
<ChevronDown
className={`w-5 h-5 text-slate-400 shrink-0 mt-0.5 transition-transform duration-200 ${
open ? 'rotate-180' : ''
}`}
/>
</button>
{open && (
<div className="mobile-export-card-body">
<PaperSettingsPanel
theme="mobile"
paper={paper}
onChangePaper={onChangePaper}
template={template}
rows={rows}
exportRange={exportRange}
totalRowCount={rows.length}
/>
<div className="space-y-3 pt-1 mt-3">
<h4 className="mobile-paper-section-title">线</h4>
<label className="flex items-center gap-3 min-h-[44px] cursor-pointer select-none">
<input
type="checkbox"
checked={cutLine.enabled}
onChange={(e) => onChangeCutLine({ ...cutLine, enabled: e.target.checked })}
className="w-5 h-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500"
/>
<span className="text-sm text-slate-700"> PDF 线</span>
</label>
<fieldset
disabled={!cutLine.enabled}
className={`space-y-3 border-0 p-0 m-0 min-w-0 ${!cutLine.enabled ? 'opacity-50' : ''}`}
>
<div>
<label className="mobile-field-label">线</label>
<select
value={cutLine.style}
onChange={(e) =>
onChangeCutLine({
...cutLine,
style: e.target.value as CutLineConfig['style'],
})
}
className="mobile-field"
>
<option value="dashed">线</option>
<option value="solid">线</option>
</select>
</div>
<div>
<label className="mobile-field-label">线 (mm)</label>
<PageInput
type="number"
min="0.02"
max="2"
step="0.02"
value={cutLine.width}
onCommit={(val) =>
onChangeCutLine({
...cutLine,
width: Math.max(0.02, Math.min(2, Number(val) || 0.1)),
})
}
inputClassName="mobile-field font-mono"
/>
</div>
<div>
<label className="mobile-field-label"></label>
<div className="flex items-center gap-2">
<input
type="color"
value={cutLine.color}
onChange={(e) => onChangeCutLine({ ...cutLine, color: e.target.value })}
className="color-input shrink-0"
aria-label="裁切线颜色"
/>
<input
type="text"
value={cutLine.color}
onChange={(e) => onChangeCutLine({ ...cutLine, color: e.target.value })}
className="mobile-field font-mono flex-1 min-w-0"
/>
</div>
</div>
</fieldset>
</div>
</div>
)}
</section>
);
};