This commit is contained in:
iqudoo
2026-06-14 04:12:21 +08:00
parent 1e03b7750a
commit ccb5b119de
6 changed files with 181 additions and 114 deletions

View File

@@ -155,9 +155,63 @@ export function applyRowVariableMapping(
export const DEFAULT_EXPORT_RANGE: ExportRangeConfig = { mode: 'all' };
export const exportRangeEquals = (a: ExportRangeConfig, b: ExportRangeConfig) =>
a.mode === b.mode &&
(a.custom ?? '') === (b.custom ?? '') &&
JSON.stringify(a.filterRules ?? []) === JSON.stringify(b.filterRules ?? []);
a.mode === b.mode && (a.custom ?? '') === (b.custom ?? '');
/** 模板数据过滤规则(仅 variable 目标) */
export function resolveDataFilterRules(
template: Pick<LabelTemplate, 'dataFilterRules'>
): VisibilityRule[] {
return resolveVariableFilterRules(template.dataFilterRules);
}
/** 按模板数据过滤条件筛选 0-based 行索引 */
export function getDataFilteredIndices(
rows: RecordRow[],
template: Pick<LabelTemplate, 'dataFilterRules'>,
variableDefaults?: Record<string, string> | null
): number[] {
const total = rows.length;
if (total <= 0) return [];
const rules = getActiveVisibilityRules(resolveDataFilterRules(template));
if (rules.length === 0) return Array.from({ length: total }, (_, i) => i);
return Array.from({ length: total }, (_, i) => i).filter((i) =>
rowMatchesVariableFilterRules(rows[i], i, rules, variableDefaults)
);
}
/** 在候选行上应用排版过滤(奇偶/自定义序号,基于原始 1-based 行号) */
export function getLayoutRangeIndices(
candidateIndices: number[],
totalRows: number,
range: ExportRangeConfig
): number[] {
if (candidateIndices.length === 0) return [];
switch (range.mode) {
case 'odd':
return candidateIndices.filter((i) => (i + 1) % 2 === 1);
case 'even':
return candidateIndices.filter((i) => (i + 1) % 2 === 0);
case 'custom': {
const parsed = parseCustomExportRange(range.custom ?? '', totalRows);
const candidateSet = new Set(candidateIndices);
return parsed.filter((i) => candidateSet.has(i));
}
case 'all':
default:
return candidateIndices;
}
}
/** 按数据过滤 + 排版过滤得到最终 0-based 行索引(保持升序) */
export function getExportRangeIndices(
rows: RecordRow[],
range: ExportRangeConfig,
template: Pick<LabelTemplate, 'dataFilterRules'>,
variableDefaults?: Record<string, string> | null
): number[] {
const dataFiltered = getDataFilteredIndices(rows, template, variableDefaults);
return getLayoutRangeIndices(dataFiltered, rows.length, range);
}
export const DEFAULT_CUT_LINE_CONFIG: CutLineConfig = {
enabled: true,
@@ -247,34 +301,6 @@ export interface PrintableLabel {
sourceIndex: number;
}
/** 按导出范围筛选 0-based 行索引(保持升序) */
export function getExportRangeIndices(
rows: RecordRow[],
range: ExportRangeConfig,
variableDefaults?: Record<string, string> | null
): number[] {
const total = rows.length;
if (total <= 0) return [];
switch (range.mode) {
case 'odd':
return Array.from({ length: total }, (_, i) => i).filter((i) => (i + 1) % 2 === 1);
case 'even':
return Array.from({ length: total }, (_, i) => i).filter((i) => (i + 1) % 2 === 0);
case 'custom':
return parseCustomExportRange(range.custom ?? '', total);
case 'conditional': {
const rules = resolveVariableFilterRules(range.filterRules);
if (rules.length === 0) return Array.from({ length: total }, (_, i) => i);
return Array.from({ length: total }, (_, i) => i).filter((i) =>
rowMatchesVariableFilterRules(rows[i], i, rules, variableDefaults)
);
}
case 'all':
default:
return Array.from({ length: total }, (_, i) => i);
}
}
/** 解析自定义范围字符串1-based 序号) */
export function parseCustomExportRange(input: string, total: number): number[] {
const trimmed = input.trim();
@@ -300,13 +326,13 @@ export function parseCustomExportRange(input: string, total: number): number[] {
export function buildPrintablePages(
rows: RecordRow[],
paper: PaperConfig,
labelSize: { width: number; height: number },
template: Pick<LabelTemplate, 'width' | 'height' | 'dataFilterRules'>,
exportRange: ExportRangeConfig,
variableDefaults?: Record<string, string> | null
) {
const gridInfo = calculateGrid(paper, labelSize);
const gridInfo = calculateGrid(paper, template);
const labelsPerPage = gridInfo.cols * gridInfo.rows;
const indices = getExportRangeIndices(rows, exportRange, variableDefaults);
const indices = getExportRangeIndices(rows, exportRange, template, variableDefaults);
const selected: PrintableLabel[] = indices.map((i) => ({ row: rows[i], sourceIndex: i }));
const totalPages = Math.ceil(selected.length / labelsPerPage) || 1;
const pages: (PrintableLabel | null)[][] = [];