init commit

This commit is contained in:
iqudoo
2026-06-12 19:34:27 +08:00
commit 89b59ecc1b
38 changed files with 17719 additions and 0 deletions

168
src/types.ts Normal file
View File

@@ -0,0 +1,168 @@
export type TextFormat = 'text' | 'number' | 'percent' | 'currency';
export type ElementVisibilityMode = 'always' | 'conditional';
export type VisibilityOperator = 'empty' | 'not_empty' | 'gt' | 'lt' | 'eq' | 'neq';
export interface VisibilityRule {
variable: string;
operator: VisibilityOperator;
/** gt / lt / eq / neq 时的比较目标值 */
value?: string;
}
export const VISIBILITY_OPERATOR_LABELS: Record<VisibilityOperator, string> = {
empty: '为空',
not_empty: '不为空',
gt: '大于',
lt: '小于',
eq: '等于',
neq: '不等于',
};
export type ElementSide = 'top' | 'right' | 'bottom' | 'left';
export type ElementCorner = 'tl' | 'tr' | 'br' | 'bl';
export interface TemplateElement {
id: string;
type: 'text' | 'barcode' | 'qrcode' | 'image';
name: string;
x: number; // in mm
y: number; // in mm
width: number; // in mm
height: number; // in mm
content: string; // static text or variable binding, e.g. "{货位}" or "格式化文本 {货位}"
/** 显示控制conditional 时按 visibilityRules 判断 */
visibilityMode?: ElementVisibilityMode;
/** 显示控制条件;全部满足时才渲染(设计预览按变量默认值判断) */
visibilityRules?: VisibilityRule[];
/** @deprecated 使用 visibilityRules */
visibilityVariables?: string[];
/** @deprecated 使用 visibilityMode=conditional */
hideWhenNoData?: boolean;
/** @deprecated 使用 visibilityRules */
visibilityVariable?: string;
fontSize: number; // in pt
textAlign: 'left' | 'center' | 'right';
/** 文本垂直对齐,仅 type=text */
verticalAlign?: 'top' | 'middle' | 'bottom';
/** 是否自动换行,仅 type=text默认 true */
wordWrap?: boolean;
fontWeight: 'normal' | 'bold';
/** 斜体,仅 type=text */
fontStyle?: 'normal' | 'italic';
/** 下划线,仅 type=text */
textUnderline?: boolean;
/** 删除线,仅 type=text */
textLineThrough?: boolean;
/** 水平拉伸倍数1 为默认,仅 type=text */
textScaleX?: number;
/** 垂直拉伸倍数1 为默认,仅 type=text */
textScaleY?: number;
/** 字间距 (mm),仅 type=text */
letterSpacing?: number;
barcodeFormat: 'CODE128' | 'CODE39' | 'EAN13' | 'ITF';
showText: boolean; // For barcode human-readable text below
fontFamily: 'sans' | 'serif' | 'mono';
backgroundColor?: string;
/** 背景不透明度 0100100 为完全不透明0 或 backgroundColor 为 transparent 时不绘制背景 */
backgroundOpacity?: number;
textColor?: string;
/** 内边距 (mm),所有元素类型均有效 */
padding?: number;
locked?: boolean;
/** 图片缩放方式,仅 type=image 时有效 */
imageFit?: 'contain' | 'cover' | 'fill';
/** 文本显示格式,仅 type=text 时有效 */
textFormat?: TextFormat;
/** 数值/百分比/货币的小数位数,默认 2 */
decimalPlaces?: number;
/** 边框宽度 (mm)0 为无边框 */
borderWidth?: number;
borderColor?: string;
/** 指定哪些边显示边框,默认四边 */
borderSides?: Partial<Record<ElementSide, boolean>>;
/** 圆角半径 (mm),可被各角覆盖 */
borderRadius?: number;
/** 指定哪些角应用圆角,默认四角 */
borderRadiusCorners?: Partial<Record<ElementCorner, boolean>>;
borderRadiusTL?: number;
borderRadiusTR?: number;
borderRadiusBR?: number;
borderRadiusBL?: number;
}
export interface DataSourceMeta {
fileName: string;
sheets: string[];
currentSheet: string;
columns: string[];
rowCount: number;
}
export type CutLineStyle = 'dashed' | 'solid';
export interface CutLineConfig {
enabled: boolean;
style: CutLineStyle;
/** 线宽 (mm) */
width: number;
color: string;
}
export type ExportRangeMode = 'all' | 'odd' | 'even' | 'custom';
export interface ExportRangeConfig {
mode: ExportRangeMode;
/** 自定义范围1-based 序号,如 "1,3,5-10" */
custom?: string;
}
export interface LabelTemplate {
id?: string;
name?: string;
width: number; // in mm
height: number; // in mm
elements: TemplateElement[];
/** 模板声明的变量名(统一管理;内容/显示控制从此选取) */
variableList?: string[];
/** 设计预览用:变量名 → 默认展示值 */
variableDefaults?: Record<string, string>;
/** 整页排版配置(每模板独立) */
paper?: PaperConfig;
/** PDF 裁切参考线配置 */
cutLine?: CutLineConfig;
/** @deprecated 由 cutLine.enabled 替代 */
showPdfCutLines?: boolean;
/** @deprecated 数据范围仅存在于导出会话,不再写入模板 */
exportRange?: ExportRangeConfig;
/** @deprecated 仅用于迁移旧数据 */
dataSource?: ImportData;
/** @deprecated 模板与数据源已解耦,不再写入 */
dataSourceMeta?: DataSourceMeta;
}
export type PaperType = 'A4' | 'A5' | 'A6' | 'custom';
export interface PaperConfig {
type: PaperType;
width: number; // in mm
height: number; // in mm
orientation: 'portrait' | 'landscape';
marginTop: number; // in mm
marginRight: number; // in mm
marginBottom: number; // in mm
marginLeft: number; // in mm
columnGap: number; // in mm (horizontal spacing between labels)
rowGap: number; // in mm (vertical spacing between labels)
flow: 'top-bottom-left-right' | 'left-right-top-bottom'; // how cells flow
}
export interface RecordRow {
[key: string]: string;
}
export interface ImportData {
fileName: string;
sheets: string[];
currentSheet: string;
columns: string[];
rows: RecordRow[];
}